From e98f9f1323342f3643da07d2fbb3347b0a3b1b25 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 2 Jun 2018 21:02:45 +0300 Subject: [PATCH 01/35] Add dropdown for selecting fullscreen resolution --- .../Sections/Graphics/LayoutSettings.cs | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 1f87a635de..b3a2243ca3 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,10 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Platform; namespace osu.Game.Overlays.Settings.Sections.Graphics { @@ -16,20 +20,32 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable letterboxing; + private OsuGame game; + private SettingsDropdown resolutionDropdown; + private SettingsEnumDropdown windowModeDropdown; + private const int transition_duration = 400; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config) + private void load(FrameworkConfigManager config, OsuGame game) { + this.game = game; + letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); Children = new Drawable[] { - new SettingsEnumDropdown + windowModeDropdown = new SettingsEnumDropdown { LabelText = "Screen mode", Bindable = config.GetBindable(FrameworkSetting.WindowMode), }, + resolutionDropdown = new SettingsDropdown + { + LabelText = "Resolution", + Items = getResolutions(), + Bindable = config.GetBindable(FrameworkSetting.FullscreenResolution) + }, new SettingsCheckbox { LabelText = "Letterboxing", @@ -62,6 +78,15 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; + windowModeDropdown.Bindable.ValueChanged += (s) => + { + if (windowModeDropdown.Bindable.Value == WindowMode.Fullscreen) + resolutionDropdown.Show(); + else + resolutionDropdown.Hide(); + }; + windowModeDropdown.Bindable.TriggerChange(); + letterboxing.ValueChanged += isVisible => { letterboxSettings.ClearTransforms(); @@ -72,5 +97,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }; letterboxing.TriggerChange(); } + + private IEnumerable> getResolutions() + { + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions; + + return (availableDisplayResolutions ?? throw new InvalidOperationException()).Select((t, i) => new KeyValuePair($"{t.Width}x{t.Height}@{t.RefreshRate}Hz", i)); + } } } From de7e4328c5c316df687ab91c5901d99961fe2d69 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 10 Jun 2018 16:17:57 +0300 Subject: [PATCH 02/35] Use bindable size --- .../Sections/Graphics/LayoutSettings.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index b3a2243ca3..2d970e41de 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,8 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -19,11 +19,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private FillFlowContainer letterboxSettings; private Bindable letterboxing; + private Bindable sizeFullscreen; private OsuGame game; private SettingsDropdown resolutionDropdown; private SettingsEnumDropdown windowModeDropdown; + private const int transition_duration = 400; [BackgroundDependencyLoader] @@ -32,6 +34,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics this.game = game; letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); + sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); + + var resolutions = getResolutions(); + var resolutionDropdownBindable = new BindableInt(resolutions.FirstOrDefault(r => r.Key.StartsWith($"{sizeFullscreen.Value.Width}x{sizeFullscreen.Value.Height}")).Value); + + resolutionDropdownBindable.ValueChanged += _ => + { + var newResolution = resolutions.First(r => r.Value == _); + var newResolutionparts = newResolution.Key.Split('x'); + sizeFullscreen.Value = new Size(int.Parse(newResolutionparts.First()), int.Parse(newResolutionparts.Last())); + }; Children = new Drawable[] { @@ -43,8 +56,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics resolutionDropdown = new SettingsDropdown { LabelText = "Resolution", - Items = getResolutions(), - Bindable = config.GetBindable(FrameworkSetting.FullscreenResolution) + Items = resolutions, + Bindable = resolutionDropdownBindable }, new SettingsCheckbox { @@ -98,11 +111,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics letterboxing.TriggerChange(); } - private IEnumerable> getResolutions() + private List> getResolutions() { var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions; + if (availableDisplayResolutions == null) + return new List>(); + var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct().ToList(); - return (availableDisplayResolutions ?? throw new InvalidOperationException()).Select((t, i) => new KeyValuePair($"{t.Width}x{t.Height}@{t.RefreshRate}Hz", i)); + return availableDisplayResolutionsStr.Select((t, i) => new KeyValuePair(t, i)).ToList(); } } } From 71371dc4b86090e493c73ee6ea5b325424a34e91 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 12 Jun 2018 19:27:55 +0300 Subject: [PATCH 03/35] ValueChanged parameters quickfix --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 2d970e41de..588be967e5 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -39,9 +39,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics var resolutions = getResolutions(); var resolutionDropdownBindable = new BindableInt(resolutions.FirstOrDefault(r => r.Key.StartsWith($"{sizeFullscreen.Value.Width}x{sizeFullscreen.Value.Height}")).Value); - resolutionDropdownBindable.ValueChanged += _ => + resolutionDropdownBindable.ValueChanged += resolution => { - var newResolution = resolutions.First(r => r.Value == _); + var newResolution = resolutions.First(r => r.Value == resolution); var newResolutionparts = newResolution.Key.Split('x'); sizeFullscreen.Value = new Size(int.Parse(newResolutionparts.First()), int.Parse(newResolutionparts.Last())); }; @@ -91,9 +91,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; - windowModeDropdown.Bindable.ValueChanged += (s) => + windowModeDropdown.Bindable.ValueChanged += windowMode => { - if (windowModeDropdown.Bindable.Value == WindowMode.Fullscreen) + if (windowMode == WindowMode.Fullscreen) resolutionDropdown.Show(); else resolutionDropdown.Hide(); From 5d26d5d4ed81d97dc0ce257d85665ce9b8495d62 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 21 Jun 2018 20:42:22 +0300 Subject: [PATCH 04/35] Fix resolutionDropdown --- .../Sections/Graphics/LayoutSettings.cs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 588be967e5..36de8d4771 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -20,6 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable letterboxing; private Bindable sizeFullscreen; + private readonly BindableInt resolutionDropdownBindable = new BindableInt(); private OsuGame game; private SettingsDropdown resolutionDropdown; @@ -36,14 +37,23 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); - var resolutions = getResolutions(); - var resolutionDropdownBindable = new BindableInt(resolutions.FirstOrDefault(r => r.Key.StartsWith($"{sizeFullscreen.Value.Width}x{sizeFullscreen.Value.Height}")).Value); + sizeFullscreen.ValueChanged += size => + { + KeyValuePair valuePair = getResolutions().FirstOrDefault(r => r.Key.StartsWith($"{size.Width}x{size.Height}")); + + resolutionDropdownBindable.Value = valuePair.Value; + }; resolutionDropdownBindable.ValueChanged += resolution => { - var newResolution = resolutions.First(r => r.Value == resolution); - var newResolutionparts = newResolution.Key.Split('x'); - sizeFullscreen.Value = new Size(int.Parse(newResolutionparts.First()), int.Parse(newResolutionparts.Last())); + var newSelection = getResolutions().First(r => r.Value == resolution); + var newSelectionParts = newSelection.Key.Split('x'); + + var newSelectionWidth = int.Parse(newSelectionParts.First()); + var newSelectionHeight = int.Parse(newSelectionParts.Last()); + + if (sizeFullscreen.Value.Width != newSelectionWidth || sizeFullscreen.Value.Height != newSelectionHeight) + sizeFullscreen.Value = new Size(newSelectionWidth, newSelectionHeight); }; Children = new Drawable[] @@ -56,7 +66,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics resolutionDropdown = new SettingsDropdown { LabelText = "Resolution", - Items = resolutions, + Items = getResolutions(), Bindable = resolutionDropdownBindable }, new SettingsCheckbox @@ -94,7 +104,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics windowModeDropdown.Bindable.ValueChanged += windowMode => { if (windowMode == WindowMode.Fullscreen) + { resolutionDropdown.Show(); + sizeFullscreen.TriggerChange(); + } else resolutionDropdown.Hide(); }; @@ -113,7 +126,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions; + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions.OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); if (availableDisplayResolutions == null) return new List>(); var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct().ToList(); From 5076fe4c2000747b34c826fd3d3925a1ce7d8f85 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 23 Jun 2018 12:45:13 +0300 Subject: [PATCH 05/35] LayoutSettings: inject OsuGameBase instead of OsuGame --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 36de8d4771..27ce8bad13 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable sizeFullscreen; private readonly BindableInt resolutionDropdownBindable = new BindableInt(); - private OsuGame game; + private OsuGameBase game; private SettingsDropdown resolutionDropdown; private SettingsEnumDropdown windowModeDropdown; @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private const int transition_duration = 400; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, OsuGame game) + private void load(FrameworkConfigManager config, OsuGameBase game) { this.game = game; From 4af45b751817f8a95624b6d7a93e98468c56a412 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 30 Jun 2018 20:06:11 +0300 Subject: [PATCH 06/35] Do not display resolutions lower than 800x600 --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 27ce8bad13..996b6a2a24 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -126,11 +126,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions.OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + if (availableDisplayResolutions == null) return new List>(); - var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct().ToList(); + var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct(); return availableDisplayResolutionsStr.Select((t, i) => new KeyValuePair(t, i)).ToList(); } } From 699702f8d027eebba3e9a676539246f184deb690 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 9 Jul 2018 21:57:31 +0300 Subject: [PATCH 07/35] Use DesktopGameWindow.GetCurrentDisplay method --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 996b6a2a24..a67548d959 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.GetCurrentDisplay().AvailableResolutions .Where(r => r.Width >= 800 && r.Height >= 600) .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); From 8f9bf4bd3e4a4e4b5da5b3cc219d38036379d87a Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 10 Jul 2018 22:07:32 +0300 Subject: [PATCH 08/35] Remove redundant DesktopGameWindow cast --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index a67548d959..7fe628016c 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Platform; namespace osu.Game.Overlays.Settings.Sections.Graphics { @@ -126,9 +125,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.GetCurrentDisplay().AvailableResolutions - .Where(r => r.Width >= 800 && r.Height >= 600) - .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + var availableDisplayResolutions = game.Window?.GetCurrentDisplay().AvailableResolutions + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); if (availableDisplayResolutions == null) return new List>(); From 0d4aa37a91b7ac4c7a18bd4f01c92a32e4184e1e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Aug 2018 00:59:30 +0900 Subject: [PATCH 09/35] Fix order of import set conflict checks --- osu.Game/Beatmaps/BeatmapManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 774a80049b..4f03cffc0c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -103,6 +103,11 @@ namespace osu.Game.Beatmaps b.BeatmapSet = beatmapSet; } + validateOnlineIds(beatmapSet.Beatmaps); + + foreach (BeatmapInfo b in beatmapSet.Beatmaps) + fetchAndPopulateOnlineIDs(b, beatmapSet.Beatmaps); + // check if a set already exists with the same online id, delete if it does. if (beatmapSet.OnlineBeatmapSetID != null) { @@ -114,11 +119,6 @@ namespace osu.Game.Beatmaps Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({beatmapSet.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database); } } - - validateOnlineIds(beatmapSet.Beatmaps); - - foreach (BeatmapInfo b in beatmapSet.Beatmaps) - fetchAndPopulateOnlineIDs(b, beatmapSet.Beatmaps); } private void validateOnlineIds(List beatmaps) From bf6fb1c38048f8a7f44cfc3bc525cab22b56591b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Sep 2018 12:55:11 +0900 Subject: [PATCH 10/35] Don't use ConcurrentQueue for API This queue type can hold several references to already dequeued requests. In our usage, this can cause old api calls to hold references to already-disposed screens (and in turn, very large memory portions). --- osu.Game/Online/API/APIAccess.cs | 56 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 12935a5ffe..ff5247e8f6 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Net; @@ -26,7 +25,7 @@ namespace osu.Game.Online.API private const string client_id = @"5"; private const string client_secret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"; - private ConcurrentQueue queue = new ConcurrentQueue(); + private readonly Queue queue = new Queue(); /// /// The username/email provided by the user when initiating a login. @@ -75,10 +74,7 @@ namespace osu.Game.Online.API public void Unregister(IOnlineComponent component) { - Scheduler.Add(delegate - { - components.Remove(component); - }); + Scheduler.Add(delegate { components.Remove(component); }); } public string AccessToken => authentication.RequestAccessToken(); @@ -103,6 +99,7 @@ namespace osu.Game.Online.API log.Add(@"Queueing a ping request"); Queue(new ListChannelsRequest { Timeout = 5000 }); } + break; case APIState.Offline: case APIState.Connecting: @@ -161,18 +158,19 @@ namespace osu.Game.Online.API continue; } - //process the request queue. - APIRequest req; - while (queue.TryPeek(out req)) + APIRequest req = null; + + lock (queue) + if (queue.Count > 0) + req = queue.Dequeue(); + + if (req != null) { - if (handleRequest(req)) - { - //we have succeeded, so let's unqueue. - queue.TryDequeue(out req); - } + // TODO: handle failures better + handleRequest(req); } - Thread.Sleep(1); + Thread.Sleep(50); } } @@ -205,7 +203,8 @@ namespace osu.Game.Online.API } catch (WebException we) { - HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); + HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode + ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); // special cases for un-typed but useful message responses. switch (we.Message) @@ -247,6 +246,7 @@ namespace osu.Game.Online.API } private APIState state; + public APIState State { get { return state; } @@ -271,7 +271,10 @@ namespace osu.Game.Online.API public bool IsLoggedIn => LocalUser.Value.Id > 1; - public void Queue(APIRequest request) => queue.Enqueue(request); + public void Queue(APIRequest request) + { + lock (queue) queue.Enqueue(request); + } public event StateChangeDelegate OnStateChange; @@ -279,16 +282,17 @@ namespace osu.Game.Online.API private void flushQueue(bool failOldRequests = true) { - var oldQueue = queue; - - //flush the queue. - queue = new ConcurrentQueue(); - - if (failOldRequests) + lock (queue) { - APIRequest req; - while (oldQueue.TryDequeue(out req)) - req.Fail(new WebException(@"Disconnected from server")); + var oldQueueRequests = queue.ToArray(); + + queue.Clear(); + + if (failOldRequests) + { + foreach (var req in oldQueueRequests) + req.Fail(new WebException(@"Disconnected from server")); + } } } From 562a792a9957e92ba82c78f0e3fff1b25428f20b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Sep 2018 13:00:55 +0900 Subject: [PATCH 11/35] Use thread instead of LongRunning for API --- osu.Game/Online/API/APIAccess.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index ff5247e8f6..eb9a60115f 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Threading; -using System.Threading.Tasks; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Logging; @@ -54,7 +53,13 @@ namespace osu.Game.Online.API authentication.TokenString = config.Get(OsuSetting.Token); authentication.Token.ValueChanged += onTokenChanged; - Task.Factory.StartNew(run, cancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + var thread = new Thread(run) + { + Name = "APIAccess", + IsBackground = true + }; + + thread.Start(); } private void onTokenChanged(OAuthToken token) => config.Set(OsuSetting.Token, config.Get(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty); From d9e9c61731d1deac746c831b94724ba52172dc7d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Sep 2018 17:39:54 +0900 Subject: [PATCH 12/35] Begin loading fonts earlier in startup Should result in a considerably faster font load, as they can be concurrently loaded alongside EF. --- osu.Game/OsuGameBase.cs | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index bada2a794d..6987b6eea7 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -114,31 +114,8 @@ namespace osu.Game dependencies.CacheAs(this); dependencies.Cache(LocalConfig); - runMigrations(); - - dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); - dependencies.CacheAs(SkinManager); - - var api = new APIAccess(LocalConfig); - - dependencies.Cache(api); - dependencies.CacheAs(api); - - dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); - dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); - dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host)); - dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore)); - dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); - dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); - dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); - dependencies.Cache(new OsuColour()); - - fileImporters.Add(BeatmapManager); - fileImporters.Add(ScoreStore); - fileImporters.Add(SkinManager); - //this completely overrides the framework default. will need to change once we make a proper FontStore. - dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }); + dependencies.Cache(Fonts = new FontStore()); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); @@ -164,6 +141,29 @@ namespace osu.Game Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Light")); + runMigrations(); + + dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); + dependencies.CacheAs(SkinManager); + + var api = new APIAccess(LocalConfig); + + dependencies.Cache(api); + dependencies.CacheAs(api); + + dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); + dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); + dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host)); + dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore)); + dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); + dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); + dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); + dependencies.Cache(new OsuColour()); + + fileImporters.Add(BeatmapManager); + fileImporters.Add(ScoreStore); + fileImporters.Add(SkinManager); + var defaultBeatmap = new DummyWorkingBeatmap(this); beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); BeatmapManager.DefaultBeatmap = defaultBeatmap; From 923acfbeaf5d49a643c047a90a1d0be1bf112316 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 10:23:23 +0900 Subject: [PATCH 13/35] Fix some web requests being run after disposal of their owner --- .../BeatmapSet/Scores/ScoresContainer.cs | 2 +- .../Beatmaps/PaginatedBeatmapContainer.cs | 17 +++++++++++------ .../PaginatedMostPlayedBeatmapContainer.cs | 18 +++++++++++++----- .../Profile/Sections/PaginatedContainer.cs | 1 + .../Sections/Ranks/PaginatedScoreContainer.cs | 16 +++++++++++----- .../Recent/PaginatedRecentActivityContainer.cs | 17 ++++++++++++----- osu.Game/Overlays/UserProfileOverlay.cs | 15 +++++++-------- 7 files changed, 56 insertions(+), 30 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 626de14c98..6cb85c778b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores loading = true; getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += r => Scores = r.Scores; + getScoresRequest.Success += r => Schedule(() => Scores = r.Scores); api.Queue(getScoresRequest); } } diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 0b06acd426..621f752b9c 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -14,8 +14,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps public class PaginatedBeatmapContainer : PaginatedContainer { private const float panel_padding = 10f; - private readonly BeatmapSetType type; + private GetUserBeatmapsRequest request; public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.") : base(user, header, missing) @@ -31,9 +31,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps { base.ShowMore(); - var req = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); - - req.Success += sets => + request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); + request.Success += sets => Schedule(() => { ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); ShowMoreLoading.Hide(); @@ -52,9 +51,15 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets)); ItemsContainer.Add(panel); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 42784682be..ad886c363b 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer { + private GetUserMostPlayedBeatmapsRequest request; + public PaginatedMostPlayedBeatmapContainer(Bindable user) :base(user, "Most Played Beatmaps", "No records. :(") { @@ -24,9 +26,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { base.ShowMore(); - var req = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); - - req.Success += beatmaps => + request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); + request.Success += beatmaps => Schedule(() => { ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); ShowMoreLoading.Hide(); @@ -43,9 +44,16 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount)); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 6dbb9b9ba3..db93fcbc1b 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections protected readonly Bindable User = new Bindable(); protected APIAccess Api; + protected APIRequest RetrievalRequest; protected RulesetStore Rulesets; public PaginatedContainer(Bindable user, string header, string missing) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 707de0a10f..ed82c62e5c 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { private readonly bool includeWeight; private readonly ScoreType type; + private GetUserScoresRequest request; public PaginatedScoreContainer(ScoreType type, Bindable user, string header, string missing, bool includeWeight = false) : base(user, header, missing) @@ -32,9 +33,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { base.ShowMore(); - var req = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); - - req.Success += scores => + request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); + request.Success += scores => Schedule(() => { foreach (var s in scores) s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID)); @@ -66,9 +66,15 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks ItemsContainer.Add(drawableScore); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index ee2f2f5973..fd5eda4e44 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { public class PaginatedRecentActivityContainer : PaginatedContainer { + private GetUserRecentActivitiesRequest request; + public PaginatedRecentActivityContainer(Bindable user, string header, string missing) : base(user, header, missing) { @@ -22,9 +24,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { base.ShowMore(); - var req = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); - - req.Success += activities => + request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); + request.Success += activities => Schedule(() => { ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); ShowMoreLoading.Hide(); @@ -41,9 +42,15 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { ItemsContainer.Add(new DrawableRecentActivity(activity)); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 11b68b0e09..ea077ff645 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -73,16 +73,15 @@ namespace osu.Game.Overlays FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } - public void ShowUser(long userId) - { - if (userId == Header.User.Id) - return; - - ShowUser(new User { Id = userId }); - } + public void ShowUser(long userId) => ShowUser(new User { Id = userId }); public void ShowUser(User user, bool fetchOnline = true) { + Show(); + + if (user.Id == Header?.User.Id) + return; + userReq?.Cancel(); Clear(); lastSection = null; @@ -97,6 +96,7 @@ namespace osu.Game.Overlays new BeatmapsSection(), new KudosuSection() }; + tabs = new ProfileTabControl { RelativeSizeAxes = Axes.X, @@ -161,7 +161,6 @@ namespace osu.Game.Overlays userLoadComplete(user); } - Show(); sectionsContainer.ScrollToTop(); } From da3eb18784fcdcd4380ebc6cde38a83b4ddca51a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 10:38:05 +0900 Subject: [PATCH 14/35] Fix the toolbar being visible during startup causing a weird offset --- osu.Game/Overlays/Toolbar/Toolbar.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 2eabf1eb74..cdc3bc2b51 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -83,14 +83,14 @@ namespace osu.Game.Overlays.Toolbar [BackgroundDependencyLoader(true)] private void load(OsuGame osuGame) { - if (osuGame != null) - overlayActivationMode.BindTo(osuGame.OverlayActivationMode); - StateChanged += visibility => { if (overlayActivationMode == OverlayActivation.Disabled) State = Visibility.Hidden; }; + + if (osuGame != null) + overlayActivationMode.BindTo(osuGame.OverlayActivationMode); } public class ToolbarBackground : Container From 581da108fc2c348dae73486e18d828f340d1fe41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 11:32:38 +0900 Subject: [PATCH 15/35] Rewrite to not suck --- .../Sections/Graphics/LayoutSettings.cs | 57 ++++++------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 14680bc7cb..4d3cdacb6a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -19,13 +19,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable letterboxing; private Bindable sizeFullscreen; - private readonly BindableInt resolutionDropdownBindable = new BindableInt(); private OsuGameBase game; - private SettingsDropdown resolutionDropdown; + private SettingsDropdown resolutionDropdown; private SettingsEnumDropdown windowModeDropdown; - private const int transition_duration = 400; [BackgroundDependencyLoader] @@ -36,25 +34,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); - sizeFullscreen.ValueChanged += size => - { - KeyValuePair valuePair = getResolutions().FirstOrDefault(r => r.Key.StartsWith($"{size.Width}x{size.Height}")); - - resolutionDropdownBindable.Value = valuePair.Value; - }; - - resolutionDropdownBindable.ValueChanged += resolution => - { - var newSelection = getResolutions().First(r => r.Value == resolution); - var newSelectionParts = newSelection.Key.Split('x'); - - var newSelectionWidth = int.Parse(newSelectionParts.First()); - var newSelectionHeight = int.Parse(newSelectionParts.Last()); - - if (sizeFullscreen.Value.Width != newSelectionWidth || sizeFullscreen.Value.Height != newSelectionHeight) - sizeFullscreen.Value = new Size(newSelectionWidth, newSelectionHeight); - }; - Children = new Drawable[] { windowModeDropdown = new SettingsEnumDropdown @@ -62,11 +41,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "Screen mode", Bindable = config.GetBindable(FrameworkSetting.WindowMode), }, - resolutionDropdown = new SettingsDropdown + resolutionDropdown = new SettingsDropdown { LabelText = "Resolution", + ShowsDefaultIndicator = false, Items = getResolutions(), - Bindable = resolutionDropdownBindable + Bindable = sizeFullscreen }, new SettingsCheckbox { @@ -100,7 +80,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; - windowModeDropdown.Bindable.ValueChanged += windowMode => + windowModeDropdown.Bindable.BindValueChanged(windowMode => { if (windowMode == WindowMode.Fullscreen) { @@ -109,31 +89,30 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } else resolutionDropdown.Hide(); - }; - windowModeDropdown.Bindable.TriggerChange(); + }, true); - letterboxing.ValueChanged += isVisible => + letterboxing.BindValueChanged(isVisible => { letterboxSettings.ClearTransforms(); letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None; if (!isVisible) letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); - }; - letterboxing.TriggerChange(); + }, true); } - private List> getResolutions() + private List> getResolutions() { - var availableDisplayResolutions = game.Window?.GetCurrentDisplay().AvailableResolutions - .Where(r => r.Width >= 800 && r.Height >= 600) - .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + if (game.Window == null) + return new List>(); - if (availableDisplayResolutions == null) - return new List>(); - - var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct(); - return availableDisplayResolutionsStr.Select((t, i) => new KeyValuePair(t, i)).ToList(); + return game.Window?.AvailableResolutions + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width) + .ThenByDescending(r => r.Height) + .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) + .Distinct() + .ToList(); } } } From 77455e44635f1358aa9012d6f2389914a3523280 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 4 Sep 2018 19:44:49 -0700 Subject: [PATCH 16/35] Fix direct list play button disappearing after preview/switch --- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 322db0b7d6..8a22ff7587 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -187,7 +187,7 @@ namespace osu.Game.Overlays.Direct base.LoadComplete(); this.FadeInFromZero(200, Easing.Out); - PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered ? 1 : 0, 120, Easing.InOutQuint); + PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint); PreviewPlaying.ValueChanged += newValue => PreviewBar.FadeTo(newValue ? 1 : 0, 120, Easing.InOutQuint); } From d5acc96efaefcf8fca81fd67bcf49c1a67bec7e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Sep 2018 14:59:37 +0900 Subject: [PATCH 17/35] Apply changes in line with osu!framework changes --- osu.Game/Graphics/DrawableDate.cs | 2 -- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 24 ------------------- osu.Game/OsuGameBase.cs | 3 +-- osu.Game/Overlays/Settings/SettingsSection.cs | 2 +- .../Drawables/DrawableStoryboard.cs | 2 +- 5 files changed, 3 insertions(+), 30 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 406fc2ffd2..be794d93a6 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -4,7 +4,6 @@ using System; using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Sprites; @@ -16,7 +15,6 @@ namespace osu.Game.Graphics public DrawableDate(DateTimeOffset date) { - AutoSizeAxes = Axes.Both; Font = "Exo2.0-RegularItalic"; Date = date.ToLocalTime(); diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index c9389bb9e2..8607d51e12 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -3,9 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Graphics.Transforms; namespace osu.Game.Graphics.Sprites @@ -19,27 +16,6 @@ namespace osu.Game.Graphics.Sprites Shadow = true; TextSize = FONT_SIZE; } - - protected override Drawable CreateFallbackCharacterDrawable() - { - var tex = GetTextureForCharacter('?'); - - if (tex != null) - { - float adjust = (RNG.NextSingle() - 0.5f) * 2; - return new Sprite - { - Texture = tex, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Scale = new Vector2(1 + adjust * 0.2f), - Rotation = adjust * 15, - Colour = Color4.White, - }; - } - - return base.CreateFallbackCharacterDrawable(); - } } public static class OsuSpriteTextTransformExtensions diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index bada2a794d..29072523f3 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -138,9 +138,8 @@ namespace osu.Game fileImporters.Add(SkinManager); //this completely overrides the framework default. will need to change once we make a proper FontStore. - dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }); + dependencies.Cache(Fonts = new FontStore(new GlyphStore(Resources, @"Fonts/FontAwesome"))); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic")); diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 9555f0fbc5..58714208c0 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Settings }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Children = new[] + Children = new Drawable[] { new OsuSpriteText { diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index d746bb90c4..c5a9514095 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -57,7 +57,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(FileStore fileStore) { - dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, }); + dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) Add(layer.CreateDrawable()); From c03d1d9566cdb95507358af2c89ec84ea415b4b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 16:45:30 +0900 Subject: [PATCH 18/35] Attempt to fix CI failures on CatcherArea.Explode --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 4327abb96f..5802f64b96 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.UI // this is required to make this run after the last caught fruit runs UpdateState at least once. // TODO: find a better alternative - if (lastPlateableFruit.IsLoaded) + if (lastPlateableFruit.LoadState > LoadState.Ready) action(); else lastPlateableFruit.OnLoadComplete = _ => action(); @@ -407,9 +407,7 @@ namespace osu.Game.Rulesets.Catch.UI /// public void Explode() { - var fruit = caughtFruit.ToArray(); - - foreach (var f in fruit) + foreach (var f in caughtFruit.ToArray()) Explode(f); } @@ -422,15 +420,15 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Anchor = Anchor.TopLeft; fruit.Position = caughtFruit.ToSpaceOfOtherDrawable(fruit.DrawPosition, ExplodingFruitTarget); - caughtFruit.Remove(fruit); + if (!caughtFruit.Remove(fruit)) + // we may have already been removed by a previous operation (due to the weird OnLoadComplete scheduling). + // this avoids a crash on potentially attempting to Add a fruit to ExplodingFruitTarget twice. + return; ExplodingFruitTarget.Add(fruit); } - fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine) - .Then() - .MoveToY(fruit.Y + 50, 500, Easing.InSine); - + fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine).Then().MoveToY(fruit.Y + 50, 500, Easing.InSine); fruit.MoveToX(fruit.X + originalX * 6, 1000); fruit.FadeOut(750); From 8d9e0ff1c34ce62d7660db1fd2ea68e4deb60ab0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 12:51:23 +0900 Subject: [PATCH 19/35] Remove async WorkingBeatmap logic --- osu.Game/Beatmaps/WorkingBeatmap.cs | 146 ++++++++++++---------------- 1 file changed, 62 insertions(+), 84 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 085c591fce..85b98413e5 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -8,10 +8,10 @@ using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using osu.Game.Storyboards; using osu.Framework.IO.File; using System.IO; +using System.Threading; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; @@ -38,12 +38,26 @@ namespace osu.Game.Beatmaps Mods.ValueChanged += mods => applyRateAdjustments(); - beatmap = new AsyncLazy(populateBeatmap); - background = new AsyncLazy(populateBackground, b => b == null || !b.IsDisposed); - track = new AsyncLazy(populateTrack); - waveform = new AsyncLazy(populateWaveform); - storyboard = new AsyncLazy(populateStoryboard); - skin = new AsyncLazy(populateSkin); + beatmap = new RecyclableLazy(() => + { + var b = GetBeatmap() ?? new Beatmap(); + // use the database-backed info. + b.BeatmapInfo = BeatmapInfo; + return b; + }); + + track = new RecyclableLazy(() => + { + // we want to ensure that we always have a track, even if it's a fake one. + var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap); + applyRateAdjustments(t); + return t; + }); + + background = new RecyclableLazy(GetBackground, BackgroundStillValid); + waveform = new RecyclableLazy(GetWaveform); + storyboard = new RecyclableLazy(GetStoryboard); + skin = new RecyclableLazy(GetSkin); } /// @@ -58,28 +72,6 @@ namespace osu.Game.Beatmaps return path; } - protected abstract IBeatmap GetBeatmap(); - protected abstract Texture GetBackground(); - protected abstract Track GetTrack(); - protected virtual Skin GetSkin() => new DefaultSkin(); - protected virtual Waveform GetWaveform() => new Waveform(); - protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; - - public bool BeatmapLoaded => beatmap.IsResultAvailable; - public IBeatmap Beatmap => beatmap.Value.Result; - public Task GetBeatmapAsync() => beatmap.Value; - private readonly AsyncLazy beatmap; - - private IBeatmap populateBeatmap() - { - var b = GetBeatmap() ?? new Beatmap(); - - // use the database-backed info. - b.BeatmapInfo = BeatmapInfo; - - return b; - } - /// /// Constructs a playable from using the applicable converters for a specific . /// @@ -136,62 +128,53 @@ namespace osu.Game.Beatmaps public override string ToString() => BeatmapInfo.ToString(); - public bool BackgroundLoaded => background.IsResultAvailable; - public Texture Background => background.Value.Result; - public Task GetBackgroundAsync() => background.Value; - private AsyncLazy background; + public bool BeatmapLoaded => beatmap.IsResultAvailable; + public IBeatmap Beatmap => beatmap.Value; + protected abstract IBeatmap GetBeatmap(); + private readonly RecyclableLazy beatmap; - private Texture populateBackground() => GetBackground(); + public bool BackgroundLoaded => background.IsResultAvailable; + public Texture Background => background.Value; + protected virtual bool BackgroundStillValid(Texture b) => b == null || !b.IsDisposed; + protected abstract Texture GetBackground(); + private readonly RecyclableLazy background; public bool TrackLoaded => track.IsResultAvailable; - public Track Track => track.Value.Result; - public Task GetTrackAsync() => track.Value; - private AsyncLazy track; - - private Track populateTrack() - { - // we want to ensure that we always have a track, even if it's a fake one. - var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap); - applyRateAdjustments(t); - return t; - } + public Track Track => track.Value; + protected abstract Track GetTrack(); + private RecyclableLazy track; public bool WaveformLoaded => waveform.IsResultAvailable; - public Waveform Waveform => waveform.Value.Result; - public Task GetWaveformAsync() => waveform.Value; - private readonly AsyncLazy waveform; - - private Waveform populateWaveform() => GetWaveform(); + public Waveform Waveform => waveform.Value; + protected virtual Waveform GetWaveform() => new Waveform(); + private readonly RecyclableLazy waveform; public bool StoryboardLoaded => storyboard.IsResultAvailable; - public Storyboard Storyboard => storyboard.Value.Result; - public Task GetStoryboardAsync() => storyboard.Value; - private readonly AsyncLazy storyboard; - - private Storyboard populateStoryboard() => GetStoryboard(); + public Storyboard Storyboard => storyboard.Value; + protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; + private readonly RecyclableLazy storyboard; public bool SkinLoaded => skin.IsResultAvailable; - public Skin Skin => skin.Value.Result; - public Task GetSkinAsync() => skin.Value; - private readonly AsyncLazy skin; + public Skin Skin => skin.Value; + protected virtual Skin GetSkin() => new DefaultSkin(); + private readonly RecyclableLazy skin; - private Skin populateSkin() => GetSkin(); - - public void TransferTo(WorkingBeatmap other) + /// + /// Transfer pieces of a beatmap to a new one, where possible, to save on loading. + /// + /// The new beatmap which is being switched to. + public virtual void TransferTo(WorkingBeatmap other) { if (track.IsResultAvailable && Track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo)) other.track = track; - - if (background.IsResultAvailable && Background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo)) - other.background = background; } public virtual void Dispose() { - if (BackgroundLoaded) Background?.Dispose(); - if (WaveformLoaded) Waveform?.Dispose(); - if (StoryboardLoaded) Storyboard?.Dispose(); - if (SkinLoaded) Skin?.Dispose(); + background.Recycle(); + waveform.Recycle(); + storyboard.Recycle(); + skin.Recycle(); } /// @@ -210,15 +193,15 @@ namespace osu.Game.Beatmaps mod.ApplyToClock(t); } - public class AsyncLazy + public class RecyclableLazy { - private Lazy> lazy; + private Lazy lazy; private readonly Func valueFactory; private readonly Func stillValidFunction; private readonly object initLock = new object(); - public AsyncLazy(Func valueFactory, Func stillValidFunction = null) + public RecyclableLazy(Func valueFactory, Func stillValidFunction = null) { this.valueFactory = valueFactory; this.stillValidFunction = stillValidFunction; @@ -230,20 +213,13 @@ namespace osu.Game.Beatmaps { if (!IsResultAvailable) return; - (lazy.Value.Result as IDisposable)?.Dispose(); + (lazy.Value as IDisposable)?.Dispose(); recreate(); } - public bool IsResultAvailable - { - get - { - recreateIfInvalid(); - return lazy.Value.IsCompleted; - } - } + public bool IsResultAvailable => stillValid; - public Task Value + public T Value { get { @@ -252,15 +228,17 @@ namespace osu.Game.Beatmaps } } + private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true); + private void recreateIfInvalid() { lock (initLock) { - if (!lazy.IsValueCreated || !lazy.Value.IsCompleted) + if (!lazy.IsValueCreated) // we have not yet been initialised or haven't run the task. return; - if (stillValidFunction?.Invoke(lazy.Value.Result) ?? true) + if (stillValid) // we are still in a valid state. return; @@ -268,7 +246,7 @@ namespace osu.Game.Beatmaps } } - private void recreate() => lazy = new Lazy>(() => Task.Run(valueFactory)); + private void recreate() => lazy = new Lazy(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication); } } } From 65018705f43bc99465572c1e983794365e784ff5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:09:57 +0900 Subject: [PATCH 20/35] Restore IsLoaded check --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 5802f64b96..9460512a8d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.UI // this is required to make this run after the last caught fruit runs UpdateState at least once. // TODO: find a better alternative - if (lastPlateableFruit.LoadState > LoadState.Ready) + if (lastPlateableFruit.IsLoaded) action(); else lastPlateableFruit.OnLoadComplete = _ => action(); From 89a92ab7eb15c86130a7127aaa7e79b75c48d0dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:27:53 +0900 Subject: [PATCH 21/35] Fix potential thread-safety issue --- osu.Game/Beatmaps/WorkingBeatmap.cs | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 85b98413e5..a2b44aab52 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -199,7 +199,7 @@ namespace osu.Game.Beatmaps private readonly Func valueFactory; private readonly Func stillValidFunction; - private readonly object initLock = new object(); + private readonly object fetchLock = new object(); public RecyclableLazy(Func valueFactory, Func stillValidFunction = null) { @@ -223,29 +223,17 @@ namespace osu.Game.Beatmaps { get { - recreateIfInvalid(); - return lazy.Value; + lock (fetchLock) + { + if (!stillValid) + recreate(); + return lazy.Value; + } } } private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true); - private void recreateIfInvalid() - { - lock (initLock) - { - if (!lazy.IsValueCreated) - // we have not yet been initialised or haven't run the task. - return; - - if (stillValid) - // we are still in a valid state. - return; - - recreate(); - } - } - private void recreate() => lazy = new Lazy(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication); } } From 29b0d62f213441c668572f56eee01bed9d663af5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:15:43 +0900 Subject: [PATCH 22/35] Changes in line with framework refcount changes --- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 15 +++++++++++++-- osu.Game/Graphics/Backgrounds/Background.cs | 2 +- .../Graphics/Textures/LargeTextureStore.cs | 18 ------------------ osu.Game/OsuGameBase.cs | 3 +-- osu.Game/Screens/Tournament/Drawings.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- .../Drawables/DrawableStoryboard.cs | 4 +++- 7 files changed, 20 insertions(+), 26 deletions(-) delete mode 100644 osu.Game/Graphics/Textures/LargeTextureStore.cs diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 43ae30f780..77ff53b893 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Game.Beatmaps.Formats; -using osu.Game.Graphics.Textures; using osu.Game.Skinning; using osu.Game.Storyboards; @@ -45,6 +44,10 @@ namespace osu.Game.Beatmaps private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath; + private LargeTextureStore textureStore; + + protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes. + protected override Texture GetBackground() { if (Metadata?.BackgroundFile == null) @@ -52,7 +55,7 @@ namespace osu.Game.Beatmaps try { - return new LargeTextureStore(new RawTextureLoaderStore(store)).Get(getPathForFile(Metadata.BackgroundFile)); + return (textureStore ?? (textureStore = new LargeTextureStore(new TextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile)); } catch { @@ -73,6 +76,14 @@ namespace osu.Game.Beatmaps } } + public override void TransferTo(WorkingBeatmap other) + { + base.TransferTo(other); + + if (other is BeatmapManagerWorkingBeatmap owb && textureStore != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo)) + owb.textureStore = textureStore; + } + protected override Waveform GetWaveform() { try diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index d5825a8c42..6fc8b0e070 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -5,8 +5,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using OpenTK.Graphics; -using osu.Game.Graphics.Textures; namespace osu.Game.Graphics.Backgrounds { diff --git a/osu.Game/Graphics/Textures/LargeTextureStore.cs b/osu.Game/Graphics/Textures/LargeTextureStore.cs deleted file mode 100644 index 4dcbb1220d..0000000000 --- a/osu.Game/Graphics/Textures/LargeTextureStore.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics.Textures; -using osu.Framework.IO.Stores; - -namespace osu.Game.Graphics.Textures -{ - /// - /// A texture store that bypasses atlasing. - /// - public class LargeTextureStore : TextureStore - { - public LargeTextureStore(IResourceStore store = null) : base(store, false) - { - } - } -} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index bada2a794d..e3ce7a19f1 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -24,7 +24,6 @@ using osu.Framework.Input; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Database; -using osu.Game.Graphics.Textures; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; @@ -109,7 +108,7 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); + dependencies.Cache(new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); dependencies.CacheAs(this); dependencies.Cache(LocalConfig); diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 63d29d5cd7..4e2109afd0 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Tournament TextureStore flagStore = new TextureStore(); // Local flag store - flagStore.AddStore(new RawTextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); + flagStore.AddStore(new TextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); // Default texture store flagStore.AddStore(textures); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9c881c6abb..ce7edf8683 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); Samples = audioManager.GetSampleManager(storage); - Textures = new TextureStore(new RawTextureLoaderStore(storage)); + Textures = new TextureStore(new TextureLoaderStore(storage)); } public override Drawable GetDrawableComponent(string componentName) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index d746bb90c4..8053a7413c 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -22,6 +22,7 @@ namespace osu.Game.Storyboards.Drawables public override bool HandleMouseInput => false; private bool passing = true; + public bool Passing { get { return passing; } @@ -36,6 +37,7 @@ namespace osu.Game.Storyboards.Drawables public override bool RemoveCompletedTransforms => false; private DependencyContainer dependencies; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -57,7 +59,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(FileStore fileStore) { - dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, }); + dependencies.Cache(new TextureStore(new TextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) Add(layer.CreateDrawable()); From e63f60231a408162d0f41ddc733363cc0fbd0a11 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:27:17 +0900 Subject: [PATCH 23/35] Optimise carousel memory usage by unloading off-screen panels --- osu.Game/Screens/Select/BeatmapCarousel.cs | 11 ++++++++++- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 9 +++++++-- .../Screens/Select/Carousel/DrawableCarouselItem.cs | 13 ++++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 7bb0b95b9a..4dbfe65ebf 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -424,7 +424,7 @@ namespace osu.Game.Screens.Select float drawHeight = DrawHeight; // Remove all items that should no longer be on-screen - scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent); + scrollableContent.RemoveAll(p => p.CanBeRemoved && (p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent)); // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); @@ -486,6 +486,15 @@ namespace osu.Game.Screens.Select updateItem(p, halfHeight); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + // aggressively dispose "off-screen" items to reduce GC pressure. + foreach (var i in Items) + i.Dispose(); + } + private CarouselBeatmapSet createCarouselSet(BeatmapSetInfo beatmapSet) { if (beatmapSet.Beatmaps.All(b => b.Hidden)) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index d554a22735..3fcea908a0 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -30,6 +30,7 @@ namespace osu.Game.Screens.Select.Carousel private DialogOverlay dialogOverlay; private readonly BeatmapSetInfo beatmapSet; + private DelayedLoadUnloadWrapper delayed; public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) : base(set) @@ -37,6 +38,10 @@ namespace osu.Game.Screens.Select.Carousel beatmapSet = set.BeatmapSet; } + public override bool CanBeRemoved => delayed?.DelayedLoadCompleted != true; + + protected override bool RequiresChildrenUpdate => true; + [BackgroundDependencyLoader(true)] private void load(LocalisationEngine localisation, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { @@ -50,12 +55,12 @@ namespace osu.Game.Screens.Select.Carousel Children = new Drawable[] { - new DelayedLoadWrapper( + delayed = new DelayedLoadUnloadWrapper(() => new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) { RelativeSizeAxes = Axes.Both, OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint), - }, 300 + }, 300, 5000 ), new FillFlowContainer { diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 8a0052559e..5bcf4e6441 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -24,6 +24,11 @@ namespace osu.Game.Screens.Select.Carousel public override bool IsPresent => base.IsPresent || Item.Visible; + /// + /// Whether this item can be removed from the scroll container (usually due to being off-screen). + /// + public virtual bool CanBeRemoved => true; + public readonly CarouselItem Item; private Container nestedContainer; @@ -86,7 +91,13 @@ namespace osu.Game.Screens.Select.Carousel base.OnHoverLost(state); } - public void SetMultiplicativeAlpha(float alpha) => borderContainer.Alpha = alpha; + protected bool VisibleInCarousel; + + public void SetMultiplicativeAlpha(float alpha) + { + borderContainer.Alpha = alpha; + VisibleInCarousel = alpha > 0; + } protected override void LoadComplete() { From 91aada8be59b227938f10a4c782bc9f719209037 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 14:20:29 +0900 Subject: [PATCH 24/35] Fix ScaleAdjust going missing --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 6987b6eea7..5e93c2547d 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -115,7 +115,7 @@ namespace osu.Game dependencies.Cache(LocalConfig); //this completely overrides the framework default. will need to change once we make a proper FontStore. - dependencies.Cache(Fonts = new FontStore()); + dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); From ccd7c1a17d10e43d5467c99197d7f6d54ef01181 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:04:33 +0900 Subject: [PATCH 25/35] Cancel request on disposal for safety --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 6cb85c778b..60811d8b12 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -134,5 +134,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores this.api = api; updateDisplay(); } + + protected override void Dispose(bool isDisposing) + { + getScoresRequest?.Cancel(); + } } } From c23b9b61a814e570635da4d08eb9fde16efb799b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:27:21 +0900 Subject: [PATCH 26/35] Simplify implementation in line with framework improvements --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 7 +------ .../Screens/Select/Carousel/DrawableCarouselItem.cs | 13 +------------ 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 4dbfe65ebf..b6cbaf45e9 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -424,7 +424,7 @@ namespace osu.Game.Screens.Select float drawHeight = DrawHeight; // Remove all items that should no longer be on-screen - scrollableContent.RemoveAll(p => p.CanBeRemoved && (p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent)); + scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent); // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 3fcea908a0..23f338b530 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -30,7 +30,6 @@ namespace osu.Game.Screens.Select.Carousel private DialogOverlay dialogOverlay; private readonly BeatmapSetInfo beatmapSet; - private DelayedLoadUnloadWrapper delayed; public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) : base(set) @@ -38,10 +37,6 @@ namespace osu.Game.Screens.Select.Carousel beatmapSet = set.BeatmapSet; } - public override bool CanBeRemoved => delayed?.DelayedLoadCompleted != true; - - protected override bool RequiresChildrenUpdate => true; - [BackgroundDependencyLoader(true)] private void load(LocalisationEngine localisation, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { @@ -55,7 +50,7 @@ namespace osu.Game.Screens.Select.Carousel Children = new Drawable[] { - delayed = new DelayedLoadUnloadWrapper(() => + new DelayedLoadUnloadWrapper(() => new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 5bcf4e6441..8a0052559e 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -24,11 +24,6 @@ namespace osu.Game.Screens.Select.Carousel public override bool IsPresent => base.IsPresent || Item.Visible; - /// - /// Whether this item can be removed from the scroll container (usually due to being off-screen). - /// - public virtual bool CanBeRemoved => true; - public readonly CarouselItem Item; private Container nestedContainer; @@ -91,13 +86,7 @@ namespace osu.Game.Screens.Select.Carousel base.OnHoverLost(state); } - protected bool VisibleInCarousel; - - public void SetMultiplicativeAlpha(float alpha) - { - borderContainer.Alpha = alpha; - VisibleInCarousel = alpha > 0; - } + public void SetMultiplicativeAlpha(float alpha) => borderContainer.Alpha = alpha; protected override void LoadComplete() { From d05cd52d9aecc3e2cc3bf888291e413167bda555 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:38:15 +0900 Subject: [PATCH 27/35] Run the queue faster if multiple requests are pending --- osu.Game/Online/API/APIAccess.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index eb9a60115f..1dda257c95 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -163,14 +163,16 @@ namespace osu.Game.Online.API continue; } - APIRequest req = null; - - lock (queue) - if (queue.Count > 0) - req = queue.Dequeue(); - - if (req != null) + while (true) { + APIRequest req; + + lock (queue) + { + if (queue.Count == 0) break; + req = queue.Dequeue(); + } + // TODO: handle failures better handleRequest(req); } From 4e012042ab55d85af59f4c5cccd9a2abf3570956 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:57:09 +0900 Subject: [PATCH 28/35] Fix renaming variables too eagerly --- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Screens/Tournament/Drawings.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Storyboards/Drawables/DrawableStoryboard.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 77ff53b893..cc70aa783f 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps try { - return (textureStore ?? (textureStore = new LargeTextureStore(new TextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile)); + return (textureStore ?? (textureStore = new LargeTextureStore(new RawTextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile)); } catch { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index e3ce7a19f1..a72abb8d4e 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -108,7 +108,7 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - dependencies.Cache(new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); + dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); dependencies.CacheAs(this); dependencies.Cache(LocalConfig); diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 4e2109afd0..63d29d5cd7 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Tournament TextureStore flagStore = new TextureStore(); // Local flag store - flagStore.AddStore(new TextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); + flagStore.AddStore(new RawTextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); // Default texture store flagStore.AddStore(textures); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ce7edf8683..9c881c6abb 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); Samples = audioManager.GetSampleManager(storage); - Textures = new TextureStore(new TextureLoaderStore(storage)); + Textures = new TextureStore(new RawTextureLoaderStore(storage)); } public override Drawable GetDrawableComponent(string componentName) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 8053a7413c..d0d4c678bf 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -59,7 +59,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(FileStore fileStore) { - dependencies.Cache(new TextureStore(new TextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); + dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) Add(layer.CreateDrawable()); From 9f67119ba90244dbdc5fb5b2dd43c2c7d74f6db7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 18:01:32 +0900 Subject: [PATCH 29/35] Fix potential nullref in IsPresent override --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index e69f340184..10cd246172 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt; + public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Clock?.CurrentTime >= HitObject.StartTime - HitObject.TimePreempt; private readonly ShakeContainer shakeContainer; From a1780fddc98fec5c353bf52cb23fe70606739655 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 18:02:04 +0900 Subject: [PATCH 30/35] DrawInfo -> DrawColourInfo --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 4 ++-- osu.Game/Graphics/SpriteIcon.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index abcd1ddbda..4a6b12d41a 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Texture.DrawQuad( new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y), - DrawInfo.Colour, + DrawColourInfo.Colour, null, v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex { diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 01b09c0a40..0f382900ce 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -116,7 +116,7 @@ namespace osu.Game.Graphics.Backgrounds float adjustedAlpha = HideAlphaDiscrepancies ? // Cubically scale alpha to make it drop off more sharply. - (float)Math.Pow(DrawInfo.Colour.AverageColour.Linear.A, 3) : + (float)Math.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) : 1; float elapsedSeconds = (float)Time.Elapsed / 1000; @@ -235,7 +235,7 @@ namespace osu.Game.Graphics.Backgrounds Vector2Extensions.Transform(particle.Position * Size + new Vector2(-offset.X, offset.Y), DrawInfo.Matrix) ); - ColourInfo colourInfo = DrawInfo.Colour; + ColourInfo colourInfo = DrawColourInfo.Colour; colourInfo.ApplyChild(particle.Colour); Texture.DrawTriangle( diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index b72ba7e02f..1b1df45c77 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -95,7 +95,7 @@ namespace osu.Game.Graphics { //adjust shadow alpha based on highest component intensity to avoid muddy display of darker text. //squared result for quadratic fall-off seems to give the best result. - var avgColour = (Color4)DrawInfo.Colour.AverageColour; + var avgColour = (Color4)DrawColourInfo.Colour.AverageColour; spriteShadow.Alpha = (float)Math.Pow(Math.Max(Math.Max(avgColour.R, avgColour.G), avgColour.B), 2); diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index fb6130fa36..a3cb2f13d0 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Menu Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy; - ColourInfo colourInfo = DrawInfo.Colour; + ColourInfo colourInfo = DrawColourInfo.Colour; colourInfo.ApplyChild(Colour); if (AudioData != null) From da906c0ddf43f6c896f6e27cfe93d82d9f598e9e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 18:03:27 +0900 Subject: [PATCH 31/35] 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 669b775674..b3df528043 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 1327aed16411a5030a49a9eef4cda420ffc033c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 19:23:19 +0900 Subject: [PATCH 32/35] Update framework again --- 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 b3df528043..cb553731c3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From a2ba68d147e99b736df230b0dfa48dc0bf4cd103 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 03:18:39 +0900 Subject: [PATCH 33/35] Mention LD_LIBRARY_PATH requirement for linux building in README Closes #3257. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a1f478e39a..dc36145337 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,9 @@ Clone the repository including submodules Build and run - Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included) -- From command line using `dotnet run --project osu.Desktop` +- From command line using `dotnet run --project osu.Desktop`. When building for non-development purposes, add `-c Release` to gain higher performance. + +Note: If you run from command line under linux, you will need to prefix the output folder to your `LD_LIBRARY_PATH`. See `.vscode/launch.json` for an example If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build. From f76d00e8aee43920d978e6551d3c0b52e7312ee7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 14:31:38 +0900 Subject: [PATCH 34/35] Simplify null checks --- .../Sections/Graphics/LayoutSettings.cs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 4d3cdacb6a..0c463ce142 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -101,18 +101,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, true); } - private List> getResolutions() - { - if (game.Window == null) - return new List>(); - - return game.Window?.AvailableResolutions - .Where(r => r.Width >= 800 && r.Height >= 600) - .OrderByDescending(r => r.Width) - .ThenByDescending(r => r.Height) - .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) - .Distinct() - .ToList(); - } + private IEnumerable> getResolutions() => + game.Window?.AvailableResolutions? + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width) + .ThenByDescending(r => r.Height) + .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) + .Distinct() + .ToList() ?? Enumerable.Empty>(); } } From bf0ad723f594f567124db69804e4c7b743b92733 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 14:35:38 +0900 Subject: [PATCH 35/35] Add default fallback for headless operation --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 0c463ce142..548d49bd36 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -6,6 +6,7 @@ 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; @@ -108,6 +109,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics .ThenByDescending(r => r.Height) .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) .Distinct() - .ToList() ?? Enumerable.Empty>(); + .ToList() ?? new KeyValuePair("Default", new Size(9999, 9999)).Yield(); } }