From eda9f838366cd46f09e3bb3401cfaf7775e21daf Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sun, 29 Apr 2018 15:32:22 +0300 Subject: [PATCH 01/35] Add activeBeatmapPreview variable for tracking beatmap preview playback --- osu.Game/Overlays/Direct/PlayButton.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 4913b11ae1..dae3b63a8f 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.Direct { public class PlayButton : Container { + private static PlayButton activeBeatmapPreview; public readonly Bindable Playing = new Bindable(); public Track Preview { get; private set; } @@ -131,6 +132,9 @@ namespace osu.Game.Overlays.Direct if (playing) { + if (activeBeatmapPreview != null) + activeBeatmapPreview.Playing.Value = false; + if (Preview == null) { beginAudioLoad(); @@ -140,6 +144,7 @@ namespace osu.Game.Overlays.Direct Preview.Restart(); audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); + activeBeatmapPreview = this; } else { From 56c1c2beca733efdeee32e7d9a0779e0dc4ca524 Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sun, 29 Apr 2018 15:50:02 +0300 Subject: [PATCH 02/35] Remove redundant multiple previews handling from PaginatedBeatmapContainer --- .../Beatmaps/PaginatedBeatmapContainer.cs | 27 ++----------------- .../Profile/Sections/BeatmapsSection.cs | 10 ------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 3fec9d8697..0b06acd426 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,14 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using OpenTK; +using System.Linq; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; using osu.Game.Users; -using System.Linq; +using OpenTK; namespace osu.Game.Overlays.Profile.Sections.Beatmaps { @@ -18,10 +17,6 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps private readonly BeatmapSetType type; - private DirectPanel currentlyPlaying; - - public event Action BeganPlayingPreview; - public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.") : base(user, header, missing) { @@ -56,28 +51,10 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets)); ItemsContainer.Add(panel); - - panel.PreviewPlaying.ValueChanged += isPlaying => - { - StopPlayingPreview(); - - if (isPlaying) - { - BeganPlayingPreview?.Invoke(this); - currentlyPlaying = panel; - } - }; } }; Api.Queue(req); } - - public void StopPlayingPreview() - { - if (currentlyPlaying == null) return; - currentlyPlaying.PreviewPlaying.Value = false; - currentlyPlaying = null; - } } } diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index 92abd20f93..367d096c16 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile.Sections.Beatmaps; @@ -22,15 +21,6 @@ namespace osu.Game.Overlays.Profile.Sections new PaginatedBeatmapContainer(BeatmapSetType.Unranked, User, "Pending Beatmaps"), new PaginatedBeatmapContainer(BeatmapSetType.Graveyard, User, "Graveyarded Beatmaps"), }; - - foreach (var paginatedBeatmapContainer in Children.OfType()) - { - paginatedBeatmapContainer.BeganPlayingPreview += _ => - { - foreach (var bc in Children.OfType()) - bc.StopPlayingPreview(); - }; - } } } } From 7cffabf7f931c367eb02ce8a0fc40342d5f6122d Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 8 May 2018 22:55:48 +0300 Subject: [PATCH 03/35] Introduce PreviewTrackManager --- osu.Game/Audio/PreviewTrackManager.cs | 60 +++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 osu.Game/Audio/PreviewTrackManager.cs diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs new file mode 100644 index 0000000000..55addac8ad --- /dev/null +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Track; +using osu.Framework.Configuration; +using osu.Framework.IO.Stores; + +namespace osu.Game.Audio +{ + public class PreviewTrackManager : TrackManager + { + private AudioManager audio; + private Track currentTrack; + private readonly BindableDouble muteBindable; + + public PreviewTrackManager() + : base(new OnlineStore()) + { + muteBindable = new BindableDouble(); + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio, FrameworkConfigManager config) + { + this.audio = audio; + + audio.AddItem(this); + + config.BindWith(FrameworkSetting.VolumeMusic, Volume); + } + + protected override void UpdateState() + { + if (currentTrack?.HasCompleted ?? false) + onStop(); + + base.UpdateState(); + } + + public void Play(Track track) + { + currentTrack?.Stop(); + currentTrack = track; + currentTrack.Restart(); + onPlay(); + } + + private void onPlay() => audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); + + public void Stop() + { + currentTrack?.Stop(); + onStop(); + } + + private void onStop() => audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); + } +} From ad50f7faf10cdc5c4090d5ff58db5cc906debe72 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Wed, 9 May 2018 14:51:04 +0300 Subject: [PATCH 04/35] Make PreviewTrackManager a Component in order to use DI --- osu.Game/Audio/PreviewTrackManager.cs | 60 +++++++++++++++------------ 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 55addac8ad..2e5f26bcf4 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -1,60 +1,66 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Configuration; +using osu.Framework.Graphics; using osu.Framework.IO.Stores; +using osu.Game.Beatmaps; namespace osu.Game.Audio { - public class PreviewTrackManager : TrackManager + public class PreviewTrackManager : Component { - private AudioManager audio; - private Track currentTrack; - private readonly BindableDouble muteBindable; + public event Action PlaybackStarted; + public event Action PlaybackStopped; - public PreviewTrackManager() - : base(new OnlineStore()) - { - muteBindable = new BindableDouble(); - } + private TrackManager trackManager; + private BindableDouble muteBindable; + + public Track CurrentTrack { get; private set; } [BackgroundDependencyLoader] private void load(AudioManager audio, FrameworkConfigManager config) { - this.audio = audio; + trackManager = new TrackManager(new OnlineStore()); - audio.AddItem(this); + muteBindable = new BindableDouble(); - config.BindWith(FrameworkSetting.VolumeMusic, Volume); + audio.AddItem(trackManager); + config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); + + PlaybackStarted += () => audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); + PlaybackStopped += () => audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); } - protected override void UpdateState() - { - if (currentTrack?.HasCompleted ?? false) - onStop(); + public Track Get(BeatmapSetInfo beatmapSetInfo) => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineBeatmapSetID}.mp3"); - base.UpdateState(); + protected override void Update() + { + if (CurrentTrack?.HasCompleted ?? false) + PlaybackStopped?.Invoke(); + + base.Update(); } public void Play(Track track) { - currentTrack?.Stop(); - currentTrack = track; - currentTrack.Restart(); - onPlay(); + Stop(); + CurrentTrack = track; + track.Restart(); + PlaybackStarted?.Invoke(); } - private void onPlay() => audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); - public void Stop() { - currentTrack?.Stop(); - onStop(); + if (CurrentTrack?.IsRunning ?? false) + { + CurrentTrack?.Stop(); + PlaybackStopped?.Invoke(); + } } - - private void onStop() => audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); } } From c492f62edaac7b92d505c8d0eaf5fa2112522e4e Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Wed, 9 May 2018 14:52:46 +0300 Subject: [PATCH 05/35] Use PreviewTrackManager in the PlayButton --- osu.Game/OsuGameBase.cs | 5 ++ osu.Game/Overlays/Direct/PlayButton.cs | 112 +++++-------------------- 2 files changed, 24 insertions(+), 93 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 487cb50c9a..4d2d4d05a7 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -23,6 +23,7 @@ using osu.Game.Online.API; using osu.Framework.Graphics.Performance; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; +using osu.Game.Audio; using osu.Game.Database; using osu.Game.Graphics.Textures; using osu.Game.Input; @@ -202,6 +203,10 @@ namespace osu.Game KeyBindingStore.Register(globalBinding); dependencies.Cache(globalBinding); + + PreviewTrackManager previewTrackManager; + dependencies.Cache(previewTrackManager = new PreviewTrackManager()); + Add(previewTrackManager); } private void runMigrations() diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index dae3b63a8f..082cf34d8e 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -1,24 +1,22 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; -using osu.Framework.IO.Stores; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using OpenTK.Graphics; namespace osu.Game.Overlays.Direct { public class PlayButton : Container { - private static PlayButton activeBeatmapPreview; public readonly Bindable Playing = new Bindable(); public Track Preview { get; private set; } @@ -33,17 +31,16 @@ namespace osu.Game.Overlays.Direct beatmapSet = value; Playing.Value = false; - trackLoader = null; Preview = null; } } + private PreviewTrackManager previewTrackManager; + private Color4 hoverColour; private readonly SpriteIcon icon; private readonly LoadingAnimation loadingAnimation; - private readonly BindableDouble muteBindable = new BindableDouble(); - private const float transition_duration = 500; private bool loading @@ -79,14 +76,20 @@ namespace osu.Game.Overlays.Direct loadingAnimation = new LoadingAnimation(), }); - Playing.ValueChanged += updatePreviewTrack; + Playing.ValueChanged += playingStateChanged; } [BackgroundDependencyLoader] - private void load(OsuColour colour, AudioManager audio) + private void load(OsuColour colour, PreviewTrackManager previewTrackManager) { hoverColour = colour.Yellow; - this.audio = audio; + this.previewTrackManager = previewTrackManager; + + previewTrackManager.PlaybackStopped += () => + { + if (Preview == previewTrackManager.CurrentTrack) + Playing.Value = false; + }; } protected override bool OnClick(InputState state) @@ -108,18 +111,7 @@ namespace osu.Game.Overlays.Direct base.OnHoverLost(state); } - protected override void Update() - { - base.Update(); - - if (Preview?.HasCompleted ?? false) - { - Playing.Value = false; - Preview = null; - } - } - - private void updatePreviewTrack(bool playing) + private void playingStateChanged(bool playing) { if (playing && BeatmapSet == null) { @@ -132,25 +124,18 @@ namespace osu.Game.Overlays.Direct if (playing) { - if (activeBeatmapPreview != null) - activeBeatmapPreview.Playing.Value = false; - if (Preview == null) { - beginAudioLoad(); - return; + loading = true; + Preview = previewTrackManager.Get(beatmapSet); + loading = false; } - Preview.Restart(); - - audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); - activeBeatmapPreview = this; + previewTrackManager.Play(Preview); } else { - audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); - - Preview?.Stop(); + previewTrackManager.Stop(); loading = false; } } @@ -160,64 +145,5 @@ namespace osu.Game.Overlays.Direct base.Dispose(isDisposing); Playing.Value = false; } - - private TrackLoader trackLoader; - private AudioManager audio; - - private void beginAudioLoad() - { - if (trackLoader != null) - { - Preview = trackLoader.Preview; - Playing.TriggerChange(); - return; - } - - loading = true; - - LoadComponentAsync(trackLoader = new TrackLoader($"https://b.ppy.sh/preview/{BeatmapSet.OnlineBeatmapSetID}.mp3"), - d => - { - // We may have been replaced by another loader - if (trackLoader != d) return; - - Preview = d?.Preview; - updatePreviewTrack(Playing); - loading = false; - - Add(trackLoader); - }); - } - - private class TrackLoader : Drawable - { - private readonly string preview; - - public Track Preview; - private TrackManager trackManager; - - public TrackLoader(string preview) - { - this.preview = preview; - } - - [BackgroundDependencyLoader] - private void load(AudioManager audio, FrameworkConfigManager config) - { - // create a local trackManager to bypass the mute we are applying above. - audio.AddItem(trackManager = new TrackManager(new OnlineStore())); - - // add back the user's music volume setting (since we are no longer in the global TrackManager's hierarchy). - config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); - - Preview = trackManager.Get(preview); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - trackManager?.Dispose(); - } - } } } From 95dd2125ee91dbda04d527d1c34d236a9190c1f9 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Wed, 9 May 2018 16:22:52 +0300 Subject: [PATCH 06/35] Load PlayButton.Preview asynchronously --- osu.Game/Overlays/Direct/PlayButton.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 082cf34d8e..77c904050b 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Configuration; @@ -126,9 +127,17 @@ namespace osu.Game.Overlays.Direct { if (Preview == null) { - loading = true; - Preview = previewTrackManager.Get(beatmapSet); - loading = false; + Task.Run(() => + { + loading = true; + return Preview = previewTrackManager.Get(beatmapSet); + }) + .ContinueWith(t => + { + playingStateChanged(true); + loading = false; + }); + return; } previewTrackManager.Play(Preview); From 498244a3089827cbd58aff593d0ec3963cf32303 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 25 May 2018 00:37:53 +0300 Subject: [PATCH 07/35] Introduce PreviewTrack class --- osu.Game/Audio/PreviewTrack.cs | 39 +++++++++++++++++ osu.Game/Audio/PreviewTrackManager.cs | 43 ++++++++----------- .../BeatmapSet/Buttons/PreviewButton.cs | 6 +-- osu.Game/Overlays/Direct/DirectPanel.cs | 16 +++---- osu.Game/Overlays/Direct/PlayButton.cs | 18 ++++---- 5 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 osu.Game/Audio/PreviewTrack.cs diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs new file mode 100644 index 0000000000..10dec7c394 --- /dev/null +++ b/osu.Game/Audio/PreviewTrack.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Audio.Track; + +namespace osu.Game.Audio +{ + public class PreviewTrack + { + public readonly Track Track; + private readonly Action onStart; + private readonly Action onStop; + + public event Action Stopped; + public event Action Started; + + public PreviewTrack(Track track, Action onStart, Action onStop) + { + Track = track; + this.onStart = onStart; + this.onStop = onStop; + } + + public void Start() + { + onStart?.Invoke(this); + Track.Restart(); + Started?.Invoke(); + } + + public void Stop() + { + onStop?.Invoke(); + Track.Stop(); + Stopped?.Invoke(); + } + } +} diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 2e5f26bcf4..5c7f580ca8 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -14,13 +14,13 @@ namespace osu.Game.Audio { public class PreviewTrackManager : Component { - public event Action PlaybackStarted; - public event Action PlaybackStopped; + private Action onTrackStart; + private Action onTrackStop; private TrackManager trackManager; private BindableDouble muteBindable; - public Track CurrentTrack { get; private set; } + public PreviewTrack CurrentTrack { get; private set; } [BackgroundDependencyLoader] private void load(AudioManager audio, FrameworkConfigManager config) @@ -32,35 +32,28 @@ namespace osu.Game.Audio audio.AddItem(trackManager); config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); - PlaybackStarted += () => audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); - PlaybackStopped += () => audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); + onTrackStart = track => + { + CurrentTrack?.Stop(); + audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); + CurrentTrack = track; + CurrentTrack.Stopped += () => CurrentTrack = null; + }; + onTrackStop = () => audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); } - public Track Get(BeatmapSetInfo beatmapSetInfo) => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineBeatmapSetID}.mp3"); + public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) => + new PreviewTrack( + trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineBeatmapSetID}.mp3"), + onTrackStart, + onTrackStop); protected override void Update() { - if (CurrentTrack?.HasCompleted ?? false) - PlaybackStopped?.Invoke(); + if (CurrentTrack?.Track.HasCompleted ?? false) + CurrentTrack.Stop(); base.Update(); } - - public void Play(Track track) - { - Stop(); - CurrentTrack = track; - track.Restart(); - PlaybackStarted?.Invoke(); - } - - public void Stop() - { - if (CurrentTrack?.IsRunning ?? false) - { - CurrentTrack?.Stop(); - PlaybackStopped?.Invoke(); - } - } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 08a99f1aea..78628675ac 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -2,13 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -25,7 +25,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private readonly Box bg, progress; private readonly PlayButton playButton; - private Track preview => playButton.Preview; + private PreviewTrack preview => playButton.Preview; public Bindable Playing => playButton.Playing; public BeatmapSetInfo BeatmapSet @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons if (Playing.Value && preview != null) { // prevent negative (potential infinite) width if a track without length was loaded - progress.Width = preview.Length > 0 ? (float)(preview.CurrentTime / preview.Length) : 0f; + progress.Width = preview.Track.Length > 0 ? (float)(preview.Track.CurrentTime / preview.Track.Length) : 0f; } else progress.Width = 0; diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index cc0123dabc..2ceefe31ef 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -4,22 +4,22 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; -using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using OpenTK.Graphics; -using osu.Framework.Input; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; -using osu.Framework.Configuration; -using osu.Framework.Audio.Track; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays.Direct { @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Direct private BeatmapManager beatmaps; private BeatmapSetOverlay beatmapSetOverlay; - public Track Preview => PlayButton.Preview; + public PreviewTrack Preview => PlayButton.Preview; public Bindable PreviewPlaying => PlayButton.Playing; protected abstract PlayButton PlayButton { get; } protected abstract Box PreviewBar { get; } @@ -121,9 +121,9 @@ namespace osu.Game.Overlays.Direct { base.Update(); - if (PreviewPlaying && Preview != null && Preview.IsLoaded) + if (PreviewPlaying && Preview != null && Preview.Track.IsLoaded) { - PreviewBar.Width = (float)(Preview.CurrentTime / Preview.Length); + PreviewBar.Width = (float)(Preview.Track.CurrentTime / Preview.Track.Length); } } diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 77c904050b..1f18faaf14 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -3,7 +3,6 @@ using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,7 +18,7 @@ namespace osu.Game.Overlays.Direct public class PlayButton : Container { public readonly Bindable Playing = new Bindable(); - public Track Preview { get; private set; } + public PreviewTrack Preview { get; private set; } private BeatmapSetInfo beatmapSet; @@ -32,6 +31,8 @@ namespace osu.Game.Overlays.Direct beatmapSet = value; Playing.Value = false; + if (Preview != null) + Preview.Stopped -= preview_Stopped; Preview = null; } } @@ -85,12 +86,6 @@ namespace osu.Game.Overlays.Direct { hoverColour = colour.Yellow; this.previewTrackManager = previewTrackManager; - - previewTrackManager.PlaybackStopped += () => - { - if (Preview == previewTrackManager.CurrentTrack) - Playing.Value = false; - }; } protected override bool OnClick(InputState state) @@ -134,21 +129,24 @@ namespace osu.Game.Overlays.Direct }) .ContinueWith(t => { + Preview.Stopped += preview_Stopped; playingStateChanged(true); loading = false; }); return; } - previewTrackManager.Play(Preview); + Preview.Start(); } else { - previewTrackManager.Stop(); + Preview.Stop(); loading = false; } } + private void preview_Stopped() => Playing.Value = false; + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From a24589f5836d87b758ba3cafcc694676fb65d208 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 25 May 2018 22:35:15 +0300 Subject: [PATCH 08/35] Cleanup external PlayButton.Playing usage --- osu.Game/Audio/PreviewTrackManager.cs | 9 ++-- .../BeatmapSet/Buttons/PreviewButton.cs | 8 +-- osu.Game/Overlays/BeatmapSet/Details.cs | 6 ++- osu.Game/Overlays/Direct/DirectPanel.cs | 1 - osu.Game/Overlays/Direct/PlayButton.cs | 52 +++++++++---------- osu.Game/Overlays/DirectOverlay.cs | 26 ---------- 6 files changed, 37 insertions(+), 65 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 5c7f580ca8..5c2656b322 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -37,14 +37,17 @@ namespace osu.Game.Audio CurrentTrack?.Stop(); audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); CurrentTrack = track; - CurrentTrack.Stopped += () => CurrentTrack = null; }; - onTrackStop = () => audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); + onTrackStop = () => + { + audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); + CurrentTrack = null; + }; } public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) => new PreviewTrack( - trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo.OnlineBeatmapSetID}.mp3"), + trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"), onTrackStart, onTrackStop); diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 78628675ac..78bc77efe8 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }; - Action = () => Playing.Value = !Playing.Value; + Action = () => playButton.TriggerOnClick(); Playing.ValueChanged += newValue => progress.FadeTo(newValue ? 1 : 0, 100); } @@ -89,12 +89,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons progress.Width = 0; } - protected override void Dispose(bool isDisposing) - { - Playing.Value = false; - base.Dispose(isDisposing); - } - protected override bool OnHover(InputState state) { bg.FadeColour(Color4.Black.Opacity(0.5f), 100); diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 5264caf936..8c16822cfc 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -102,7 +102,11 @@ namespace osu.Game.Overlays.BeatmapSet updateDisplay(); } - public void StopPreview() => preview.Playing.Value = false; + public void StopPreview() + { + if (preview.Playing) + preview.TriggerOnClick(); + } private class DetailBox : Container { diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 2ceefe31ef..1c7abd4cdd 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -149,7 +149,6 @@ namespace osu.Game.Overlays.Direct protected override bool OnClick(InputState state) { ShowInformation(); - PreviewPlaying.Value = false; return true; } diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 1f18faaf14..677f74540b 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -31,8 +31,6 @@ namespace osu.Game.Overlays.Direct beatmapSet = value; Playing.Value = false; - if (Preview != null) - Preview.Stopped -= preview_Stopped; Preview = null; } } @@ -90,7 +88,30 @@ namespace osu.Game.Overlays.Direct protected override bool OnClick(InputState state) { - Playing.Value = !Playing.Value; + if (!Playing.Value) + { + if (Preview == null) + { + Task.Run(() => + { + loading = true; + return Preview = previewTrackManager.Get(beatmapSet); + }) + .ContinueWith(t => + { + Preview.Started += () => Playing.Value = true; + Preview.Stopped += () => Playing.Value = false; + Preview.Start(); + loading = false; + }); + return true; + } + + Preview.Start(); + } + else + Preview?.Stop(); + return true; } @@ -118,35 +139,12 @@ namespace osu.Game.Overlays.Direct icon.Icon = playing ? FontAwesome.fa_pause : FontAwesome.fa_play; icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); - if (playing) + if (!playing) { - if (Preview == null) - { - Task.Run(() => - { - loading = true; - return Preview = previewTrackManager.Get(beatmapSet); - }) - .ContinueWith(t => - { - Preview.Stopped += preview_Stopped; - playingStateChanged(true); - loading = false; - }); - return; - } - - Preview.Start(); - } - else - { - Preview.Stop(); loading = false; } } - private void preview_Stopped() => Playing.Value = false; - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index f437546888..35a6e5fc48 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -33,7 +33,6 @@ namespace osu.Game.Overlays private readonly FillFlowContainer resultCountsContainer; private readonly OsuSpriteText resultCountsText; private FillFlowContainer panels; - private DirectPanel playing; protected override Color4 BackgroundColour => OsuColour.FromHex(@"485e74"); protected override Color4 TrianglesColourLight => OsuColour.FromHex(@"465b71"); @@ -217,12 +216,6 @@ namespace osu.Game.Overlays panels.FadeOut(200); panels.Expire(); panels = null; - - if (playing != null) - { - playing.PreviewPlaying.Value = false; - playing = null; - } } if (BeatmapSets == null) return; @@ -253,17 +246,6 @@ namespace osu.Game.Overlays { if (panels != null) ScrollFlow.Remove(panels); ScrollFlow.Add(panels = newPanels); - - foreach (DirectPanel panel in p.Children) - panel.PreviewPlaying.ValueChanged += newValue => - { - if (newValue) - { - if (playing != null && playing != panel) - playing.PreviewPlaying.Value = false; - playing = panel; - } - }; }); } @@ -313,14 +295,6 @@ namespace osu.Game.Overlays api.Queue(getSetsRequest); } - protected override void PopOut() - { - base.PopOut(); - - if (playing != null) - playing.PreviewPlaying.Value = false; - } - private int distinctCount(List list) => list.Distinct().ToArray().Length; protected override void Dispose(bool isDisposing) From 572c3f518948a1729a34e24646f252d7d65d6e1e Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 25 May 2018 23:51:05 +0300 Subject: [PATCH 09/35] Stop preview playback when an overlay is popping out --- osu.Game/Overlays/BeatmapSet/Details.cs | 6 ------ osu.Game/Overlays/BeatmapSetOverlay.cs | 15 +++++++++------ osu.Game/Overlays/DirectOverlay.cs | 13 +++++++++++-- osu.Game/Overlays/UserProfileOverlay.cs | 10 +++++++--- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 8c16822cfc..ccd0fa04ab 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -102,12 +102,6 @@ namespace osu.Game.Overlays.BeatmapSet updateDisplay(); } - public void StopPreview() - { - if (preview.Playing) - preview.TriggerOnClick(); - } - private class DetailBox : Container { private readonly Container content; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 096f7bb63c..53bae54379 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -1,23 +1,24 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Allocation; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.BeatmapSet; -using osu.Game.Rulesets; using osu.Game.Overlays.BeatmapSet.Scores; -using System.Linq; +using osu.Game.Rulesets; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays { @@ -37,6 +38,7 @@ namespace osu.Game.Overlays private readonly ScrollContainer scroll; private BeatmapSetInfo beatmapSet; + private PreviewTrackManager previewTrackManager; public BeatmapSetInfo BeatmapSet { @@ -109,10 +111,11 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api, RulesetStore rulesets) + private void load(APIAccess api, RulesetStore rulesets, PreviewTrackManager previewTrackManager) { this.api = api; this.rulesets = rulesets; + this.previewTrackManager = previewTrackManager; } protected override void PopIn() @@ -124,7 +127,7 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - header.Details.StopPreview(); + previewTrackManager.CurrentTrack?.Stop(); FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => BeatmapSet = null); } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 35a6e5fc48..c69dc57342 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -4,12 +4,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using OpenTK; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -18,6 +18,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; using osu.Game.Overlays.SearchableList; using osu.Game.Rulesets; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Overlays @@ -176,11 +177,12 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, APIAccess api, RulesetStore rulesets, BeatmapManager beatmaps) + private void load(OsuColour colours, APIAccess api, RulesetStore rulesets, BeatmapManager beatmaps, PreviewTrackManager previewTrackManager) { this.api = api; this.rulesets = rulesets; this.beatmaps = beatmaps; + this.previewTrackManager = previewTrackManager; resultCountsContainer.Colour = colours.Yellow; @@ -254,6 +256,7 @@ namespace osu.Game.Overlays private readonly Bindable currentQuery = new Bindable(); private ScheduledDelegate queryChangedDebounce; + private PreviewTrackManager previewTrackManager; private void updateSearch() { @@ -297,6 +300,12 @@ namespace osu.Game.Overlays private int distinctCount(List list) => list.Distinct().ToArray().Length; + protected override void PopOut() + { + previewTrackManager.CurrentTrack?.Stop(); + base.PopOut(); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index a4dd0c9ec3..04a93dea23 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -2,14 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -18,6 +17,8 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Sections; using osu.Game.Users; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays { @@ -30,6 +31,7 @@ namespace osu.Game.Overlays protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; + private PreviewTrackManager previewTrackManager; public const float CONTENT_X_MARGIN = 50; @@ -56,9 +58,10 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(APIAccess api, PreviewTrackManager previewTrackManager) { this.api = api; + this.previewTrackManager = previewTrackManager; } protected override void PopIn() @@ -70,6 +73,7 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); + previewTrackManager.CurrentTrack?.Stop(); FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } From 88ac427ba67a216dff3dc654279fa95cac013df4 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 1 Jun 2018 21:06:37 +0300 Subject: [PATCH 10/35] PreviewTrack.Owner --- osu.Game/Audio/PreviewTrack.cs | 6 +++++- osu.Game/Audio/PreviewTrackManager.cs | 6 ++++-- osu.Game/Overlays/BeatmapSetOverlay.cs | 3 ++- osu.Game/Overlays/Direct/PlayButton.cs | 14 +++++++++++++- osu.Game/Overlays/DirectOverlay.cs | 3 ++- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 10dec7c394..d182df42e4 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -3,23 +3,27 @@ using System; using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Containers; namespace osu.Game.Audio { public class PreviewTrack { public readonly Track Track; + public readonly OverlayContainer Owner; + private readonly Action onStart; private readonly Action onStop; public event Action Stopped; public event Action Started; - public PreviewTrack(Track track, Action onStart, Action onStop) + public PreviewTrack(Track track, Action onStart, Action onStop, OverlayContainer owner) { Track = track; this.onStart = onStart; this.onStop = onStop; + Owner = owner; } public void Start() diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 5c2656b322..59a088d954 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.IO.Stores; using osu.Game.Beatmaps; @@ -45,11 +46,12 @@ namespace osu.Game.Audio }; } - public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) => + public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo, OverlayContainer previewOwner) => new PreviewTrack( trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"), onTrackStart, - onTrackStop); + onTrackStop, + previewOwner); protected override void Update() { diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 53bae54379..cccd51a621 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -127,7 +127,8 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - previewTrackManager.CurrentTrack?.Stop(); + if (previewTrackManager.CurrentTrack?.Owner == this) + previewTrackManager.CurrentTrack?.Stop(); FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => BeatmapSet = null); } diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 677f74540b..a5c9da4fba 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -35,6 +35,18 @@ namespace osu.Game.Overlays.Direct } } + private OverlayContainer parentOverlayContainer + { + get + { + var d = Parent; + while (!(d is OverlayContainer)) + d = d.Parent; + + return (OverlayContainer)d; + } + } + private PreviewTrackManager previewTrackManager; private Color4 hoverColour; @@ -95,7 +107,7 @@ namespace osu.Game.Overlays.Direct Task.Run(() => { loading = true; - return Preview = previewTrackManager.Get(beatmapSet); + return Preview = previewTrackManager.Get(beatmapSet, parentOverlayContainer); }) .ContinueWith(t => { diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index c69dc57342..72de8ebc84 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -302,7 +302,8 @@ namespace osu.Game.Overlays protected override void PopOut() { - previewTrackManager.CurrentTrack?.Stop(); + if (previewTrackManager.CurrentTrack?.Owner == this) + previewTrackManager.CurrentTrack?.Stop(); base.PopOut(); } From 556673266427af65322f62e4893dd224df330165 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 1 Jun 2018 21:36:30 +0300 Subject: [PATCH 11/35] Get rid of PreviewTrackManager.onTrackStart and PreviewTrackManager.onTrackStop delegates --- osu.Game/Audio/PreviewTrack.cs | 9 +----- osu.Game/Audio/PreviewTrackManager.cs | 43 ++++++++++++++------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index d182df42e4..1250d4864e 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -12,30 +12,23 @@ namespace osu.Game.Audio public readonly Track Track; public readonly OverlayContainer Owner; - private readonly Action onStart; - private readonly Action onStop; - public event Action Stopped; public event Action Started; - public PreviewTrack(Track track, Action onStart, Action onStop, OverlayContainer owner) + public PreviewTrack(Track track, OverlayContainer owner) { Track = track; - this.onStart = onStart; - this.onStop = onStop; Owner = owner; } public void Start() { - onStart?.Invoke(this); Track.Restart(); Started?.Invoke(); } public void Stop() { - onStop?.Invoke(); Track.Stop(); Stopped?.Invoke(); } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 59a088d954..4189468b77 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; @@ -15,9 +14,7 @@ namespace osu.Game.Audio { public class PreviewTrackManager : Component { - private Action onTrackStart; - private Action onTrackStop; - + private AudioManager audio; private TrackManager trackManager; private BindableDouble muteBindable; @@ -27,32 +24,36 @@ namespace osu.Game.Audio private void load(AudioManager audio, FrameworkConfigManager config) { trackManager = new TrackManager(new OnlineStore()); - muteBindable = new BindableDouble(); + this.audio = audio; audio.AddItem(trackManager); - config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); - onTrackStart = track => - { - CurrentTrack?.Stop(); - audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); - CurrentTrack = track; - }; - onTrackStop = () => - { - audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); - CurrentTrack = null; - }; + config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); } - public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo, OverlayContainer previewOwner) => - new PreviewTrack( + public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo, OverlayContainer previewOwner) + { + var previewTrack = new PreviewTrack( trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"), - onTrackStart, - onTrackStop, previewOwner); + previewTrack.Started += () => + { + CurrentTrack?.Stop(); + CurrentTrack = previewTrack; + audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); + }; + + previewTrack.Stopped += () => + { + CurrentTrack = null; + audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); + }; + + return previewTrack; + } + protected override void Update() { if (CurrentTrack?.Track.HasCompleted ?? false) From 330ce1904122d4169104ae500ce5338e3ba584e5 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 1 Jun 2018 23:36:25 +0300 Subject: [PATCH 12/35] Make PreviewTrack a component and use LoadComponentAsync --- osu.Game/Audio/PreviewTrack.cs | 19 +++++++++++++++---- osu.Game/Audio/PreviewTrackManager.cs | 23 +++++++++-------------- osu.Game/Overlays/Direct/PlayButton.cs | 13 ++++++------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 1250d4864e..d8898dfede 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -2,25 +2,36 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using osu.Framework.Allocation; using osu.Framework.Audio.Track; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; namespace osu.Game.Audio { - public class PreviewTrack + public class PreviewTrack : Component { - public readonly Track Track; + public Track Track { get; private set; } public readonly OverlayContainer Owner; + private readonly BeatmapSetInfo beatmapSetInfo; + public event Action Stopped; public event Action Started; - public PreviewTrack(Track track, OverlayContainer owner) + public PreviewTrack(BeatmapSetInfo beatmapSetInfo, OverlayContainer owner) { - Track = track; + this.beatmapSetInfo = beatmapSetInfo; Owner = owner; } + [BackgroundDependencyLoader] + private void load(PreviewTrackManager previewTrackManager) + { + Track = previewTrackManager.Get(this, beatmapSetInfo); + } + public void Start() { Track.Restart(); diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 4189468b77..a3da930af0 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -6,7 +6,6 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.IO.Stores; using osu.Game.Beatmaps; @@ -32,12 +31,16 @@ namespace osu.Game.Audio config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); } - public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo, OverlayContainer previewOwner) + protected override void Update() { - var previewTrack = new PreviewTrack( - trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"), - previewOwner); + if (CurrentTrack?.Track.HasCompleted ?? false) + CurrentTrack.Stop(); + base.Update(); + } + + public Track Get(PreviewTrack previewTrack, BeatmapSetInfo beatmapSetInfo) + { previewTrack.Started += () => { CurrentTrack?.Stop(); @@ -51,15 +54,7 @@ namespace osu.Game.Audio audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); }; - return previewTrack; - } - - protected override void Update() - { - if (CurrentTrack?.Track.HasCompleted ?? false) - CurrentTrack.Stop(); - - base.Update(); + return trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"); } } } diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index a5c9da4fba..36d1170380 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -104,18 +103,18 @@ namespace osu.Game.Overlays.Direct { if (Preview == null) { - Task.Run(() => - { - loading = true; - return Preview = previewTrackManager.Get(beatmapSet, parentOverlayContainer); - }) - .ContinueWith(t => + loading = true; + + LoadComponentAsync( + Preview = new PreviewTrack(beatmapSet, parentOverlayContainer), + t => { Preview.Started += () => Playing.Value = true; Preview.Stopped += () => Playing.Value = false; Preview.Start(); loading = false; }); + return true; } From 70120aa14c1018f1ecb18ecc5ed50852673f7fa3 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 2 Jun 2018 12:28:16 +0300 Subject: [PATCH 13/35] Remove unused previewTrackManager variable --- osu.Game/Overlays/Direct/PlayButton.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 36d1170380..92d1acbaa4 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -46,8 +46,6 @@ namespace osu.Game.Overlays.Direct } } - private PreviewTrackManager previewTrackManager; - private Color4 hoverColour; private readonly SpriteIcon icon; private readonly LoadingAnimation loadingAnimation; @@ -94,7 +92,6 @@ namespace osu.Game.Overlays.Direct private void load(OsuColour colour, PreviewTrackManager previewTrackManager) { hoverColour = colour.Yellow; - this.previewTrackManager = previewTrackManager; } protected override bool OnClick(InputState state) From 5bb6757cbdbc24cc130cb2cbea643353032c7ae6 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 2 Jun 2018 13:03:17 +0300 Subject: [PATCH 14/35] Remove unused previewTrackManager parameter --- osu.Game/Overlays/Direct/PlayButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 92d1acbaa4..dc8042a137 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -89,7 +89,7 @@ namespace osu.Game.Overlays.Direct } [BackgroundDependencyLoader] - private void load(OsuColour colour, PreviewTrackManager previewTrackManager) + private void load(OsuColour colour) { hoverColour = colour.Yellow; } From 9b69e1825da552b934c539ee6b499fc2feb0864a Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 2 Jun 2018 22:06:45 +0300 Subject: [PATCH 15/35] Make PreviewTrack.owner private --- osu.Game/Audio/PreviewTrack.cs | 12 +++++++++--- osu.Game/Overlays/BeatmapSetOverlay.cs | 3 +-- osu.Game/Overlays/DirectOverlay.cs | 3 +-- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index d8898dfede..cfc47497d0 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -13,7 +13,7 @@ namespace osu.Game.Audio public class PreviewTrack : Component { public Track Track { get; private set; } - public readonly OverlayContainer Owner; + private readonly OverlayContainer owner; private readonly BeatmapSetInfo beatmapSetInfo; @@ -23,7 +23,7 @@ namespace osu.Game.Audio public PreviewTrack(BeatmapSetInfo beatmapSetInfo, OverlayContainer owner) { this.beatmapSetInfo = beatmapSetInfo; - Owner = owner; + this.owner = owner; } [BackgroundDependencyLoader] @@ -38,8 +38,14 @@ namespace osu.Game.Audio Started?.Invoke(); } - public void Stop() + /// + /// Stop preview playback + /// + /// An which is probably the owner of this + public void Stop(OverlayContainer source = null) { + if (source != null && owner != source) + return; Track.Stop(); Stopped?.Invoke(); } diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index cccd51a621..234d91b9e6 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -127,8 +127,7 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - if (previewTrackManager.CurrentTrack?.Owner == this) - previewTrackManager.CurrentTrack?.Stop(); + previewTrackManager.CurrentTrack?.Stop(this); FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => BeatmapSet = null); } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 72de8ebc84..406554eb5e 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -302,8 +302,7 @@ namespace osu.Game.Overlays protected override void PopOut() { - if (previewTrackManager.CurrentTrack?.Owner == this) - previewTrackManager.CurrentTrack?.Stop(); + previewTrackManager.CurrentTrack?.Stop(this); base.PopOut(); } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 04a93dea23..6a8dd30890 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - previewTrackManager.CurrentTrack?.Stop(); + previewTrackManager.CurrentTrack?.Stop(this); FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } From dd75cd973be81bc6ae960b36fed441f2b0e92891 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 7 Jun 2018 01:13:35 +0900 Subject: [PATCH 16/35] Show UI mouse cursor when hovering volume meters during gameplay Also adds a hover animation. --- osu.Game/Overlays/Volume/VolumeMeter.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 64106967f4..04a04bc86e 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.MathUtils; using osu.Game.Graphics; @@ -189,5 +190,18 @@ namespace osu.Game.Overlays.Volume } public bool OnReleased(GlobalAction action) => false; + + private const float transition_length = 500; + + protected override bool OnHover(InputState state) + { + this.ScaleTo(1.04f, transition_length, Easing.OutExpo); + return true; + } + + protected override void OnHoverLost(InputState state) + { + this.ScaleTo(1f, transition_length, Easing.OutExpo); + } } } From 17ba129e616764855f61d980e6396527fde05783 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 7 Jun 2018 01:14:43 +0900 Subject: [PATCH 17/35] Make volume controls stay open when hovered Closes #2743. --- osu.Game/Overlays/VolumeOverlay.cs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index f922c507f7..5a3d51c00a 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Input.Bindings; @@ -86,16 +87,10 @@ namespace osu.Game.Overlays { base.LoadComplete(); - volumeMeterMaster.Bindable.ValueChanged += _ => settingChanged(); - volumeMeterEffect.Bindable.ValueChanged += _ => settingChanged(); - volumeMeterMusic.Bindable.ValueChanged += _ => settingChanged(); - muteButton.Current.ValueChanged += _ => settingChanged(); - } - - private void settingChanged() - { - Show(); - schedulePopOut(); + volumeMeterMaster.Bindable.ValueChanged += _ => Show(); + volumeMeterEffect.Bindable.ValueChanged += _ => Show(); + volumeMeterMusic.Bindable.ValueChanged += _ => Show(); + muteButton.Current.ValueChanged += _ => Show(); } public bool Adjust(GlobalAction action) @@ -140,10 +135,22 @@ namespace osu.Game.Overlays this.FadeOut(100); } + protected override bool OnMouseMove(InputState state) + { + // keep the scheduled event correctly timed as long as we have movement. + schedulePopOut(); + return base.OnMouseMove(state); + } + private void schedulePopOut() { popOutDelegate?.Cancel(); - this.Delay(1000).Schedule(Hide, out popOutDelegate); + this.Delay(1000).Schedule(() => + { + // only actually hide if the mouse isn't within our bounds. + if (!ScreenSpaceDrawQuad.Contains(GetContainingInputManager().CurrentState.Mouse.Position)) + Hide(); + }, out popOutDelegate); } } } From 3033294df1a583097d64b0b35f954bba13d3b2b3 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 7 Jun 2018 14:30:11 +0300 Subject: [PATCH 18/35] Stop Preview on BeatmapSet change --- osu.Game/Overlays/Direct/PlayButton.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index dc8042a137..607d6d218f 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -29,6 +29,7 @@ namespace osu.Game.Overlays.Direct if (value == beatmapSet) return; beatmapSet = value; + Preview.Stop(parentOverlayContainer); Playing.Value = false; Preview = null; } From ab6699b1fb599c7d8d6da4f30afb7bd986c17494 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 7 Jun 2018 14:40:41 +0300 Subject: [PATCH 19/35] Stop DirectOverlay preview on search update --- osu.Game/Overlays/DirectOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 406554eb5e..fb1be8e05e 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -273,6 +273,8 @@ namespace osu.Game.Overlays if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return; + previewTrackManager.CurrentTrack?.Stop(this); + getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value ?? string.Empty, ((FilterControl)Filter).Ruleset.Value, Filter.DisplayStyleControl.Dropdown.Current.Value, From 1fdbd2047151f42fb1f59fdb15fabfd423bf78e4 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 7 Jun 2018 14:50:21 +0300 Subject: [PATCH 20/35] Nullref quickfix in PlayButton --- osu.Game/Overlays/Direct/PlayButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 607d6d218f..94c3cb748f 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Direct if (value == beatmapSet) return; beatmapSet = value; - Preview.Stop(parentOverlayContainer); + Preview?.Stop(parentOverlayContainer); Playing.Value = false; Preview = null; } From 2a18625b2c95f2f2fda8981365f177417e339969 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 16:46:27 +0900 Subject: [PATCH 21/35] Correctly block scroll events when hovering controls --- osu.Game/Overlays/Volume/VolumeMeter.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 451809867d..29fef48d13 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -177,12 +177,13 @@ namespace osu.Game.Overlays.Volume { float amount = adjust_step * direction; - var mouse = GetContainingInputManager().CurrentState.Mouse; - if (mouse.HasPreciseScroll) + // handle the case where the OnPressed action was actually a mouse wheel. + // this allows for precise wheel handling. + var state = GetContainingInputManager().CurrentState; + if (state.Mouse?.ScrollDelta.Y != 0) { - float scrollDelta = mouse.ScrollDelta.Y; - if (scrollDelta != 0) - amount *= Math.Abs(scrollDelta / 10); + OnScroll(state); + return; } Volume += amount; @@ -205,6 +206,14 @@ namespace osu.Game.Overlays.Volume return false; } + protected override bool OnScroll(InputState state) + { + double amount = adjust_step * state.Mouse.ScrollDelta.Y * (state.Mouse.HasPreciseScroll ? 0.5f : 1); + + Volume += Math.Sign(amount) * Math.Max(0.01, Math.Abs(amount)); + return true; + } + public bool OnReleased(GlobalAction action) => false; private const float transition_length = 500; From a55bf82fd9c4c76f269fb08fd2dbd4697194c9e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 16:46:48 +0900 Subject: [PATCH 22/35] Handle hover blocking in VolumeOverlay to ensure correct hide scheduling --- osu.Game/Overlays/Volume/VolumeMeter.cs | 2 +- osu.Game/Overlays/VolumeOverlay.cs | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 29fef48d13..b3dd06022e 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -221,7 +221,7 @@ namespace osu.Game.Overlays.Volume protected override bool OnHover(InputState state) { this.ScaleTo(1.04f, transition_length, Easing.OutExpo); - return true; + return false; } protected override void OnHoverLost(InputState state) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 5a3d51c00a..a56a160e20 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -142,13 +142,18 @@ namespace osu.Game.Overlays return base.OnMouseMove(state); } + protected override bool OnHover(InputState state) + { + Show(); + return true; + } + private void schedulePopOut() { popOutDelegate?.Cancel(); this.Delay(1000).Schedule(() => { - // only actually hide if the mouse isn't within our bounds. - if (!ScreenSpaceDrawQuad.Contains(GetContainingInputManager().CurrentState.Mouse.Position)) + if (!IsHovered) Hide(); }, out popOutDelegate); } From e0b68e4e09c0838c93e3c96746b284c5110314c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 16:47:10 +0900 Subject: [PATCH 23/35] Fix hide re-schedule not triggering on noop state change --- osu.Game/Overlays/VolumeOverlay.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index a56a160e20..24afa414d6 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -122,6 +122,14 @@ namespace osu.Game.Overlays private ScheduledDelegate popOutDelegate; + public override void Show() + { + if (State == Visibility.Visible) + schedulePopOut(); + + base.Show(); + } + protected override void PopIn() { ClearTransforms(); From cee5be1d56028f9c0858a6923583ba5ed8ce9e2b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 17:03:56 +0900 Subject: [PATCH 24/35] Improve precision wheel adjustment handling --- osu.Game/Overlays/Volume/VolumeMeter.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index b3dd06022e..4d20166784 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -206,11 +206,18 @@ namespace osu.Game.Overlays.Volume return false; } + // because volume precision is set to 0.01, this local is required to keep track of more precise adjustments and only apply when possible. + private double scrollAmount; + protected override bool OnScroll(InputState state) { - double amount = adjust_step * state.Mouse.ScrollDelta.Y * (state.Mouse.HasPreciseScroll ? 0.5f : 1); + scrollAmount += adjust_step * state.Mouse.ScrollDelta.Y * (state.Mouse.HasPreciseScroll ? 0.1f : 1); - Volume += Math.Sign(amount) * Math.Max(0.01, Math.Abs(amount)); + if (Math.Abs(scrollAmount) < Bindable.Precision) + return true; + + Volume += scrollAmount; + scrollAmount = 0; return true; } From 5d105cd08d036d78009733546c80711c1503e592 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jun 2018 17:15:04 +0900 Subject: [PATCH 25/35] Avoid errors being logged when importing beatmaps while logged out --- osu.Game/Beatmaps/BeatmapManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 895b47d62b..0b45aa9506 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -390,6 +390,9 @@ namespace osu.Game.Beatmaps if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null) return true; + if (api.State != APIState.Online) + return false; + Logger.Log("Attempting online lookup for IDs...", LoggingTarget.Database); try From b2066c5d739d55e05d8a6dfb9f77f9e84f91fb29 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Jun 2018 16:19:07 +0900 Subject: [PATCH 26/35] Rework preview tracks to reduce usage complexities --- osu.Game/Audio/IPreviewTrackOwner.cs | 16 ++++ osu.Game/Audio/PreviewTrack.cs | 88 +++++++++++++------ osu.Game/Audio/PreviewTrackManager.cs | 59 +++++++++---- .../Containers/OsuFocusedOverlayContainer.cs | 24 ++++- .../BeatmapSet/Buttons/PreviewButton.cs | 2 +- osu.Game/Overlays/BeatmapSetOverlay.cs | 7 +- osu.Game/Overlays/Direct/DirectPanel.cs | 4 +- osu.Game/Overlays/Direct/PlayButton.cs | 48 +++++----- osu.Game/Overlays/DirectOverlay.cs | 8 +- osu.Game/Overlays/UserProfileOverlay.cs | 6 +- 10 files changed, 172 insertions(+), 90 deletions(-) create mode 100644 osu.Game/Audio/IPreviewTrackOwner.cs diff --git a/osu.Game/Audio/IPreviewTrackOwner.cs b/osu.Game/Audio/IPreviewTrackOwner.cs new file mode 100644 index 0000000000..f166096601 --- /dev/null +++ b/osu.Game/Audio/IPreviewTrackOwner.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Audio +{ + /// + /// Interface for objects that can own s. + /// + /// + /// s can cancel the currently playing through the + /// global if they're the owner of the playing . + /// + public interface IPreviewTrackOwner + { + } +} diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index cfc47497d0..59baa86f80 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -5,49 +5,87 @@ using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; +using osu.Framework.Threading; namespace osu.Game.Audio { - public class PreviewTrack : Component + public abstract class PreviewTrack : Component { - public Track Track { get; private set; } - private readonly OverlayContainer owner; - - private readonly BeatmapSetInfo beatmapSetInfo; - public event Action Stopped; public event Action Started; - public PreviewTrack(BeatmapSetInfo beatmapSetInfo, OverlayContainer owner) - { - this.beatmapSetInfo = beatmapSetInfo; - this.owner = owner; - } + private Track track; + private bool wasPlaying; [BackgroundDependencyLoader] - private void load(PreviewTrackManager previewTrackManager) + private void load() { - Track = previewTrackManager.Get(this, beatmapSetInfo); - } + track = GetTrack(); - public void Start() - { - Track.Restart(); - Started?.Invoke(); + if (track != null) + track.Looping = false; } /// - /// Stop preview playback + /// Length of the track. /// - /// An which is probably the owner of this - public void Stop(OverlayContainer source = null) + public double Length => track?.Length ?? 0; + + /// + /// The current track time. + /// + public double CurrentTime => track?.CurrentTime ?? 0; + + /// + /// Whether the track is loaded. + /// + public bool TrackLoaded => track?.IsLoaded ?? false; + + protected override void Update() { - if (source != null && owner != source) + base.Update(); + + // Todo: Track currently doesn't signal its completion, so we have to handle it manually + if (track != null && wasPlaying && track.HasCompleted) + Stop(); + } + + private ScheduledDelegate startDelegate; + + public void Start() => startDelegate = Schedule(() => + { + if (!IsLoaded) return; - Track.Stop(); + + if (track == null) + return; + + if (wasPlaying) + return; + wasPlaying = true; + + track.Restart(); + Started?.Invoke(); + }); + + public void Stop() + { + startDelegate?.Cancel(); + + if (!IsLoaded) + return; + + if (track == null) + return; + + if (!wasPlaying) + return; + wasPlaying = false; + + track.Stop(); Stopped?.Invoke(); } + + protected abstract Track GetTrack(); } } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index a3da930af0..499e4a1eea 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -13,17 +13,17 @@ namespace osu.Game.Audio { public class PreviewTrackManager : Component { + private readonly BindableDouble muteBindable = new BindableDouble(); + private AudioManager audio; private TrackManager trackManager; - private BindableDouble muteBindable; - public PreviewTrack CurrentTrack { get; private set; } + private TrackManagerPreviewTrack current; [BackgroundDependencyLoader] private void load(AudioManager audio, FrameworkConfigManager config) { trackManager = new TrackManager(new OnlineStore()); - muteBindable = new BindableDouble(); this.audio = audio; audio.AddItem(trackManager); @@ -31,30 +31,55 @@ namespace osu.Game.Audio config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); } - protected override void Update() + public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) { - if (CurrentTrack?.Track.HasCompleted ?? false) - CurrentTrack.Stop(); + var track = new TrackManagerPreviewTrack(beatmapSetInfo, trackManager); - base.Update(); - } - - public Track Get(PreviewTrack previewTrack, BeatmapSetInfo beatmapSetInfo) - { - previewTrack.Started += () => + track.Started += () => { - CurrentTrack?.Stop(); - CurrentTrack = previewTrack; + current?.Stop(); + current = track; audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); }; - previewTrack.Stopped += () => + track.Stopped += () => { - CurrentTrack = null; + current = null; audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); }; - return trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"); + return track; + } + + public void Stop(IPreviewTrackOwner source) + { + if (current?.Owner != source) + return; + + current?.Stop(); + current = null; + } + + private class TrackManagerPreviewTrack : PreviewTrack + { + public IPreviewTrackOwner Owner { get; private set; } + + private readonly BeatmapSetInfo beatmapSetInfo; + private readonly TrackManager trackManager; + + public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) + { + this.beatmapSetInfo = beatmapSetInfo; + this.trackManager = trackManager; + } + + [BackgroundDependencyLoader] + private void load(IPreviewTrackOwner owner) + { + Owner = owner; + } + + protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"); } } } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 0528f7b3ae..e3179b5631 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -8,20 +8,32 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using OpenTK; using osu.Framework.Configuration; +using osu.Game.Audio; using osu.Game.Overlays; namespace osu.Game.Graphics.Containers { - public class OsuFocusedOverlayContainer : FocusedOverlayContainer + public class OsuFocusedOverlayContainer : FocusedOverlayContainer, IPreviewTrackOwner { private SampleChannel samplePopIn; private SampleChannel samplePopOut; + private PreviewTrackManager previewTrackManager; + protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); - [BackgroundDependencyLoader(true)] - private void load(OsuGame osuGame, AudioManager audio) + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) { + var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + dependencies.CacheAs(this); + return dependencies; + } + + [BackgroundDependencyLoader(true)] + private void load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager) + { + this.previewTrackManager = previewTrackManager; + if (osuGame != null) OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); @@ -66,5 +78,11 @@ namespace osu.Game.Graphics.Containers break; } } + + protected override void PopOut() + { + base.PopOut(); + previewTrackManager.Stop(this); + } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 78bc77efe8..505b7a7540 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons if (Playing.Value && preview != null) { // prevent negative (potential infinite) width if a track without length was loaded - progress.Width = preview.Track.Length > 0 ? (float)(preview.Track.CurrentTime / preview.Track.Length) : 0f; + progress.Width = preview.Length > 0 ? (float)(preview.CurrentTime / preview.Length) : 0f; } else progress.Width = 0; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 234d91b9e6..88f0a72ddf 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; -using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -38,7 +37,6 @@ namespace osu.Game.Overlays private readonly ScrollContainer scroll; private BeatmapSetInfo beatmapSet; - private PreviewTrackManager previewTrackManager; public BeatmapSetInfo BeatmapSet { @@ -111,11 +109,10 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api, RulesetStore rulesets, PreviewTrackManager previewTrackManager) + private void load(APIAccess api, RulesetStore rulesets) { this.api = api; this.rulesets = rulesets; - this.previewTrackManager = previewTrackManager; } protected override void PopIn() @@ -127,8 +124,6 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - previewTrackManager.CurrentTrack?.Stop(this); - FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => BeatmapSet = null); } diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 93f28194e4..e63c290ce5 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -113,9 +113,9 @@ namespace osu.Game.Overlays.Direct { base.Update(); - if (PreviewPlaying && Preview != null && Preview.Track.IsLoaded) + if (PreviewPlaying && Preview != null && Preview.TrackLoaded) { - PreviewBar.Width = (float)(Preview.Track.CurrentTime / Preview.Track.Length); + PreviewBar.Width = (float)(Preview.CurrentTime / Preview.Length); } } diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index e6f409cbce..d9881f2b23 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -29,21 +29,14 @@ namespace osu.Game.Overlays.Direct if (value == beatmapSet) return; beatmapSet = value; - Preview?.Stop(parentOverlayContainer); + if (Preview != null) + { + Preview.Stop(); + RemoveInternal(Preview); + Preview = null; + } + Playing.Value = false; - Preview = null; - } - } - - private OverlayContainer parentOverlayContainer - { - get - { - var d = Parent; - while (!(d is OverlayContainer)) - d = d.Parent; - - return (OverlayContainer)d; } } @@ -89,9 +82,13 @@ namespace osu.Game.Overlays.Direct Playing.ValueChanged += playingStateChanged; } + private PreviewTrackManager previewTrackManager; + [BackgroundDependencyLoader] - private void load(OsuColour colour) + private void load(OsuColour colour, PreviewTrackManager previewTrackManager) { + this.previewTrackManager = previewTrackManager; + hoverColour = colour.Yellow; } @@ -103,15 +100,18 @@ namespace osu.Game.Overlays.Direct { loading = true; - LoadComponentAsync( - Preview = new PreviewTrack(beatmapSet, parentOverlayContainer), - t => - { - Preview.Started += () => Playing.Value = true; - Preview.Stopped += () => Playing.Value = false; - Preview.Start(); - loading = false; - }); + Preview = previewTrackManager.Get(beatmapSet); + Preview.Started += () => Playing.Value = true; + Preview.Stopped += () => Playing.Value = false; + + LoadComponentAsync(Preview, t => + { + AddInternal(t); + + Preview.Start(); + + loading = false; + }); return true; } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 5f5ef44949..c28ecb3c9f 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -262,7 +262,7 @@ namespace osu.Game.Overlays if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return; - previewTrackManager.CurrentTrack?.Stop(this); + previewTrackManager.Stop(this); getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value ?? string.Empty, ((FilterControl)Filter).Ruleset.Value, @@ -289,12 +289,6 @@ namespace osu.Game.Overlays private int distinctCount(List list) => list.Distinct().ToArray().Length; - protected override void PopOut() - { - previewTrackManager.CurrentTrack?.Stop(this); - base.PopOut(); - } - public class ResultCounts { public readonly int Artists; diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 6a8dd30890..745f2f3def 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; -using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -31,7 +30,6 @@ namespace osu.Game.Overlays protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; - private PreviewTrackManager previewTrackManager; public const float CONTENT_X_MARGIN = 50; @@ -58,10 +56,9 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api, PreviewTrackManager previewTrackManager) + private void load(APIAccess api) { this.api = api; - this.previewTrackManager = previewTrackManager; } protected override void PopIn() @@ -73,7 +70,6 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - previewTrackManager.CurrentTrack?.Stop(this); FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } From 40ed3fdd05df4d11d01edbac79373b91c03bcbf3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Jun 2018 18:45:32 +0900 Subject: [PATCH 27/35] Fix possible incorrect order of events due to threaded load --- osu.Game/Overlays/Direct/PlayButton.cs | 36 ++++++++++++++------------ 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index d9881f2b23..4bf6cf2bf7 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -96,27 +96,29 @@ namespace osu.Game.Overlays.Direct { if (!Playing.Value) { - if (Preview == null) + if (Preview != null) { - loading = true; - - Preview = previewTrackManager.Get(beatmapSet); - Preview.Started += () => Playing.Value = true; - Preview.Stopped += () => Playing.Value = false; - - LoadComponentAsync(Preview, t => - { - AddInternal(t); - - Preview.Start(); - - loading = false; - }); - + Preview.Start(); return true; } - Preview.Start(); + loading = true; + + var loadingPreview = previewTrackManager.Get(beatmapSet); + loadingPreview.Started += () => Playing.Value = true; + loadingPreview.Stopped += () => Playing.Value = false; + + LoadComponentAsync(Preview = loadingPreview, t => + { + if (Preview != loadingPreview) + return; + + AddInternal(t); + + Preview.Start(); + + loading = false; + }); } else Preview?.Stop(); From 63a6fc25963ef227429f02ba7bce093e0a441a0d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Jun 2018 18:54:42 +0900 Subject: [PATCH 28/35] XMLDoc all the things --- osu.Game/Audio/PreviewTrack.cs | 16 ++++++++++++++++ osu.Game/Audio/PreviewTrackManager.cs | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 59baa86f80..5fd3dbfe8f 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -11,7 +11,14 @@ namespace osu.Game.Audio { public abstract class PreviewTrack : Component { + /// + /// Invoked when this has stopped playing. + /// public event Action Stopped; + + /// + /// Invoked when this has started playing. + /// public event Action Started; private Track track; @@ -52,6 +59,9 @@ namespace osu.Game.Audio private ScheduledDelegate startDelegate; + /// + /// Starts playing this . + /// public void Start() => startDelegate = Schedule(() => { if (!IsLoaded) @@ -68,6 +78,9 @@ namespace osu.Game.Audio Started?.Invoke(); }); + /// + /// Stops playing this . + /// public void Stop() { startDelegate?.Cancel(); @@ -86,6 +99,9 @@ namespace osu.Game.Audio Stopped?.Invoke(); } + /// + /// Retrieves the audio track. + /// protected abstract Track GetTrack(); } } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 499e4a1eea..8febf8e621 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -11,6 +11,9 @@ using osu.Game.Beatmaps; namespace osu.Game.Audio { + /// + /// A central store for the retrieval of s. + /// public class PreviewTrackManager : Component { private readonly BindableDouble muteBindable = new BindableDouble(); @@ -31,6 +34,11 @@ namespace osu.Game.Audio config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); } + /// + /// Retrieves a for a . + /// + /// The to retrieve the preview track for. + /// The playable . public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) { var track = new TrackManagerPreviewTrack(beatmapSetInfo, trackManager); @@ -51,6 +59,15 @@ namespace osu.Game.Audio return track; } + /// + /// Stops the currently playing . + /// + /// + /// Only the immediate owner (an object that implements ) of the playing + /// can globally stop the currently playing . The object holding a reference to the + /// can always stop the themselves through . + /// + /// The which may be the owner of the . public void Stop(IPreviewTrackOwner source) { if (current?.Owner != source) From 1932399521c87a672f657422a853bfbfec44fc7d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Jun 2018 19:31:07 +0900 Subject: [PATCH 29/35] Add testcases --- .../Visual/TestCasePreviewTrackManager.cs | 131 ++++++++++++++++++ osu.Game/Audio/PreviewTrack.cs | 5 + osu.Game/Audio/PreviewTrackManager.cs | 9 +- 3 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs diff --git a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs new file mode 100644 index 0000000000..b394202706 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs @@ -0,0 +1,131 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Containers; +using osu.Game.Audio; +using osu.Game.Beatmaps; + +namespace osu.Game.Tests.Visual +{ + public class TestCasePreviewTrackManager : OsuTestCase, IPreviewTrackOwner + { + private readonly PreviewTrackManager trackManager = new TestPreviewTrackManager(); + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + dependencies.CacheAs(trackManager); + dependencies.CacheAs(this); + return dependencies; + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(trackManager); + } + + [Test] + public void TestStartStop() + { + PreviewTrack track = null; + + AddStep("get track", () => track = getOwnedTrack()); + AddStep("start", () => track.Start()); + AddAssert("started", () => track.IsRunning); + AddStep("stop", () => track.Stop()); + AddAssert("stopped", () => !track.IsRunning); + } + + [Test] + public void TestStartMultipleTracks() + { + PreviewTrack track1 = null; + PreviewTrack track2 = null; + + AddStep("get tracks", () => + { + track1 = getOwnedTrack(); + track2 = getOwnedTrack(); + }); + + AddStep("start track 1", () => track1.Start()); + AddStep("start track 2", () => track2.Start()); + AddAssert("track 1 stopped", () => !track1.IsRunning); + AddAssert("track 2 started", () => track2.IsRunning); + } + + [Test] + public void TestCancelFromOwner() + { + PreviewTrack track = null; + + AddStep("get track", () => track = getOwnedTrack()); + AddStep("start", () => track.Start()); + AddStep("stop by owner", () => trackManager.Stop(this)); + AddAssert("stopped", () => !track.IsRunning); + } + + [Test] + public void TestCancelFromNonOwner() + { + TestTrackOwner owner = null; + PreviewTrack track = null; + + AddStep("get track", () => AddInternal(owner = new TestTrackOwner(track = getTrack()))); + AddStep("start", () => track.Start()); + AddStep("attempt stop", () => trackManager.Stop(this)); + AddAssert("not stopped", () => track.IsRunning); + AddStep("stop by true owner", () => trackManager.Stop(owner)); + AddAssert("stopped", () => !track.IsRunning); + } + + private PreviewTrack getTrack() => trackManager.Get(null); + + private PreviewTrack getOwnedTrack() + { + var track = getTrack(); + + AddInternal(track); + + return track; + } + + private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner + { + private readonly PreviewTrack track; + + public TestTrackOwner(PreviewTrack track) + { + this.track = track; + + AddInternal(track); + } + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + dependencies.CacheAs(this); + return dependencies; + } + } + + private class TestPreviewTrackManager : PreviewTrackManager + { + protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) => new TestPreviewTrack(beatmapSetInfo, trackManager); + + protected class TestPreviewTrack : TrackManagerPreviewTrack + { + public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) + : base(beatmapSetInfo, trackManager) + { + } + + protected override Track GetTrack() => new TrackVirtual { Length = 100000 }; + } + } + } +} diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 5fd3dbfe8f..50366e35eb 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -48,6 +48,11 @@ namespace osu.Game.Audio /// public bool TrackLoaded => track?.IsLoaded ?? false; + /// + /// Whether the track is playing. + /// + public bool IsRunning => track?.IsRunning ?? false; + protected override void Update() { base.Update(); diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 8febf8e621..56bedc9dd2 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -41,7 +41,7 @@ namespace osu.Game.Audio /// The playable . public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo) { - var track = new TrackManagerPreviewTrack(beatmapSetInfo, trackManager); + var track = CreatePreviewTrack(beatmapSetInfo, trackManager); track.Started += () => { @@ -77,7 +77,12 @@ namespace osu.Game.Audio current = null; } - private class TrackManagerPreviewTrack : PreviewTrack + /// + /// Creates the . + /// + protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) => new TrackManagerPreviewTrack(beatmapSetInfo, trackManager); + + protected class TrackManagerPreviewTrack : PreviewTrack { public IPreviewTrackOwner Owner { get; private set; } From 15bb301d14bf0a6c0ee7a1c9fa3e6dfe22f68c5f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Jun 2018 19:37:42 +0900 Subject: [PATCH 30/35] Remove unused field --- osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs index b394202706..7d02519007 100644 --- a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs @@ -96,12 +96,8 @@ namespace osu.Game.Tests.Visual private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner { - private readonly PreviewTrack track; - public TestTrackOwner(PreviewTrack track) { - this.track = track; - AddInternal(track); } From 4b2b1f51f946d858aa44dd65872cb3dbe068e272 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Jun 2018 12:12:59 +0900 Subject: [PATCH 31/35] Apply some code review --- osu.Game/Audio/PreviewTrack.cs | 21 ++----- osu.Game/Overlays/Direct/PlayButton.cs | 87 +++++++++++--------------- 2 files changed, 44 insertions(+), 64 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 50366e35eb..3c9122b941 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -22,15 +22,12 @@ namespace osu.Game.Audio public event Action Started; private Track track; - private bool wasPlaying; + private bool hasStarted; [BackgroundDependencyLoader] private void load() { track = GetTrack(); - - if (track != null) - track.Looping = false; } /// @@ -58,7 +55,7 @@ namespace osu.Game.Audio base.Update(); // Todo: Track currently doesn't signal its completion, so we have to handle it manually - if (track != null && wasPlaying && track.HasCompleted) + if (hasStarted && track.HasCompleted) Stop(); } @@ -69,15 +66,12 @@ namespace osu.Game.Audio /// public void Start() => startDelegate = Schedule(() => { - if (!IsLoaded) - return; - if (track == null) return; - if (wasPlaying) + if (hasStarted) return; - wasPlaying = true; + hasStarted = true; track.Restart(); Started?.Invoke(); @@ -90,15 +84,12 @@ namespace osu.Game.Audio { startDelegate?.Cancel(); - if (!IsLoaded) - return; - if (track == null) return; - if (!wasPlaying) + if (!hasStarted) return; - wasPlaying = false; + hasStarted = false; track.Stop(); Stopped?.Invoke(); diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 4bf6cf2bf7..4b91a3d700 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Direct { public class PlayButton : Container { - public readonly Bindable Playing = new Bindable(); + public readonly BindableBool Playing = new BindableBool(); public PreviewTrack Preview { get; private set; } private BeatmapSetInfo beatmapSet; @@ -29,12 +29,9 @@ namespace osu.Game.Overlays.Direct if (value == beatmapSet) return; beatmapSet = value; - if (Preview != null) - { - Preview.Stop(); - RemoveInternal(Preview); - Preview = null; - } + Preview?.Stop(); + Preview?.Expire(); + Preview = null; Playing.Value = false; } @@ -51,15 +48,9 @@ namespace osu.Game.Overlays.Direct set { if (value) - { loadingAnimation.Show(); - icon.FadeOut(transition_duration * 5, Easing.OutQuint); - } else - { loadingAnimation.Hide(); - icon.FadeIn(transition_duration, Easing.OutQuint); - } } } @@ -94,35 +85,7 @@ namespace osu.Game.Overlays.Direct protected override bool OnClick(InputState state) { - if (!Playing.Value) - { - if (Preview != null) - { - Preview.Start(); - return true; - } - - loading = true; - - var loadingPreview = previewTrackManager.Get(beatmapSet); - loadingPreview.Started += () => Playing.Value = true; - loadingPreview.Stopped += () => Playing.Value = false; - - LoadComponentAsync(Preview = loadingPreview, t => - { - if (Preview != loadingPreview) - return; - - AddInternal(t); - - Preview.Start(); - - loading = false; - }); - } - else - Preview?.Stop(); - + Playing.Toggle(); return true; } @@ -141,17 +104,43 @@ namespace osu.Game.Overlays.Direct private void playingStateChanged(bool playing) { - if (playing && BeatmapSet == null) - { - Playing.Value = false; - return; - } - icon.Icon = playing ? FontAwesome.fa_stop : FontAwesome.fa_play; icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); - if (!playing) + if (playing) { + if (BeatmapSet == null) + { + Playing.Value = false; + return; + } + + if (Preview != null) + { + Preview.Start(); + return; + } + + loading = true; + + LoadComponentAsync(Preview = previewTrackManager.Get(beatmapSet), preview => + { + // beatmapset may have changed. + if (Preview != preview) + return; + + AddInternal(preview); + loading = false; + preview.Stopped += () => Playing.Value = false; + + // user may have changed their mind. + if (Playing) + preview.Start(); + }); + } + else + { + Preview?.Stop(); loading = false; } } From 73e13e2d63c3d9a6509cb0c664399f458781b3a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Jun 2018 12:35:43 +0900 Subject: [PATCH 32/35] Rename Stop to StopAnyPlaying for clarity --- osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs | 6 +++--- osu.Game/Audio/PreviewTrackManager.cs | 8 ++++---- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 2 +- osu.Game/Overlays/DirectOverlay.cs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs index 7d02519007..d711d501fe 100644 --- a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual AddStep("get track", () => track = getOwnedTrack()); AddStep("start", () => track.Start()); - AddStep("stop by owner", () => trackManager.Stop(this)); + AddStep("stop by owner", () => trackManager.StopAnyPlaying(this)); AddAssert("stopped", () => !track.IsRunning); } @@ -77,9 +77,9 @@ namespace osu.Game.Tests.Visual AddStep("get track", () => AddInternal(owner = new TestTrackOwner(track = getTrack()))); AddStep("start", () => track.Start()); - AddStep("attempt stop", () => trackManager.Stop(this)); + AddStep("attempt stop", () => trackManager.StopAnyPlaying(this)); AddAssert("not stopped", () => track.IsRunning); - AddStep("stop by true owner", () => trackManager.Stop(owner)); + AddStep("stop by true owner", () => trackManager.StopAnyPlaying(owner)); AddAssert("stopped", () => !track.IsRunning); } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 56bedc9dd2..07fbe86ff4 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -60,7 +60,7 @@ namespace osu.Game.Audio } /// - /// Stops the currently playing . + /// Stops any currently playing . /// /// /// Only the immediate owner (an object that implements ) of the playing @@ -68,12 +68,12 @@ namespace osu.Game.Audio /// can always stop the themselves through . /// /// The which may be the owner of the . - public void Stop(IPreviewTrackOwner source) + public void StopAnyPlaying(IPreviewTrackOwner source) { - if (current?.Owner != source) + if (current == null || current.Owner != source) return; - current?.Stop(); + current.Stop(); current = null; } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index e3179b5631..d6b6595b69 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -82,7 +82,7 @@ namespace osu.Game.Graphics.Containers protected override void PopOut() { base.PopOut(); - previewTrackManager.Stop(this); + previewTrackManager.StopAnyPlaying(this); } } } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index c28ecb3c9f..423211659d 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -262,7 +262,7 @@ namespace osu.Game.Overlays if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return; - previewTrackManager.Stop(this); + previewTrackManager.StopAnyPlaying(this); getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value ?? string.Empty, ((FilterControl)Filter).Ruleset.Value, From 206f913a4c102a0a9e6fbc966c7ae3fea810ac3e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 22 Jun 2018 13:31:32 +0900 Subject: [PATCH 33/35] Make mute button not handle hover --- osu.Game/Overlays/Volume/MuteButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index b62c639ee3..d0aa58e668 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.Volume protected override bool OnHover(InputState state) { this.TransformTo("BorderColour", hoveredColour, 500, Easing.OutQuint); - return true; + return false; } protected override void OnHoverLost(InputState state) From 72aee8344e5d1795d1700dce26ac7ef9ce841ef3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 22 Jun 2018 13:32:00 +0900 Subject: [PATCH 34/35] Always call schedulePopOut --- osu.Game/Overlays/VolumeOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 24afa414d6..6a55dbad26 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -152,7 +152,7 @@ namespace osu.Game.Overlays protected override bool OnHover(InputState state) { - Show(); + schedulePopOut(); return true; } From 67a067ffa51f7b9d873172b1d19b82652d79bd45 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 22 Jun 2018 13:32:19 +0900 Subject: [PATCH 35/35] Fix overlay not disappearing when losing hover from the last pixel OnMouseMove isn't invoked when hover is lost. --- osu.Game/Overlays/VolumeOverlay.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 6a55dbad26..1c9c615bbb 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -156,6 +156,12 @@ namespace osu.Game.Overlays return true; } + protected override void OnHoverLost(InputState state) + { + schedulePopOut(); + base.OnHoverLost(state); + } + private void schedulePopOut() { popOutDelegate?.Cancel();