From 027d71ffd8b7886c1c5c05adacde5f8ab96053c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Nov 2016 12:34:03 +0900 Subject: [PATCH 01/15] Fix unit tests failing. --- .../Beatmaps/IO/ImportBeatmapTest.cs | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 7acbdbf3d9..37d89b6497 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -35,29 +35,31 @@ namespace osu.Game.Tests.Beatmaps.IO public void TestImportWhenClosed() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. - HeadlessGameHost host = new HeadlessGameHost(); - - var osu = loadOsu(host); - osu.Dependencies.Get().Import(osz_path); - ensureLoaded(osu); + using (HeadlessGameHost host = new HeadlessGameHost()) + { + var osu = loadOsu(host); + osu.Dependencies.Get().Import(osz_path); + ensureLoaded(osu); + } } [Test] public void TestImportOverIPC() { - HeadlessGameHost host = new HeadlessGameHost("host", true); - HeadlessGameHost client = new HeadlessGameHost("client", true); + using (HeadlessGameHost host = new HeadlessGameHost("host", true)) + using (HeadlessGameHost client = new HeadlessGameHost("client", true)) + { + Assert.IsTrue(host.IsPrimaryInstance); + Assert.IsTrue(!client.IsPrimaryInstance); - Assert.IsTrue(host.IsPrimaryInstance); - Assert.IsTrue(!client.IsPrimaryInstance); + var osu = loadOsu(host); - var osu = loadOsu(host); + var importer = new BeatmapImporter(client); + if (!importer.Import(osz_path).Wait(1000)) + Assert.Fail(@"IPC took too long to send"); - var importer = new BeatmapImporter(client); - if (!importer.Import(osz_path).Wait(1000)) - Assert.Fail(@"IPC took too long to send"); - - ensureLoaded(osu, 10000); + ensureLoaded(osu, 10000); + } } private OsuGameBase loadOsu(BasicGameHost host) From 41a84ba00caca2beda16a5bbf7fdf64e30279e21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Nov 2016 21:35:10 +0900 Subject: [PATCH 02/15] Add finalizer logic for WorkingBeatmap for now. --- osu.Game/Beatmaps/WorkingBeatmap.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index f2f4a39d91..d06ad50b8a 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -89,6 +89,12 @@ namespace osu.Game.Beatmaps set { lock (trackLock) track = value; } } + + ~WorkingBeatmap() + { + Dispose(false); + } + public WorkingBeatmap(Beatmap beatmap) { this.beatmap = beatmap; @@ -116,6 +122,7 @@ namespace osu.Game.Beatmaps public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } public void TransferTo(WorkingBeatmap working) From 3e9c39865200ba8d1d0ca5aeb8788b3b0e6c4ae2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Nov 2016 21:35:53 +0900 Subject: [PATCH 03/15] Update input handler logic to match framework changes. --- osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs | 2 +- osu.Game/Screens/Play/Player.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs index bcd1d9f8db..4cba437883 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs @@ -75,7 +75,7 @@ namespace osu.Game.Graphics.UserInterface.Volume protected override bool OnWheel(InputState state) { - Volume += 0.05f * state.Mouse.WheelDiff; + Volume += 0.05f * state.Mouse.WheelDelta; return true; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 90abf55421..14df8d37b4 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -125,9 +125,9 @@ namespace osu.Game.Screens.Play { } - protected override void UpdateMouseState(InputState state) + protected override void TransformState(InputState state) { - base.UpdateMouseState(state); + base.TransformState(state); MouseState mouse = (MouseState)state.Mouse; From b0dfcf5429b48caee482a308abc9a15d3d0441a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 12:26:18 +0900 Subject: [PATCH 04/15] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 9ed3a191bf..1d43e1ed56 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 9ed3a191bf76ead6ff34ac468898a0119b8e5454 +Subproject commit 1d43e1ed56421fbbefdf6c23dab8deeeaa0f592a From 7df8324957155500f48e57496acb9316375483d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 14:53:23 +0900 Subject: [PATCH 05/15] Explicit disposal via using() to WorkingBeatmap. --- osu.Game/Beatmaps/IO/ArchiveReader.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/osu.Game/Beatmaps/IO/ArchiveReader.cs b/osu.Game/Beatmaps/IO/ArchiveReader.cs index bde6bb8b35..a052b9eb0d 100644 --- a/osu.Game/Beatmaps/IO/ArchiveReader.cs +++ b/osu.Game/Beatmaps/IO/ArchiveReader.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.IO public Func Test { get; set; } public Type Type { get; set; } } - + private static List readers { get; } = new List(); public static ArchiveReader GetReader(BasicStorage storage, string path) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index d06ad50b8a..153539d5f4 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -18,7 +18,7 @@ namespace osu.Game.Beatmaps public readonly BeatmapSetInfo BeatmapSetInfo; private readonly BeatmapDatabase database; - private ArchiveReader reader => database?.GetReader(BeatmapSetInfo); + private ArchiveReader GetReader() => database?.GetReader(BeatmapSetInfo); private Texture background; private object backgroundLock = new object(); @@ -32,7 +32,8 @@ namespace osu.Game.Beatmaps try { - background = new TextureStore(new RawTextureLoaderStore(reader)).Get(BeatmapInfo.Metadata.BackgroundFile); + using (var reader = GetReader()) + background = new TextureStore(new RawTextureLoaderStore(reader)).Get(BeatmapInfo.Metadata.BackgroundFile); } catch { } @@ -54,6 +55,7 @@ namespace osu.Game.Beatmaps try { + using (var reader = GetReader()) using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path))) beatmap = BeatmapDecoder.GetDecoder(stream)?.Decode(stream); } @@ -77,9 +79,12 @@ namespace osu.Game.Beatmaps try { - var trackData = reader?.GetStream(BeatmapInfo.Metadata.AudioFile); - if (trackData != null) - track = new AudioTrackBass(trackData); + using (var reader = GetReader()) + { + var trackData = reader?.GetStream(BeatmapInfo.Metadata.AudioFile); + if (trackData != null) + track = new AudioTrackBass(trackData); + } } catch { } @@ -89,12 +94,6 @@ namespace osu.Game.Beatmaps set { lock (trackLock) track = value; } } - - ~WorkingBeatmap() - { - Dispose(false); - } - public WorkingBeatmap(Beatmap beatmap) { this.beatmap = beatmap; @@ -114,7 +113,7 @@ namespace osu.Game.Beatmaps if (!isDisposed) { track?.Dispose(); - reader?.Dispose(); + background?.Dispose(); isDisposed = true; } } From a251db804c20201c587f788bb6ded8d4ee9e1cec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 16:13:38 +0900 Subject: [PATCH 06/15] Stop adding beatmaps to song select when disposed. --- osu.Game/Screens/Select/PlaySongSelect.cs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index d5b66d5bd7..2a0aff0de6 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -44,6 +45,7 @@ namespace osu.Game.Screens.Select private Container wedgedBeatmapInfo; private static readonly Vector2 BACKGROUND_BLUR = new Vector2(20); + private CancellationTokenSource initialAddSetsTask; /// Optionally provide a database to use instead of the OsuGame one. public PlaySongSelect(BeatmapDatabase database = null) @@ -156,11 +158,18 @@ namespace osu.Game.Screens.Select if (database == null) database = beatmaps; - database.BeatmapSetAdded += s => Schedule(() => addBeatmapSet(s, game)); + database.BeatmapSetAdded += onDatabaseOnBeatmapSetAdded; trackManager = audio.Track; - Task.Factory.StartNew(() => addBeatmapSets(game)); + initialAddSetsTask = new CancellationTokenSource(); + + Task.Factory.StartNew(() => addBeatmapSets(game, initialAddSetsTask.Token), initialAddSetsTask.Token); + } + + private void onDatabaseOnBeatmapSetAdded(BeatmapSetInfo s) + { + Schedule(() => addBeatmapSet(s, Game)); } protected override void OnEntering(GameMode last) @@ -199,6 +208,10 @@ namespace osu.Game.Screens.Select base.Dispose(isDisposing); if (playMode != null) playMode.ValueChanged -= playMode_ValueChanged; + + database.BeatmapSetAdded -= onDatabaseOnBeatmapSetAdded; + + initialAddSetsTask.Cancel(); } private void playMode_ValueChanged(object sender, EventArgs e) @@ -396,10 +409,13 @@ namespace osu.Game.Screens.Select })); } - private void addBeatmapSets(BaseGame game) + private void addBeatmapSets(BaseGame game, CancellationToken token) { foreach (var beatmapSet in database.Query()) + { + if (token.IsCancellationRequested) return; addBeatmapSet(beatmapSet, game); + } } } } From 2ba365657ebb8f49f6b1fe25687dcda3ae02756e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 17:21:42 +0900 Subject: [PATCH 07/15] Tidy up some linq. --- osu.Game/Database/BeatmapDatabase.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index aa68a3be15..f6e67202aa 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -136,7 +136,7 @@ namespace osu.Game.Database public BeatmapSetInfo GetBeatmapSet(int id) { - return Query().Where(s => s.BeatmapSetID == id).FirstOrDefault(); + return Query().FirstOrDefault(s => s.BeatmapSetID == id); } public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null) @@ -175,10 +175,10 @@ namespace osu.Game.Database return connection.GetWithChildren(id); } - public List GetAllWithChildren(Expression> filter = null, - bool recursive = true) where T : class + public List GetAllWithChildren(Expression> filter = null, bool recursive = true) + where T : class { - return connection.GetAllWithChildren(filter, recursive); + return connection.GetAllWithChildren(filter, recursive); } public T GetChildren(T item, bool recursive = true) @@ -199,7 +199,7 @@ namespace osu.Game.Database public void Update(T record, bool cascade = true) where T : class { - if (!validTypes.Any(t => t == typeof(T))) + if (validTypes.All(t => t != typeof(T))) throw new ArgumentException(nameof(T), "Must be a type managed by BeatmapDatabase"); if (cascade) connection.UpdateWithChildren(record); From 0109c79caebae55d4e0cf65b8f064758614b4eed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 19:48:03 +0900 Subject: [PATCH 08/15] Async load of panel backgrounds (failing for on-screen panels). --- .../Beatmaps/Drawable/BeatmapSetHeader.cs | 124 ++++++++++++------ 1 file changed, 84 insertions(+), 40 deletions(-) diff --git a/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs index e42a6271c6..b97b955ec5 100644 --- a/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs @@ -14,6 +14,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Game.Configuration; using osu.Framework.Graphics.Colour; +using osu.Framework; namespace osu.Game.Beatmaps.Drawable { @@ -25,40 +26,6 @@ namespace osu.Game.Beatmaps.Drawable private OsuConfigManager config; private Bindable preferUnicode; - protected override void Selected() - { - base.Selected(); - - GainedSelection?.Invoke(this); - } - - protected override void Deselected() - { - base.Deselected(); - } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - this.config = config; - - preferUnicode = config.GetBindable(OsuConfig.ShowUnicode); - preferUnicode.ValueChanged += preferUnicode_changed; - preferUnicode_changed(preferUnicode, null); - } - private void preferUnicode_changed(object sender, EventArgs e) - { - title.Text = config.GetUnicodeString(beatmapSet.Metadata.Title, beatmapSet.Metadata.TitleUnicode); - artist.Text = config.GetUnicodeString(beatmapSet.Metadata.Artist, beatmapSet.Metadata.ArtistUnicode); - } - - protected override void Dispose(bool isDisposing) - { - if (preferUnicode != null) - preferUnicode.ValueChanged -= preferUnicode_changed; - base.Dispose(isDisposing); - } - public BeatmapSetHeader(BeatmapSetInfo beatmapSet, WorkingBeatmap working) { this.beatmapSet = beatmapSet; @@ -70,12 +37,9 @@ namespace osu.Game.Beatmaps.Drawable RelativeSizeAxes = Axes.Both, Children = new Framework.Graphics.Drawable[] { - working.Background == null ? new Box{ RelativeSizeAxes = Axes.Both, Colour = new Color4(200, 200, 200, 255) } : new Sprite - { - Texture = working.Background, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1366 / working.Background.Width * 0.6f), + new PanelBackground(working) + { + RelativeSizeAxes = Axes.Both }, new FlowContainer { @@ -151,6 +115,86 @@ namespace osu.Game.Beatmaps.Drawable } } }; + } + + protected override void Selected() + { + base.Selected(); + GainedSelection?.Invoke(this); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + this.config = config; + + preferUnicode = config.GetBindable(OsuConfig.ShowUnicode); + preferUnicode.ValueChanged += preferUnicode_changed; + preferUnicode_changed(preferUnicode, null); + } + private void preferUnicode_changed(object sender, EventArgs e) + { + title.Text = config.GetUnicodeString(beatmapSet.Metadata.Title, beatmapSet.Metadata.TitleUnicode); + artist.Text = config.GetUnicodeString(beatmapSet.Metadata.Artist, beatmapSet.Metadata.ArtistUnicode); + } + + protected override void Dispose(bool isDisposing) + { + if (preferUnicode != null) + preferUnicode.ValueChanged -= preferUnicode_changed; + base.Dispose(isDisposing); + } + + class PanelBackground : Container + { + private readonly WorkingBeatmap working; + + private AsyncBackground backgroundSprite; + + public PanelBackground(WorkingBeatmap working) + { + this.working = working; + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase game) + { + OnUpdate += () => + { + //todo: masking check + if (backgroundSprite == null) + { + //moving this to ctor fixes the issue. + (backgroundSprite = new AsyncBackground(working) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }).Preload(game, Add); + } + }; + } + + class AsyncBackground : Sprite + { + private readonly WorkingBeatmap working; + + public AsyncBackground(WorkingBeatmap working) + { + this.working = working; + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase game) + { + Texture = working.Background; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Scale = new Vector2(1366 / (Texture?.Width ?? 1) * 0.6f); + } + } } } } \ No newline at end of file From f576b4bf8298ff3a3e548b1ab26aaa4b70d2c79a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 20:14:58 +0900 Subject: [PATCH 09/15] Don't use texture atlases for beatmap backgrounds. --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 153539d5f4..5feaef6fc6 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps try { using (var reader = GetReader()) - background = new TextureStore(new RawTextureLoaderStore(reader)).Get(BeatmapInfo.Metadata.BackgroundFile); + background = new TextureStore(new RawTextureLoaderStore(reader), false).Get(BeatmapInfo.Metadata.BackgroundFile); } catch { } From 3bc38268a011217297bab3420bdb61ffc9f3105e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 20:47:28 +0900 Subject: [PATCH 10/15] Make MusicController more async. --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 + osu.Game/Overlays/MusicController.cs | 91 +++++++++++++++++----------- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 5feaef6fc6..4c9848363b 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -94,6 +94,8 @@ namespace osu.Game.Beatmaps set { lock (trackLock) track = value; } } + public bool TrackLoaded => track != null; + public WorkingBeatmap(Beatmap beatmap) { this.beatmap = beatmap; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index f84d2052c3..1a3245e41c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -34,7 +34,6 @@ namespace osu.Game.Overlays private DragBar progress; private TextAwesome playButton, listButton; private SpriteText title, artist; - private Texture fallbackTexture; private List playList; private List playHistory = new List(); @@ -47,6 +46,7 @@ namespace osu.Game.Overlays private OsuConfigManager config; private WorkingBeatmap current; private BeatmapDatabase beatmaps; + private BaseGame game; public MusicController() { @@ -208,7 +208,7 @@ namespace osu.Game.Overlays beatmapSource = osuGame.Beatmap ?? new Bindable(); playList = beatmaps.GetAllWithChildren(); - backgroundSprite = new MusicControllerBackground(fallbackTexture = textures.Get(@"Backgrounds/bg4")); + backgroundSprite = new MusicControllerBackground(); AddInternal(backgroundSprite); } @@ -222,12 +222,15 @@ namespace osu.Game.Overlays protected override void Update() { base.Update(); - if (current?.Track == null) return; - progress.UpdatePosition((float)(current.Track.CurrentTime / current.Track.Length)); - playButton.Icon = current.Track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o; + if (current?.TrackLoaded ?? false) + { - if (current.Track.HasCompleted && !current.Track.Looping) next(); + progress.UpdatePosition((float)(current.Track.CurrentTime / current.Track.Length)); + playButton.Icon = current.Track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o; + + if (current.Track.HasCompleted && !current.Track.Looping) next(); + } } void preferUnicode_changed(object sender, EventArgs e) @@ -304,36 +307,49 @@ namespace osu.Game.Overlays updateDisplay(current, isNext ? TransformDirection.Next : TransformDirection.Prev); } + protected override void PerformLoad(BaseGame game) + { + this.game = game; + base.PerformLoad(game); + } + private void updateDisplay(WorkingBeatmap beatmap, TransformDirection direction) { - if (beatmap.Beatmap == null) - //todo: we may need to display some default text here (currently in the constructor). - return; - - BeatmapMetadata metadata = beatmap.Beatmap.BeatmapInfo.Metadata; - title.Text = config.GetUnicodeString(metadata.Title, metadata.TitleUnicode); - artist.Text = config.GetUnicodeString(metadata.Artist, metadata.ArtistUnicode); - - MusicControllerBackground newBackground = new MusicControllerBackground(beatmap.Background ?? fallbackTexture); - - Add(newBackground); - - switch (direction) + Task.Run(() => { - case TransformDirection.Next: - newBackground.Position = new Vector2(400, 0); - newBackground.MoveToX(0, 500, EasingTypes.OutCubic); - backgroundSprite.MoveToX(-400, 500, EasingTypes.OutCubic); - break; - case TransformDirection.Prev: - newBackground.Position = new Vector2(-400, 0); - newBackground.MoveToX(0, 500, EasingTypes.OutCubic); - backgroundSprite.MoveToX(400, 500, EasingTypes.OutCubic); - break; - } + if (beatmap.Beatmap == null) + //todo: we may need to display some default text here (currently in the constructor). + return; - backgroundSprite.Expire(); - backgroundSprite = newBackground; + BeatmapMetadata metadata = beatmap.Beatmap.BeatmapInfo.Metadata; + title.Text = config.GetUnicodeString(metadata.Title, metadata.TitleUnicode); + artist.Text = config.GetUnicodeString(metadata.Artist, metadata.ArtistUnicode); + }); + + MusicControllerBackground newBackground; + + (newBackground = new MusicControllerBackground(beatmap)).Preload(game, delegate + { + + Add(newBackground); + + switch (direction) + { + case TransformDirection.Next: + newBackground.Position = new Vector2(400, 0); + newBackground.MoveToX(0, 500, EasingTypes.OutCubic); + backgroundSprite.MoveToX(-400, 500, EasingTypes.OutCubic); + break; + case TransformDirection.Prev: + newBackground.Position = new Vector2(-400, 0); + newBackground.MoveToX(0, 500, EasingTypes.OutCubic); + backgroundSprite.MoveToX(400, 500, EasingTypes.OutCubic); + break; + } + + backgroundSprite.Expire(); + backgroundSprite = newBackground; + }); } private void seek(float position) @@ -363,9 +379,11 @@ namespace osu.Game.Overlays private class MusicControllerBackground : BufferedContainer { private Sprite sprite; + private WorkingBeatmap beatmap; - public MusicControllerBackground(Texture backgroundTexture) + public MusicControllerBackground(WorkingBeatmap beatmap = null) { + this.beatmap = beatmap; CacheDrawnFrameBuffer = true; RelativeSizeAxes = Axes.Both; Depth = float.MinValue; @@ -374,7 +392,6 @@ namespace osu.Game.Overlays { sprite = new Sprite { - Texture = backgroundTexture, Colour = new Color4(150, 150, 150, 255) }, new Box @@ -388,6 +405,12 @@ namespace osu.Game.Overlays }; } + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4"); + } + protected override void LoadComplete() { base.LoadComplete(); From a3234a52694f55faa130ecbf384f8009b9673509 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 21:22:12 +0900 Subject: [PATCH 11/15] Avoid synchronous queries in BackgroundModeBeatmap. --- .../Backgrounds/BackgroundModeBeatmap.cs | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs index 649952ccfb..e599198009 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundModeBeatmap.cs @@ -1,9 +1,8 @@ //Copyright (c) 2007-2016 ppy Pty Ltd . //Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using OpenTK; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transformations; using osu.Game.Beatmaps; using osu.Game.Graphics.Background; @@ -15,6 +14,7 @@ namespace osu.Game.Screens.Backgrounds private Background background; private WorkingBeatmap beatmap; + private Vector2 blurTarget; public WorkingBeatmap Beatmap { @@ -30,20 +30,26 @@ namespace osu.Game.Screens.Backgrounds beatmap = value; - Background oldBackground = background; - - addBackground(background = new Background()); - background.Sprite.Texture = beatmap.Background; - - if (oldBackground != null) + Schedule(() => { - oldBackground.Depth = 1; - oldBackground.Flush(); - oldBackground.FadeOut(250); - oldBackground.Expire(); + Background newBackground = new BeatmapBackground(beatmap); - background.BlurSigma = oldBackground.BlurSigma; - } + newBackground.Preload(Game, delegate + { + Background oldBackground = background; + + Add(background = newBackground); + background.BlurSigma = blurTarget; + + if (oldBackground != null) + { + oldBackground.Depth = 1; + oldBackground.Flush(); + oldBackground.FadeOut(250); + oldBackground.Expire(); + } + }); + }); } } @@ -52,20 +58,33 @@ namespace osu.Game.Screens.Backgrounds Beatmap = beatmap; } - private void addBackground(Background background) - { - background.CacheDrawnFrameBuffer = true; - Add(background); - } - public void BlurTo(Vector2 sigma, double duration) { background?.BlurTo(sigma, duration, EasingTypes.OutExpo); + blurTarget = sigma; } public override bool Equals(BackgroundMode other) { return base.Equals(other) && beatmap == ((BackgroundModeBeatmap)other).Beatmap; } + + class BeatmapBackground : Background + { + private WorkingBeatmap beatmap; + + public BeatmapBackground(WorkingBeatmap beatmap) + { + this.beatmap = beatmap; + CacheDrawnFrameBuffer = true; + } + + [BackgroundDependencyLoader] + private void load() + { + Sprite.Texture = beatmap.Background; + } + + } } } From b73cdba08cdae63ebf2aac41a436c3b32e513cd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 21:38:46 +0900 Subject: [PATCH 12/15] Change the structure of BeatmapSetHeader to allow for bufferedcontainer invalidation. --- .../Beatmaps/Drawable/BeatmapSetHeader.cs | 120 +++++++++--------- 1 file changed, 57 insertions(+), 63 deletions(-) diff --git a/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs index b97b955ec5..7e39a820d2 100644 --- a/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs @@ -31,54 +31,9 @@ namespace osu.Game.Beatmaps.Drawable this.beatmapSet = beatmapSet; Children = new Framework.Graphics.Drawable[] { - new BufferedContainer + new PanelBackground(working) { - CacheDrawnFrameBuffer = true, RelativeSizeAxes = Axes.Both, - Children = new Framework.Graphics.Drawable[] - { - new PanelBackground(working) - { - RelativeSizeAxes = Axes.Both - }, - new FlowContainer - { - Direction = FlowDirection.HorizontalOnly, - RelativeSizeAxes = Axes.Both, - // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle - Shear = new Vector2(0.8f, 0), - Alpha = 0.5f, - Children = new[] - { - // The left half with no gradient applied - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Width = 0.4f, - }, - // Piecewise-linear gradient with 3 segments to make it appear smoother - new Box - { - RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)), - Width = 0.05f, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)), - Width = 0.2f, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)), - Width = 0.05f, - }, - } - }, - } }, new FlowContainer { @@ -145,40 +100,79 @@ namespace osu.Game.Beatmaps.Drawable base.Dispose(isDisposing); } - class PanelBackground : Container + class PanelBackground : BufferedContainer { private readonly WorkingBeatmap working; - private AsyncBackground backgroundSprite; - public PanelBackground(WorkingBeatmap working) { this.working = working; + + CacheDrawnFrameBuffer = true; + + Children = new[] + { + new FlowContainer + { + Depth = 1, + Direction = FlowDirection.HorizontalOnly, + RelativeSizeAxes = Axes.Both, + // This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle + Shear = new Vector2(0.8f, 0), + Alpha = 0.5f, + Children = new[] + { + // The left half with no gradient applied + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Width = 0.4f, + }, + // Piecewise-linear gradient with 3 segments to make it appear smoother + new Box + { + RelativeSizeAxes = Axes.Both, + ColourInfo = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)), + Width = 0.05f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + ColourInfo = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)), + Width = 0.2f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + ColourInfo = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)), + Width = 0.05f, + }, + } + }, + }; } [BackgroundDependencyLoader] private void load(OsuGameBase game) { - OnUpdate += () => + //todo: masking check + new BeatmapBackground(working) { - //todo: masking check - if (backgroundSprite == null) - { - //moving this to ctor fixes the issue. - (backgroundSprite = new AsyncBackground(working) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }).Preload(game, Add); - } - }; + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }.Preload(game, (bg) => + { + Add(bg); + ForceRedraw(); + }); } - class AsyncBackground : Sprite + class BeatmapBackground : Sprite { private readonly WorkingBeatmap working; - public AsyncBackground(WorkingBeatmap working) + public BeatmapBackground(WorkingBeatmap working) { this.working = working; } From ccb00aeb94536e9c92841ab30aaec47dc2d35ff8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 21:43:35 +0900 Subject: [PATCH 13/15] Add comment about wedgedBeatmapInfo performance issues. --- osu.Game/Screens/Select/PlaySongSelect.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 2a0aff0de6..522ce87242 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -231,6 +231,7 @@ namespace osu.Game.Screens.Select (Background as BackgroundModeBeatmap)?.BlurTo(BACKGROUND_BLUR, 1000); } + //todo: move to own class and fix async logic (move every call on WorkingBeatmap.* to load() and use Preload to create it. refreshWedgedBeatmapInfo(beatmap); } From 4cf2dd90d64d0e083b00f4bdae5a7d63cec3451b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 22:07:15 +0900 Subject: [PATCH 14/15] Standardise and simplify the amount of beatmap information passed around song select. --- osu.Game/Beatmaps/Drawable/BeatmapGroup.cs | 10 ++++----- .../Beatmaps/Drawable/BeatmapSetHeader.cs | 21 ++++++++++--------- osu.Game/Screens/Select/PlaySongSelect.cs | 5 +++-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs index 2dc4218d39..ec9e36af3b 100644 --- a/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs +++ b/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs @@ -26,12 +26,12 @@ namespace osu.Game.Beatmaps.Drawable /// public Action SelectionChanged; - private BeatmapSetInfo beatmapSet; public BeatmapSetHeader Header; private BeatmapGroupState state; public List BeatmapPanels; + private WorkingBeatmap beatmap; public BeatmapGroupState State { @@ -65,11 +65,11 @@ namespace osu.Game.Beatmaps.Drawable } } - public BeatmapGroup(BeatmapSetInfo beatmapSet, WorkingBeatmap working) + public BeatmapGroup(WorkingBeatmap beatmap) { - this.beatmapSet = beatmapSet; + this.beatmap = beatmap; - Header = new BeatmapSetHeader(beatmapSet, working) + Header = new BeatmapSetHeader(beatmap) { GainedSelection = headerGainedSelection, RelativeSizeAxes = Axes.X, @@ -77,7 +77,7 @@ namespace osu.Game.Beatmaps.Drawable Origin = Anchor.TopRight, }; - BeatmapPanels = beatmapSet.Beatmaps.Select(b => new BeatmapPanel(b) + BeatmapPanels = beatmap.BeatmapSetInfo.Beatmaps.Select(b => new BeatmapPanel(b) { GainedSelection = panelGainedSelection, Anchor = Anchor.TopRight, diff --git a/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs index 7e39a820d2..4d46a02388 100644 --- a/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawable/BeatmapSetHeader.cs @@ -21,17 +21,18 @@ namespace osu.Game.Beatmaps.Drawable class BeatmapSetHeader : Panel { public Action GainedSelection; - private BeatmapSetInfo beatmapSet; private SpriteText title, artist; private OsuConfigManager config; - private Bindable preferUnicode; - - public BeatmapSetHeader(BeatmapSetInfo beatmapSet, WorkingBeatmap working) + private Bindable preferUnicode; + private WorkingBeatmap beatmap; + + public BeatmapSetHeader(WorkingBeatmap beatmap) { - this.beatmapSet = beatmapSet; + this.beatmap = beatmap; + Children = new Framework.Graphics.Drawable[] { - new PanelBackground(working) + new PanelBackground(beatmap) { RelativeSizeAxes = Axes.Both, }, @@ -45,7 +46,7 @@ namespace osu.Game.Beatmaps.Drawable title = new SpriteText { Font = @"Exo2.0-BoldItalic", - Text = beatmapSet.Metadata.Title, + Text = beatmap.BeatmapSetInfo.Metadata.Title, TextSize = 22, Shadow = true, }, @@ -53,7 +54,7 @@ namespace osu.Game.Beatmaps.Drawable { Margin = new MarginPadding { Top = -1 }, Font = @"Exo2.0-SemiBoldItalic", - Text = beatmapSet.Metadata.Artist, + Text = beatmap.BeatmapSetInfo.Metadata.Artist, TextSize = 17, Shadow = true, }, @@ -89,8 +90,8 @@ namespace osu.Game.Beatmaps.Drawable } private void preferUnicode_changed(object sender, EventArgs e) { - title.Text = config.GetUnicodeString(beatmapSet.Metadata.Title, beatmapSet.Metadata.TitleUnicode); - artist.Text = config.GetUnicodeString(beatmapSet.Metadata.Artist, beatmapSet.Metadata.ArtistUnicode); + title.Text = config.GetUnicodeString(beatmap.BeatmapSetInfo.Metadata.Title, beatmap.BeatmapSetInfo.Metadata.TitleUnicode); + artist.Text = config.GetUnicodeString(beatmap.BeatmapSetInfo.Metadata.Artist, beatmap.BeatmapSetInfo.Metadata.ArtistUnicode); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 522ce87242..ba6cfa37cd 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -346,6 +346,7 @@ namespace osu.Game.Screens.Select { base.OnBeatmapChanged(beatmap); + //todo: change background in selectionChanged instead; support per-difficulty backgrounds. changeBackground(beatmap); selectBeatmap(beatmap.BeatmapInfo); @@ -389,9 +390,9 @@ namespace osu.Game.Screens.Select beatmapSet.Beatmaps.ForEach(b => database.GetChildren(b)); beatmapSet.Beatmaps = beatmapSet.Beatmaps.OrderBy(b => b.BaseDifficulty.OverallDifficulty).ToList(); - var working = database.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault()); + var beatmap = database.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault()); - var group = new BeatmapGroup(beatmapSet, working) { SelectionChanged = selectionChanged }; + var group = new BeatmapGroup(beatmap) { SelectionChanged = selectionChanged }; //for the time being, let's completely load the difficulty panels in the background. //this likely won't scale so well, but allows us to completely async the loading flow. From d71550d22ad80b77fa3bcf5919af0e63dd0f09de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Nov 2016 22:07:28 +0900 Subject: [PATCH 15/15] Don't do a recursive fill by default, we don't need it. --- osu.Game/Database/BeatmapDatabase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index f6e67202aa..619eacc90f 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -144,7 +144,7 @@ namespace osu.Game.Database var beatmapSetInfo = Query().FirstOrDefault(s => s.BeatmapSetID == beatmapInfo.BeatmapSetID); //we need metadata - GetChildren(beatmapSetInfo); + GetChildren(beatmapSetInfo, false); if (beatmapSetInfo == null) throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetID} is not in the local database.");