From f76878e2fea6b2e7fd23163cd9d42dc6211f623d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 00:34:12 +0900 Subject: [PATCH 01/12] Add a very basic popup testcase --- osu.Game.Tests/Visual/TestCasePopupDialog.cs | 37 ++++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + 2 files changed, 38 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCasePopupDialog.cs diff --git a/osu.Game.Tests/Visual/TestCasePopupDialog.cs b/osu.Game.Tests/Visual/TestCasePopupDialog.cs new file mode 100644 index 0000000000..ed9c47a253 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCasePopupDialog.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2007-2017 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.Overlays.Dialog; + +namespace osu.Game.Tests.Visual +{ + public class TestCasePopupDialog : OsuTestCase + { + public TestCasePopupDialog() + { + var popup = new PopupDialog + { + RelativeSizeAxes = Axes.Both, + State = Framework.Graphics.Containers.Visibility.Visible, + Icon = FontAwesome.fa_assistive_listening_systems, + HeaderText = @"This is a test popup", + BodyText = "I can say lots of stuff and even wrap my words!", + Buttons = new PopupDialogButton[] + { + new PopupDialogCancelButton + { + Text = @"Yes. That you can.", + }, + new PopupDialogOkButton + { + Text = @"You're a fake!", + }, + } + }; + + Add(popup); + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index ff012bb6e2..134fc4a6ac 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -134,6 +134,7 @@ + From 929633efaa8ad611969e678a9cfe796d4014b86b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 00:34:40 +0900 Subject: [PATCH 02/12] Make body text in popups word wrap properly --- osu.Game/Overlays/Dialog/PopupDialog.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 9b19b8150e..d2bd50cad6 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Dialog private readonly FillFlowContainer buttonsContainer; private readonly SpriteIcon icon; private readonly SpriteText header; - private readonly SpriteText body; + private readonly TextFlowContainer body; public FontAwesome Icon { @@ -48,7 +48,6 @@ namespace osu.Game.Overlays.Dialog public string BodyText { - get { return body.Text; } set { body.Text = value; } } @@ -220,17 +219,15 @@ namespace osu.Game.Overlays.Dialog { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Text = @"Header", TextSize = 25, Shadow = true, }, - body = new OsuSpriteText + body = new OsuTextFlowContainer(t => t.TextSize = 18) { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Text = @"Body", - TextSize = 18, - Shadow = true, + Padding = new MarginPadding(15), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + TextAnchor = Anchor.TopCentre, }, }, }, From 3c1654e5e496d8c22927019ca9a90d0177045b58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 00:44:35 +0900 Subject: [PATCH 03/12] Fix many instances of non-osu-prefixed text classes being used Results in incorrect default formatting. --- osu.Game/Overlays/BeatmapSet/Info.cs | 3 ++- osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 3 ++- osu.Game/Overlays/Notifications/ProgressNotification.cs | 3 ++- osu.Game/Overlays/Notifications/SimpleNotification.cs | 5 +++-- osu.Game/Overlays/OnScreenDisplay.cs | 7 ++++--- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs | 3 ++- osu.Game/Screens/Ranking/Results.cs | 9 +++++---- osu.Game/Screens/Ranking/ResultsPageScore.cs | 4 ++-- osu.Game/Screens/Select/BeatmapDetails.cs | 5 +++-- osu.Game/Tests/Visual/TestCasePerformancePoints.cs | 3 +-- osu.sln.DotSettings | 5 +++++ 12 files changed, 32 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index bd108a193b..b4aea898b2 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -8,6 +8,7 @@ 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; using OpenTK; using OpenTK.Graphics; @@ -176,7 +177,7 @@ namespace osu.Game.Overlays.BeatmapSet Shadow = false, Margin = new MarginPadding { Top = 20 }, }, - textFlow = new TextFlowContainer + textFlow = new OsuTextFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index 53d77dab6c..c6be428987 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; 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.Users; @@ -88,7 +89,7 @@ namespace osu.Game.Overlays.MedalSplash Alpha = 0f, Scale = new Vector2(1f / scale_when_full), }, - description = new TextFlowContainer + description = new OsuTextFlowContainer { TextAnchor = Anchor.TopCentre, Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 12c7fe64ba..9211c227f8 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -7,6 +7,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 OpenTK; using OpenTK.Graphics; @@ -114,7 +115,7 @@ namespace osu.Game.Overlays.Notifications RelativeSizeAxes = Axes.Both, }); - Content.Add(textDrawable = new TextFlowContainer(t => + Content.Add(textDrawable = new OsuTextFlowContainer(t => { t.TextSize = 16; }) diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index daf1ac838d..0b8b365c48 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using OpenTK; namespace osu.Game.Overlays.Notifications @@ -58,7 +59,7 @@ namespace osu.Game.Overlays.Notifications } }); - Content.Add(textDrawable = new TextFlowContainer(t => t.TextSize = 16) + Content.Add(textDrawable = new OsuTextFlowContainer(t => t.TextSize = 16) { Colour = OsuColour.Gray(128), AutoSizeAxes = Axes.Y, @@ -87,4 +88,4 @@ namespace osu.Game.Overlays.Notifications } } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index dcab942522..ce0feeb4c6 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays { @@ -63,7 +64,7 @@ namespace osu.Game.Overlays Width = 240, RelativeSizeAxes = Axes.Y, }, - textLine1 = new SpriteText + textLine1 = new OsuSpriteText { Padding = new MarginPadding(10), Font = @"Exo2.0-Black", @@ -72,7 +73,7 @@ namespace osu.Game.Overlays Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, - textLine2 = new SpriteText + textLine2 = new OsuSpriteText { TextSize = 24, Font = @"Exo2.0-Light", @@ -97,7 +98,7 @@ namespace osu.Game.Overlays Origin = Anchor.TopCentre, AutoSizeAxes = Axes.Both }, - textLine3 = new SpriteText + textLine3 = new OsuSpriteText { Padding = new MarginPadding { Bottom = 15 }, Font = @"Exo2.0-Bold", diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index a706799664..4cdb6ec958 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -473,7 +473,7 @@ namespace osu.Game.Overlays.Profile Width = width, Height = 26 }); - Add(numberText = new SpriteText + Add(numberText = new OsuSpriteText { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index 8a835634b8..904ed609e8 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users; @@ -120,7 +121,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu } } }, - new TextFlowContainer(t => { t.TextSize = 19; }) + new OsuTextFlowContainer(t => { t.TextSize = 19; }) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 8e27cb235c..406887624c 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -17,6 +17,7 @@ using OpenTK.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Ranking { @@ -183,7 +184,7 @@ namespace osu.Game.Screens.Ranking Height = 50, Margin = new MarginPadding { Bottom = 110 }, }, - new SpriteText + new OsuSpriteText { Text = $"{score.MaxCombo}x", TextSize = 40, @@ -194,7 +195,7 @@ namespace osu.Game.Screens.Ranking Anchor = Anchor.CentreLeft, Origin = Anchor.BottomCentre, }, - new SpriteText + new OsuSpriteText { Text = "max combo", TextSize = 20, @@ -204,7 +205,7 @@ namespace osu.Game.Screens.Ranking Anchor = Anchor.CentreLeft, Origin = Anchor.TopCentre, }, - new SpriteText + new OsuSpriteText { Text = $"{score.Accuracy:P2}", TextSize = 40, @@ -215,7 +216,7 @@ namespace osu.Game.Screens.Ranking Anchor = Anchor.CentreLeft, Origin = Anchor.BottomCentre, }, - new SpriteText + new OsuSpriteText { Text = "accuracy", TextSize = 20, diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 911b688669..4c776aa7ab 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -201,14 +201,14 @@ namespace osu.Game.Screens.Ranking { Children = new Drawable[] { - new SpriteText { + new OsuSpriteText { Text = statistic.Value.ToString().PadLeft(4, '0'), Colour = colours.Gray7, TextSize = 30, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, - new SpriteText { + new OsuSpriteText { Text = statistic.Key, Colour = colours.Gray7, Font = @"Exo2.0-Bold", diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index a9a778fe17..79d76dd00e 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -17,6 +17,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Screens.Select.Details; using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select { @@ -334,7 +335,7 @@ namespace osu.Game.Screens.Select TextSize = 14, }, }, - textFlow = new TextFlowContainer + textFlow = new OsuTextFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -359,7 +360,7 @@ namespace osu.Game.Screens.Select private void setTextAsync(string text) { - LoadComponentAsync(new TextFlowContainer(s => s.TextSize = 14) + LoadComponentAsync(new OsuTextFlowContainer(s => s.TextSize = 14) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs index f71bece279..8984fc843f 100644 --- a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs +++ b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs @@ -12,7 +12,6 @@ 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; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; @@ -224,7 +223,7 @@ namespace osu.Game.Tests.Visual if (!api.IsLoggedIn) { - InternalChild = new SpriteText + InternalChild = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 2f52881d6d..20007e3306 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -172,6 +172,7 @@ NEXT_LINE NEXT_LINE True + NEVER False False True @@ -655,7 +656,11 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-frame <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> True + True + True + True True True + True True True From 3c8d30f8e67158ce5b105ce28eff9b726aa09093 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 00:37:50 +0900 Subject: [PATCH 04/12] Add a dialog offering to import beatmaps from stable --- osu.Game/Beatmaps/BeatmapManager.cs | 6 ++-- .../Sections/Maintenance/GeneralSettings.cs | 3 +- .../Screens/Select/ImportFromStablePopup.cs | 33 +++++++++++++++++++ osu.Game/Screens/Select/PlaySongSelect.cs | 15 +++++++-- osu.Game/osu.Game.csproj | 1 + 5 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Screens/Select/ImportFromStablePopup.cs diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 0325785016..c86860f7b0 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -697,10 +697,12 @@ namespace osu.Game.Beatmaps } } + public bool StableInstallationAvailable => GetStableStorage?.Invoke() != null; + /// /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. /// - public void ImportFromStable() + public async Task ImportFromStable() { var stable = GetStableStorage?.Invoke(); @@ -710,7 +712,7 @@ namespace osu.Game.Beatmaps return; } - Import(stable.GetDirectories("Songs")); + await Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs")), TaskCreationOptions.LongRunning); } public void DeleteAll() diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index e288445c6d..9ab4143613 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -30,8 +30,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Action = () => { importButton.Enabled.Value = false; - Task.Factory.StartNew(beatmaps.ImportFromStable) - .ContinueWith(t => Schedule(() => importButton.Enabled.Value = true), TaskContinuationOptions.LongRunning); + beatmaps.ImportFromStable().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true)); } }, deleteButton = new DangerousSettingsButton diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs new file mode 100644 index 0000000000..489ab79fa4 --- /dev/null +++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; +using osu.Game.Overlays.Dialog; + +namespace osu.Game.Screens.Select +{ + public class ImportFromStablePopup : PopupDialog + { + 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?"; + + Icon = FontAwesome.fa_trash_o; + + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Yes please!", + Action = importFromStable + }, + new PopupDialogCancelButton + { + Text = @"No, I'd like to start from scratch", + }, + }; + } + } +} diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 4a0ee31fbb..727cdb9959 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Screens.Edit; using osu.Game.Screens.Play; @@ -45,8 +46,8 @@ namespace osu.Game.Screens.Select private SampleChannel sampleConfirm; - [BackgroundDependencyLoader] - private void load(OsuColour colours, AudioManager audio) + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay) { sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); @@ -59,6 +60,16 @@ namespace osu.Game.Screens.Select ValidForResume = false; Push(new Editor()); }, Key.Number3); + + if (dialogOverlay != null) + { + Schedule(() => + { + // if we have no beatmaps but osu-stable is found, let's prompt the user to import. + if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) + dialogOverlay.Push(new ImportFromStablePopup(() => beatmaps.ImportFromStable())); + }); + } } protected override void UpdateBeatmap(WorkingBeatmap beatmap) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 94678106bf..fa25fa7048 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -310,6 +310,7 @@ + From dff082ed940ad1cd93e0a52f62bd8dd46a5546f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:12:46 +0900 Subject: [PATCH 05/12] Make toolbar testable and add the most basic of visual tests --- osu.Game.Tests/Visual/TestCaseToolbar.cs | 25 +++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + .../Overlays/Toolbar/ToolbarChatButton.cs | 2 +- .../Overlays/Toolbar/ToolbarDirectButton.cs | 2 +- .../Overlays/Toolbar/ToolbarModeSelector.cs | 7 ++++-- .../Overlays/Toolbar/ToolbarMusicButton.cs | 2 +- .../Toolbar/ToolbarNotificationButton.cs | 2 +- .../Toolbar/ToolbarOverlayToggleButton.cs | 7 ++++-- .../Overlays/Toolbar/ToolbarSettingsButton.cs | 2 +- .../Overlays/Toolbar/ToolbarSocialButton.cs | 2 +- 10 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseToolbar.cs diff --git a/osu.Game.Tests/Visual/TestCaseToolbar.cs b/osu.Game.Tests/Visual/TestCaseToolbar.cs new file mode 100644 index 0000000000..9045249b9a --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseToolbar.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2017 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.Containers; +using osu.Game.Overlays.Toolbar; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseToolbar : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ToolbarButton), + typeof(ToolbarModeSelector), + typeof(ToolbarModeButton), + }; + + public TestCaseToolbar() + { + Add(new Toolbar { State = Visibility.Visible }); + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index ff012bb6e2..71703d264a 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -148,6 +148,7 @@ + diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index ed206e7e1d..b0171feb30 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar SetIcon(FontAwesome.fa_comments); } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(ChatOverlay chat) { StateContainer = chat; diff --git a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs index 7d25440e2c..5c64ae69ec 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar SetIcon(FontAwesome.fa_osu_chevron_down_o); } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(DirectOverlay direct) { StateContainer = direct; diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 319dd63bc9..f38c772890 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Toolbar }; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(RulesetStore rulesets, OsuGame game) { foreach (var r in rulesets.AvailableRulesets) @@ -81,7 +81,10 @@ namespace osu.Game.Overlays.Toolbar ruleset.ValueChanged += rulesetChanged; ruleset.DisabledChanged += disabledChanged; - ruleset.BindTo(game.Ruleset); + if (game != null) + ruleset.BindTo(game.Ruleset); + else + ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(); } public override bool HandleInput => !ruleset.Disabled; diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index d150aacdf9..81c57a984f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar Icon = FontAwesome.fa_music; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(MusicController music) { StateContainer = music; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index e11a22d675..dbe8b48424 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Toolbar TooltipSub = "Waiting for 'ya"; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(NotificationOverlay notificationOverlay) { StateContainer = notificationOverlay; diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index 69fdd27d5d..59314b8771 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -21,8 +21,11 @@ namespace osu.Game.Overlays.Toolbar set { stateContainer = value; - Action = stateContainer.ToggleVisibility; - stateContainer.StateChanged += stateChanged; + if (stateContainer != null) + { + Action = stateContainer.ToggleVisibility; + stateContainer.StateChanged += stateChanged; + } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index cf4f664e81..d0d76dd5d2 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Toolbar TooltipSub = "Change your settings"; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(SettingsOverlay settings) { StateContainer = settings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index 234d6f0f9a..74d1da4384 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar Icon = FontAwesome.fa_users; } - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(SocialOverlay chat) { StateContainer = chat; From bb33d0211a5802c6706c3a18570cbc16ffa4c227 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:36:58 +0900 Subject: [PATCH 06/12] Add a count of unread notifications to the toolbar --- osu.Game.Tests/Visual/TestCaseToolbar.cs | 16 ++++- .../Toolbar/ToolbarNotificationButton.cs | 64 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseToolbar.cs b/osu.Game.Tests/Visual/TestCaseToolbar.cs index 9045249b9a..9f538af09b 100644 --- a/osu.Game.Tests/Visual/TestCaseToolbar.cs +++ b/osu.Game.Tests/Visual/TestCaseToolbar.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Toolbar; @@ -15,11 +16,24 @@ namespace osu.Game.Tests.Visual typeof(ToolbarButton), typeof(ToolbarModeSelector), typeof(ToolbarModeButton), + typeof(ToolbarNotificationButton), }; public TestCaseToolbar() { - Add(new Toolbar { State = Visibility.Visible }); + var toolbar = new Toolbar { State = Visibility.Visible }; + + Add(toolbar); + + var notificationButton = toolbar.Children.OfType().Last().Children.OfType().First(); + + void setNotifications(int count) => AddStep($"set notification count to {count}", () => notificationButton.NotificationCount.Value = count); + + setNotifications(1); + setNotifications(2); + setNotifications(3); + setNotifications(0); + setNotifications(144); } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index dbe8b48424..78a04d156a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -2,8 +2,14 @@ // 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.Game.Graphics; +using osu.Game.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar { @@ -11,17 +17,75 @@ namespace osu.Game.Overlays.Toolbar { protected override Anchor TooltipAnchor => Anchor.TopRight; + public BindableInt NotificationCount = new BindableInt(); + + private CountCircle countDisplay; + public ToolbarNotificationButton() { Icon = FontAwesome.fa_bars; TooltipMain = "Notifications"; TooltipSub = "Waiting for 'ya"; + + Add(countDisplay = new CountCircle + { + Alpha = 0, + Height = 16, + RelativePositionAxes = Axes.Both, + Origin = Anchor.TopCentre, + Position = new Vector2(0.7f, 0.05f), + }); } [BackgroundDependencyLoader(true)] private void load(NotificationOverlay notificationOverlay) { StateContainer = notificationOverlay; + + NotificationCount.ValueChanged += count => + { + if (count == 0) + countDisplay.FadeOut(200, Easing.OutQuint); + else + countDisplay.FadeIn(200, Easing.OutQuint); + + countDisplay.Count = count; + }; + } + + private class CountCircle : CompositeDrawable + { + private readonly OsuSpriteText count; + + public int Count + { + set { count.Text = value.ToString("#,0"); } + } + + public CountCircle() + { + AutoSizeAxes = Axes.X; + + InternalChildren = new Drawable[] + { + new Circle + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Red + }, + count = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = -1, + TextSize = 14, + Padding = new MarginPadding(5), + Colour = Color4.White, + UseFullGlyphHeight = true, + Font = "Exo2.0-Bold", + } + }; + } } } } From 1fc240f6c594ad7f1469f4276a0778034c59bb2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:50:05 +0900 Subject: [PATCH 07/12] Expose unread notification count --- .../Visual/TestCaseNotificationOverlay.cs | 7 ++++ osu.Game/Overlays/NotificationOverlay.cs | 42 ++++++++++++------- .../Notifications/NotificationSection.cs | 4 +- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs index b93c2d812f..233914767d 100644 --- a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -25,6 +26,12 @@ namespace osu.Game.Tests.Visual Origin = Anchor.TopRight }); + SpriteText displayedCount = new SpriteText(); + + Content.Add(displayedCount); + + manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count}"; }; + AddStep(@"toggle", manager.ToggleVisibility); AddStep(@"simple #1", sendHelloNotification); AddStep(@"simple #2", sendAmazingNotification); diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index a4b5486596..2f1c3285ef 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -11,6 +11,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using System; +using osu.Framework.Configuration; namespace osu.Game.Overlays { @@ -75,34 +76,38 @@ namespace osu.Game.Overlays }; } + private int totalCount => sections.Select(c => c.DisplayedCount).Sum(); + private int unreadCount => sections.Select(c => c.UnreadCount).Sum(); + + public readonly BindableInt UnreadCount = new BindableInt(); + private int runningDepth; private void notificationClosed() { // hide ourselves if all notifications have been dismissed. - if (sections.Select(c => c.DisplayedCount).Sum() == 0) + if (totalCount == 0) State = Visibility.Hidden; + + updateCounts(); } - public void Post(Notification notification) + public void Post(Notification notification) => Schedule(() => { - Schedule(() => - { - State = Visibility.Visible; + ++runningDepth; + notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; - ++runningDepth; - notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; + notification.Closed += notificationClosed; - notification.Closed += notificationClosed; + var hasCompletionTarget = notification as IHasCompletionTarget; + if (hasCompletionTarget != null) + hasCompletionTarget.CompletionTarget = Post; - var hasCompletionTarget = notification as IHasCompletionTarget; - if (hasCompletionTarget != null) - hasCompletionTarget.CompletionTarget = Post; + var ourType = notification.GetType(); + sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification); - var ourType = notification.GetType(); - sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification); - }); - } + updateCounts(); + }); protected override void PopIn() { @@ -122,9 +127,16 @@ namespace osu.Game.Overlays this.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint); } + private void updateCounts() + { + UnreadCount.Value = unreadCount; + } + private void markAllRead() { sections.Children.ForEach(s => s.MarkAllRead()); + + updateCounts(); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 09768ba0ea..2bd0321d12 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -26,6 +26,8 @@ namespace osu.Game.Overlays.Notifications public int DisplayedCount => notifications.Count(n => !n.WasClosed); + public int UnreadCount => notifications.Count(n => !n.WasClosed && !n.Read); + public void Add(Notification notification) => notifications.Add(notification); public IEnumerable AcceptTypes; @@ -157,4 +159,4 @@ namespace osu.Game.Overlays.Notifications notifications?.Children.ForEach(n => n.Read = true); } } -} \ No newline at end of file +} From 0886107ec911c79d6d3f25317b31c0586ddc0ba2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 01:56:57 +0900 Subject: [PATCH 08/12] Connect counter with button display --- .../Toolbar/ToolbarNotificationButton.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 78a04d156a..faf802f5e7 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Toolbar public BindableInt NotificationCount = new BindableInt(); - private CountCircle countDisplay; + private readonly CountCircle countDisplay; public ToolbarNotificationButton() { @@ -32,8 +32,8 @@ namespace osu.Game.Overlays.Toolbar Alpha = 0, Height = 16, RelativePositionAxes = Axes.Both, - Origin = Anchor.TopCentre, - Position = new Vector2(0.7f, 0.05f), + Origin = Anchor.Centre, + Position = new Vector2(0.7f, 0.25f), }); } @@ -42,24 +42,34 @@ namespace osu.Game.Overlays.Toolbar { StateContainer = notificationOverlay; + if (notificationOverlay != null) + NotificationCount.BindTo(notificationOverlay.UnreadCount); + NotificationCount.ValueChanged += count => { if (count == 0) countDisplay.FadeOut(200, Easing.OutQuint); else + { + countDisplay.Count = count; countDisplay.FadeIn(200, Easing.OutQuint); - - countDisplay.Count = count; + } }; } private class CountCircle : CompositeDrawable { private readonly OsuSpriteText count; + private readonly Circle circle; public int Count { - set { count.Text = value.ToString("#,0"); } + set + { + count.Text = value.ToString("#,0"); + circle.FlashColour(Color4.White, 600, Easing.OutQuint); + this.ScaleTo(1.1f).Then().ScaleTo(1, 600, Easing.OutElastic); + } } public CountCircle() @@ -68,7 +78,7 @@ namespace osu.Game.Overlays.Toolbar InternalChildren = new Drawable[] { - new Circle + circle = new Circle { RelativeSizeAxes = Axes.Both, Colour = Color4.Red From 798c2c66667cdb7f5b2c54d59731d3ae71486894 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Dec 2017 12:57:45 +0900 Subject: [PATCH 09/12] Add special logic to song select to avoid obvious clipping when notifications are displayed Not sure if we will keep this going forward (there will likely be an opaque tab control on the notifications overlay similar to options) but let's go with this for now. --- osu.Game/Screens/Select/FilterControl.cs | 4 +- osu.Game/Screens/Select/SongSelect.cs | 48 +++++++++++++++++------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 1b86cec613..2dbd63f77b 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Select { Children = new Drawable[] { - new Box + Background = new Box { Colour = Color4.Black, Alpha = 0.8f, @@ -167,6 +167,8 @@ namespace osu.Game.Screens.Select private Bindable showConverted; + public readonly Box Background; + [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuColour colours, OsuGame osu, OsuConfigManager config) { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 68ee08e721..8189624ce1 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -103,21 +103,41 @@ namespace osu.Game.Screens.Select Right = left_area_padding * 2, } }, - carousel = new BeatmapCarousel + new Container { - RelativeSizeAxes = Axes.Y, - Size = new Vector2(carousel_width, 1), - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - SelectionChanged = carouselSelectionChanged, - BeatmapSetsChanged = carouselBeatmapsLoaded, - }, - FilterControl = new FilterControl - { - RelativeSizeAxes = Axes.X, - Height = filter_height, - FilterChanged = c => carousel.Filter(c), - Exit = Exit, + RelativeSizeAxes = Axes.Both, + Masking = true, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 2, //avoid horizontal masking so the panels don't clip when screen stack is pushed. + Child = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.5f, + Children = new Drawable[] + { + carousel = new BeatmapCarousel + { + Masking = false, + RelativeSizeAxes = Axes.Y, + Size = new Vector2(carousel_width, 1), + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + SelectionChanged = carouselSelectionChanged, + BeatmapSetsChanged = carouselBeatmapsLoaded, + }, + FilterControl = new FilterControl + { + RelativeSizeAxes = Axes.X, + Height = filter_height, + FilterChanged = c => carousel.Filter(c), + Background = { Width = 2 }, + Exit = Exit, + }, + } + }, }, beatmapInfoWedge = new BeatmapInfoWedge { From c737e5245e0442d097d7e9efd6cd6c18cd9dfc60 Mon Sep 17 00:00:00 2001 From: FreezyLemon Date: Tue, 26 Dec 2017 01:50:05 +0100 Subject: [PATCH 10/12] Removed unnecessary SelectNext() call and change to dummy map when no items present --- 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 be176c1459..802667e6a0 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -142,7 +142,6 @@ namespace osu.Game.Screens.Select if (newSet == null) { itemsCache.Invalidate(); - SelectNext(); return; } @@ -512,7 +511,7 @@ namespace osu.Game.Screens.Select currentY += DrawHeight / 2; scrollableContent.Height = currentY; - if (selectedBeatmapSet != null && selectedBeatmapSet.State.Value != CarouselItemState.Selected) + if (!Items.Any() || selectedBeatmapSet != null && selectedBeatmapSet.State.Value != CarouselItemState.Selected) { selectedBeatmapSet = null; SelectionChanged?.Invoke(null); From c82273572430b6bcefa1b3dbfe45644e543fed2f Mon Sep 17 00:00:00 2001 From: FreezyLemon Date: Tue, 26 Dec 2017 03:57:18 +0100 Subject: [PATCH 11/12] Added tests for hiding diffs (and especially the last visible diff) --- .../Visual/TestCaseBeatmapCarousel.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index 639befef74..c09b987407 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -70,6 +70,7 @@ namespace osu.Game.Tests.Visual testRemoveAll(); testEmptyTraversal(); + testHiding(); } private void ensureRandomFetchSuccess() => @@ -295,6 +296,40 @@ namespace osu.Game.Tests.Visual checkNoSelection(); } + private void testHiding() + { + var hidingSet = createTestBeatmapSet(1); + hidingSet.Beatmaps[1].Hidden = true; + AddStep("Add set with diff 2 hidden", () => carousel.UpdateBeatmapSet(hidingSet)); + setSelected(1, 1); + + checkVisibleItemCount(true, 2); + advanceSelection(true); + checkSelected(1, 3); + + setHidden(3); + checkSelected(1, 1); + + setHidden(2, false); + advanceSelection(true); + checkSelected(1, 2); + + setHidden(1); + checkSelected(1, 2); + + setHidden(2); + checkNoSelection(); + + void setHidden(int diff, bool hidden = true) + { + AddStep((hidden ? "" : "un") + $"hide diff {diff}", () => + { + hidingSet.Beatmaps[diff - 1].Hidden = hidden; + carousel.UpdateBeatmapSet(hidingSet); + }); + } + } + private BeatmapSetInfo createTestBeatmapSet(int i) { return new BeatmapSetInfo From 09ce24a7dba54deb34d629e75eee48978d1f26a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Dec 2017 13:41:02 +0900 Subject: [PATCH 12/12] Switch to a better way of deciding on null selection This avoids `SelectionChanged` potentially being invoked multiple times after `selectedBeatmapSet` is already `null`. --- 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 802667e6a0..87edfe9692 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -511,7 +511,7 @@ namespace osu.Game.Screens.Select currentY += DrawHeight / 2; scrollableContent.Height = currentY; - if (!Items.Any() || selectedBeatmapSet != null && selectedBeatmapSet.State.Value != CarouselItemState.Selected) + if (selectedBeatmapSet != null && (selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)) { selectedBeatmapSet = null; SelectionChanged?.Invoke(null);