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/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index ad52c31108..15102edc42 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,16 +13,19 @@ 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; + public int Progress { get { return progress; } @@ -36,6 +40,7 @@ namespace osu.Game.Screens.Play private float[] calculatedValues = { }; // values but adjusted to fit the amount of columns private int[] values; + public int[] Values { get { return values; } @@ -48,6 +53,7 @@ namespace osu.Game.Screens.Play } private Color4 fillColour; + public Color4 FillColour { get { return fillColour; } @@ -59,13 +65,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) @@ -73,25 +72,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(); } /// @@ -101,7 +145,7 @@ namespace osu.Game.Screens.Play { for (int i = 0; i < ColumnCount; i++) columns[i].Filled = calculatedValues.ElementAtOrDefault(i); - ForceRedraw(); + columns?.ForceRedraw(); } /// @@ -130,34 +174,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); @@ -174,6 +190,7 @@ namespace osu.Game.Screens.Play private readonly List drawableRows = new List(); private float filled; + public float Filled { get { return filled; } @@ -203,21 +220,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;