diff --git a/osu.Game.Tests/Visual/TestCaseOsuGame.cs b/osu.Game.Tests/Visual/TestCaseOsuGame.cs index c527bce683..9e649b92e4 100644 --- a/osu.Game.Tests/Visual/TestCaseOsuGame.cs +++ b/osu.Game.Tests/Visual/TestCaseOsuGame.cs @@ -4,10 +4,10 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Framework.Screens; -using osu.Game.Screens; +using osu.Framework.Platform; using osu.Game.Screens.Menu; using osuTK.Graphics; @@ -21,8 +21,12 @@ namespace osu.Game.Tests.Visual typeof(OsuLogo), }; - public TestCaseOsuGame() + [BackgroundDependencyLoader] + private void load(GameHost host) { + OsuGame game = new OsuGame(); + game.SetHost(host); + Children = new Drawable[] { new Box @@ -30,10 +34,7 @@ namespace osu.Game.Tests.Visual RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - new ScreenStack(new Loader()) - { - RelativeSizeAxes = Axes.Both, - } + game }; } } diff --git a/osu.Game.Tests/Visual/TestCaseSongProgress.cs b/osu.Game.Tests/Visual/TestCaseSongProgress.cs index 9ce33f21d6..9845df7461 100644 --- a/osu.Game.Tests/Visual/TestCaseSongProgress.cs +++ b/osu.Game.Tests/Visual/TestCaseSongProgress.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual public class TestCaseSongProgress : OsuTestCase { private readonly SongProgress progress; - private readonly SongProgressGraph graph; + private readonly TestSongProgressGraph graph; private readonly StopwatchClock clock; @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual Origin = Anchor.BottomLeft, }); - Add(graph = new SongProgressGraph + Add(graph = new TestSongProgressGraph { RelativeSizeAxes = Axes.X, Height = 200, @@ -39,13 +39,24 @@ namespace osu.Game.Tests.Visual Origin = Anchor.TopLeft, }); + AddWaitStep(5); + AddAssert("ensure not created", () => graph.CreationCount == 0); + + AddStep("display values", displayNewValues); + AddWaitStep(5); + AddUntilStep(() => graph.CreationCount == 1, "wait for creation count"); + AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); AddWaitStep(5); + AddUntilStep(() => graph.CreationCount == 1, "wait for creation count"); + AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); - AddWaitStep(2); + AddWaitStep(5); + AddUntilStep(() => graph.CreationCount == 1, "wait for creation count"); AddRepeatStep("New Values", displayNewValues, 5); - displayNewValues(); + AddWaitStep(5); + AddAssert("ensure debounced", () => graph.CreationCount == 2); } private void displayNewValues() @@ -60,5 +71,16 @@ namespace osu.Game.Tests.Visual progress.AudioClock = clock; progress.OnSeek = pos => clock.Seek(pos); } + + private class TestSongProgressGraph : SongProgressGraph + { + public int CreationCount { get; private set; } + + protected override void RecreateGraph() + { + base.RecreateGraph(); + CreationCount++; + } + } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9f6adc373c..59b7120d95 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -626,6 +626,10 @@ namespace osu.Game try { Logger.Log($"Loading {d}...", level: LogLevel.Debug); + + if (IsDisposed) + return; + await LoadComponentAsync(d, add); Logger.Log($"Loaded {d}!", level: LogLevel.Debug); } diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index 58be491daf..e37156b39d 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -63,8 +63,11 @@ namespace osu.Game.Overlays.Direct { base.Dispose(isDisposing); - beatmaps.BeatmapDownloadBegan -= attachDownload; - beatmaps.ItemAdded -= setAdded; + if (beatmaps != null) + { + beatmaps.BeatmapDownloadBegan -= attachDownload; + beatmaps.ItemAdded -= setAdded; + } State.UnbindAll(); diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index d3610b219a..5b8f406dd5 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using osu.Framework; using osu.Framework.Caching; using osu.Framework.Extensions.Color4Extensions; @@ -12,14 +13,16 @@ using osu.Framework.Graphics.Containers; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Framework.Allocation; +using osu.Framework.Threading; namespace osu.Game.Screens.Play { - public class SquareGraph : BufferedContainer + public class SquareGraph : Container { - private Column[] columns = { }; + private BufferedContainer columns; - public int ColumnCount => columns.Length; + public int ColumnCount => columns?.Children.Count ?? 0; private int progress; @@ -65,13 +68,6 @@ namespace osu.Game.Screens.Play } } - public SquareGraph() - { - CacheDrawnFrameBuffer = true; - } - - private Cached layout = new Cached(); - public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { if ((invalidation & Invalidation.DrawSize) > 0) @@ -79,25 +75,70 @@ namespace osu.Game.Screens.Play return base.Invalidate(invalidation, source, shallPropagate); } + private Cached layout = new Cached(); + private ScheduledDelegate scheduledCreate; + protected override void Update() { base.Update(); - if (!layout.IsValid) + if (values != null && !layout.IsValid) { - recreateGraph(); + columns?.FadeOut(500, Easing.OutQuint).Expire(); + + scheduledCreate?.Cancel(); + scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + layout.Validate(); } } + private CancellationTokenSource cts; + + /// + /// Recreates the entire graph. + /// + protected virtual void RecreateGraph() + { + var newColumns = new BufferedContainer + { + CacheDrawnFrameBuffer = true, + RelativeSizeAxes = Axes.Both, + }; + + for (float x = 0; x < DrawWidth; x += Column.WIDTH) + { + newColumns.Add(new Column(DrawHeight) + { + LitColour = fillColour, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Position = new Vector2(x, 0), + State = ColumnState.Dimmed, + }); + } + + cts?.Cancel(); + + LoadComponentAsync(newColumns, c => + { + Child = columns = c; + columns.FadeInFromZero(500, Easing.OutQuint); + + recalculateValues(); + redrawFilled(); + redrawProgress(); + }, (cts = new CancellationTokenSource()).Token); + } + /// /// Redraws all the columns to match their lit/dimmed state. /// private void redrawProgress() { - for (int i = 0; i < columns.Length; i++) + for (int i = 0; i < ColumnCount; i++) columns[i].State = i <= progress ? ColumnState.Lit : ColumnState.Dimmed; - ForceRedraw(); + columns?.ForceRedraw(); } /// @@ -107,7 +148,7 @@ namespace osu.Game.Screens.Play { for (int i = 0; i < ColumnCount; i++) columns[i].Filled = calculatedValues.ElementAtOrDefault(i); - ForceRedraw(); + columns?.ForceRedraw(); } /// @@ -136,34 +177,6 @@ namespace osu.Game.Screens.Play calculatedValues = newValues.ToArray(); } - /// - /// Recreates the entire graph. - /// - private void recreateGraph() - { - var newColumns = new List(); - - for (float x = 0; x < DrawWidth; x += Column.WIDTH) - { - newColumns.Add(new Column - { - LitColour = fillColour, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Height = DrawHeight, - Position = new Vector2(x, 0), - State = ColumnState.Dimmed, - }); - } - - columns = newColumns.ToArray(); - Children = columns; - - recalculateValues(); - redrawFilled(); - redrawProgress(); - } - public class Column : Container, IStateful { protected readonly Color4 EmptyColour = Color4.White.Opacity(20); @@ -210,21 +223,20 @@ namespace osu.Game.Screens.Play } } - public Column() + public Column(float height) { Width = WIDTH; + Height = height; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load() { - for (int r = 0; r < cubeCount; r++) + drawableRows.AddRange(Enumerable.Range(0, (int)cubeCount).Select(r => new Box { - drawableRows.Add(new Box - { - Size = new Vector2(cube_size), - Position = new Vector2(0, r * WIDTH + padding), - }); - } + Size = new Vector2(cube_size), + Position = new Vector2(0, r * WIDTH + padding), + })); Children = drawableRows; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index e98ccd5afe..0c5871f483 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -512,12 +512,6 @@ namespace osu.Game.Screens.Select if (base.OnExiting(next)) return true; - if (ModSelect.State == Visibility.Visible) - { - ModSelect.Hide(); - return true; - } - beatmapInfoWedge.State = Visibility.Hidden; this.FadeOut(100); diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index 16a3405e43..955ef7b65b 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -92,6 +92,9 @@ namespace osu.Game.Skinning protected override void Dispose(bool isDisposing) { + // Must be done before base.Dispose() + SourceChanged = null; + base.Dispose(isDisposing); if (fallbackSource != null) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f464dafd3f..82c23fc491 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index bf38335e0c..f95f42d933 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + +