From 2c7343e9659b73c37d4d7e4f77c9275fb04722b0 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 21 Oct 2017 12:42:11 +1030 Subject: [PATCH 01/36] Add revert-to-default glow for settings items --- osu.Game/Overlays/Settings/SettingsItem.cs | 89 ++++++++++++++++++- osu.Game/Overlays/Settings/SettingsSection.cs | 5 +- .../Overlays/Settings/SettingsSubsection.cs | 2 +- 3 files changed, 89 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index f2044f178b..c98b2f1ee9 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -2,17 +2,23 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using OpenTK.Graphics; using osu.Framework.Configuration; +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; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Settings { - public abstract class SettingsItem : FillFlowContainer, IFilterable + public abstract class SettingsItem : Container, IFilterable { protected abstract Drawable CreateControl(); @@ -20,8 +26,16 @@ namespace osu.Game.Overlays.Settings private IHasCurrentValue controlWithCurrent => Control as IHasCurrentValue; + protected override Container Content => FlowContent; + + protected readonly FillFlowContainer FlowContent; + private SpriteText text; + private readonly SettingsItemDefaultIndicator defaultIndicator = new SettingsItemDefaultIndicator(); + + public bool ShowsDefaultIndicator = true; + public virtual string LabelText { get { return text?.Text ?? string.Empty; } @@ -51,6 +65,11 @@ namespace osu.Game.Overlays.Settings { bindable = value; controlWithCurrent?.Current.BindTo(bindable); + if (ShowsDefaultIndicator) + { + defaultIndicator.Bindable.BindTo(bindable); + defaultIndicator.Bindable.TriggerChange(); + } } } @@ -69,14 +88,78 @@ namespace osu.Game.Overlays.Settings { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Right = 5 }; + Padding = new MarginPadding { Right = SettingsOverlay.CONTENT_MARGINS }; + + FlowContent = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = 5 }, + }; if ((Control = CreateControl()) != null) { if (controlWithCurrent != null) controlWithCurrent.Current.DisabledChanged += disabled => { Colour = disabled ? Color4.Gray : Color4.White; }; - Add(Control); + FlowContent.Add(Control); } } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AddInternal(FlowContent); + + if (defaultIndicator != null) + { + defaultIndicator.Colour = ColourInfo.GradientHorizontal(colours.Yellow.Opacity(0.8f), colours.Yellow.Opacity(0)); + defaultIndicator.Alpha = 0f; + AddInternal(defaultIndicator); + } + } + + private class SettingsItemDefaultIndicator : Box + { + internal readonly Bindable Bindable = new Bindable(); + + private bool hovering; + + public SettingsItemDefaultIndicator() + { + Bindable.ValueChanged += value => updateAlpha(); + + RelativeSizeAxes = Axes.Y; + Width = SettingsOverlay.CONTENT_MARGINS; + Alpha = 0f; + } + + public override bool HandleInput => true; + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => true; + + protected override bool OnClick(InputState state) + { + Bindable.SetDefault(); + return true; + } + + protected override bool OnHover(InputState state) + { + hovering = true; + updateAlpha(); + return true; + } + + protected override void OnHoverLost(InputState state) + { + hovering = false; + updateAlpha(); + } + + private void updateAlpha() => + Alpha = Bindable.IsDefault ? 0f : hovering ? 1f : 0.5f; + } } } diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index eb6e398477..a107878fb8 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -69,8 +69,6 @@ namespace osu.Game.Overlays.Settings Padding = new MarginPadding { Top = 20 + border_size, - Left = SettingsOverlay.CONTENT_MARGINS, - Right = SettingsOverlay.CONTENT_MARGINS, Bottom = 10, }, RelativeSizeAxes = Axes.X, @@ -81,7 +79,8 @@ namespace osu.Game.Overlays.Settings { TextSize = header_size, Text = Header, - Colour = colours.Yellow + Colour = colours.Yellow, + Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS } }, FlowContent } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 4164ceee21..79a644b2cb 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.Settings new OsuSpriteText { Text = Header.ToUpper(), - Margin = new MarginPadding { Bottom = 10 }, + Margin = new MarginPadding { Bottom = 10, Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }, Font = @"Exo2.0-Black", }, FlowContent From 98044a17d3de8bc29e240a10c920ce95b3766a45 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 21 Oct 2017 13:16:06 +1030 Subject: [PATCH 02/36] Fix misaligned settings buttons --- .../KeyBinding/KeyBindingsSubsection.cs | 1 + .../Settings/Sections/Audio/OffsetSettings.cs | 3 +-- .../Settings/Sections/Debug/GCSettings.cs | 3 +-- .../Settings/Sections/General/LoginSettings.cs | 6 ++---- .../Settings/Sections/General/UpdateSettings.cs | 3 +-- .../Settings/Sections/Input/KeyboardSettings.cs | 3 +-- .../Sections/Maintenance/GeneralSettings.cs | 9 +++------ osu.Game/Overlays/Settings/SettingsButton.cs | 17 +++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 9 files changed, 28 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Overlays/Settings/SettingsButton.cs diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index 128b5e2f09..2ff5d7b81f 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -28,6 +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 }; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index bc09a2145a..8d3f4ee672 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -22,9 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio LabelText = "Audio Offset", Bindable = config.GetBindable(OsuSetting.AudioOffset) }, - new OsuButton + new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Offset wizard" } }; diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs index 495a2543d1..50768fb646 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs @@ -24,9 +24,8 @@ namespace osu.Game.Overlays.Settings.Sections.Debug LabelText = "Active mode", Bindable = config.GetBindable(DebugSetting.ActiveGCMode) }, - new OsuButton + new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Force garbage collection", Action = GC.Collect }, diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 8b7d7b0d69..56b9a55398 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -230,15 +230,13 @@ namespace osu.Game.Overlays.Settings.Sections.General LabelText = "Stay logged in", Bindable = config.GetBindable(OsuSetting.SavePassword), }, - new OsuButton + new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Sign in", Action = performLogin }, - new OsuButton + new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Register new account", //Action = registerLink } diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 833a5ff966..6ccb16f538 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -23,9 +23,8 @@ namespace osu.Game.Overlays.Settings.Sections.General LabelText = "Release stream", Bindable = config.GetBindable(OsuSetting.ReleaseStream), }, - new OsuButton + new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Open osu! folder", Action = storage.OpenInNativeExplorer, } diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index b68fd4bc04..4bc16cd0e1 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -14,9 +14,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input { Children = new Drawable[] { - new OsuButton + new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Key Configuration", Action = keyConfig.ToggleVisibility }, diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index 233ca7be60..e14094cf3a 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -22,9 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { Children = new Drawable[] { - importButton = new OsuButton + importButton = new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Import beatmaps from stable", Action = () => { @@ -32,9 +31,8 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Task.Run(() => beatmaps.ImportFromStable()).ContinueWith(t => Schedule(() => importButton.Enabled.Value = true)); } }, - deleteButton = new OsuButton + deleteButton = new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Delete ALL beatmaps", Action = () => { @@ -42,9 +40,8 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Task.Run(() => beatmaps.DeleteAll()).ContinueWith(t => Schedule(() => deleteButton.Enabled.Value = true)); } }, - restoreButton = new OsuButton + restoreButton = new SettingsButton { - RelativeSizeAxes = Axes.X, Text = "Restore all hidden difficulties", Action = () => { diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs new file mode 100644 index 0000000000..252ef30629 --- /dev/null +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Settings.Sections +{ + public class SettingsButton : OsuButton + { + public SettingsButton() + { + RelativeSizeAxes = Axes.X; + Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }; + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 601c99e19f..16589c72ff 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -288,6 +288,7 @@ + From 290fac89909bd6c4accc8e2c9ca417cb3c57eaef Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 21 Oct 2017 13:17:03 +1030 Subject: [PATCH 03/36] Temporarily disable revert functionality for audio device, since it crashes --- .../Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index a2f3ad545b..1e1dd86808 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Children = new Drawable[] { - dropdown = new SettingsDropdown() + dropdown = new SettingsDropdown { ShowsDefaultIndicator = false } }; updateItems(); From b4d575fbcd4fab7fb30ffa568d0564d2678993d2 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 21 Oct 2017 13:22:21 +1030 Subject: [PATCH 04/36] Fix namespace and unnecessary using --- osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs | 1 - osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs | 1 - osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs | 1 - osu.Game/Overlays/Settings/SettingsButton.cs | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs index 50768fb646..23e7433732 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs @@ -6,7 +6,6 @@ using System.Runtime; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings.Sections.Debug { diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 6ccb16f538..3bca0af3af 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Game.Configuration; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings.Sections.General { diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index 4bc16cd0e1..00a1c093fd 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings.Sections.Input { diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 252ef30629..6ac8aa9f46 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Overlays.Settings.Sections +namespace osu.Game.Overlays.Settings { public class SettingsButton : OsuButton { From 840ba9f48efa82f31018e2042a72f2608561cf8a Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 21 Oct 2017 16:05:37 +1030 Subject: [PATCH 05/36] Allow the default indicator colour to be specified, and fix bug where disabled bindables could be reset --- osu.Game/Overlays/Settings/SettingsItem.cs | 43 ++++++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index c98b2f1ee9..01b76605e0 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -36,6 +36,18 @@ namespace osu.Game.Overlays.Settings public bool ShowsDefaultIndicator = true; + private Color4? defaultIndicatorColour; + + public Color4 DefaultIndicatorColour + { + get { return defaultIndicatorColour ?? Color4.White; } + set + { + defaultIndicatorColour = value; + defaultIndicator?.SetIndicatorColour(DefaultIndicatorColour); + } + } + public virtual string LabelText { get { return text?.Text ?? string.Empty; } @@ -112,8 +124,9 @@ namespace osu.Game.Overlays.Settings if (defaultIndicator != null) { - defaultIndicator.Colour = ColourInfo.GradientHorizontal(colours.Yellow.Opacity(0.8f), colours.Yellow.Opacity(0)); - defaultIndicator.Alpha = 0f; + if (!defaultIndicatorColour.HasValue) + defaultIndicatorColour = colours.Yellow; + defaultIndicator.SetIndicatorColour(DefaultIndicatorColour); AddInternal(defaultIndicator); } } @@ -122,11 +135,14 @@ namespace osu.Game.Overlays.Settings { internal readonly Bindable Bindable = new Bindable(); + private Color4 indicatorColour; + private bool hovering; public SettingsItemDefaultIndicator() { - Bindable.ValueChanged += value => updateAlpha(); + Bindable.ValueChanged += value => UpdateState(); + Bindable.DisabledChanged += disabled => UpdateState(); RelativeSizeAxes = Axes.Y; Width = SettingsOverlay.CONTENT_MARGINS; @@ -141,25 +157,36 @@ namespace osu.Game.Overlays.Settings protected override bool OnClick(InputState state) { - Bindable.SetDefault(); + if (!Bindable.Disabled) + Bindable.SetDefault(); return true; } protected override bool OnHover(InputState state) { hovering = true; - updateAlpha(); + UpdateState(); return true; } protected override void OnHoverLost(InputState state) { hovering = false; - updateAlpha(); + UpdateState(); } - private void updateAlpha() => - Alpha = Bindable.IsDefault ? 0f : hovering ? 1f : 0.5f; + internal void SetIndicatorColour(Color4 indicatorColour) + { + this.indicatorColour = indicatorColour; + UpdateState(); + } + + internal void UpdateState() + { + var colour = Bindable.Disabled ? Color4.Gray : indicatorColour; + Alpha = Bindable.IsDefault ? 0f : (hovering && !Bindable.Disabled) ? 1f : 0.5f; + Colour = ColourInfo.GradientHorizontal(colour.Opacity(0.8f), colour.Opacity(0)); + } } } } From f5946c0e07b7aa39dd7fb14e62a29c7cc77f3f71 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 21 Oct 2017 16:28:03 +1030 Subject: [PATCH 06/36] Fix wrong license header --- osu.Game/Overlays/Settings/SettingsButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 6ac8aa9f46..5320cef850 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; From 59b10981dc24659bec8a10be7aa9131ffbd193bb Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 21 Oct 2017 17:06:28 +1030 Subject: [PATCH 07/36] CI fixes --- osu.Game/Overlays/Settings/SettingsItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 01b76605e0..d77552bb47 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -184,7 +184,7 @@ namespace osu.Game.Overlays.Settings internal void UpdateState() { var colour = Bindable.Disabled ? Color4.Gray : indicatorColour; - Alpha = Bindable.IsDefault ? 0f : (hovering && !Bindable.Disabled) ? 1f : 0.5f; + Alpha = Bindable.IsDefault ? 0f : hovering && !Bindable.Disabled ? 1f : 0.5f; Colour = ColourInfo.GradientHorizontal(colour.Opacity(0.8f), colour.Opacity(0)); } } From 5785af9f6a74727ceb2f01e134d6376c715341e4 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sun, 22 Oct 2017 14:22:57 +1030 Subject: [PATCH 08/36] Reenable revert indicator on audio device since the potential crash was addressed in #1101 --- .../Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 1e1dd86808..a2f3ad545b 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Children = new Drawable[] { - dropdown = new SettingsDropdown { ShowsDefaultIndicator = false } + dropdown = new SettingsDropdown() }; updateItems(); From 448ff3bf384a3116a0bde63ca8d41dfb43b2526b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Oct 2017 13:28:17 +0900 Subject: [PATCH 09/36] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 383a8da7bc..88e7c85a9b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 383a8da7bc45af498288b4b72c72a048a0996e74 +Subproject commit 88e7c85a9bb20ad5806528d8682ca61baf3d5237 From 2e6a68d358aa47f32bd5da2cccade93f08645319 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sun, 22 Oct 2017 16:10:41 +1030 Subject: [PATCH 10/36] Rename indicator class, add colour/fade easing, and add tooltip --- osu.Game/Overlays/Settings/SettingsItem.cs | 45 ++++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index d77552bb47..5a0f25f7e0 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.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.UserInterface; @@ -32,19 +33,19 @@ namespace osu.Game.Overlays.Settings private SpriteText text; - private readonly SettingsItemDefaultIndicator defaultIndicator = new SettingsItemDefaultIndicator(); + private readonly RestoreDefaultValueButton restoreDefaultValueButton = new RestoreDefaultValueButton(); public bool ShowsDefaultIndicator = true; - private Color4? defaultIndicatorColour; + private Color4? restoreDefaultValueColour; - public Color4 DefaultIndicatorColour + public Color4 RestoreDefaultValueColour { - get { return defaultIndicatorColour ?? Color4.White; } + get { return restoreDefaultValueColour ?? Color4.White; } set { - defaultIndicatorColour = value; - defaultIndicator?.SetIndicatorColour(DefaultIndicatorColour); + restoreDefaultValueColour = value; + restoreDefaultValueButton?.SetButtonColour(RestoreDefaultValueColour); } } @@ -79,8 +80,8 @@ namespace osu.Game.Overlays.Settings controlWithCurrent?.Current.BindTo(bindable); if (ShowsDefaultIndicator) { - defaultIndicator.Bindable.BindTo(bindable); - defaultIndicator.Bindable.TriggerChange(); + restoreDefaultValueButton.Bindable.BindTo(bindable); + restoreDefaultValueButton.Bindable.TriggerChange(); } } } @@ -122,24 +123,24 @@ namespace osu.Game.Overlays.Settings { AddInternal(FlowContent); - if (defaultIndicator != null) + if (restoreDefaultValueButton != null) { - if (!defaultIndicatorColour.HasValue) - defaultIndicatorColour = colours.Yellow; - defaultIndicator.SetIndicatorColour(DefaultIndicatorColour); - AddInternal(defaultIndicator); + if (!restoreDefaultValueColour.HasValue) + restoreDefaultValueColour = colours.Yellow; + restoreDefaultValueButton.SetButtonColour(RestoreDefaultValueColour); + AddInternal(restoreDefaultValueButton); } } - private class SettingsItemDefaultIndicator : Box + private class RestoreDefaultValueButton : Box, IHasTooltip { internal readonly Bindable Bindable = new Bindable(); - private Color4 indicatorColour; + private Color4 buttonColour; private bool hovering; - public SettingsItemDefaultIndicator() + public RestoreDefaultValueButton() { Bindable.ValueChanged += value => UpdateState(); Bindable.DisabledChanged += disabled => UpdateState(); @@ -149,6 +150,8 @@ namespace osu.Game.Overlays.Settings Alpha = 0f; } + public string TooltipText => "Revert to default"; + public override bool HandleInput => true; protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; @@ -175,17 +178,17 @@ namespace osu.Game.Overlays.Settings UpdateState(); } - internal void SetIndicatorColour(Color4 indicatorColour) + internal void SetButtonColour(Color4 buttonColour) { - this.indicatorColour = indicatorColour; + this.buttonColour = buttonColour; UpdateState(); } internal void UpdateState() { - var colour = Bindable.Disabled ? Color4.Gray : indicatorColour; - Alpha = Bindable.IsDefault ? 0f : hovering && !Bindable.Disabled ? 1f : 0.5f; - Colour = ColourInfo.GradientHorizontal(colour.Opacity(0.8f), colour.Opacity(0)); + var colour = Bindable.Disabled ? Color4.Gray : buttonColour; + this.FadeTo(Bindable.IsDefault ? 0f : hovering && !Bindable.Disabled ? 1f : 0.5f, 200, Easing.OutQuint); + this.FadeColour(ColourInfo.GradientHorizontal(colour.Opacity(0.8f), colour.Opacity(0)), 200, Easing.OutQuint); } } } From 29fcd210aa0f2168613088f6d2a44cda060822dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Oct 2017 16:17:40 +0900 Subject: [PATCH 11/36] Centralise transaction committing --- osu.Game/Beatmaps/BeatmapManager.cs | 6 ++---- osu.Game/Database/OsuDbContext.cs | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 47dbc72837..b81e239015 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -198,7 +198,7 @@ namespace osu.Game.Beatmaps context.SaveChanges(); } - transaction.Commit(); + context.SaveChanges(transaction); return set; } } @@ -313,9 +313,7 @@ namespace osu.Game.Beatmaps } context.ChangeTracker.AutoDetectChangesEnabled = true; - context.SaveChanges(); - - transaction.Commit(); + context.SaveChanges(transaction); } } } diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index c509093cf9..99e5fa9741 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -93,6 +93,13 @@ namespace osu.Game.Database modelBuilder.Entity().HasOne(b => b.BaseDifficulty); } + public new int SaveChanges(IDbContextTransaction transaction = null) + { + var ret = base.SaveChanges(); + transaction?.Commit(); + return ret; + } + private class OsuDbLoggerFactory : ILoggerFactory { #region Disposal From 9aa46bfb0dd98ed35f337bd6bcd47f605bc95412 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Oct 2017 16:17:55 +0900 Subject: [PATCH 12/36] Add transaction usage for key binding defaults --- osu.Game/Input/KeyBindingStore.cs | 40 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 54cf48bc2a..bebbb471ac 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -36,29 +36,31 @@ namespace osu.Game.Input private void insertDefaults(IEnumerable defaults, int? rulesetId = null, int? variant = null) { - var context = GetContext(); - - // compare counts in database vs defaults - foreach (var group in defaults.GroupBy(k => k.Action)) + using (var context = GetContext()) + using (var transaction = context.Database.BeginTransaction()) { - int count = query(context, rulesetId, variant).Count(k => (int)k.Action == (int)group.Key); - int aimCount = group.Count(); + // compare counts in database vs defaults + foreach (var group in defaults.GroupBy(k => k.Action)) + { + int count = query(context, rulesetId, variant).Count(k => (int)k.Action == (int)group.Key); + int aimCount = group.Count(); - if (aimCount <= count) - continue; + if (aimCount <= count) + continue; - foreach (var insertable in group.Skip(count).Take(aimCount - count)) - // insert any defaults which are missing. - context.DatabasedKeyBinding.Add(new DatabasedKeyBinding - { - KeyCombination = insertable.KeyCombination, - Action = insertable.Action, - RulesetID = rulesetId, - Variant = variant - }); + foreach (var insertable in group.Skip(count).Take(aimCount - count)) + // insert any defaults which are missing. + context.DatabasedKeyBinding.Add(new DatabasedKeyBinding + { + KeyCombination = insertable.KeyCombination, + Action = insertable.Action, + RulesetID = rulesetId, + Variant = variant + }); + } + + context.SaveChanges(transaction); } - - context.SaveChanges(); } /// From 1514d8451e896a41298a99ba99279e46647d95a5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Oct 2017 16:18:19 +0900 Subject: [PATCH 13/36] Use a more elegant method of setting the connection timeout --- osu.Game/Database/OsuDbContext.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 99e5fa9741..271fde719b 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -3,6 +3,7 @@ using System; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; using osu.Framework.Logging; @@ -50,8 +51,6 @@ namespace osu.Game.Database { this.connectionString = connectionString; - Database.SetCommandTimeout(new TimeSpan(TimeSpan.TicksPerSecond * 10)); - var connection = Database.GetDbConnection(); connection.Open(); using (var cmd = connection.CreateCommand()) @@ -68,7 +67,7 @@ namespace osu.Game.Database // this is required for the time being due to the way we are querying in places like BeatmapStore. // if we ever move to having consumers file their own .Includes, or get eager loading support, this could be re-enabled. .ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)) - .UseSqlite(connectionString) + .UseSqlite(connectionString, sqliteOptions => sqliteOptions.CommandTimeout(10)) .UseLoggerFactory(logger.Value); } From 5b2219a692761b1d1e4413f61ac210cb54cdeb7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Oct 2017 16:18:39 +0900 Subject: [PATCH 14/36] Add back test cleanup before run --- osu.Game/Tests/Visual/OsuTestCase.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index ca0aaebb5e..b2c8be47bd 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -13,11 +13,9 @@ namespace osu.Game.Tests.Visual { using (var host = new HeadlessGameHost($"test-{Guid.NewGuid()}", realtime: false)) { + host.Storage.DeleteDirectory(string.Empty); host.Run(new OsuTestCaseTestRunner(this)); } - - // clean up after each run - //storage.DeleteDirectory(string.Empty); } public class OsuTestCaseTestRunner : OsuGameBase From aff30db89d42ee0889145a3b8974d959eaeb02e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Oct 2017 16:21:41 +0900 Subject: [PATCH 15/36] Add thread sleep as a temporary workaround for failing tests --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index e5b8c7fe57..0f9ee60ac7 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -100,6 +100,10 @@ namespace osu.Game.Tests.Beatmaps.IO waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); + // this is a temporary workaround for database transaction clashes. + // see https://github.com/aspnet/EntityFrameworkCore/issues/9994 for more information. + Thread.Sleep(1000); + return osu; } From 61c1dd36366c17d740a2f8be3eda04f0a61a030d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 22 Oct 2017 19:46:08 +0900 Subject: [PATCH 16/36] Don't output database logs unless DEBUG_DATABASE is specified compile-time --- osu.Game/Database/OsuDbContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 271fde719b..cf97a8f216 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -157,7 +157,7 @@ namespace osu.Game.Database public bool IsEnabled(LogLevel logLevel) { -#if DEBUG +#if DEBUG_DATABASE return logLevel > LogLevel.Debug; #else return logLevel > LogLevel.Information; From b1d5fc523fd86a38c843bf69ed5031575dd8ac20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 00:29:52 +0900 Subject: [PATCH 17/36] Add sqlite raw packages to osu.Desktop to ensure sqlite is copied locally --- osu.Desktop/app.config | 28 ++++++++++++++++++++++++++-- osu.Desktop/osu.Desktop.csproj | 33 ++++++++++++++++++++++++++++----- osu.Desktop/packages.config | 32 +++++++++++++++++++------------- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/osu.Desktop/app.config b/osu.Desktop/app.config index 0841541f3d..ea1576b3d8 100644 --- a/osu.Desktop/app.config +++ b/osu.Desktop/app.config @@ -12,8 +12,32 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index fb1ca7eb10..7db35c27cb 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -133,30 +133,42 @@ - ..\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll + $(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll True - ..\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True - ..\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll + $(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll True $(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll True + + $(SolutionDir)\packages\SQLitePCLRaw.bundle_green.1.1.8\lib\net45\SQLitePCLRaw.batteries_green.dll + + + $(SolutionDir)\packages\SQLitePCLRaw.bundle_green.1.1.8\lib\net45\SQLitePCLRaw.batteries_v2.dll + + + $(SolutionDir)\packages\SQLitePCLRaw.core.1.1.8\lib\net45\SQLitePCLRaw.core.dll + + + $(SolutionDir)\packages\SQLitePCLRaw.provider.e_sqlite3.net45.1.1.8\lib\net45\SQLitePCLRaw.provider.e_sqlite3.dll + - ..\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll + $(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll True - ../packages/System.ValueTuple.4.4.0/lib/net461/System.ValueTuple.dll + $(SolutionDir)\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll True @@ -258,4 +270,15 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/osu.Desktop/packages.config b/osu.Desktop/packages.config index 80eb533644..6b6361b578 100644 --- a/osu.Desktop/packages.config +++ b/osu.Desktop/packages.config @@ -1,14 +1,20 @@ - - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file From ea2934d92c69f437e5550bcb5ed40de6f33847c7 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Mon, 23 Oct 2017 16:06:08 +1030 Subject: [PATCH 18/36] Add KeyboardStep values for configuration options --- .../Settings/Sections/Audio/OffsetSettings.cs | 3 ++- .../Settings/Sections/Audio/VolumeSettings.cs | 6 +++--- .../Settings/Sections/Gameplay/GeneralSettings.cs | 3 ++- .../Settings/Sections/Gameplay/SongSelectSettings.cs | 6 ++++-- .../Settings/Sections/Graphics/LayoutSettings.cs | 6 ++++-- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 6 ++++-- osu.Game/Overlays/Settings/SettingsSlider.cs | 11 +++++++++++ .../Screens/Play/ReplaySettings/PlaybackSettings.cs | 3 ++- 8 files changed, 32 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index bc09a2145a..984fe28ec5 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -20,7 +20,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio new SettingsSlider { LabelText = "Audio Offset", - Bindable = config.GetBindable(OsuSetting.AudioOffset) + Bindable = config.GetBindable(OsuSetting.AudioOffset), + KeyboardStep = 100f }, new OsuButton { diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index ea442cdfc2..d197f8c466 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -16,9 +16,9 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { Children = new Drawable[] { - new SettingsSlider { LabelText = "Master", Bindable = audio.Volume }, - new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample }, - new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack }, + new SettingsSlider { LabelText = "Master", Bindable = audio.Volume, KeyboardStep = 0.1f }, + new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.1f }, + new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.1f }, }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index a8ec04514a..8ec6af5cd0 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -19,7 +19,8 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsSlider { LabelText = "Background dim", - Bindable = config.GetBindable(OsuSetting.DimLevel) + Bindable = config.GetBindable(OsuSetting.DimLevel), + KeyboardStep = 0.1f }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index 08dba011df..07a8e7464a 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -20,12 +20,14 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsSlider { LabelText = "Display beatmaps from", - Bindable = config.GetBindable(OsuSetting.DisplayStarsMinimum) + Bindable = config.GetBindable(OsuSetting.DisplayStarsMinimum), + KeyboardStep = 1f }, new SettingsSlider { LabelText = "up to", - Bindable = config.GetBindable(OsuSetting.DisplayStarsMaximum) + Bindable = config.GetBindable(OsuSetting.DisplayStarsMaximum), + KeyboardStep = 1f }, new SettingsEnumDropdown { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index c4ce742153..3d09d6b901 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -49,12 +49,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics new SettingsSlider { LabelText = "Horizontal position", - Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionX) + Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionX), + KeyboardStep = 0.1f }, new SettingsSlider { LabelText = "Vertical position", - Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionY) + Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionY), + KeyboardStep = 0.1f }, } }, diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 4b4426aca8..b4475aebb1 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -24,12 +24,14 @@ namespace osu.Game.Overlays.Settings.Sections new SettingsSlider { LabelText = "Menu cursor size", - Bindable = config.GetBindable(OsuSetting.MenuCursorSize) + Bindable = config.GetBindable(OsuSetting.MenuCursorSize), + KeyboardStep = 0.1f }, new SettingsSlider { LabelText = "Gameplay cursor size", - Bindable = config.GetBindable(OsuSetting.GameplayCursorSize) + Bindable = config.GetBindable(OsuSetting.GameplayCursorSize), + KeyboardStep = 0.1f }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 2881d02302..49d73f77ec 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -2,6 +2,7 @@ // 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.UserInterface; using osu.Game.Graphics.UserInterface; @@ -22,5 +23,15 @@ namespace osu.Game.Overlays.Settings Margin = new MarginPadding { Top = 5, Bottom = 5 }, RelativeSizeAxes = Axes.X }; + + public float KeyboardStep; + + [BackgroundDependencyLoader] + private void load() + { + var slider = Control as U; + if (slider != null) + slider.KeyboardStep = KeyboardStep; + } } } diff --git a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs index ea958d05f9..16868e5843 100644 --- a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs @@ -19,7 +19,8 @@ namespace osu.Game.Screens.Play.ReplaySettings new ReplaySliderBar { LabelText = "Playback speed", - Bindable = config.GetBindable(OsuSetting.PlaybackSpeed) + Bindable = config.GetBindable(OsuSetting.PlaybackSpeed), + KeyboardStep = 0.5f } }; } From 8fab6abf908b2c53d5428d7fca294f5f66879b5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 14:46:17 +0900 Subject: [PATCH 19/36] Update WebRequest usage in line with framework changes --- osu-framework | 2 +- osu.Desktop.Deploy/Program.cs | 12 +++--------- osu.Game/Online/API/APIRequest.cs | 2 +- osu.Game/Online/API/OAuth.cs | 4 ++-- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/osu-framework b/osu-framework index 383a8da7bc..26f3091dca 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 383a8da7bc45af498288b4b72c72a048a0996e74 +Subproject commit 26f3091dcaf47e3b355b7f7ad83b292621d7d6b5 diff --git a/osu.Desktop.Deploy/Program.cs b/osu.Desktop.Deploy/Program.cs index 785f915a3e..385bc444d1 100644 --- a/osu.Desktop.Deploy/Program.cs +++ b/osu.Desktop.Deploy/Program.cs @@ -7,7 +7,6 @@ using System.Configuration; using System.Diagnostics; using System.IO; using System.Linq; -using System.Net; using Newtonsoft.Json; using osu.Framework.IO.Network; using FileWebRequest = osu.Framework.IO.Network.FileWebRequest; @@ -391,8 +390,8 @@ namespace osu.Desktop.Deploy public static void AuthenticatedBlockingPerform(this WebRequest r) { - r.AddHeader("Authorization", $"token {GitHubAccessToken}"); - r.BlockingPerform(); + r.Headers.Add("Authorization", $"token {GitHubAccessToken}"); + r.Perform(); } } @@ -402,12 +401,7 @@ namespace osu.Desktop.Deploy { } - protected override HttpWebRequest CreateWebRequest(string requestString = null) - { - var req = base.CreateWebRequest(requestString); - req.Accept = "application/octet-stream"; - return req; - } + protected override string Accept => "application/octet-stream"; } internal class ReleaseLine diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 37903f924f..9a8180778d 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -106,7 +106,7 @@ namespace osu.Game.Online.API return; if (!WebRequest.Aborted) //could have been aborted by a Cancel() call - WebRequest.BlockingPerform(); + WebRequest.Perform(); if (checkAndProcessFailure()) return; diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index 5410bcc55d..445688f2ce 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -37,7 +37,7 @@ namespace osu.Game.Online.API { try { - req.BlockingPerform(); + req.Perform(); } catch { @@ -61,7 +61,7 @@ namespace osu.Game.Online.API ClientSecret = clientSecret }) { - req.BlockingPerform(); + req.Perform(); Token = req.ResponseObject; return true; From 4a68dd88cb2fc731c070d8641a0c27f164121161 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 14:53:13 +0900 Subject: [PATCH 20/36] Centralise BeginTransaction and disable transaction use for now --- osu.Game/Beatmaps/BeatmapManager.cs | 4 ++-- osu.Game/Database/OsuDbContext.cs | 6 ++++++ osu.Game/Input/KeyBindingStore.cs | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b81e239015..55c3e192e3 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -184,7 +184,7 @@ namespace osu.Game.Beatmaps { var context = importContext.Value; - using (var transaction = context.Database.BeginTransaction()) + using (var transaction = context.BeginTransaction()) { // create local stores so we can isolate and thread safely, and share a context/transaction. var iFiles = new FileStore(() => context, storage); @@ -295,7 +295,7 @@ namespace osu.Game.Beatmaps { var context = importContext.Value; - using (var transaction = context.Database.BeginTransaction()) + using (var transaction = context.BeginTransaction()) { context.ChangeTracker.AutoDetectChangesEnabled = false; diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index cf97a8f216..6c267811a1 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -92,6 +92,12 @@ namespace osu.Game.Database modelBuilder.Entity().HasOne(b => b.BaseDifficulty); } + public IDbContextTransaction BeginTransaction() + { + // return Database.BeginTransaction(); + return null; + } + public new int SaveChanges(IDbContextTransaction transaction = null) { var ret = base.SaveChanges(); diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index b434ce4eb7..0a0cd3dd6f 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -39,7 +39,7 @@ namespace osu.Game.Input private void insertDefaults(IEnumerable defaults, int? rulesetId = null, int? variant = null) { using (var context = GetContext()) - using (var transaction = context.Database.BeginTransaction()) + using (var transaction = context.BeginTransaction()) { // compare counts in database vs defaults foreach (var group in defaults.GroupBy(k => k.Action)) From df20845fbb170528ad5c8c0d96c8a4d4c73ac991 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 16:35:35 +0900 Subject: [PATCH 21/36] Share one context per file store for performance reasons There is now a CreateContext method for retrieving a stand-alone context for threaded use. We may want to add safety against this context being disposed (or just return a fresh one if it is). --- osu.Game/Database/DatabaseBackedStore.cs | 18 +++++++++++++++--- osu.Game/Database/OsuDbContext.cs | 1 + osu.Game/IO/FileStore.cs | 2 +- osu.Game/Input/KeyBindingStore.cs | 15 +++++++-------- .../Sections/Maintenance/GeneralSettings.cs | 3 ++- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/osu.Game/Database/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs index be86d35335..35700e90fc 100644 --- a/osu.Game/Database/DatabaseBackedStore.cs +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -11,12 +11,24 @@ namespace osu.Game.Database { protected readonly Storage Storage; - protected readonly Func GetContext; + /// + /// Create a new instance (separate from the shared context via for performing isolated operations. + /// + protected readonly Func CreateContext; - protected DatabaseBackedStore(Func getContext, Storage storage = null) + private readonly Lazy queryContext; + + /// + /// Retrieve a shared context for performing lookups (or write operations on the update thread, for now). + /// + protected OsuDbContext GetContext() => queryContext.Value; + + protected DatabaseBackedStore(Func createContext, Storage storage = null) { + CreateContext = createContext; + queryContext = new Lazy(CreateContext); + Storage = storage; - GetContext = getContext; try { diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 6c267811a1..0904a5151d 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -24,6 +24,7 @@ namespace osu.Game.Database public DbSet DatabasedKeyBinding { get; set; } public DbSet FileInfo { get; set; } public DbSet RulesetInfo { get; set; } + private readonly string connectionString; private static readonly Lazy logger = new Lazy(() => new OsuDbLoggerFactory()); diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs index 6654fa7cb1..b69916e565 100644 --- a/osu.Game/IO/FileStore.cs +++ b/osu.Game/IO/FileStore.cs @@ -22,7 +22,7 @@ namespace osu.Game.IO public Storage Storage => base.Storage; - public FileStore(Func getContext, Storage storage) : base(getContext, storage.GetStorageForDirectory(@"files")) + public FileStore(Func createContext, Storage storage) : base(createContext, storage.GetStorageForDirectory(@"files")) { Store = new StorageBackedResourceStore(Storage); } diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 0a0cd3dd6f..1e1b1d74d4 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -17,8 +17,8 @@ namespace osu.Game.Input { public event Action KeyBindingChanged; - public KeyBindingStore(Func getContext, RulesetStore rulesets, Storage storage = null) - : base(getContext, storage) + public KeyBindingStore(Func createContext, RulesetStore rulesets, Storage storage = null) + : base(createContext, storage) { foreach (var info in rulesets.AvailableRulesets) { @@ -38,13 +38,14 @@ namespace osu.Game.Input private void insertDefaults(IEnumerable defaults, int? rulesetId = null, int? variant = null) { - using (var context = GetContext()) + var context = GetContext(); + using (var transaction = context.BeginTransaction()) { // compare counts in database vs defaults foreach (var group in defaults.GroupBy(k => k.Action)) { - int count = query(context, rulesetId, variant).Count(k => (int)k.Action == (int)group.Key); + int count = Query(rulesetId, variant).Count(k => (int)k.Action == (int)group.Key); int aimCount = group.Count(); if (aimCount <= count) @@ -71,10 +72,8 @@ namespace osu.Game.Input /// The ruleset's internal ID. /// An optional variant. /// - public IEnumerable Query(int? rulesetId = null, int? variant = null) => query(GetContext(), rulesetId, variant); - - private IEnumerable query(OsuDbContext context, int? rulesetId = null, int? variant = null) => - context.DatabasedKeyBinding.Where(b => b.RulesetID == rulesetId && b.Variant == variant); + public IEnumerable Query(int? rulesetId = null, int? variant = null) => + GetContext().DatabasedKeyBinding.Where(b => b.RulesetID == rulesetId && b.Variant == variant); public void Update(KeyBinding keyBinding) { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index 233ca7be60..cea070102d 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -51,7 +52,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance restoreButton.Enabled.Value = false; Task.Run(() => { - foreach (var b in beatmaps.QueryBeatmaps(b => b.Hidden)) + foreach (var b in beatmaps.QueryBeatmaps(b => b.Hidden).ToList()) beatmaps.Restore(b); }).ContinueWith(t => Schedule(() => restoreButton.Enabled.Value = true)); } From e7931ef4c79302434d5468cdbf3acadb0b771ff8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 16:56:29 +0900 Subject: [PATCH 22/36] Add a default icon when a ruleset isn't present --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 42db025a40..1aff764ede 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -35,7 +35,8 @@ namespace osu.Game.Beatmaps.Drawables new ConstrainedIconContainer { RelativeSizeAxes = Axes.Both, - Icon = beatmap.Ruleset.CreateInstance().CreateIcon() + // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) + Icon = beatmap.Ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o } } }; } From 1a3debc91dc814fad0854a7899bc9860cc5748f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 17:56:04 +0900 Subject: [PATCH 23/36] Ensure thread safety on shared contexts Let's call this one temporary. --- osu.Game/Database/DatabaseBackedStore.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs index 35700e90fc..68f412eee6 100644 --- a/osu.Game/Database/DatabaseBackedStore.cs +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading; using osu.Framework.Logging; using osu.Framework.Platform; @@ -16,7 +17,7 @@ namespace osu.Game.Database /// protected readonly Func CreateContext; - private readonly Lazy queryContext; + private readonly ThreadLocal queryContext; /// /// Retrieve a shared context for performing lookups (or write operations on the update thread, for now). @@ -26,7 +27,9 @@ namespace osu.Game.Database protected DatabaseBackedStore(Func createContext, Storage storage = null) { CreateContext = createContext; - queryContext = new Lazy(CreateContext); + + // todo: while this seems to work quite well, we need to consider that contexts could enter a state where they are never cleaned up. + queryContext = new ThreadLocal(CreateContext); Storage = storage; From d4789e4a9cf1c0f8bcf63af0fe1d6825c1695b11 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Mon, 23 Oct 2017 19:08:53 +0300 Subject: [PATCH 24/36] Make TextAwesome TestCase more useful --- osu.Game.Tests/Visual/TestCaseTextAwesome.cs | 39 ++++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseTextAwesome.cs b/osu.Game.Tests/Visual/TestCaseTextAwesome.cs index 32934d3c5e..beec5ab271 100644 --- a/osu.Game.Tests/Visual/TestCaseTextAwesome.cs +++ b/osu.Game.Tests/Visual/TestCaseTextAwesome.cs @@ -4,10 +4,9 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.MathUtils; +using osu.Framework.Graphics.Cursor; using osu.Game.Graphics; using OpenTK; -using OpenTK.Graphics; namespace osu.Game.Tests.Visual { @@ -19,29 +18,37 @@ namespace osu.Game.Tests.Visual { FillFlowContainer flow; - Add(flow = new FillFlowContainer + Add(new ScrollContainer { RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.5f), - Anchor = Anchor.Centre, - Origin = Anchor.Centre + Child = flow = new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Full, + }, }); - int i = 50; foreach (FontAwesome fa in Enum.GetValues(typeof(FontAwesome))) + flow.Add(new Icon(fa)); + } + + private class Icon : Container, IHasTooltip + { + public string TooltipText { get; } + + public Icon(FontAwesome fa) { - flow.Add(new SpriteIcon + TooltipText = fa.ToString(); + + AutoSizeAxes = Axes.Both; + Child = new SpriteIcon { Icon = fa, Size = new Vector2(60), - Colour = new Color4( - Math.Max(0.5f, RNG.NextSingle()), - Math.Max(0.5f, RNG.NextSingle()), - Math.Max(0.5f, RNG.NextSingle()), - 1) - }); - - if (i-- == 0) break; + }; } } } From 7dadb7e21e91adb765903e62c63e7bcf47ab1225 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Oct 2017 06:13:39 +0900 Subject: [PATCH 25/36] Mark IPC non-parallelizable --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 0f9ee60ac7..602549e37c 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -41,6 +41,7 @@ namespace osu.Game.Tests.Beatmaps.IO } [Test] + [NonParallelizable] public void TestImportOverIPC() { using (HeadlessGameHost host = new HeadlessGameHost("host", true)) From c704c0349a51bdf30c6cb71ae10244f1d69614a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Oct 2017 06:50:33 +0900 Subject: [PATCH 26/36] Disable IPC test for now --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 602549e37c..77a1688730 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -42,13 +42,14 @@ namespace osu.Game.Tests.Beatmaps.IO [Test] [NonParallelizable] + [Ignore("Binding IPC on Appveyor isn't working (port in use). Need to figure out why")] public void TestImportOverIPC() { using (HeadlessGameHost host = new HeadlessGameHost("host", true)) using (HeadlessGameHost client = new HeadlessGameHost("client", true)) { Assert.IsTrue(host.IsPrimaryInstance); - Assert.IsTrue(!client.IsPrimaryInstance); + Assert.IsFalse(client.IsPrimaryInstance); var osu = loadOsu(host); From 0316ec3098affd3f3bf8362836fc8a1a19b1a973 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Oct 2017 09:48:02 +0900 Subject: [PATCH 27/36] Remove no-longer-necessary Thread.Sleep --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 77a1688730..77d78b8bd6 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -102,10 +102,6 @@ namespace osu.Game.Tests.Beatmaps.IO waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); - // this is a temporary workaround for database transaction clashes. - // see https://github.com/aspnet/EntityFrameworkCore/issues/9994 for more information. - Thread.Sleep(1000); - return osu; } From ae0029082ab9fbb36454ba086a0fe4ed403fc275 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 01:19:28 +0900 Subject: [PATCH 28/36] Allow version manager to load completely async --- osu.Desktop/OsuGameDesktop.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 1e4bf3119d..5a9d2adfd4 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -12,7 +12,6 @@ using osu.Desktop.Overlays; using osu.Framework.Graphics.Containers; using osu.Framework.Platform; using osu.Game; -using osu.Game.Screens.Menu; using OpenTK.Input; namespace osu.Desktop @@ -82,16 +81,11 @@ namespace osu.Desktop { base.LoadComplete(); - LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }); - - ScreenChanged += s => + LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v => { - if (s is Intro && s.ChildScreen == null) - { - Add(versionManager); - versionManager.State = Visibility.Visible; - } - }; + Add(v); + v.State = Visibility.Visible; + }); } public override void SetHost(GameHost host) From 9b7d569a6593d564a5a23edb9362ed9eab56c9cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 01:20:12 +0900 Subject: [PATCH 29/36] Add a single-file loading sequence for main components This stops aync loading from getting overloaded with tasks, which was happening previously. --- osu.Game/OsuGame.cs | 61 +++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d1baca68db..41153c4d34 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -16,6 +16,7 @@ using osu.Game.Screens; using osu.Game.Screens.Menu; using OpenTK; using System.Linq; +using System.Threading; using System.Threading.Tasks; using osu.Framework.Input.Bindings; using osu.Framework.Platform; @@ -172,25 +173,35 @@ namespace osu.Game new OnScreenDisplay(), }); - LoadComponentAsync(screenStack = new Loader(), d => + loadComponentSingleFile(screenStack = new Loader(), d => { screenStack.ModePushed += screenAdded; screenStack.Exited += screenRemoved; mainContent.Add(screenStack); }); + loadComponentSingleFile(Toolbar = new Toolbar + { + Depth = -5, + OnHome = delegate + { + hideAllOverlays(); + intro?.ChildScreen?.MakeCurrent(); + }, + }, overlayContent.Add); + //overlay elements - LoadComponentAsync(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); - LoadComponentAsync(social = new SocialOverlay { Depth = -1 }, mainContent.Add); - LoadComponentAsync(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); - LoadComponentAsync(settings = new MainSettings + loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); + loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, mainContent.Add); + loadComponentSingleFile(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); + loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset, Depth = -1 }, overlayContent.Add); - LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add); - LoadComponentAsync(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -3 }, mainContent.Add); - LoadComponentAsync(musicController = new MusicController + loadComponentSingleFile(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add); + loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -3 }, mainContent.Add); + loadComponentSingleFile(musicController = new MusicController { Depth = -4, Position = new Vector2(0, Toolbar.HEIGHT), @@ -198,16 +209,16 @@ namespace osu.Game Origin = Anchor.TopRight, }, overlayContent.Add); - LoadComponentAsync(notificationOverlay = new NotificationOverlay + loadComponentSingleFile(notificationOverlay = new NotificationOverlay { Depth = -4, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, overlayContent.Add); - LoadComponentAsync(dialogOverlay = new DialogOverlay + loadComponentSingleFile(dialogOverlay = new DialogOverlay { - Depth = -5, + Depth = -6, }, overlayContent.Add); Logger.NewEntry += entry => @@ -246,16 +257,6 @@ namespace osu.Game }; } - LoadComponentAsync(Toolbar = new Toolbar - { - Depth = -4, - OnHome = delegate - { - hideAllOverlays(); - intro?.ChildScreen?.MakeCurrent(); - }, - }, overlayContent.Add); - settings.StateChanged += delegate { switch (settings.State) @@ -272,6 +273,24 @@ namespace osu.Game Cursor.State = Visibility.Hidden; } + private Task asyncLoadStream; + + private void loadComponentSingleFile(T d, Action add) + where T : Drawable + { + Schedule(() => + { + if (asyncLoadStream != null) + asyncLoadStream = asyncLoadStream.ContinueWith(t => + { + Thread.Sleep(100); + LoadComponentAsync(d, add).Wait(); + }); + else + asyncLoadStream = LoadComponentAsync(d, add); + }); + } + public bool OnPressed(GlobalAction action) { if (intro == null) return false; From 65b23f38f161b328befa1562046221e0e2378f3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 12:48:33 +0900 Subject: [PATCH 30/36] fixup! Allow version manager to load completely async --- osu.Desktop/OsuGameDesktop.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 5a9d2adfd4..5f05fae213 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -18,8 +18,6 @@ namespace osu.Desktop { internal class OsuGameDesktop : OsuGame { - private VersionManager versionManager; - public OsuGameDesktop(string[] args = null) : base(args) { @@ -81,7 +79,7 @@ namespace osu.Desktop { base.LoadComplete(); - LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v => + LoadComponentAsync(new VersionManager { Depth = int.MinValue }, v => { Add(v); v.State = Visibility.Visible; From 777cdcbdc15ebe2526ec479d258c12f92d6ac391 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 13:08:58 +0900 Subject: [PATCH 31/36] Load even more components async --- 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 41153c4d34..cb502963f7 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -158,19 +158,15 @@ namespace osu.Game BeatmapManager.PostNotification = n => notificationOverlay?.Post(n); BeatmapManager.GetStableStorage = GetStorageForStableInstall; - AddRange(new Drawable[] { + AddRange(new Drawable[] + { new VolumeControlReceptor { RelativeSizeAxes = Axes.Both, ActionRequested = action => volume.Adjust(action) }, - mainContent = new Container - { - RelativeSizeAxes = Axes.Both, - }, - volume = new VolumeControl(), - overlayContent = new Container { RelativeSizeAxes = Axes.Both }, - new OnScreenDisplay(), + mainContent = new Container { RelativeSizeAxes = Axes.Both }, + overlayContent = new Container { RelativeSizeAxes = Axes.Both, Depth = float.MinValue }, }); loadComponentSingleFile(screenStack = new Loader(), d => @@ -190,6 +186,9 @@ namespace osu.Game }, }, overlayContent.Add); + loadComponentSingleFile(volume = new VolumeControl(), AddInternal); + loadComponentSingleFile(new OnScreenDisplay(), AddInternal); + //overlay elements loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, mainContent.Add); From 0e04260b3c0083e831de9b429eaa4e9d4c964dff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 13:43:47 +0900 Subject: [PATCH 32/36] Move ToolbarUserArea initialisation to BDL --- osu.Game/Overlays/Toolbar/ToolbarUserArea.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs index c1fd234628..95a25fcb86 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 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.Primitives; @@ -11,11 +12,12 @@ namespace osu.Game.Overlays.Toolbar internal class ToolbarUserArea : Container { public LoginOverlay LoginOverlay; - private readonly ToolbarUserButton button; + private ToolbarUserButton button; public override RectangleF BoundingBox => button.BoundingBox; - public ToolbarUserArea() + [BackgroundDependencyLoader] + private void load() { RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; @@ -36,4 +38,4 @@ namespace osu.Game.Overlays.Toolbar }; } } -} \ No newline at end of file +} From cc01878f2ba54e3c90e3a33172f03362160813c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Oct 2017 10:12:32 +0900 Subject: [PATCH 33/36] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 26f3091dca..ecc5e3189e 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 26f3091dcaf47e3b355b7f7ad83b292621d7d6b5 +Subproject commit ecc5e3189e8229d36095882b9a7a0efc95402be9 From e98bfec6444a0841558987d50938936562c6504c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Oct 2017 11:40:38 +0900 Subject: [PATCH 34/36] Remove Thread.Sleep and tidy up new method --- osu.Game/OsuGame.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index cb502963f7..b8c197abc9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -277,17 +277,7 @@ namespace osu.Game private void loadComponentSingleFile(T d, Action add) where T : Drawable { - Schedule(() => - { - if (asyncLoadStream != null) - asyncLoadStream = asyncLoadStream.ContinueWith(t => - { - Thread.Sleep(100); - LoadComponentAsync(d, add).Wait(); - }); - else - asyncLoadStream = LoadComponentAsync(d, add); - }); + Schedule(() => { asyncLoadStream = asyncLoadStream?.ContinueWith(t => LoadComponentAsync(d, add).Wait()) ?? LoadComponentAsync(d, add); }); } public bool OnPressed(GlobalAction action) From 9ec870a8219f4832b6552f5dd4acdc74994892ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Oct 2017 11:50:18 +0900 Subject: [PATCH 35/36] Add comment pertaining to why Schedule() is required --- osu.Game/OsuGame.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b8c197abc9..a278366e3e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -277,6 +277,9 @@ namespace osu.Game private void loadComponentSingleFile(T d, Action add) where T : Drawable { + // 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. Schedule(() => { asyncLoadStream = asyncLoadStream?.ContinueWith(t => LoadComponentAsync(d, add).Wait()) ?? LoadComponentAsync(d, add); }); } From 635f26badca57f47887837512744c0185ca8bb68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 24 Oct 2017 11:59:57 +0900 Subject: [PATCH 36/36] Remove unnecessary using --- osu.Game/OsuGame.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a278366e3e..1e7b0dc0bc 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -16,7 +16,6 @@ using osu.Game.Screens; using osu.Game.Screens.Menu; using OpenTK; using System.Linq; -using System.Threading; using System.Threading.Tasks; using osu.Framework.Input.Bindings; using osu.Framework.Platform;