From 8b25e4c9eea54cb5353da8ca743ba38edff0d60d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Jan 2019 12:04:36 +0900 Subject: [PATCH 01/21] Fix searching for "channel" matching all channels --- osu.Game/Overlays/Chat/Selection/ChannelSection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSection.cs b/osu.Game/Overlays/Chat/Selection/ChannelSection.cs index 94ee9d4bf6..c02215d690 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSection.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSection.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Linq; using osuTK; @@ -18,7 +19,7 @@ namespace osu.Game.Overlays.Chat.Selection public readonly FillFlowContainer ChannelFlow; public IEnumerable FilterableChildren => ChannelFlow.Children; - public IEnumerable FilterTerms => new[] { Header }; + public IEnumerable FilterTerms => Array.Empty(); public bool MatchingFilter { set From 3953f829c8e9b0b0247b6a43a6b0cbbfeda2bab3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 13:29:37 +0900 Subject: [PATCH 02/21] Add letterbox/screen scaling support --- osu.Game/Configuration/OsuConfigManager.cs | 15 ++- osu.Game/Configuration/ScalingMode.cs | 12 ++ .../Graphics/Containers/ScalingContainer.cs | 122 ++++++++++++++++++ .../Graphics/UserInterface/OsuSliderBar.cs | 2 +- osu.Game/OsuGame.cs | 15 ++- osu.Game/OsuGameBase.cs | 6 +- .../Sections/Graphics/LayoutSettings.cs | 47 ++++--- .../Backgrounds/BackgroundScreenEmpty.cs | 20 ++- osu.Game/Screens/Menu/Intro.cs | 2 +- osu.Game/Screens/Menu/MenuSideFlashes.cs | 2 + osu.Game/Screens/Play/Player.cs | 16 ++- 11 files changed, 228 insertions(+), 31 deletions(-) create mode 100644 osu.Game/Configuration/ScalingMode.cs create mode 100644 osu.Game/Graphics/Containers/ScalingContainer.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 8975ab8a0e..be293d02f6 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -96,6 +96,14 @@ namespace osu.Game.Configuration Set(OsuSetting.ScreenshotCaptureMenuCursor, false); Set(OsuSetting.SongSelectRightMouseScroll, false); + + Set(OsuSetting.Scaling, ScalingMode.Off); + + Set(OsuSetting.ScalingSizeX, 0.8f, 0.2f, 1f); + Set(OsuSetting.ScalingSizeY, 0.8f, 0.2f, 1f); + + Set(OsuSetting.ScalingPositionX, 0.5f, 0f, 1f); + Set(OsuSetting.ScalingPositionY, 0.5f, 0f, 1f); } public OsuConfigManager(Storage storage) : base(storage) @@ -151,6 +159,11 @@ namespace osu.Game.Configuration BeatmapHitsounds, IncreaseFirstObjectVisibility, ScoreDisplayMode, - ExternalLinkWarning + ExternalLinkWarning, + Scaling, + ScalingPositionX, + ScalingPositionY, + ScalingSizeX, + ScalingSizeY } } diff --git a/osu.Game/Configuration/ScalingMode.cs b/osu.Game/Configuration/ScalingMode.cs new file mode 100644 index 0000000000..063e967fa3 --- /dev/null +++ b/osu.Game/Configuration/ScalingMode.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2019 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +namespace osu.Game.Configuration +{ + public enum ScalingMode + { + Off, + Everything, + ExcludeOverlays, + Gameplay, + } +} \ No newline at end of file diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs new file mode 100644 index 0000000000..6686e6057e --- /dev/null +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -0,0 +1,122 @@ +// Copyright (c) 2007-2019 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; +using osu.Game.Graphics.Backgrounds; +using osuTK; + +namespace osu.Game.Graphics.Containers +{ + /// + /// Handles user-defined scaling, allowing application at multiple levels defined by . + /// + public class ScalingContainer : Container + { + private readonly bool isTopLevel; + + private Bindable sizeX; + private Bindable sizeY; + private Bindable posX; + private Bindable posY; + + private readonly ScalingMode targetMode; + + private Bindable scalingMode; + + private readonly Container content; + protected override Container Content => content; + + private readonly Container sizableContainer; + + private Drawable backgroundLayer; + + /// + /// Create a new instance. + /// + /// The mode which this container should be handling. + public ScalingContainer(ScalingMode targetMode) + { + this.targetMode = targetMode; + RelativeSizeAxes = Axes.Both; + + InternalChild = sizableContainer = new Container + { + RelativeSizeAxes = Axes.Both, + RelativePositionAxes = Axes.Both, + CornerRadius = 10, + Child = content = new DrawSizePreservingFillContainer() + }; + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + scalingMode = config.GetBindable(OsuSetting.Scaling); + scalingMode.ValueChanged += _ => updateSize(); + + sizeX = config.GetBindable(OsuSetting.ScalingSizeX); + sizeX.ValueChanged += _ => updateSize(); + + sizeY = config.GetBindable(OsuSetting.ScalingSizeY); + sizeY.ValueChanged += _ => updateSize(); + + posX = config.GetBindable(OsuSetting.ScalingPositionX); + posX.ValueChanged += _ => updateSize(); + + posY = config.GetBindable(OsuSetting.ScalingPositionY); + posY.ValueChanged += _ => updateSize(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updateSize(); + content.FinishTransforms(); + } + + private bool requiresBackgroundVisible => (scalingMode == ScalingMode.Everything || scalingMode == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1); + + private void updateSize() + { + if (targetMode == ScalingMode.Everything) + { + // the top level scaling container manages the background to be displayed while scaling. + if (requiresBackgroundVisible) + { + if (backgroundLayer == null) + LoadComponentAsync(backgroundLayer = new Background("Menu/menu-background-1") + { + Colour = OsuColour.Gray(0.1f), + Alpha = 0, + Depth = float.MaxValue + }, d => + { + AddInternal(d); + d.FadeTo(requiresBackgroundVisible ? 1 : 0, 4000, Easing.OutQuint); + }); + else + backgroundLayer.FadeIn(500); + } + else + backgroundLayer?.FadeOut(500); + } + + bool letterbox = scalingMode.Value == targetMode; + + var targetSize = letterbox ? new Vector2(sizeX, sizeY) : Vector2.One; + var targetPosition = letterbox ? new Vector2(posX, posY) * (Vector2.One - targetSize) : Vector2.Zero; + bool requiresMasking = targetSize != Vector2.One; + + if (requiresMasking) + sizableContainer.Masking = true; + + sizableContainer.MoveTo(targetPosition, 500, Easing.OutQuart); + sizableContainer.ResizeTo(targetSize, 500, Easing.OutQuart).OnComplete(_ => { content.Masking = requiresMasking; }); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index a59abcbcee..10b83c2610 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -47,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface var floatMinValue = bindableDouble?.MinValue ?? bindableFloat.MinValue; var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat.MaxValue; - if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) + if (floatMaxValue == 1 && floatMinValue >= -1) return floatValue.Value.ToString("P0"); var decimalPrecision = normalise((decimal)floatPrecision, max_decimal_digits); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2a4c812401..c9385359bc 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -26,6 +26,7 @@ using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Input; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; @@ -187,6 +188,7 @@ namespace osu.Game } private ExternalLinkOpener externalLinkOpener; + public void OpenUrlExternally(string url) { if (url.StartsWith("/")) @@ -353,7 +355,11 @@ namespace osu.Game ActionRequested = action => volume.Adjust(action), ScrollActionRequested = (action, amount, isPrecise) => volume.Adjust(action, amount, isPrecise), }, - mainContent = new Container { RelativeSizeAxes = Axes.Both }, + screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays) + { + RelativeSizeAxes = Axes.Both, + }, + mainContent = new DrawSizePreservingFillContainer(), overlayContent = new Container { RelativeSizeAxes = Axes.Both, Depth = float.MinValue }, idleTracker = new IdleTracker(6000) }); @@ -362,7 +368,7 @@ namespace osu.Game { screenStack.ModePushed += screenAdded; screenStack.Exited += screenRemoved; - mainContent.Add(screenStack); + screenContainer.Add(screenStack); }); loadComponentSingleFile(Toolbar = new Toolbar @@ -497,7 +503,7 @@ namespace osu.Game if (notifications.State == Visibility.Visible) offset -= ToolbarButton.WIDTH / 2; - screenStack.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint); + screenContainer.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint); } settings.StateChanged += _ => updateScreenOffset(); @@ -555,7 +561,7 @@ namespace osu.Game focused.StateChanged += s => { visibleOverlayCount += s == Visibility.Visible ? 1 : -1; - screenStack.FadeColour(visibleOverlayCount > 0 ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint); + screenContainer.FadeColour(visibleOverlayCount > 0 ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint); }; } @@ -646,6 +652,7 @@ namespace osu.Game private OsuScreen currentScreen; private FrameworkConfigManager frameworkConfig; + private ScalingContainer screenContainer; protected override bool OnExiting() { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 683fa30818..b6c642c9dc 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -24,6 +24,7 @@ using osu.Framework.Input; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Database; +using osu.Game.Graphics.Containers; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; @@ -189,7 +190,7 @@ namespace osu.Game Child = content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both } }; - base.Content.Add(new DrawSizePreservingFillContainer { Child = MenuCursorContainer }); + base.Content.Add(new ScalingContainer(ScalingMode.Everything) { Child = MenuCursorContainer }); KeyBindingStore.Register(globalBinding); dependencies.Cache(globalBinding); @@ -247,7 +248,8 @@ namespace osu.Game var extension = Path.GetExtension(paths.First())?.ToLowerInvariant(); foreach (var importer in fileImporters) - if (importer.HandledExtensions.Contains(extension)) importer.Import(paths); + if (importer.HandledExtensions.Contains(extension)) + importer.Import(paths); } public string[] HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions).ToArray(); diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 685244e06b..0386065a82 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings.Sections.Graphics @@ -16,9 +17,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override string Header => "Layout"; - private FillFlowContainer letterboxSettings; + private FillFlowContainer scalingSettings; - private Bindable letterboxing; + private Bindable scalingMode; private Bindable sizeFullscreen; private OsuGameBase game; @@ -28,11 +29,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private const int transition_duration = 400; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, OsuGameBase game) + private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, OsuGameBase game) { this.game = game; - letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); + scalingMode = osuConfig.GetBindable(OsuSetting.Scaling); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); Container resolutionSettingsContainer; @@ -49,12 +50,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y }, - new SettingsCheckbox + new SettingsEnumDropdown { - LabelText = "Letterboxing", - Bindable = letterboxing, + LabelText = "Scaling", + Bindable = osuConfig.GetBindable(OsuSetting.Scaling), }, - letterboxSettings = new FillFlowContainer + scalingSettings = new FillFlowContainer { Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, @@ -65,16 +66,28 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Children = new Drawable[] { - new SettingsSlider + new SettingsSlider { LabelText = "Horizontal position", - Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionX), + Bindable = osuConfig.GetBindable(OsuSetting.ScalingPositionX), KeyboardStep = 0.01f }, - new SettingsSlider + new SettingsSlider { LabelText = "Vertical position", - Bindable = config.GetBindable(FrameworkSetting.LetterboxPositionY), + Bindable = osuConfig.GetBindable(OsuSetting.ScalingPositionY), + KeyboardStep = 0.01f + }, + new SettingsSlider + { + LabelText = "Horizontal size", + Bindable = osuConfig.GetBindable(OsuSetting.ScalingSizeX), + KeyboardStep = 0.01f + }, + new SettingsSlider + { + LabelText = "Vertical size", + Bindable = osuConfig.GetBindable(OsuSetting.ScalingSizeY), KeyboardStep = 0.01f }, } @@ -105,13 +118,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, true); } - letterboxing.BindValueChanged(isVisible => + scalingMode.BindValueChanged(mode => { - letterboxSettings.ClearTransforms(); - letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None; + scalingSettings.ClearTransforms(); + scalingSettings.AutoSizeAxes = mode != ScalingMode.Off ? Axes.Y : Axes.None; - if (!isVisible) - letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); + if (mode == ScalingMode.Off) + scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); }, true); } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs index 5e08db8907..c097d25178 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs @@ -1,9 +1,27 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; +using osuTK.Graphics; + namespace osu.Game.Screens.Backgrounds { - public class BackgroundScreenEmpty : BackgroundScreen + public class BackgroundScreenBlack : BackgroundScreen { + public BackgroundScreenBlack() + { + Child = new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }; + } + + protected override void OnEntering(Screen last) + { + Show(); + } } } diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index fa01411a0f..8d9cd8dbe9 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Menu public override bool CursorVisible => false; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty(); + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); private Bindable menuVoice; private Bindable menuMusic; diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index ec5528b13f..188e95ced5 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -58,6 +58,7 @@ namespace osu.Game.Screens.Menu Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.Y, Width = box_width * 2, + Height = 1.5f, // align off-screen to make sure our edges don't become visible during parallax. X = -box_width, Alpha = 0, @@ -70,6 +71,7 @@ namespace osu.Game.Screens.Menu Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Y, Width = box_width * 2, + Height = 1.5f, X = box_width, Alpha = 0, Blending = BlendingMode.Additive, diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c102fb0223..93102228a4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -20,6 +20,7 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Online.API; using osu.Game.Overlays; @@ -179,10 +180,14 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both, Alpha = 0, }, - new LocalSkinOverrideContainer(working.Skin) + new ScalingContainer(ScalingMode.Gameplay) { - RelativeSizeAxes = Axes.Both, - Child = RulesetContainer + Child = + new LocalSkinOverrideContainer(working.Skin) + { + RelativeSizeAxes = Axes.Both, + Child = RulesetContainer + } }, new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { @@ -191,7 +196,10 @@ namespace osu.Game.Screens.Play ProcessCustomClock = false, Breaks = beatmap.Breaks }, - RulesetContainer.Cursor?.CreateProxy() ?? new Container(), + new ScalingContainer(ScalingMode.Gameplay) + { + Child = RulesetContainer.Cursor?.CreateProxy() ?? new Container(), + }, hudOverlay = new HUDOverlay(ScoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) { Clock = Clock, // hud overlay doesn't want to use the audio clock directly From 5a807f2143893e91459f22d22e3d28cfa942e160 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 14:18:29 +0900 Subject: [PATCH 03/21] Add OSD support --- osu.Game/Configuration/OsuConfigManager.cs | 25 ++++++++++++++++++---- osu.Game/Configuration/ScalingMode.cs | 7 +++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index be293d02f6..aced8e3024 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -1,8 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; +using osu.Framework.Extensions; using osu.Framework.Platform; using osu.Game.Overlays; using osu.Game.Rulesets.Scoring; @@ -106,14 +108,29 @@ namespace osu.Game.Configuration Set(OsuSetting.ScalingPositionY, 0.5f, 0f, 1f); } - public OsuConfigManager(Storage storage) : base(storage) + public OsuConfigManager(Storage storage) + : base(storage) { } - public override TrackedSettings CreateTrackedSettings() => new TrackedSettings + public override TrackedSettings CreateTrackedSettings() { - new TrackedSetting(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled")) - }; + Func scalingDescription = () => + { + var scalingMode = Get(OsuSetting.Scaling); + return new SettingDescription(scalingMode, "scaling", scalingMode.GetDescription()); + }; + + return new TrackedSettings + { + new TrackedSetting(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled")), + new TrackedSetting(OsuSetting.Scaling, _ => scalingDescription()), + new TrackedSetting(OsuSetting.ScalingSizeX, _ => scalingDescription()), + new TrackedSetting(OsuSetting.ScalingSizeY, _ => scalingDescription()), + new TrackedSetting(OsuSetting.ScalingPositionX, _ => scalingDescription()), + new TrackedSetting(OsuSetting.ScalingPositionY, _ => scalingDescription()), + }; + } } public enum OsuSetting diff --git a/osu.Game/Configuration/ScalingMode.cs b/osu.Game/Configuration/ScalingMode.cs index 063e967fa3..9673cc9251 100644 --- a/osu.Game/Configuration/ScalingMode.cs +++ b/osu.Game/Configuration/ScalingMode.cs @@ -1,12 +1,17 @@ // Copyright (c) 2007-2019 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; + namespace osu.Game.Configuration { public enum ScalingMode { + Off, Everything, + [Description("Excluding overlays")] ExcludeOverlays, Gameplay, } -} \ No newline at end of file +} From 35a6257642ed7600ee85cf069735b1ddf7246340 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 14:55:59 +0900 Subject: [PATCH 04/21] Delay updates when changes would affect mouse position --- .../Sections/Graphics/LayoutSettings.cs | 55 +++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 0386065a82..13c4156db6 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -8,8 +9,10 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osuTK.Input; namespace osu.Game.Overlays.Settings.Sections.Graphics { @@ -26,6 +29,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private SettingsDropdown resolutionDropdown; private SettingsEnumDropdown windowModeDropdown; + private Bindable scalingPositionX; + private Bindable scalingPositionY; + private Bindable scalingSizeX; + private Bindable scalingSizeY; + private const int transition_duration = 400; [BackgroundDependencyLoader] @@ -35,6 +43,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingMode = osuConfig.GetBindable(OsuSetting.Scaling); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); + scalingSizeX = osuConfig.GetBindable(OsuSetting.ScalingSizeX); + scalingSizeY = osuConfig.GetBindable(OsuSetting.ScalingSizeY); + scalingPositionX = osuConfig.GetBindable(OsuSetting.ScalingPositionX); + scalingPositionY = osuConfig.GetBindable(OsuSetting.ScalingPositionY); Container resolutionSettingsContainer; @@ -69,25 +81,25 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics new SettingsSlider { LabelText = "Horizontal position", - Bindable = osuConfig.GetBindable(OsuSetting.ScalingPositionX), + Bindable = delayedBindable(scalingPositionX), KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Vertical position", - Bindable = osuConfig.GetBindable(OsuSetting.ScalingPositionY), + Bindable = delayedBindable(scalingPositionY), KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Horizontal size", - Bindable = osuConfig.GetBindable(OsuSetting.ScalingSizeX), + Bindable = delayedBindable(scalingSizeX), KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Vertical size", - Bindable = osuConfig.GetBindable(OsuSetting.ScalingSizeY), + Bindable = delayedBindable(scalingSizeY), KeyboardStep = 0.01f }, } @@ -128,6 +140,41 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, true); } + /// + /// Create a delayed bindable which only updates when a condition is met. + /// + /// The config bindable. + /// A bindable which will propagate updates with a delay. + private Bindable delayedBindable(Bindable configBindable) + { + var delayed = new BindableFloat { MinValue = 0, MaxValue = 1, Default = configBindable.Default }; + + configBindable.BindValueChanged(v => delayed.Value = v, true); + delayed.ValueChanged += v => + { + if (scalingMode == ScalingMode.Everything) + applyWithDelay(() => configBindable.Value = v); + else + configBindable.Value = v; + }; + + return delayed; + } + + private ScheduledDelegate delayedApplication; + + private void applyWithDelay(Action func, bool firstRun = true) + { + if (!firstRun && !GetContainingInputManager().CurrentState.Mouse.IsPressed(MouseButton.Left)) + { + func(); + return; + } + + delayedApplication?.Cancel(); + delayedApplication = Scheduler.AddDelayed(() => applyWithDelay(func, false), 250); + } + private IReadOnlyList getResolutions() { var resolutions = new List { new Size(9999, 9999) }; From 9c7830d83bf4b88608e5c9de04e77773f6ae4cad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 14:58:44 +0900 Subject: [PATCH 05/21] Size -> scale --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 13c4156db6..3b0de5db10 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -75,7 +75,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics AutoSizeDuration = transition_duration, AutoSizeEasing = Easing.OutQuint, Masking = true, - Children = new Drawable[] { new SettingsSlider @@ -92,13 +91,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, new SettingsSlider { - LabelText = "Horizontal size", + LabelText = "Horizontal scale", Bindable = delayedBindable(scalingSizeX), KeyboardStep = 0.01f }, new SettingsSlider { - LabelText = "Vertical size", + LabelText = "Vertical scale", Bindable = delayedBindable(scalingSizeY), KeyboardStep = 0.01f }, From 3a10dd47d5c8fdc7d01d1f32f8d53691aef7a16f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 15:28:35 +0900 Subject: [PATCH 06/21] Add preview for gameplay region --- .../Graphics/Containers/ScalingContainer.cs | 15 +++---- .../Sections/Graphics/LayoutSettings.cs | 41 +++++++++++++++++-- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 6686e6057e..0fba88bb28 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics.Containers private Bindable posX; private Bindable posY; - private readonly ScalingMode targetMode; + private readonly ScalingMode? targetMode; private Bindable scalingMode; @@ -37,8 +37,8 @@ namespace osu.Game.Graphics.Containers /// /// Create a new instance. /// - /// The mode which this container should be handling. - public ScalingContainer(ScalingMode targetMode) + /// The mode which this container should be handling. Handles all modes if null. + public ScalingContainer(ScalingMode? targetMode = null) { this.targetMode = targetMode; RelativeSizeAxes = Axes.Both; @@ -47,6 +47,7 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, + Masking = true, CornerRadius = 10, Child = content = new DrawSizePreservingFillContainer() }; @@ -76,7 +77,7 @@ namespace osu.Game.Graphics.Containers base.LoadComplete(); updateSize(); - content.FinishTransforms(); + sizableContainer.FinishTransforms(); } private bool requiresBackgroundVisible => (scalingMode == ScalingMode.Everything || scalingMode == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1); @@ -106,10 +107,10 @@ namespace osu.Game.Graphics.Containers backgroundLayer?.FadeOut(500); } - bool letterbox = scalingMode.Value == targetMode; + bool scaling = targetMode == null || scalingMode.Value == targetMode; - var targetSize = letterbox ? new Vector2(sizeX, sizeY) : Vector2.One; - var targetPosition = letterbox ? new Vector2(posX, posY) * (Vector2.One - targetSize) : Vector2.Zero; + var targetSize = scaling ? new Vector2(sizeX, sizeY) : Vector2.One; + var targetPosition = scaling ? new Vector2(posX, posY) * (Vector2.One - targetSize) : Vector2.Zero; bool requiresMasking = targetSize != Vector2.One; if (requiresMasking) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 3b0de5db10..9a55e97452 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -9,9 +9,12 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Threading; using osu.Game.Configuration; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Overlays.Settings.Sections.Graphics @@ -151,15 +154,32 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics configBindable.BindValueChanged(v => delayed.Value = v, true); delayed.ValueChanged += v => { - if (scalingMode == ScalingMode.Everything) - applyWithDelay(() => configBindable.Value = v); - else - configBindable.Value = v; + switch (scalingMode.Value) + { + case ScalingMode.Everything: + applyWithDelay(() => configBindable.Value = v); + return; + case ScalingMode.Gameplay: + showPreview(); + break; + } + + configBindable.Value = v; }; return delayed; } + private Drawable preview; + private void showPreview() + { + if (preview?.IsAlive != true) + game.Add(preview = new ScalingPreview()); + + preview.FadeOutFromOne(1500); + preview.Expire(); + } + private ScheduledDelegate delayedApplication; private void applyWithDelay(Action func, bool firstRun = true) @@ -191,6 +211,19 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics return resolutions; } + private class ScalingPreview : ScalingContainer + { + public ScalingPreview() + { + Child = new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + }; + } + } + private class ResolutionSettingsDropdown : SettingsDropdown { protected override OsuDropdown CreateDropdown() => new ResolutionDropdownControl { Items = Items }; From 4c3310ca8026da130cee2ff679c98e4dc5d0d00c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 15:28:48 +0900 Subject: [PATCH 07/21] Remove unnecessary tracked settings (for now) --- osu.Game/Configuration/OsuConfigManager.cs | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index aced8e3024..46b51024f2 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Extensions; @@ -113,24 +112,12 @@ namespace osu.Game.Configuration { } - public override TrackedSettings CreateTrackedSettings() - { - Func scalingDescription = () => - { - var scalingMode = Get(OsuSetting.Scaling); - return new SettingDescription(scalingMode, "scaling", scalingMode.GetDescription()); - }; - - return new TrackedSettings + public override TrackedSettings CreateTrackedSettings() => + new TrackedSettings { new TrackedSetting(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled")), - new TrackedSetting(OsuSetting.Scaling, _ => scalingDescription()), - new TrackedSetting(OsuSetting.ScalingSizeX, _ => scalingDescription()), - new TrackedSetting(OsuSetting.ScalingSizeY, _ => scalingDescription()), - new TrackedSetting(OsuSetting.ScalingPositionX, _ => scalingDescription()), - new TrackedSetting(OsuSetting.ScalingPositionY, _ => scalingDescription()), + new TrackedSetting(OsuSetting.Scaling, m => new SettingDescription(m, "scaling", m.GetDescription())), }; - } } public enum OsuSetting From c528a3896dbcc9a3ef1910eade2943a8665c2746 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 15:34:32 +0900 Subject: [PATCH 08/21] Formatting and naming --- osu.Game/Configuration/OsuConfigManager.cs | 11 +++++------ osu.Game/Configuration/ScalingMode.cs | 1 - ...kgroundScreenEmpty.cs => BackgroundScreenBlack.cs} | 0 osu.Game/Screens/Play/Player.cs | 11 +++++------ 4 files changed, 10 insertions(+), 13 deletions(-) rename osu.Game/Screens/Backgrounds/{BackgroundScreenEmpty.cs => BackgroundScreenBlack.cs} (100%) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 46b51024f2..8df286ffb2 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -112,12 +112,11 @@ namespace osu.Game.Configuration { } - public override TrackedSettings CreateTrackedSettings() => - new TrackedSettings - { - new TrackedSetting(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled")), - new TrackedSetting(OsuSetting.Scaling, m => new SettingDescription(m, "scaling", m.GetDescription())), - }; + public override TrackedSettings CreateTrackedSettings() => new TrackedSettings + { + new TrackedSetting(OsuSetting.MouseDisableButtons, v => new SettingDescription(!v, "gameplay mouse buttons", v ? "disabled" : "enabled")), + new TrackedSetting(OsuSetting.Scaling, m => new SettingDescription(m, "scaling", m.GetDescription())), + }; } public enum OsuSetting diff --git a/osu.Game/Configuration/ScalingMode.cs b/osu.Game/Configuration/ScalingMode.cs index 9673cc9251..4d15fe8b4b 100644 --- a/osu.Game/Configuration/ScalingMode.cs +++ b/osu.Game/Configuration/ScalingMode.cs @@ -7,7 +7,6 @@ namespace osu.Game.Configuration { public enum ScalingMode { - Off, Everything, [Description("Excluding overlays")] diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs similarity index 100% rename from osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs rename to osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 93102228a4..20cc80a104 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -182,12 +182,11 @@ namespace osu.Game.Screens.Play }, new ScalingContainer(ScalingMode.Gameplay) { - Child = - new LocalSkinOverrideContainer(working.Skin) - { - RelativeSizeAxes = Axes.Both, - Child = RulesetContainer - } + Child = new LocalSkinOverrideContainer(working.Skin) + { + RelativeSizeAxes = Axes.Both, + Child = RulesetContainer + } }, new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { From f2ccf70d1ba97a8c8f174f89ed06d198b89184f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 4 Jan 2019 15:37:27 +0900 Subject: [PATCH 09/21] Backdate license header for now --- osu.Game/Configuration/ScalingMode.cs | 2 +- osu.Game/Graphics/Containers/ScalingContainer.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Configuration/ScalingMode.cs b/osu.Game/Configuration/ScalingMode.cs index 4d15fe8b4b..b907d55d82 100644 --- a/osu.Game/Configuration/ScalingMode.cs +++ b/osu.Game/Configuration/ScalingMode.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2019 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 0fba88bb28..4dc25ae3d1 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2019 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; From dd960e6a89da0cf69f728911035e74790b6cd500 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Jan 2019 12:50:42 +0900 Subject: [PATCH 10/21] Remove unused variable --- osu.Game/Graphics/Containers/ScalingContainer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 4dc25ae3d1..6cfbc5d9d2 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -16,8 +16,6 @@ namespace osu.Game.Graphics.Containers /// public class ScalingContainer : Container { - private readonly bool isTopLevel; - private Bindable sizeX; private Bindable sizeY; private Bindable posX; From 440f4703cb5612cc3d07bfc4535cc4dcd3021011 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Jan 2019 12:57:31 +0900 Subject: [PATCH 11/21] Fix toolbar offset not being applied --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c004bc6000..bb356ce7f0 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -692,7 +692,7 @@ namespace osu.Game ruleset.Disabled = applyBeatmapRulesetRestrictions; Beatmap.Disabled = applyBeatmapRulesetRestrictions; - mainContent.Padding = new MarginPadding { Top = ToolbarOffset }; + screenContainer.Padding = new MarginPadding { Top = ToolbarOffset }; MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; } From 199b614eba541210a13e45cc4359616345b891b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Jan 2019 13:36:07 +0900 Subject: [PATCH 12/21] Fix masking being unapplied incorrectly --- osu.Game/Graphics/Containers/ScalingContainer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 6cfbc5d9d2..ff7a1cdacf 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -45,7 +45,6 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, - Masking = true, CornerRadius = 10, Child = content = new DrawSizePreservingFillContainer() }; @@ -109,13 +108,13 @@ namespace osu.Game.Graphics.Containers var targetSize = scaling ? new Vector2(sizeX, sizeY) : Vector2.One; var targetPosition = scaling ? new Vector2(posX, posY) * (Vector2.One - targetSize) : Vector2.Zero; - bool requiresMasking = targetSize != Vector2.One; + bool requiresMasking = scaling && targetSize != Vector2.One; if (requiresMasking) sizableContainer.Masking = true; sizableContainer.MoveTo(targetPosition, 500, Easing.OutQuart); - sizableContainer.ResizeTo(targetSize, 500, Easing.OutQuart).OnComplete(_ => { content.Masking = requiresMasking; }); + sizableContainer.ResizeTo(targetSize, 500, Easing.OutQuart).OnComplete(_ => { sizableContainer.Masking = requiresMasking; }); } } } From 01aa4c2a72a1d7b43a62953482ff6faede1c4842 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Jan 2019 13:48:38 +0900 Subject: [PATCH 13/21] Use TransferOnCommit --- .../Sections/Graphics/LayoutSettings.cs | 36 +++++++++---------- osu.Game/Overlays/Settings/SettingsItem.cs | 2 +- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 9a55e97452..b6c5c4d1e6 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -7,9 +7,11 @@ using System.Drawing; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics.Containers; @@ -23,7 +25,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override string Header => "Layout"; - private FillFlowContainer scalingSettings; + private FillFlowContainer> scalingSettings; private Bindable scalingMode; private Bindable sizeFullscreen; @@ -70,7 +72,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "Scaling", Bindable = osuConfig.GetBindable(OsuSetting.Scaling), }, - scalingSettings = new FillFlowContainer + scalingSettings = new FillFlowContainer> { Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, @@ -78,36 +80,38 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics AutoSizeDuration = transition_duration, AutoSizeEasing = Easing.OutQuint, Masking = true, - Children = new Drawable[] + Children = new [] { new SettingsSlider { LabelText = "Horizontal position", - Bindable = delayedBindable(scalingPositionX), + Bindable = scalingPositionX, KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Vertical position", - Bindable = delayedBindable(scalingPositionY), + Bindable = scalingPositionY, KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Horizontal scale", - Bindable = delayedBindable(scalingSizeX), + Bindable = scalingSizeX, KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Vertical scale", - Bindable = delayedBindable(scalingSizeY), + Bindable = scalingSizeY, KeyboardStep = 0.01f }, } }, }; + scalingSettings.ForEach(s => bindPreviewEvent(s.Bindable)); + var resolutions = getResolutions(); if (resolutions.Count > 1) @@ -139,35 +143,27 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (mode == ScalingMode.Off) scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); + + scalingSettings.ForEach(s => ((SliderBar)s.Control).TransferValueOnCommit = mode == ScalingMode.Everything); }, true); } /// /// Create a delayed bindable which only updates when a condition is met. /// - /// The config bindable. + /// The config bindable. /// A bindable which will propagate updates with a delay. - private Bindable delayedBindable(Bindable configBindable) + private void bindPreviewEvent(Bindable bindable) { - var delayed = new BindableFloat { MinValue = 0, MaxValue = 1, Default = configBindable.Default }; - - configBindable.BindValueChanged(v => delayed.Value = v, true); - delayed.ValueChanged += v => + bindable.ValueChanged += v => { switch (scalingMode.Value) { - case ScalingMode.Everything: - applyWithDelay(() => configBindable.Value = v); - return; case ScalingMode.Gameplay: showPreview(); break; } - - configBindable.Value = v; }; - - return delayed; } private Drawable preview; diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 1d7e6350ae..5ba682c7dd 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings { protected abstract Drawable CreateControl(); - protected Drawable Control { get; } + public Drawable Control { get; } private IHasCurrentValue controlWithCurrent => Control as IHasCurrentValue; From a2a7aa708fa837128168aeb7ceb3d852bf1a633c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Jan 2019 14:56:42 +0900 Subject: [PATCH 14/21] Use better logic for setting slider bar settings --- .../Sections/Graphics/LayoutSettings.cs | 3 +-- osu.Game/Overlays/Settings/SettingsItem.cs | 2 +- osu.Game/Overlays/Settings/SettingsSlider.cs | 17 +++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index b6c5c4d1e6..7f74719890 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -11,7 +11,6 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics.Containers; @@ -144,7 +143,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (mode == ScalingMode.Off) scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); - scalingSettings.ForEach(s => ((SliderBar)s.Control).TransferValueOnCommit = mode == ScalingMode.Everything); + scalingSettings.ForEach(s => s.TransferValueOnCommit = mode == ScalingMode.Everything); }, true); } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 5ba682c7dd..1d7e6350ae 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings { protected abstract Drawable CreateControl(); - public Drawable Control { get; } + protected Drawable Control { get; } private IHasCurrentValue controlWithCurrent => Control as IHasCurrentValue; diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index a3698c36e6..39a974dd2e 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -2,7 +2,6 @@ // 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.Game.Graphics.UserInterface; @@ -23,14 +22,16 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X }; - public float KeyboardStep; - - [BackgroundDependencyLoader] - private void load() + public bool TransferValueOnCommit { - var slider = Control as U; - if (slider != null) - slider.KeyboardStep = KeyboardStep; + get => ((U)Control).TransferValueOnCommit; + set => ((U)Control).TransferValueOnCommit = value; + } + + public float KeyboardStep + { + get => ((U)Control).KeyboardStep; + set => ((U)Control).KeyboardStep = value; } } } From 8692be9de3d1ebebb38d2bae841ce5a21d65de0b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Jan 2019 16:07:54 +0900 Subject: [PATCH 15/21] Fix sliderbar not working correctly with TransferValueOnCommit = true --- .../Graphics/UserInterface/OsuSliderBar.cs | 87 +++++++++---------- .../Graphics/UserInterface/ProgressBar.cs | 2 +- .../Compose/Components/BeatDivisorControl.cs | 6 +- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- 4 files changed, 45 insertions(+), 52 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index a59abcbcee..2bd84ab2b4 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -8,7 +8,6 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; @@ -33,38 +32,7 @@ namespace osu.Game.Graphics.UserInterface private readonly Box leftBox; private readonly Box rightBox; - public virtual string TooltipText - { - get - { - var bindableDouble = CurrentNumber as BindableNumber; - var bindableFloat = CurrentNumber as BindableNumber; - var floatValue = bindableDouble?.Value ?? bindableFloat?.Value; - var floatPrecision = bindableDouble?.Precision ?? bindableFloat?.Precision; - - if (floatValue != null) - { - var floatMinValue = bindableDouble?.MinValue ?? bindableFloat.MinValue; - var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat.MaxValue; - - if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) - return floatValue.Value.ToString("P0"); - - var decimalPrecision = normalise((decimal)floatPrecision, max_decimal_digits); - - // Find the number of significant digits (we could have less than 5 after normalize()) - var significantDigits = findPrecision(decimalPrecision); - - return floatValue.Value.ToString($"N{significantDigits}"); - } - - var bindableInt = CurrentNumber as BindableNumber; - if (bindableInt != null) - return bindableInt.Value.ToString("N0"); - - return Current.Value.ToString(CultureInfo.InvariantCulture); - } - } + public virtual string TooltipText { get; private set; } private Color4 accentColour; public Color4 AccentColour @@ -136,21 +104,34 @@ namespace osu.Game.Graphics.UserInterface base.OnHoverLost(e); } - protected override void OnUserChange() + protected override bool OnMouseDown(MouseDownEvent e) { - base.OnUserChange(); - playSample(); + Nub.Current.Value = true; + return base.OnMouseDown(e); } - private void playSample() + protected override bool OnMouseUp(MouseUpEvent e) + { + Nub.Current.Value = false; + return base.OnMouseUp(e); + } + + protected override void OnUserChange(T value) + { + base.OnUserChange(value); + playSample(value); + updateTooltipText(value); + } + + private void playSample(T value) { if (Clock == null || Clock.CurrentTime - lastSampleTime <= 50) return; - if (Current.Value.Equals(lastSampleValue)) + if (value.Equals(lastSampleValue)) return; - lastSampleValue = Current.Value; + lastSampleValue = value; lastSampleTime = Clock.CurrentTime; sample.Frequency.Value = 1 + NormalizedValue * 0.2f; @@ -163,16 +144,28 @@ namespace osu.Game.Graphics.UserInterface sample.Play(); } - protected override bool OnMouseDown(MouseDownEvent e) + private void updateTooltipText(T value) { - Nub.Current.Value = true; - return base.OnMouseDown(e); - } + if (CurrentNumber.IsInteger) + TooltipText = ((int)Convert.ChangeType(value, typeof(int))).ToString("N0"); + else + { + double floatValue = (double)Convert.ChangeType(value, typeof(double)); + double floatMinValue = (double)Convert.ChangeType(CurrentNumber.MinValue, typeof(double)); + double floatMaxValue = (double)Convert.ChangeType(CurrentNumber.MaxValue, typeof(double)); - protected override bool OnMouseUp(MouseUpEvent e) - { - Nub.Current.Value = false; - return base.OnMouseUp(e); + if (floatMaxValue == 1 && floatMinValue >= -1) + TooltipText = floatValue.ToString("P0"); + else + { + var decimalPrecision = normalise((decimal)Convert.ChangeType(CurrentNumber.Precision, typeof(decimal)), max_decimal_digits); + + // Find the number of significant digits (we could have less than 5 after normalize()) + var significantDigits = findPrecision(decimalPrecision); + + TooltipText = floatValue.ToString($"N{significantDigits}"); + } + } } protected override void UpdateAfterChildren() diff --git a/osu.Game/Graphics/UserInterface/ProgressBar.cs b/osu.Game/Graphics/UserInterface/ProgressBar.cs index ee64c7c25c..d03b9b30dc 100644 --- a/osu.Game/Graphics/UserInterface/ProgressBar.cs +++ b/osu.Game/Graphics/UserInterface/ProgressBar.cs @@ -62,6 +62,6 @@ namespace osu.Game.Graphics.UserInterface fill.Width = value * UsableWidth; } - protected override void OnUserChange() => OnSeek?.Invoke(Current); + protected override void OnUserChange(double value) => OnSeek?.Invoke(Current); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index aa63b02013..373f4d1682 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -238,11 +238,11 @@ namespace osu.Game.Screens.Edit.Compose.Components { case Key.Right: beatDivisor.Next(); - OnUserChange(); + OnUserChange(Current); return true; case Key.Left: beatDivisor.Previous(); - OnUserChange(); + OnUserChange(Current); return true; default: return false; @@ -279,7 +279,7 @@ namespace osu.Game.Screens.Edit.Compose.Components var xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth; CurrentNumber.Value = availableDivisors.OrderBy(d => Math.Abs(getMappedPosition(d) - xPosition)).First(); - OnUserChange(); + OnUserChange(Current); } private float getMappedPosition(float divisor) => (float)Math.Pow((divisor - 1) / (availableDivisors.Last() - 1), 0.90f); diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 1f0c4936a5..00206e05ff 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -112,6 +112,6 @@ namespace osu.Game.Screens.Play handleBase.X = xFill; } - protected override void OnUserChange() => OnSeek?.Invoke(Current); + protected override void OnUserChange(double value) => OnSeek?.Invoke(Current); } } From 38a3ccc817de72c87c665b9d9760c743d112f178 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Jan 2019 16:31:44 +0900 Subject: [PATCH 16/21] Use value where applicable --- osu.Game/Graphics/UserInterface/ProgressBar.cs | 2 +- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ProgressBar.cs b/osu.Game/Graphics/UserInterface/ProgressBar.cs index d03b9b30dc..6dca58f70d 100644 --- a/osu.Game/Graphics/UserInterface/ProgressBar.cs +++ b/osu.Game/Graphics/UserInterface/ProgressBar.cs @@ -62,6 +62,6 @@ namespace osu.Game.Graphics.UserInterface fill.Width = value * UsableWidth; } - protected override void OnUserChange(double value) => OnSeek?.Invoke(Current); + protected override void OnUserChange(double value) => OnSeek?.Invoke(value); } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 00206e05ff..b06a34e603 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -112,6 +112,6 @@ namespace osu.Game.Screens.Play handleBase.X = xFill; } - protected override void OnUserChange(double value) => OnSeek?.Invoke(Current); + protected override void OnUserChange(double value) => OnSeek?.Invoke(value); } } From daeba63242302f47e3787cbbbbf917128437b97d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Jan 2019 16:37:18 +0900 Subject: [PATCH 17/21] Remove more unused code --- .../Settings/Sections/Graphics/LayoutSettings.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 7f74719890..22fcf8a6a4 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -175,20 +175,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics preview.Expire(); } - private ScheduledDelegate delayedApplication; - - private void applyWithDelay(Action func, bool firstRun = true) - { - if (!firstRun && !GetContainingInputManager().CurrentState.Mouse.IsPressed(MouseButton.Left)) - { - func(); - return; - } - - delayedApplication?.Cancel(); - delayedApplication = Scheduler.AddDelayed(() => applyWithDelay(func, false), 250); - } - private IReadOnlyList getResolutions() { var resolutions = new List { new Size(9999, 9999) }; From 2c44b928d37d4fd4d4ac49d507d11c36c74c954e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Jan 2019 16:38:34 +0900 Subject: [PATCH 18/21] Remove unused references --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 22fcf8a6a4..3fa4276616 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -11,12 +10,10 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; -using osuTK.Input; namespace osu.Game.Overlays.Settings.Sections.Graphics { From cf8bcb7ba29ebfdd38a242735bfe21c6ceb7e2e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 8 Jan 2019 17:53:43 +0900 Subject: [PATCH 19/21] Add explicit beatmap -> scores relationship rather than relying on cascades --- osu.Game/Beatmaps/BeatmapInfo.cs | 7 ++++ osu.Game/Beatmaps/BeatmapStore.cs | 3 +- .../Migrations/OsuDbContextModelSnapshot.cs | 42 +++++++++---------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 0534fd9253..6ad5b2070e 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; @@ -9,6 +10,7 @@ using Newtonsoft.Json; using osu.Game.Database; using osu.Game.IO.Serialization; using osu.Game.Rulesets; +using osu.Game.Scoring; namespace osu.Game.Beatmaps { @@ -112,6 +114,11 @@ namespace osu.Game.Beatmaps [JsonProperty("difficulty_rating")] public double StarDifficulty { get; set; } + /// + /// Currently only populated for beatmap deletion. Use to query scores. + /// + public List Scores { get; set; } + public override string ToString() => $"{Metadata} [{Version}]"; public bool Equals(BeatmapInfo other) diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index 5bdc42cdf3..6817c0653d 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -64,7 +64,8 @@ namespace osu.Game.Beatmaps base.AddIncludesForDeletion(query) .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata) .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) - .Include(s => s.Metadata); + .Include(s => s.Metadata) + .Include(s => s.Beatmaps).ThenInclude(b => b.Scores); protected override IQueryable AddIncludesForConsumption(IQueryable query) => base.AddIncludesForConsumption(query) diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 8026847e3b..2dafedc3ac 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + .HasAnnotation("ProductVersion", "2.2.0-rtm-35687"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -215,6 +215,25 @@ namespace osu.Game.Migrations b.ToTable("Settings"); }); + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => { b.Property("ID") @@ -239,25 +258,6 @@ namespace osu.Game.Migrations b.ToTable("KeyBinding"); }); - modelBuilder.Entity("osu.Game.IO.FileInfo", b => - { - b.Property("ID") - .ValueGeneratedOnAdd(); - - b.Property("Hash"); - - b.Property("ReferenceCount"); - - b.HasKey("ID"); - - b.HasIndex("Hash") - .IsUnique(); - - b.HasIndex("ReferenceCount"); - - b.ToTable("FileInfo"); - }); - modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => { b.Property("ID") @@ -454,7 +454,7 @@ namespace osu.Game.Migrations modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => { b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") - .WithMany() + .WithMany("Scores") .HasForeignKey("BeatmapInfoID") .OnDelete(DeleteBehavior.Cascade); From 415df52c69ec42846a26f1e9d43ffc8fdbaa2edf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 8 Jan 2019 21:23:57 +0900 Subject: [PATCH 20/21] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d6dbb6f11c..8f00e81237 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 045ed741b0a253352f82b5a7806d942f1565dced Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Jan 2019 15:29:27 +0900 Subject: [PATCH 21/21] Fix API getting stuck in eternal failing state if login request fails --- osu.Game/Online/API/APIAccess.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 10b4e73419..db273dd00a 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -101,6 +101,9 @@ namespace osu.Game.Online.API //todo: replace this with a ping request. log.Add(@"In a failing state, waiting a bit before we try again..."); Thread.Sleep(5000); + + if (!IsLoggedIn) goto case APIState.Connecting; + if (queue.Count == 0) { log.Add(@"Queueing a ping request");