From eda9f838366cd46f09e3bb3401cfaf7775e21daf Mon Sep 17 00:00:00 2001 From: TocoToucan Date: Sun, 29 Apr 2018 15:32:22 +0300 Subject: [PATCH 001/199] 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 002/199] 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 003/199] 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 004/199] 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 005/199] 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 006/199] 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 95a207ef56a9907fff4c892f7e36c47fbf6e843d Mon Sep 17 00:00:00 2001 From: KoziLord Date: Tue, 15 May 2018 00:17:42 +0200 Subject: [PATCH 007/199] Fixed the parallax background missing from the space occupied by the top toolbar. --- osu.Game/Screens/Ranking/Results.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 32161a0b8e..38dbf1a65d 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -160,7 +160,7 @@ namespace osu.Game.Screens.Ranking { RelativeSizeAxes = Axes.Both, ParallaxAmount = 0.01f, - Scale = new Vector2(1 / circle_outer_scale / overscan), + Scale = new Vector2(1 / circle_outer_scale), Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] From ca05fde14c7c9f984caf6c7fcbbdbe3ce78ed010 Mon Sep 17 00:00:00 2001 From: KoziLord Date: Tue, 15 May 2018 00:47:03 +0200 Subject: [PATCH 008/199] Fix the Parallax Background not filling the entire Circle Container. --- osu.Game/Screens/Ranking/Results.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 38dbf1a65d..a2990d7902 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -159,8 +159,11 @@ namespace osu.Game.Screens.Ranking backgroundParallax = new ParallaxContainer { RelativeSizeAxes = Axes.Both, - ParallaxAmount = 0.01f, - Scale = new Vector2(1 / circle_outer_scale), + ParallaxAmount = 0.02f, + //Compensate for the Toolbar + Scale = new Vector2(1.06f / circle_outer_scale / overscan), + //Offset the background to account for the toolbar. + Position = new Vector2(0, -20), Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] From be56d8cb8253a7c710579f54377f5563e9c01170 Mon Sep 17 00:00:00 2001 From: KoziLord Date: Tue, 15 May 2018 00:53:31 +0200 Subject: [PATCH 009/199] Change the parallax amount --- osu.Game/Screens/Ranking/Results.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index a2990d7902..17e8666ebf 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -159,7 +159,7 @@ namespace osu.Game.Screens.Ranking backgroundParallax = new ParallaxContainer { RelativeSizeAxes = Axes.Both, - ParallaxAmount = 0.02f, + ParallaxAmount = 0.01f, //Compensate for the Toolbar Scale = new Vector2(1.06f / circle_outer_scale / overscan), //Offset the background to account for the toolbar. From be1159444d2fb9cb15f0019b275fa9f6a6df48e4 Mon Sep 17 00:00:00 2001 From: KoziLord Date: Tue, 15 May 2018 15:56:49 +0200 Subject: [PATCH 010/199] Use the absolute value of ParallaxAmount to make sure we're not scaling stuff down when using a negative ParallaxAmount --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index dc635ce7e7..51be40c1e8 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.Containers if (!parallaxEnabled) { content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); - content.Scale = new Vector2(1 + ParallaxAmount); + content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); } }; } @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.Containers double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 1000, Easing.OutQuint); - content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + ParallaxAmount), 0, 1000, Easing.OutQuint); + content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } firstUpdate = false; From 1e88f216f27831a8c5bc76cf09ce271be61e0580 Mon Sep 17 00:00:00 2001 From: KoziLord Date: Wed, 16 May 2018 01:27:18 +0200 Subject: [PATCH 011/199] Revert the ParallaxContainer changes I made by accident back. --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 4 ++-- osu.Game/Screens/Ranking/Results.cs | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 51be40c1e8..dc635ce7e7 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.Containers if (!parallaxEnabled) { content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); - content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); + content.Scale = new Vector2(1 + ParallaxAmount); } }; } @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.Containers double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 1000, Easing.OutQuint); - content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); + content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + ParallaxAmount), 0, 1000, Easing.OutQuint); } firstUpdate = false; diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 17e8666ebf..32161a0b8e 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -160,10 +160,7 @@ namespace osu.Game.Screens.Ranking { RelativeSizeAxes = Axes.Both, ParallaxAmount = 0.01f, - //Compensate for the Toolbar - Scale = new Vector2(1.06f / circle_outer_scale / overscan), - //Offset the background to account for the toolbar. - Position = new Vector2(0, -20), + Scale = new Vector2(1 / circle_outer_scale / overscan), Anchor = Anchor.Centre, Origin = Anchor.Centre, Children = new Drawable[] From 428d0f5deec85cfb2153d8246301f3f269865346 Mon Sep 17 00:00:00 2001 From: KoziLord Date: Wed, 16 May 2018 01:30:16 +0200 Subject: [PATCH 012/199] Re-implement the fix after it got deleted in the previous commit. --- osu.Game/Screens/Ranking/Results.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 32161a0b8e..162c428444 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -160,8 +160,11 @@ namespace osu.Game.Screens.Ranking { RelativeSizeAxes = Axes.Both, ParallaxAmount = 0.01f, - Scale = new Vector2(1 / circle_outer_scale / overscan), + //Compensate for the Toolbar + Scale = new Vector2(1.06f / circle_outer_scale / overscan), + //Offset the background to account for the toolbar. Anchor = Anchor.Centre, + Position = new Vector2(0, -20), Origin = Anchor.Centre, Children = new Drawable[] { From 3b708f650591a015ccd1e54721981f4316fbce4b Mon Sep 17 00:00:00 2001 From: KoziLord Date: Wed, 16 May 2018 01:34:08 +0200 Subject: [PATCH 013/199] make it equal with the original codebase. --- osu.Game/Screens/Ranking/Results.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 162c428444..67949f8e14 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -160,17 +160,14 @@ namespace osu.Game.Screens.Ranking { RelativeSizeAxes = Axes.Both, ParallaxAmount = 0.01f, - //Compensate for the Toolbar - Scale = new Vector2(1.06f / circle_outer_scale / overscan), - //Offset the background to account for the toolbar. + Scale = new Vector2(1 / circle_outer_scale / overscan), Anchor = Anchor.Centre, - Position = new Vector2(0, -20), Origin = Anchor.Centre, Children = new Drawable[] { new Sprite { - RelativeSizeAxes = Axes.Both, + RelativeSsizeAxes = Axes.Both, Alpha = 0.2f, Texture = Beatmap.Value.Background, Anchor = Anchor.Centre, From 705960dabbc32591ccd36841e66e101e41133189 Mon Sep 17 00:00:00 2001 From: KoziLord Date: Wed, 16 May 2018 01:36:26 +0200 Subject: [PATCH 014/199] Fix typo --- osu.Game/Screens/Ranking/Results.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 67949f8e14..32161a0b8e 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -167,7 +167,7 @@ namespace osu.Game.Screens.Ranking { new Sprite { - RelativeSsizeAxes = Axes.Both, + RelativeSizeAxes = Axes.Both, Alpha = 0.2f, Texture = Beatmap.Value.Background, Anchor = Anchor.Centre, From d2b2d3e2e078de26188030f79c1722e2f30d2589 Mon Sep 17 00:00:00 2001 From: KoziLord Date: Wed, 16 May 2018 01:38:46 +0200 Subject: [PATCH 015/199] Use the absolute value of ParallaxAmount to make sure we're not scaling things down when using a negative value for the Parallax (moving against the cursor instead of with it) --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index dc635ce7e7..51be40c1e8 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.Containers if (!parallaxEnabled) { content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); - content.Scale = new Vector2(1 + ParallaxAmount); + content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); } }; } @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.Containers double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 1000, Easing.OutQuint); - content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + ParallaxAmount), 0, 1000, Easing.OutQuint); + content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } firstUpdate = false; From 79c64d16e43da33e3e21fdcefdd192da9eaba2b7 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 09:49:23 +0800 Subject: [PATCH 016/199] Realization on Catch Star Rating --- .../Difficulty/CatchDifficultyCalculator.cs | 160 +++++++++++++++++- .../Difficulty/CatchDifficultyHitObject.cs | 127 ++++++++++++++ 2 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index f8351b7519..5351bd746d 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -1,18 +1,174 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchDifficultyCalculator : DifficultyCalculator { - public CatchDifficultyCalculator(IBeatmap beatmap) : base(beatmap) + private const double STAR_SCALING_FACTOR = 0.145; + private const float PLAYFIELD_WIDTH = CatchPlayfield.BASE_WIDTH; + + private readonly List difficultyHitObjects = new List(); + + public CatchDifficultyCalculator(IBeatmap beatmap) + : base(beatmap) { } - public override double Calculate(Dictionary categoryDifficulty = null) => 0; + public CatchDifficultyCalculator(IBeatmap beatmap, Mod[] mods) + : base(beatmap, mods) + { + } + + public override double Calculate(Dictionary categoryDifficulty = null) + { + + difficultyHitObjects.Clear(); + + float circleSize = Beatmap.BeatmapInfo.BaseDifficulty.CircleSize; + float catcherWidth = (1.0f - 0.7f * (circleSize - 5) / 5) * 0.62064f * 172; + //float catcherWidth = (float)(305.0f / 1.6f * ((102.4f * (1.0f - 0.7 * (circleSize - 5.0f)) / 5.0f) / 128.0f * 0.7f)); + float catcherWidthHalf = catcherWidth / 2; + catcherWidthHalf *= 0.8f; + + foreach (var hitObject in Beatmap.HitObjects) + { + // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. + if (hitObject is Fruit) + { + difficultyHitObjects.Add(new CatchDifficultyHitObject((CatchHitObject)hitObject, catcherWidthHalf)); + } + if (hitObject is JuiceStream) + { + IEnumerator nestedHitObjectsEnumerator = hitObject.NestedHitObjects.GetEnumerator(); + while (nestedHitObjectsEnumerator.MoveNext()) + { + CatchHitObject objectInJuiceStream = (CatchHitObject)nestedHitObjectsEnumerator.Current; + if (!(objectInJuiceStream is TinyDroplet)) + difficultyHitObjects.Add(new CatchDifficultyHitObject(objectInJuiceStream, catcherWidthHalf)); + } + } + } + + difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); + + if (!CalculateStrainValues()) return 0; + + double starRating = Math.Sqrt(CalculateDifficulty()) * STAR_SCALING_FACTOR; + + if (categoryDifficulty != null) + { + categoryDifficulty["Aim"] = starRating; + + double ar = Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate; + double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; + + categoryDifficulty["AR"] = preEmpt > 1200.0 ? -(preEmpt - 1800.0) / 120.0 : -(preEmpt - 1200.0) / 150.0 + 5.0; + + //categoryDifficulty.Add("AR", (preEmpt > 1200.0 ? -(preEmpt - 1800.0) / 120.0 : -(preEmpt - 1200.0) / 150.0 + 5.0).ToString("0.00", GameBase.nfi)); + //categoryDifficulty.Add("Max combo", DifficultyHitObjects.Count.ToString(GameBase.nfi)); + } + + return starRating; + } + + protected bool CalculateStrainValues() + { + // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. + using (List.Enumerator hitObjectsEnumerator = difficultyHitObjects.GetEnumerator()) + { + + if (!hitObjectsEnumerator.MoveNext()) return false; + + CatchDifficultyHitObject currentHitObject = hitObjectsEnumerator.Current; + CatchDifficultyHitObject nextHitObject; + + // First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject. + while (hitObjectsEnumerator.MoveNext()) + { + nextHitObject = hitObjectsEnumerator.Current; + nextHitObject.CalculateStrains(currentHitObject, TimeRate); + currentHitObject = nextHitObject; + } + + return true; + } + } + + /// + /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP. + /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. + /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. + /// + protected const double STRAIN_STEP = 750; + + /// + /// The weighting of each strain value decays to this number * it's previous value + /// + protected const double DECAY_WEIGHT = 0.94; + + protected double CalculateDifficulty() + { + // The strain step needs to be adjusted for the algorithm to be considered equal with speed changing mods + double actualStrainStep = STRAIN_STEP * TimeRate; + + // Find the highest strain value within each strain step + List highestStrains = new List(); + double intervalEndTime = actualStrainStep; + double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval + + CatchDifficultyHitObject previousHitObject = null; + foreach (CatchDifficultyHitObject hitObject in difficultyHitObjects) + { + // While we are beyond the current interval push the currently available maximum to our strain list + while (hitObject.BaseHitObject.StartTime > intervalEndTime) + { + highestStrains.Add(maximumStrain); + + // The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay + // until the beginning of the next interval. + if (previousHitObject == null) + { + maximumStrain = 0; + } + else + { + double decay = Math.Pow(CatchDifficultyHitObject.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); + maximumStrain = previousHitObject.Strain * decay; + } + + // Go to the next time interval + intervalEndTime += actualStrainStep; + } + + // Obtain maximum strain + maximumStrain = Math.Max(hitObject.Strain, maximumStrain); + + previousHitObject = hitObject; + } + + + // Build the weighted sum over the highest strains for each interval + double difficulty = 0; + double weight = 1; + highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. + + foreach (double strain in highestStrains) + { + difficulty += weight * strain; + weight *= DECAY_WEIGHT; + } + + return difficulty; + } } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs new file mode 100644 index 0000000000..14f9445c75 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs @@ -0,0 +1,127 @@ +using System; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using OpenTK; + +namespace osu.Game.Rulesets.Catch.Difficulty +{ + class CatchDifficultyHitObject + { + internal static readonly double DECAY_BASE = 0.20; + private const float NORMALIZED_HITOBJECT_RADIUS = 41.0f; + private const float ABSOLUTE_PLAYER_POSITIONING_ERROR = 16f; + private float playerPositioningError; + + internal CatchHitObject BaseHitObject; + + /// + /// Measures jump difficulty. CtB doesn't have something like button pressing speed or accuracy + /// + internal double Strain = 1; + + /// + /// This is required to keep track of lazy player movement (always moving only as far as necessary) + /// Without this quick repeat sliders / weirdly shaped streams might become ridiculously overrated + /// + internal float PlayerPositionOffset; + internal float LastMovement; + + internal float NormalizedPosition; + internal float ActualNormalizedPosition => NormalizedPosition + PlayerPositionOffset; + + internal CatchDifficultyHitObject(CatchHitObject baseHitObject, float catcherWidthHalf) + { + BaseHitObject = baseHitObject; + + // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. + float scalingFactor = NORMALIZED_HITOBJECT_RADIUS / catcherWidthHalf; + + playerPositioningError = ABSOLUTE_PLAYER_POSITIONING_ERROR;// * scalingFactor; + NormalizedPosition = baseHitObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; + } + + private const double DIRECTION_CHANGE_BONUS = 12.5; + internal void CalculateStrains(CatchDifficultyHitObject previousHitObject, double timeRate) + { + // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. + // See Taiko feedback thread. + double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; + double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000); + + // Update new position with lazy movement. + PlayerPositionOffset = + MathHelper.Clamp( + previousHitObject.ActualNormalizedPosition, + NormalizedPosition - (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError), + NormalizedPosition + (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player. + - NormalizedPosition; // Subtract HitObject position to obtain offset + + LastMovement = DistanceTo(previousHitObject); + double addition = spacingWeight(LastMovement); + + if (NormalizedPosition < previousHitObject.NormalizedPosition) + { + LastMovement = -LastMovement; + } + + CatchHitObject previousHitCircle = previousHitObject.BaseHitObject; + + double additionBonus = 0; + double sqrtTime = Math.Sqrt(Math.Max(timeElapsed, 25)); + + // Direction changes give an extra point! + if (Math.Abs(LastMovement) > 0.1) + { + if (Math.Abs(previousHitObject.LastMovement) > 0.1 && Math.Sign(LastMovement) != Math.Sign(previousHitObject.LastMovement)) + { + double bonus = DIRECTION_CHANGE_BONUS / sqrtTime; + + // Weight bonus by how + double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError; + + // We want time to play a role twice here! + addition += bonus * bonusFactor; + + // Bonus for tougher direction switches and "almost" hyperdashes at this point + if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) + { + additionBonus += 0.3 * bonusFactor; + } + } + + // Base bonus for every movement, giving some weight to streams. + addition += 7.5 * Math.Min(Math.Abs(LastMovement), NORMALIZED_HITOBJECT_RADIUS * 2) / (NORMALIZED_HITOBJECT_RADIUS * 6) / sqrtTime; + } + + // Bonus for "almost" hyperdashes at corner points + if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) + { + if (!previousHitCircle.HyperDash) + { + additionBonus += 1.0; + } + else + { + // After a hyperdash we ARE in the correct position. Always! + PlayerPositionOffset = 0; + } + + addition *= 1.0 + additionBonus * ((10 - previousHitCircle.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 10); + } + + addition *= 850.0 / Math.Max(timeElapsed, 25); + + Strain = previousHitObject.Strain * decay + addition; + } + + private static double spacingWeight(float distance) + { + return Math.Pow(distance, 1.3) / 500; + } + + internal float DistanceTo(CatchDifficultyHitObject other) + { + return Math.Abs(ActualNormalizedPosition - other.ActualNormalizedPosition); + } + } +} From 6bf5ea73d5f19ba4d706f9754a7169c5ae8e5f8e Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 09:53:20 +0800 Subject: [PATCH 017/199] Fix CatcherWidth --- .../Difficulty/CatchDifficultyCalculator.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 5351bd746d..59c512c469 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -35,8 +35,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty difficultyHitObjects.Clear(); float circleSize = Beatmap.BeatmapInfo.BaseDifficulty.CircleSize; - float catcherWidth = (1.0f - 0.7f * (circleSize - 5) / 5) * 0.62064f * 172; - //float catcherWidth = (float)(305.0f / 1.6f * ((102.4f * (1.0f - 0.7 * (circleSize - 5.0f)) / 5.0f) / 128.0f * 0.7f)); + float catcherWidth = (1.0f - 0.7f * (circleSize - 5) / 5) * 0.62064f * CatcherArea.CATCHER_SIZE; float catcherWidthHalf = catcherWidth / 2; catcherWidthHalf *= 0.8f; From 0ef718a09e6269343b6a3a04b1b3f9bfaaaf7d3a Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 09:55:07 +0800 Subject: [PATCH 018/199] Fixes on categoryDifficulty --- .../Difficulty/CatchDifficultyCalculator.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 59c512c469..63570d44b0 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -72,9 +72,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; categoryDifficulty["AR"] = preEmpt > 1200.0 ? -(preEmpt - 1800.0) / 120.0 : -(preEmpt - 1200.0) / 150.0 + 5.0; - - //categoryDifficulty.Add("AR", (preEmpt > 1200.0 ? -(preEmpt - 1800.0) / 120.0 : -(preEmpt - 1200.0) / 150.0 + 5.0).ToString("0.00", GameBase.nfi)); - //categoryDifficulty.Add("Max combo", DifficultyHitObjects.Count.ToString(GameBase.nfi)); + categoryDifficulty["Max combo"] = difficultyHitObjects.Count; } return starRating; From 44fd4b95bd7ce7c7ec58e6dc82cd57f5447ac2b1 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 09:58:46 +0800 Subject: [PATCH 019/199] We need DistanceToHyperDash for star rating calculation --- osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 548813fbd2..d55cdac115 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -24,6 +24,11 @@ namespace osu.Game.Rulesets.Catch.Objects public int ComboIndex { get; set; } + /// + /// The distance for a fruit to to next hyper if it's not a hyper. + /// + public float DistanceToHyperDash { get; set; } + /// /// The next fruit starts a new combo. Used for explodey. /// From 0405383e4e3eb352b2e78e428ab473f00e69fca6 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 10:12:18 +0800 Subject: [PATCH 020/199] Fixing code style --- .../Difficulty/CatchDifficultyCalculator.cs | 21 +++++-------------- .../Difficulty/CatchDifficultyHitObject.cs | 2 +- .../Difficulty/TaikoDifficultyCalculator.cs | 12 ++--------- .../Difficulty/DifficultyCalculator.cs | 15 +++++++++++++ 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 63570d44b0..83b5b3bb5c 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -31,7 +31,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty public override double Calculate(Dictionary categoryDifficulty = null) { - difficultyHitObjects.Clear(); float circleSize = Beatmap.BeatmapInfo.BaseDifficulty.CircleSize; @@ -83,7 +82,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. using (List.Enumerator hitObjectsEnumerator = difficultyHitObjects.GetEnumerator()) { - if (!hitObjectsEnumerator.MoveNext()) return false; CatchDifficultyHitObject currentHitObject = hitObjectsEnumerator.Current; @@ -106,17 +104,17 @@ namespace osu.Game.Rulesets.Catch.Difficulty /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. /// - protected const double STRAIN_STEP = 750; + protected const double strain_step = 750; /// /// The weighting of each strain value decays to this number * it's previous value /// - protected const double DECAY_WEIGHT = 0.94; + protected const double decay_weight = 0.94; protected double CalculateDifficulty() { // The strain step needs to be adjusted for the algorithm to be considered equal with speed changing mods - double actualStrainStep = STRAIN_STEP * TimeRate; + double actualStrainStep = strain_step * TimeRate; // Find the highest strain value within each strain step List highestStrains = new List(); @@ -153,17 +151,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty previousHitObject = hitObject; } - - // Build the weighted sum over the highest strains for each interval - double difficulty = 0; - double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - - foreach (double strain in highestStrains) - { - difficulty += weight * strain; - weight *= DECAY_WEIGHT; - } + // calculate maximun strain difficulty + double difficulty = StrainCalculator(highestStrains, decay_weight); return difficulty; } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs index 14f9445c75..f4eefdd7cd 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. float scalingFactor = NORMALIZED_HITOBJECT_RADIUS / catcherWidthHalf; - playerPositioningError = ABSOLUTE_PLAYER_POSITIONING_ERROR;// * scalingFactor; + playerPositioningError = ABSOLUTE_PLAYER_POSITIONING_ERROR; // * scalingFactor; NormalizedPosition = baseHitObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 57e1e65064..197464c10a 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -122,16 +122,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty previousHitObject = hitObject; } - // Build the weighted sum over the highest strains for each interval - double difficulty = 0; - double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - - foreach (double strain in highestStrains) - { - difficulty += weight * strain; - weight *= decay_weight; - } + // calculate maximun strain difficulty + double difficulty = StrainCalculator(highestStrains, decay_weight); return difficulty; } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 070bc7ddb0..348435b0d0 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -37,5 +37,20 @@ namespace osu.Game.Rulesets.Difficulty } public abstract double Calculate(Dictionary categoryDifficulty = null); + + protected double StrainCalculator(List highestStrains, double decayWeight) + { + // Build the weighted sum over the highest strains for each interval + double difficulty = 0; + double weight = 1; + highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. + + foreach (double strain in highestStrains) + { + difficulty += weight * strain; + weight *= decayWeight; + } + return difficulty; + } } } From 886be8ce1f7c29d558e3a34f42863740c7ca6515 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 10:16:32 +0800 Subject: [PATCH 021/199] Adding lisence header --- .../Difficulty/CatchDifficultyCalculator.cs | 2 +- .../Difficulty/CatchDifficultyHitObject.cs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 83b5b3bb5c..19d1bab0ac 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return true; } } - + /// /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP. /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs index f4eefdd7cd..778ab9df28 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using OpenTK; @@ -76,7 +79,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty { double bonus = DIRECTION_CHANGE_BONUS / sqrtTime; - // Weight bonus by how + // Weight bonus by how double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError; // We want time to play a role twice here! From 68a929eb0c1d78e38687f55b42b61c05d6a1e9a1 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 10:39:16 +0800 Subject: [PATCH 022/199] Fixing parameters naming --- .../Difficulty/CatchDifficultyCalculator.cs | 17 +++++------ .../Difficulty/CatchDifficultyHitObject.cs | 28 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 19d1bab0ac..31de9cfc8d 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -14,8 +14,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchDifficultyCalculator : DifficultyCalculator { - private const double STAR_SCALING_FACTOR = 0.145; - private const float PLAYFIELD_WIDTH = CatchPlayfield.BASE_WIDTH; + private const double star_scaling_factor = 0.145; + private const float playfield_width = CatchPlayfield.BASE_WIDTH; private readonly List difficultyHitObjects = new List(); @@ -54,6 +54,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty if (!(objectInJuiceStream is TinyDroplet)) difficultyHitObjects.Add(new CatchDifficultyHitObject(objectInJuiceStream, catcherWidthHalf)); } + // Dispose the enumerator after counting all fruits. + nestedHitObjectsEnumerator.Dispose(); } } @@ -61,7 +63,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty if (!CalculateStrainValues()) return 0; - double starRating = Math.Sqrt(CalculateDifficulty()) * STAR_SCALING_FACTOR; + double starRating = Math.Sqrt(CalculateDifficulty()) * star_scaling_factor; if (categoryDifficulty != null) { @@ -85,12 +87,11 @@ namespace osu.Game.Rulesets.Catch.Difficulty if (!hitObjectsEnumerator.MoveNext()) return false; CatchDifficultyHitObject currentHitObject = hitObjectsEnumerator.Current; - CatchDifficultyHitObject nextHitObject; // First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject. while (hitObjectsEnumerator.MoveNext()) { - nextHitObject = hitObjectsEnumerator.Current; + CatchDifficultyHitObject nextHitObject = hitObjectsEnumerator.Current; nextHitObject.CalculateStrains(currentHitObject, TimeRate); currentHitObject = nextHitObject; } @@ -104,12 +105,12 @@ namespace osu.Game.Rulesets.Catch.Difficulty /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. /// - protected const double strain_step = 750; + private const double strain_step = 750; /// /// The weighting of each strain value decays to this number * it's previous value /// - protected const double decay_weight = 0.94; + private const double decay_weight = 0.94; protected double CalculateDifficulty() { @@ -137,7 +138,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty } else { - double decay = Math.Pow(CatchDifficultyHitObject.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); + double decay = Math.Pow(CatchDifficultyHitObject.decay_base, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); maximumStrain = previousHitObject.Strain * decay; } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs index 778ab9df28..190c92b319 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs @@ -8,12 +8,12 @@ using OpenTK; namespace osu.Game.Rulesets.Catch.Difficulty { - class CatchDifficultyHitObject + internal class CatchDifficultyHitObject { - internal static readonly double DECAY_BASE = 0.20; - private const float NORMALIZED_HITOBJECT_RADIUS = 41.0f; - private const float ABSOLUTE_PLAYER_POSITIONING_ERROR = 16f; - private float playerPositioningError; + internal static readonly double decay_base = 0.20; + private const float normalized_hitobject_radius = 41.0f; + private const float absolute_player_positioning_error = 16f; + private readonly float playerPositioningError; internal CatchHitObject BaseHitObject; @@ -37,26 +37,26 @@ namespace osu.Game.Rulesets.Catch.Difficulty BaseHitObject = baseHitObject; // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. - float scalingFactor = NORMALIZED_HITOBJECT_RADIUS / catcherWidthHalf; + float scalingFactor = normalized_hitobject_radius / catcherWidthHalf; - playerPositioningError = ABSOLUTE_PLAYER_POSITIONING_ERROR; // * scalingFactor; + playerPositioningError = absolute_player_positioning_error; // * scalingFactor; NormalizedPosition = baseHitObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; } - private const double DIRECTION_CHANGE_BONUS = 12.5; + private const double direction_change_bonus = 12.5; internal void CalculateStrains(CatchDifficultyHitObject previousHitObject, double timeRate) { // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. // See Taiko feedback thread. double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000); + double decay = Math.Pow(decay_base, timeElapsed / 1000); // Update new position with lazy movement. PlayerPositionOffset = MathHelper.Clamp( previousHitObject.ActualNormalizedPosition, - NormalizedPosition - (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError), - NormalizedPosition + (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player. + NormalizedPosition - (normalized_hitobject_radius - playerPositioningError), + NormalizedPosition + (normalized_hitobject_radius - playerPositioningError)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player. - NormalizedPosition; // Subtract HitObject position to obtain offset LastMovement = DistanceTo(previousHitObject); @@ -77,9 +77,9 @@ namespace osu.Game.Rulesets.Catch.Difficulty { if (Math.Abs(previousHitObject.LastMovement) > 0.1 && Math.Sign(LastMovement) != Math.Sign(previousHitObject.LastMovement)) { - double bonus = DIRECTION_CHANGE_BONUS / sqrtTime; + double bonus = direction_change_bonus / sqrtTime; - // Weight bonus by how + // Weight bonus by how double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError; // We want time to play a role twice here! @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty } // Base bonus for every movement, giving some weight to streams. - addition += 7.5 * Math.Min(Math.Abs(LastMovement), NORMALIZED_HITOBJECT_RADIUS * 2) / (NORMALIZED_HITOBJECT_RADIUS * 6) / sqrtTime; + addition += 7.5 * Math.Min(Math.Abs(LastMovement), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtTime; } // Bonus for "almost" hyperdashes at corner points From 871743204b00983179fff782745cdea1bf341b5a Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 10:41:58 +0800 Subject: [PATCH 023/199] Fixing parameters naming --- osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs index 190c92b319..d9b16c2a0b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty { double bonus = direction_change_bonus / sqrtTime; - // Weight bonus by how + // Weight bonus by how double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError; // We want time to play a role twice here! From 2e5bc4323ad553b8f85fef881b552b8e8c9e956d Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 13:31:00 +0800 Subject: [PATCH 024/199] Fixing null reference exception bugs --- .../Difficulty/CatchDifficultyCalculator.cs | 9 +++++---- .../Difficulty/CatchDifficultyHitObject.cs | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 31de9cfc8d..2fa946f41c 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty difficultyHitObjects.Clear(); float circleSize = Beatmap.BeatmapInfo.BaseDifficulty.CircleSize; - float catcherWidth = (1.0f - 0.7f * (circleSize - 5) / 5) * 0.62064f * CatcherArea.CATCHER_SIZE; + float catcherWidth = ((1.0f - 0.7f * (circleSize - 5) / 5) * 0.62064f) * CatcherArea.CATCHER_SIZE; float catcherWidthHalf = catcherWidth / 2; catcherWidthHalf *= 0.8f; @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty double ar = Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate; double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; - categoryDifficulty["AR"] = preEmpt > 1200.0 ? -(preEmpt - 1800.0) / 120.0 : -(preEmpt - 1200.0) / 150.0 + 5.0; + categoryDifficulty["AR"] = (preEmpt > 1200.0) ? -(preEmpt - 1800.0) / 120.0 : (-(preEmpt - 1200.0) / 150.0) + 5.0; categoryDifficulty["Max combo"] = difficultyHitObjects.Count; } @@ -92,7 +92,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty while (hitObjectsEnumerator.MoveNext()) { CatchDifficultyHitObject nextHitObject = hitObjectsEnumerator.Current; - nextHitObject.CalculateStrains(currentHitObject, TimeRate); + if (nextHitObject != null) + nextHitObject.CalculateStrains(currentHitObject, TimeRate); currentHitObject = nextHitObject; } @@ -111,7 +112,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty /// The weighting of each strain value decays to this number * it's previous value /// private const double decay_weight = 0.94; - + protected double CalculateDifficulty() { // The strain step needs to be adjusted for the algorithm to be considered equal with speed changing mods diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs index d9b16c2a0b..72fc6d211b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty { internal class CatchDifficultyHitObject { - internal static readonly double decay_base = 0.20; + internal static readonly double DECAY_BASE = 0.20; private const float normalized_hitobject_radius = 41.0f; private const float absolute_player_positioning_error = 16f; private readonly float playerPositioningError; @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. // See Taiko feedback thread. double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double decay = Math.Pow(decay_base, timeElapsed / 1000); + double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000); // Update new position with lazy movement. PlayerPositionOffset = From 6d71f7f220940eb8bcc2750dd3e192b85fa6e777 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 13:35:02 +0800 Subject: [PATCH 025/199] Minor fixes --- osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 2fa946f41c..beee332504 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty /// The weighting of each strain value decays to this number * it's previous value /// private const double decay_weight = 0.94; - + protected double CalculateDifficulty() { // The strain step needs to be adjusted for the algorithm to be considered equal with speed changing mods From 193a29860144f3e5c41b8b09c5492271ff07a2fd Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 13:36:57 +0800 Subject: [PATCH 026/199] Fixing minor bugs --- osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index beee332504..43c157df06 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty } else { - double decay = Math.Pow(CatchDifficultyHitObject.decay_base, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); + double decay = Math.Pow(CatchDifficultyHitObject.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); maximumStrain = previousHitObject.Strain * decay; } From 4784538d7349a2e1fcef059141c992524a2e2bd6 Mon Sep 17 00:00:00 2001 From: frankhjwx Date: Mon, 21 May 2018 13:53:48 +0800 Subject: [PATCH 027/199] Fixing minor bugs --- osu-framework | 2 +- .../Difficulty/CatchDifficultyCalculator.cs | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu-framework b/osu-framework index 80e78fd45b..fac688633b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 80e78fd45bb79ca4bc46ecc05deb6058f3879faa +Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4 diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 43c157df06..975e8eed58 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty difficultyHitObjects.Clear(); float circleSize = Beatmap.BeatmapInfo.BaseDifficulty.CircleSize; - float catcherWidth = ((1.0f - 0.7f * (circleSize - 5) / 5) * 0.62064f) * CatcherArea.CATCHER_SIZE; + float catcherWidth = (1.0f - 0.7f * (circleSize - 5) / 5) * 0.62064f * CatcherArea.CATCHER_SIZE; float catcherWidthHalf = catcherWidth / 2; catcherWidthHalf *= 0.8f; @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty double ar = Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate; double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate; - categoryDifficulty["AR"] = (preEmpt > 1200.0) ? -(preEmpt - 1800.0) / 120.0 : (-(preEmpt - 1200.0) / 150.0) + 5.0; + categoryDifficulty["AR"] = preEmpt > 1200.0 ? -(preEmpt - 1800.0) / 120.0 : -(preEmpt - 1200.0) / 150.0 + 5.0; categoryDifficulty["Max combo"] = difficultyHitObjects.Count; } @@ -92,8 +92,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty while (hitObjectsEnumerator.MoveNext()) { CatchDifficultyHitObject nextHitObject = hitObjectsEnumerator.Current; - if (nextHitObject != null) - nextHitObject.CalculateStrains(currentHitObject, TimeRate); + nextHitObject?.CalculateStrains(currentHitObject, TimeRate); currentHitObject = nextHitObject; } From 49f893d5e42b3712a7801ea329128bb2701538dd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 May 2018 12:00:11 +0900 Subject: [PATCH 028/199] Couple the timeline to the audio --- .../Visual/TestCaseEditorComposeTimeline.cs | 13 ++- .../Edit/Screens/Compose/Timeline/Timeline.cs | 80 +++++++++++++++++++ 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index 0776bc123e..aff7abe03d 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -14,14 +14,15 @@ using osu.Game.Screens.Edit.Screens.Compose.Timeline; namespace osu.Game.Tests.Visual { [TestFixture] - public class TestCaseEditorComposeTimeline : OsuTestCase + public class TestCaseEditorComposeTimeline : EditorClockTestCase { public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineArea), typeof(Timeline), typeof(BeatmapWaveformGraph), typeof(TimelineButton) }; - private readonly TimelineArea timelineArea; - - public TestCaseEditorComposeTimeline() + [BackgroundDependencyLoader] + private void load(OsuGameBase osuGame) { + TimelineArea timelineArea; + Children = new Drawable[] { new MusicController @@ -38,11 +39,7 @@ namespace osu.Game.Tests.Visual Size = new Vector2(0.8f, 100) } }; - } - [BackgroundDependencyLoader] - private void load(OsuGameBase osuGame) - { timelineArea.Beatmap.BindTo(osuGame.Beatmap); } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index 9801ba12a1..e8d34b466c 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -1,8 +1,11 @@ // 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.Configuration; using osu.Framework.Graphics; +using osu.Framework.Input; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -13,6 +16,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline public readonly Bindable WaveformVisible = new Bindable(); public readonly Bindable Beatmap = new Bindable(); + private IAdjustableClock adjustableClock; + public Timeline() { ZoomDuration = 200; @@ -32,12 +37,87 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } + [BackgroundDependencyLoader] + private void load(IAdjustableClock adjustableClock) + { + this.adjustableClock = adjustableClock; + } + + private bool handlingUserInput; + private bool trackWasPlaying; + protected override void Update() { base.Update(); // We want time = 0 to be at the centre of the container when scrolled to the start Content.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; + + if (!handlingUserInput) + ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); + else + adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + if (base.OnMouseDown(state, args)) + { + beginUserInput(); + return true; + } + + return false; + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + endUserInput(); + return base.OnMouseUp(state, args); + } + + private void beginUserInput() + { + handlingUserInput = true; + trackWasPlaying = adjustableClock.IsRunning; + adjustableClock.Stop(); + } + + private void endUserInput() + { + handlingUserInput = false; + if (trackWasPlaying) + adjustableClock.Start(); + } + + protected override ScrollbarContainer CreateScrollbar(Direction direction) => new TimelineScrollbar(this, direction); + + private class TimelineScrollbar : ScrollbarContainer + { + private readonly Timeline timeline; + + public TimelineScrollbar(Timeline timeline, Direction scrollDir) + : base(scrollDir) + { + this.timeline = timeline; + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + if (base.OnMouseDown(state, args)) + { + timeline.beginUserInput(); + return true; + } + + return false; + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + timeline.endUserInput(); + return base.OnMouseUp(state, args); + } } } } From f18677382c59446d4cdc307ed5969c5a4c2b71f7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 May 2018 12:00:23 +0900 Subject: [PATCH 029/199] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 8f007de13e..907265b750 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 8f007de13e4a1aed46cb35e5018448f809bd5e88 +Subproject commit 907265b7501964a09eb2cd89ec2257941183c65c From 6b0eeb343651bd50764199b3413c59dd946ae2df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 May 2018 14:14:32 +0900 Subject: [PATCH 030/199] Rework seeking interactions to support smooth scrolling --- .../Edit/Screens/Compose/Timeline/Timeline.cs | 53 ++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index e8d34b466c..9dbaa1586d 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -43,20 +43,59 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline this.adjustableClock = adjustableClock; } - private bool handlingUserInput; + /// + /// The track's time in the previous frame. + /// + private double lastTrackTime; + + /// + /// Whether the user is currently dragging the timeline. + /// + private bool handlingDragInput; + + /// + /// Whether the track was playing before a user drag event. + /// private bool trackWasPlaying; protected override void Update() { base.Update(); - // We want time = 0 to be at the centre of the container when scrolled to the start + // The extrema of track time should be positioned at the centre of the container when scrolled to the start or end Content.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; - if (!handlingUserInput) - ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); - else + if (handlingDragInput) + { + // The user is dragging - the track should always follow the timeline adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); + } + else if (adjustableClock.IsRunning) + { + // If the user hasn't provided mouse input but the track is running, always follow the track + ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); + } + else + { + // The track isn't playing, so we want to smooth-scroll once more, and re-enable wheel scrolling + // There are two cases we have to be wary of: + // 1) The user scrolls on this timeline: We want the track to follow us + // 2) The user changes the track time through some other means (scrolling in the editor or overview timeline): We want to follow the track time + + // The simplest way to cover both cases is by checking that inter-frame track times are identical + if (adjustableClock.CurrentTime == lastTrackTime) + { + // The track hasn't been seeked externally + adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); + } + else + { + // The track has been seeked externally + ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); + } + } + + lastTrackTime = adjustableClock.CurrentTime; } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) @@ -78,14 +117,14 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline private void beginUserInput() { - handlingUserInput = true; + handlingDragInput = true; trackWasPlaying = adjustableClock.IsRunning; adjustableClock.Stop(); } private void endUserInput() { - handlingUserInput = false; + handlingDragInput = false; if (trackWasPlaying) adjustableClock.Start(); } From a30f72b477d6353d0e785d94cd66aac6fefe50de Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 23 May 2018 14:32:00 +0900 Subject: [PATCH 031/199] Add helper methods for seeking/scrolling --- .../Screens/Edit/Screens/Compose/Timeline/Timeline.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index 9dbaa1586d..df615ad035 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -68,12 +68,12 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline if (handlingDragInput) { // The user is dragging - the track should always follow the timeline - adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); + seekTrackToCurrent(); } else if (adjustableClock.IsRunning) { // If the user hasn't provided mouse input but the track is running, always follow the track - ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); + scrollToTrackTime(); } else { @@ -86,16 +86,19 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline if (adjustableClock.CurrentTime == lastTrackTime) { // The track hasn't been seeked externally - adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); + seekTrackToCurrent(); } else { // The track has been seeked externally - ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); + scrollToTrackTime(); } } lastTrackTime = adjustableClock.CurrentTime; + + void seekTrackToCurrent() => adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); + void scrollToTrackTime() => ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) From d4f68e0b673c9e258180d5290e016a3fb0e7d105 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 May 2018 14:26:53 +0900 Subject: [PATCH 032/199] Fix possible NaN values due to trackvirtual infinite length --- .../Edit/Screens/Compose/Timeline/Timeline.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index df615ad035..3fdde1fc1d 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -2,6 +2,7 @@ // 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.Graphics; using osu.Framework.Input; @@ -97,8 +98,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline lastTrackTime = adjustableClock.CurrentTime; - void seekTrackToCurrent() => adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); - void scrollToTrackTime() => ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); + void seekTrackToCurrent() + { + if (!(Beatmap.Value.Track is TrackVirtual)) + adjustableClock.Seek(Current / Content.DrawWidth * Beatmap.Value.Track.Length); + } + + void scrollToTrackTime() + { + if (!(Beatmap.Value.Track is TrackVirtual)) + ScrollTo((float)(adjustableClock.CurrentTime / Beatmap.Value.Track.Length) * Content.DrawWidth, false); + } } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) From b649025e861b14506754794e6416235b1e43d205 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 May 2018 14:36:48 +0900 Subject: [PATCH 033/199] beginUserDrag/endUserDrag --- .../Edit/Screens/Compose/Timeline/Timeline.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index 3fdde1fc1d..0ae6cd6da2 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { if (base.OnMouseDown(state, args)) { - beginUserInput(); + beginUserDrag(); return true; } @@ -124,18 +124,18 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - endUserInput(); + endUserDrag(); return base.OnMouseUp(state, args); } - private void beginUserInput() + private void beginUserDrag() { handlingDragInput = true; trackWasPlaying = adjustableClock.IsRunning; adjustableClock.Stop(); } - private void endUserInput() + private void endUserDrag() { handlingDragInput = false; if (trackWasPlaying) @@ -158,7 +158,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { if (base.OnMouseDown(state, args)) { - timeline.beginUserInput(); + timeline.beginUserDrag(); return true; } @@ -167,7 +167,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - timeline.endUserInput(); + timeline.endUserDrag(); return base.OnMouseUp(state, args); } } From 38e5e35743f372de3be1324d3adf0473f29d8bd1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 01:20:05 +0900 Subject: [PATCH 034/199] modify catch hyperdash behavior --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 62 ++++++++++++++--------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 181536a91e..56826d228c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -248,37 +248,46 @@ namespace osu.Game.Rulesets.Catch.UI if (validCatch && fruit.HyperDash) { - HyperDashModifier = Math.Abs(fruit.HyperDashTarget.X - fruit.X) / Math.Abs(fruit.HyperDashTarget.StartTime - fruit.StartTime) / BASE_SPEED; - HyperDashDirection = fruit.HyperDashTarget.X - fruit.X; + var target = fruit.HyperDashTarget; + double timeDifference = target.StartTime - fruit.StartTime; + double positionDifference = target.X * CatchPlayfield.BASE_WIDTH - catcherPosition; + double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); + + HyperDashing = true; + hyperDashModifier = Math.Abs(velocity); + hyperDashDirection = (int)Math.Sign(velocity); + hyperDashTargetPosition = target.X; } else - HyperDashModifier = 1; + { + HyperDashing = false; + } return validCatch; } + private double hyperDashModifier = 1; + private int hyperDashDirection = 0; + private float hyperDashTargetPosition; + private bool hyperDashing = false; + /// /// Whether we are hypderdashing or not. /// - public bool HyperDashing => hyperDashModifier != 1; - - private double hyperDashModifier = 1; - - /// - /// The direction in which hyperdash is allowed. 0 allows both directions. - /// - public double HyperDashDirection; - - /// - /// The speed modifier resultant from hyperdash. Will trigger hyperdash when not equal to 1. - /// - public double HyperDashModifier + protected bool HyperDashing { - get { return hyperDashModifier; } + get => hyperDashing; set { - if (value == hyperDashModifier) return; - hyperDashModifier = value; + if (hyperDashing == value) return; + + hyperDashing = value; + + if (!HyperDashing) + { + hyperDashModifier = 1; + hyperDashDirection = 0; + } const float transition_length = 180; @@ -290,7 +299,6 @@ namespace osu.Game.Rulesets.Catch.UI } else { - HyperDashDirection = 0; this.FadeColour(Color4.White, transition_length, Easing.OutQuint); this.FadeTo(1, transition_length, Easing.OutQuint); } @@ -347,12 +355,18 @@ namespace osu.Game.Rulesets.Catch.UI var direction = Math.Sign(currentDirection); double dashModifier = Dashing ? 1 : 0.5; - - if (hyperDashModifier != 1 && (HyperDashDirection == 0 || direction == Math.Sign(HyperDashDirection))) - dashModifier = hyperDashModifier; + double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); + X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + + // Correct overshooting. + if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || + (hyperDashDirection < 0 && hyperDashTargetPosition > X)) + { + X = hyperDashTargetPosition; + HyperDashing = false; + } } /// From 99c0e19189b95df33b332784e8a13f8a985c2181 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 01:52:15 +0900 Subject: [PATCH 035/199] Fix build error --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index f239290ed4..ed6600c55d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -26,7 +26,6 @@ namespace osu.Game.Rulesets.Catch.Tests public TestCaseCatcherArea() { AddSliderStep("CircleSize", 0, 8, 5, createCatcher); - AddToggleStep("Hyperdash", t => catcherArea.ToggleHyperDash(t)); } private void createCatcher(float size) @@ -54,8 +53,6 @@ namespace osu.Game.Rulesets.Catch.Tests : base(beatmapDifficulty) { } - - public void ToggleHyperDash(bool status) => MovableCatcher.HyperDashModifier = status ? 2 : 1; } } } From be323c71477d009bb8bcda38560fa5c370bcd6f1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Fri, 25 May 2018 02:14:56 +0900 Subject: [PATCH 036/199] Fix InspectCode issues. --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 3 +-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index ed6600c55d..511cda6399 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -16,7 +16,6 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCaseCatcherArea : OsuTestCase { private RulesetInfo catchRuleset; - private TestCatcherArea catcherArea; public override IReadOnlyList RequiredTypes => new[] { @@ -33,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.Tests Child = new CatchInputManager(catchRuleset) { RelativeSizeAxes = Axes.Both, - Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) + Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, Origin = Anchor.BottomLeft diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56826d228c..d57d52cf5f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -255,7 +255,7 @@ namespace osu.Game.Rulesets.Catch.UI HyperDashing = true; hyperDashModifier = Math.Abs(velocity); - hyperDashDirection = (int)Math.Sign(velocity); + hyperDashDirection = Math.Sign(velocity); hyperDashTargetPosition = target.X; } else @@ -267,9 +267,9 @@ namespace osu.Game.Rulesets.Catch.UI } private double hyperDashModifier = 1; - private int hyperDashDirection = 0; + private int hyperDashDirection; private float hyperDashTargetPosition; - private bool hyperDashing = false; + private bool hyperDashing; /// /// Whether we are hypderdashing or not. @@ -361,8 +361,8 @@ namespace osu.Game.Rulesets.Catch.UI X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. - if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || - (hyperDashDirection < 0 && hyperDashTargetPosition > X)) + if (hyperDashDirection > 0 && hyperDashTargetPosition < X || + hyperDashDirection < 0 && hyperDashTargetPosition > X) { X = hyperDashTargetPosition; HyperDashing = false; From 498244a3089827cbd58aff593d0ec3963cf32303 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 25 May 2018 00:37:53 +0300 Subject: [PATCH 037/199] 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 038/199] 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 039/199] 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 ab3ac49a2d6ac9667709b61a694be91206ab9925 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 28 May 2018 21:01:56 -0300 Subject: [PATCH 040/199] Add empty Match screen. --- osu.Game.Tests/Visual/TestCaseMatch.cs | 23 ++++++++++++ .../Screens/Multi/Screens/Lounge/Lounge.cs | 2 +- osu.Game/Screens/Multi/Screens/Match.cs | 37 ------------------- osu.Game/Screens/Multi/Screens/Match/Match.cs | 19 ++++++++++ osu.Game/Screens/Multi/Screens/MatchCreate.cs | 20 ---------- 5 files changed, 43 insertions(+), 58 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMatch.cs delete mode 100644 osu.Game/Screens/Multi/Screens/Match.cs create mode 100644 osu.Game/Screens/Multi/Screens/Match/Match.cs delete mode 100644 osu.Game/Screens/Multi/Screens/MatchCreate.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs new file mode 100644 index 0000000000..9e62a19897 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Screens.Match; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseMatch : OsuTestCase + { + public TestCaseMatch() + { + Room room = new Room + { + }; + + Match match = new Match(room); + + AddStep(@"show", () => Add(match)); + AddStep(@"exit", match.Exit); + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs index 60ffe2c0b9..c83ecee1f0 100644 --- a/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs +++ b/osu.Game/Screens/Multi/Screens/Lounge/Lounge.cs @@ -164,7 +164,7 @@ namespace osu.Game.Screens.Multi.Screens.Lounge // open the room if its selected and is clicked again if (room.State == SelectionState.Selected) - Push(new Match()); + Push(new Match.Match(room.Room)); } private class RoomsFilterContainer : FillFlowContainer, IHasFilterableChildren diff --git a/osu.Game/Screens/Multi/Screens/Match.cs b/osu.Game/Screens/Multi/Screens/Match.cs deleted file mode 100644 index 4ba7fe9f6a..0000000000 --- a/osu.Game/Screens/Multi/Screens/Match.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Framework.Screens; -using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Play; -using osu.Game.Screens.Select; -using OpenTK.Graphics; - -namespace osu.Game.Screens.Multi.Screens -{ - public class Match : ScreenWhiteBox - { - protected override IEnumerable PossibleChildren => new[] { - typeof(MatchSongSelect), - typeof(Player), - }; - - protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); - - protected override void OnEntering(Screen last) - { - base.OnEntering(last); - - Background.FadeColour(Color4.DarkGray, 500); - } - - protected override bool OnExiting(Screen next) - { - Background.FadeColour(Color4.White, 500); - return base.OnExiting(next); - } - } -} diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs new file mode 100644 index 0000000000..f70ed9eaa4 --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi.Screens.Match +{ + public class Match : MultiplayerScreen + { + private readonly Room room; + + public override string Title => room.Name.Value; + + public Match(Room room) + { + this.room = room; + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/MatchCreate.cs b/osu.Game/Screens/Multi/Screens/MatchCreate.cs deleted file mode 100644 index 6b4e26d5e5..0000000000 --- a/osu.Game/Screens/Multi/Screens/MatchCreate.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; - -namespace osu.Game.Screens.Multi.Screens -{ - public class MatchCreate : ScreenWhiteBox - { - protected override IEnumerable PossibleChildren => new[] { - typeof(Match) - }; - - public MatchCreate() - { - ValidForResume = false; - } - } -} From 98819880c4a3018e2d840be335ce2a542629611d Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 28 May 2018 22:11:01 -0300 Subject: [PATCH 041/199] Add match screen header. --- osu.Game.Tests/Visual/TestCaseMatch.cs | 17 ++ .../Screens/Multi/Screens/Match/Header.cs | 169 ++++++++++++++++++ osu.Game/Screens/Multi/Screens/Match/Match.cs | 23 +++ 3 files changed, 209 insertions(+) create mode 100644 osu.Game/Screens/Multi/Screens/Match/Header.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index 9e62a19897..5dc330704d 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.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 osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Screens.Match; @@ -12,6 +13,22 @@ namespace osu.Game.Tests.Visual { Room room = new Room { + Beatmap = + { + Value = new BeatmapInfo + { + BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/765055/covers/cover.jpg?1526955337", + }, + }, + }, + }, + }, }; Match match = new Match(room); diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs new file mode 100644 index 0000000000..b1f9e0dfc6 --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -0,0 +1,169 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.SearchableList; +using OpenTK.Graphics; + +namespace osu.Game.Screens.Multi.Screens.Match +{ + public class Header : Container + { + private readonly Box tabStrip; + private readonly UpdateableBeatmapSetCover cover; + + public readonly OsuClickableContainer BeatmapButton; + + public BeatmapSetInfo BeatmapSet + { + set { cover.BeatmapSet = value; } + } + + public Header() + { + RelativeSizeAxes = Axes.X; + Height = 200; + + Children = new Drawable[] + { + cover = new UpdateableBeatmapSetCover + { + RelativeSizeAxes = Axes.Both, + Masking = true, + }, + tabStrip = new Box + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 1, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Children = new Drawable[] + { + new Container + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Y, + Width = 200, + Padding = new MarginPadding { Vertical = 5 }, + Child = BeatmapButton = new BeatmapSelectButton + { + RelativeSizeAxes = Axes.Both, + }, + }, + new PageTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + }, + }, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + tabStrip.Colour = colours.Yellow; + } + + private class BeatmapSelectButton : OsuClickableContainer + { + private const float corner_radius = 5; + private const float bg_opacity = 0.5f; + private const float transition_duration = 100; + + private readonly Box bg; + private readonly Container border; + + public BeatmapSelectButton() + { + Masking = true; + CornerRadius = corner_radius; + + Children = new Drawable[] + { + bg = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = bg_opacity, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = @"Exo2.0-Bold", + Text = "Select Beatmap", + }, + border = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = corner_radius, + BorderThickness = 4, + Alpha = 0f, + Child = new Box // needs a child to show the border + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0), + }, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + border.BorderColour = colours.Yellow; + } + + protected override bool OnHover(InputState state) + { + border.FadeIn(transition_duration); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + base.OnHoverLost(state); + border.FadeOut(transition_duration); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + bg.FadeTo(0.75f, 1000, Easing.Out); + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + bg.FadeTo(bg_opacity, transition_duration); + return base.OnMouseUp(state, args); + } + } + } + + public enum MatchHeaderPage + { + Settings, + Room, + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index f70ed9eaa4..82f5b53ee2 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -1,19 +1,42 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Select; namespace osu.Game.Screens.Multi.Screens.Match { public class Match : MultiplayerScreen { private readonly Room room; + private readonly Bindable beatmapBind = new Bindable(); public override string Title => room.Name.Value; public Match(Room room) { this.room = room; + Header header; + + Children = new Drawable[] + { + header = new Header(), + }; + + header.BeatmapButton.Action = () => + { + Push(new MatchSongSelect()); + }; + + beatmapBind.ValueChanged += b => + { + header.BeatmapSet = b.BeatmapSet; + }; + + beatmapBind.BindTo(room.Beatmap); } } } From c8ce34b6d4a80f8c8a2414a3296e21642003f24d Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 01:51:04 -0300 Subject: [PATCH 042/199] Add Match Info. --- osu.Game.Tests/Visual/TestCaseMatch.cs | 17 +- .../Screens/Multi/Screens/Match/Header.cs | 5 +- osu.Game/Screens/Multi/Screens/Match/Info.cs | 194 ++++++++++++++++++ osu.Game/Screens/Multi/Screens/Match/Match.cs | 24 ++- 4 files changed, 234 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Screens/Multi/Screens/Match/Info.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index 5dc330704d..9c385feacb 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -1,22 +1,37 @@ // 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.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; using osu.Game.Screens.Multi.Screens.Match; namespace osu.Game.Tests.Visual { public class TestCaseMatch : OsuTestCase { - public TestCaseMatch() + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) { Room room = new Room { + Name = { Value = @"One Awesome Room" }, + Status = { Value = new RoomStatusOpen() }, + Availability = { Value = RoomAvailability.Public }, + Type = { Value = new GameTypeTeamVersus() }, Beatmap = { Value = new BeatmapInfo { + StarDifficulty = 5.02, + Ruleset = rulesets.GetRuleset(1), + Metadata = new BeatmapMetadata + { + Title = @"Paradigm Shift", + Artist = @"Morimori Atsushi", + AuthorString = @"eiri-", + }, BeatmapSet = new BeatmapSetInfo { OnlineInfo = new BeatmapSetOnlineInfo diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index b1f9e0dfc6..fde6859d95 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -20,6 +20,8 @@ namespace osu.Game.Screens.Multi.Screens.Match { public class Header : Container { + public const float HEIGHT = 200; + private readonly Box tabStrip; private readonly UpdateableBeatmapSetCover cover; @@ -33,10 +35,11 @@ namespace osu.Game.Screens.Multi.Screens.Match public Header() { RelativeSizeAxes = Axes.X; - Height = 200; + Height = HEIGHT; Children = new Drawable[] { + // todo: gradient over the cover cover = new UpdateableBeatmapSetCover { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Screens/Match/Info.cs new file mode 100644 index 0000000000..634b91cf7a --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Match/Info.cs @@ -0,0 +1,194 @@ +// 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.Configuration; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.Multiplayer; +using osu.Game.Overlays.SearchableList; +using osu.Game.Screens.Multi.Components; + +namespace osu.Game.Screens.Multi.Screens.Match +{ + public class Info : Container + { + public const float HEIGHT = 128; + + private readonly OsuSpriteText name, availabilityStatus; + private readonly BeatmapTypeInfo beatmapTypeInfo; + + private OsuColour colours; + + public string Name + { + set { name.Text = value; } + } + + private RoomAvailability availability; + public RoomAvailability Availability + { + set + { + if (value == availability) return; + availability = value; + + if (IsLoaded) + updateAvailabilityStatus(); + } + } + + private RoomStatus status; + public RoomStatus Status + { + set + { + if (value == status) return; + status = value; + + if (IsLoaded) + updateAvailabilityStatus(); + } + } + + public BeatmapInfo Beatmap + { + set { beatmapTypeInfo.Beatmap = value; } + } + + public GameType Type + { + set { beatmapTypeInfo.Type = value; } + } + + public Info() + { + RelativeSizeAxes = Axes.X; + Height = HEIGHT; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"28242d"), + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Padding = new MarginPadding { Vertical = 20 }, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + name = new OsuSpriteText + { + TextSize = 30, + }, + availabilityStatus = new OsuSpriteText + { + TextSize = 14, + }, + }, + }, + beatmapTypeInfo = new BeatmapTypeInfo + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }, + }, + }, + new ReadyButton + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Y, + Width = 200, + Padding = new MarginPadding { Vertical = 10 }, + }, + }, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + this.colours = colours; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updateAvailabilityStatus(); + } + + private void updateAvailabilityStatus() + { + if (status != null) + { + availabilityStatus.FadeColour(status.GetAppropriateColour(colours)); + availabilityStatus.Text = $"{availability.GetDescription()}, {status.Message}"; + } + } + + private class ReadyButton : TriangleButton + { + public readonly Bindable Ready = new Bindable(); + + protected override SpriteText CreateText() => new OsuSpriteText + { + Depth = -1, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Font = @"Exo2.0-Light", + TextSize = 30, + }; + + public ReadyButton() + { + Height = 1; + Text = "Ready"; + + Action = () => Ready.Value = !Ready.Value; + } + + [BackgroundDependencyLoader] + private void load() + { + BackgroundColour = OsuColour.FromHex(@"1187aa"); + Triangles.ColourLight = OsuColour.FromHex(@"277b9c"); + Triangles.ColourDark = OsuColour.FromHex(@"1f6682"); + Triangles.TriangleScale = 1.5f; + + // todo: visually select + Ready.ValueChanged += value => + { + if (value) + Text = "Not Ready"; + else + Text = "Ready"; + }; + } + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 82f5b53ee2..e83769daa0 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -12,6 +12,11 @@ namespace osu.Game.Screens.Multi.Screens.Match public class Match : MultiplayerScreen { private readonly Room room; + + private readonly Bindable nameBind = new Bindable(); + private readonly Bindable statusBind = new Bindable(); + private readonly Bindable availabilityBind = new Bindable(); + private readonly Bindable typeBind = new Bindable(); private readonly Bindable beatmapBind = new Bindable(); public override string Title => room.Name.Value; @@ -20,22 +25,33 @@ namespace osu.Game.Screens.Multi.Screens.Match { this.room = room; Header header; + Info info; Children = new Drawable[] { header = new Header(), + info = new Info + { + Margin = new MarginPadding { Top = Header.HEIGHT }, + }, }; - header.BeatmapButton.Action = () => - { - Push(new MatchSongSelect()); - }; + header.BeatmapButton.Action = () => Push(new MatchSongSelect()); + nameBind.ValueChanged += n => info.Name = n; + statusBind.ValueChanged += s => info.Status = s; + availabilityBind.ValueChanged += a => info.Availability = a; + typeBind.ValueChanged += t => info.Type = t; beatmapBind.ValueChanged += b => { header.BeatmapSet = b.BeatmapSet; + info.Beatmap = b; }; + nameBind.BindTo(room.Name); + statusBind.BindTo(room.Status); + availabilityBind.BindTo(room.Availability); + typeBind.BindTo(room.Type); beatmapBind.BindTo(room.Beatmap); } } From 77ff0640c24a5005486337b8ac3cd95369b6a3c2 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 01:53:45 -0300 Subject: [PATCH 043/199] Add a gradient over the cover in Header. --- osu.Game/Screens/Multi/Screens/Match/Header.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index fde6859d95..1d414e338c 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; @@ -39,12 +40,16 @@ namespace osu.Game.Screens.Multi.Screens.Match Children = new Drawable[] { - // todo: gradient over the cover cover = new UpdateableBeatmapSetCover { RelativeSizeAxes = Axes.Both, Masking = true, }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Color4.Black.Opacity(0.5f)), + }, tabStrip = new Box { Anchor = Anchor.BottomLeft, From 3915cb7f2f7cde41e6688905cd9bfed2c8487008 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 02:42:52 -0300 Subject: [PATCH 044/199] Add Match Participants, change Room.Users to IEnumerable. --- osu.Game.Tests/Visual/TestCaseMatch.cs | 38 ++++++++++ osu.Game/Online/Multiplayer/Room.cs | 3 +- .../Screens/Multi/Components/DrawableRoom.cs | 2 +- .../Screens/Multi/Components/RoomInspector.cs | 5 +- osu.Game/Screens/Multi/Screens/Match/Match.cs | 17 +++++ .../Multi/Screens/Match/Participants.cs | 71 +++++++++++++++++++ .../Multi/Screens/MultiplayerScreen.cs | 1 + 7 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Screens/Multi/Screens/Match/Participants.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index 9c385feacb..6f41723982 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -6,6 +6,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Users; namespace osu.Game.Tests.Visual { @@ -44,6 +45,43 @@ namespace osu.Game.Tests.Visual }, }, }, + MaxParticipants = { Value = 5 }, + Participants = + { + Value = new[] + { + new User + { + Username = @"eiri-", + Id = 3388410, + Country = new Country { FlagName = @"US" }, + CoverUrl = @"https://assets.ppy.sh/user-profile-covers/3388410/00a8486a247831e1cc4375db519f611ac970bda8bc0057d78b0f540ea38c3e58.jpeg", + IsSupporter = true, + }, + new User + { + Username = @"Nepuri", + Id = 6637817, + Country = new Country { FlagName = @"DE" }, + CoverUrl = @"https://assets.ppy.sh/user-profile-covers/6637817/9085fc60248b6b5327a72c1dcdecf2dbedba810ae0ab6bcf7224e46b1339632a.jpeg", + IsSupporter = true, + }, + new User + { + Username = @"goheegy", + Id = 8057655, + Country = new Country { FlagName = @"GB" }, + CoverUrl = @"https://assets.ppy.sh/user-profile-covers/8057655/21cec27c25a11dc197a4ec6a74253dbabb495949b0e0697113352f12007018c5.jpeg", + }, + new User + { + Username = @"Alumetri", + Id = 5371497, + Country = new Country { FlagName = @"RU" }, + CoverUrl = @"https://assets.ppy.sh/user-profile-covers/5371497/e023b8c7fbe3613e64bd4856703517ea50fbed8a5805dc9acda9efe9897c67e2.jpeg", + }, + } + }, }; Match match = new Match(room); diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index ae3fb5ec6e..b076afbcdb 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.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.Collections.Generic; using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Users; @@ -16,6 +17,6 @@ namespace osu.Game.Online.Multiplayer public Bindable Type = new Bindable(); public Bindable Beatmap = new Bindable(); public Bindable MaxParticipants = new Bindable(); - public Bindable Participants = new Bindable(); + public Bindable> Participants = new Bindable>(); } } diff --git a/osu.Game/Screens/Multi/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Components/DrawableRoom.cs index d31019a259..54bd0ae7cc 100644 --- a/osu.Game/Screens/Multi/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Components/DrawableRoom.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Multi.Components private readonly Bindable statusBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable beatmapBind = new Bindable(); - private readonly Bindable participantsBind = new Bindable(); + private readonly Bindable> participantsBind = new Bindable>(); public readonly Room Room; diff --git a/osu.Game/Screens/Multi/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Components/RoomInspector.cs index 14f4feab05..22bca1efc7 100644 --- a/osu.Game/Screens/Multi/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Components/RoomInspector.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.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -33,7 +34,7 @@ namespace osu.Game.Screens.Multi.Components private readonly Bindable typeBind = new Bindable(); private readonly Bindable beatmapBind = new Bindable(); private readonly Bindable maxParticipantsBind = new Bindable(); - private readonly Bindable participantsBind = new Bindable(); + private readonly Bindable> participantsBind = new Bindable>(); private OsuColour colours; private Box statusStrip; @@ -214,7 +215,7 @@ namespace osu.Game.Screens.Multi.Components participantsBind.ValueChanged += p => { - participantCount.Count = p.Length; + participantCount.Count = p.Count(); participantInfo.Participants = p; participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u)); }; diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index e83769daa0..3a2aef2ff4 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -1,23 +1,31 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Select; +using osu.Game.Users; namespace osu.Game.Screens.Multi.Screens.Match { public class Match : MultiplayerScreen { private readonly Room room; + private readonly Participants participants; private readonly Bindable nameBind = new Bindable(); private readonly Bindable statusBind = new Bindable(); private readonly Bindable availabilityBind = new Bindable(); private readonly Bindable typeBind = new Bindable(); private readonly Bindable beatmapBind = new Bindable(); + private readonly Bindable maxParticipantsBind = new Bindable(); + private readonly Bindable> participantsBind = new Bindable>(); + + protected override Container TransitionContent => participants; public override string Title => room.Name.Value; @@ -34,6 +42,11 @@ namespace osu.Game.Screens.Multi.Screens.Match { Margin = new MarginPadding { Top = Header.HEIGHT }, }, + participants = new Participants + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = Header.HEIGHT + Info.HEIGHT }, + }, }; header.BeatmapButton.Action = () => Push(new MatchSongSelect()); @@ -41,6 +54,8 @@ namespace osu.Game.Screens.Multi.Screens.Match statusBind.ValueChanged += s => info.Status = s; availabilityBind.ValueChanged += a => info.Availability = a; typeBind.ValueChanged += t => info.Type = t; + maxParticipantsBind.ValueChanged += m => { participants.Max = m; }; + participantsBind.ValueChanged += p => participants.Users = p; beatmapBind.ValueChanged += b => { @@ -53,6 +68,8 @@ namespace osu.Game.Screens.Multi.Screens.Match availabilityBind.BindTo(room.Availability); typeBind.BindTo(room.Type); beatmapBind.BindTo(room.Beatmap); + maxParticipantsBind.BindTo(room.MaxParticipants); + participantsBind.BindTo(room.Participants); } } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Screens/Match/Participants.cs new file mode 100644 index 0000000000..11e27c0a18 --- /dev/null +++ b/osu.Game/Screens/Multi/Screens/Match/Participants.cs @@ -0,0 +1,71 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays.SearchableList; +using osu.Game.Screens.Multi.Components; +using osu.Game.Users; +using OpenTK; + +namespace osu.Game.Screens.Multi.Screens.Match +{ + public class Participants : Container + { + private readonly ParticipantCount count; + private readonly FillFlowContainer usersFlow; + + public IEnumerable Users + { + set { + usersFlow.Children = value.Select(u => new UserPanel(u) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 300, + }).ToList(); + + count.Count = value.Count(); + } + } + + public int? Max + { + set { count.Max = value; } + } + + public Participants() + { + Child = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Children = new Drawable[] + { + new ScrollContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 10 }, + Children = new Drawable[] + { + count = new ParticipantCount + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + usersFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(5), + Padding = new MarginPadding { Top = 40 }, + }, + }, + }, + }, + }; + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs index 191fe66037..9daa4e732b 100644 --- a/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs +++ b/osu.Game/Screens/Multi/Screens/MultiplayerScreen.cs @@ -21,6 +21,7 @@ namespace osu.Game.Screens.Multi.Screens TransitionContent.MoveToX(200); + Content.FadeInFromZero(WaveContainer.APPEAR_DURATION, in_easing); TransitionContent.FadeInFromZero(WaveContainer.APPEAR_DURATION, in_easing); TransitionContent.MoveToX(0, WaveContainer.APPEAR_DURATION, in_easing); } From 94b54a0520d4f2d091d531786c63b527a8db2629 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 03:03:51 -0300 Subject: [PATCH 045/199] Adjust design of ReadyButton. --- osu.Game/Screens/Multi/Screens/Match/Info.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Screens/Match/Info.cs index 634b91cf7a..88dda4a67b 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Info.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Info.cs @@ -180,13 +180,31 @@ namespace osu.Game.Screens.Multi.Screens.Match Triangles.ColourDark = OsuColour.FromHex(@"1f6682"); Triangles.TriangleScale = 1.5f; - // todo: visually select + Container active; + Add(active = new Container + { + RelativeSizeAxes = Axes.Both, + Alpha = 0f, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.15f, + Blending = BlendingMode.Additive, + }, + }); + Ready.ValueChanged += value => { if (value) + { Text = "Not Ready"; + active.FadeIn(200); + } else + { Text = "Ready"; + active.FadeOut(200); + } }; } } From b4b4a8a157a0bbcb5e99269ff3772afeff7f2545 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 03:24:38 -0300 Subject: [PATCH 046/199] Add TestCaseMatchInfo. --- osu.Game.Tests/Visual/TestCaseMatch.cs | 2 + osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 59 ++++++++++++++++++++ osu.Game/Screens/Multi/Screens/Match/Info.cs | 7 ++- 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchInfo.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index 6f41723982..69c1a6a0b2 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.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 NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; @@ -10,6 +11,7 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual { + [TestFixture] public class TestCaseMatch : OsuTestCase { [BackgroundDependencyLoader] diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs new file mode 100644 index 0000000000..f58bc0e30a --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -0,0 +1,59 @@ +// 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.Game.Beatmaps; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Screens.Multi.Screens.Match; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseMatchInfo : OsuTestCase + { + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + Info info = new Info(); + Add(info); + + AddStep(@"set name", () => info.Name = @"Room Name?"); + AddStep(@"set availability", () => info.Availability = RoomAvailability.FriendsOnly); + AddStep(@"set status", () => info.Status = new RoomStatusPlaying()); + + AddStep(@"set beatmap", () => info.Beatmap = new BeatmapInfo + { + StarDifficulty = 2.4, + Ruleset = rulesets.GetRuleset(0), + Metadata = new BeatmapMetadata + { + Title = @"My Song", + Artist = @"VisualTests", + AuthorString = @"osu!lazer", + }, + }); + + AddStep(@"set type", () => info.Type = new GameTypeTagTeam()); + + AddStep(@"change name", () => info.Name = @"Room Name!"); + AddStep(@"change availability", () => info.Availability = RoomAvailability.InviteOnly); + AddStep(@"change status", () => info.Status = new RoomStatusOpen()); + + AddStep(@"change beatmap", () => info.Beatmap = new BeatmapInfo + { + StarDifficulty = 4.2, + Ruleset = rulesets.GetRuleset(3), + Metadata = new BeatmapMetadata + { + Title = @"Your Song", + Artist = @"Tester", + AuthorString = @"Someone", + }, + }); + + AddStep(@"change type", () => info.Type = new GameTypeTeamVersus()); + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match/Info.cs b/osu.Game/Screens/Multi/Screens/Match/Info.cs index 88dda4a67b..e2efbad269 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Info.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Info.cs @@ -24,9 +24,12 @@ namespace osu.Game.Screens.Multi.Screens.Match private readonly OsuSpriteText name, availabilityStatus; private readonly BeatmapTypeInfo beatmapTypeInfo; + private readonly ReadyButton readyButton; private OsuColour colours; + public Bindable Ready => readyButton.Ready; + public string Name { set { name.Text = value; } @@ -116,7 +119,7 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }, }, - new ReadyButton + readyButton = new ReadyButton { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -146,7 +149,7 @@ namespace osu.Game.Screens.Multi.Screens.Match { if (status != null) { - availabilityStatus.FadeColour(status.GetAppropriateColour(colours)); + availabilityStatus.FadeColour(status.GetAppropriateColour(colours), 100); availabilityStatus.Text = $"{availability.GetDescription()}, {status.Message}"; } } From 8595c821b438cf2d5c8a2d7bb3d06b8d46f9a1ec Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 03:34:02 -0300 Subject: [PATCH 047/199] Add TestCaseMatchHeader. --- osu.Game.Tests/Visual/TestCaseMatchHeader.cs | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchHeader.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs new file mode 100644 index 0000000000..34f98f97c2 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchHeader.cs @@ -0,0 +1,43 @@ +// 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.Game.Beatmaps; +using osu.Game.Screens.Multi.Screens.Match; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseMatchHeader : OsuTestCase + { + public TestCaseMatchHeader() + { + Header header = new Header(); + Add(header); + + AddStep(@"set beatmap set", () => header.BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/760757/covers/cover.jpg?1526944540", + }, + }, + }); + + AddStep(@"change beatmap set", () => header.BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/761883/covers/cover.jpg?1525557400", + }, + }, + }); + + AddStep(@"null beatmap set", () => header.BeatmapSet = null); + } + } +} From 7edb82eb85db1bca1bbccaabca2a625242d16f3a Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 03:53:30 -0300 Subject: [PATCH 048/199] Add TestCaseMatchParticipants. --- osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 2 - .../Visual/TestCaseMatchParticipants.cs | 56 +++++++++++++++++++ .../Multi/Screens/Match/Participants.cs | 3 + 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseMatchParticipants.cs diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index f58bc0e30a..da5f429363 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -22,7 +22,6 @@ namespace osu.Game.Tests.Visual AddStep(@"set name", () => info.Name = @"Room Name?"); AddStep(@"set availability", () => info.Availability = RoomAvailability.FriendsOnly); AddStep(@"set status", () => info.Status = new RoomStatusPlaying()); - AddStep(@"set beatmap", () => info.Beatmap = new BeatmapInfo { StarDifficulty = 2.4, @@ -40,7 +39,6 @@ namespace osu.Game.Tests.Visual AddStep(@"change name", () => info.Name = @"Room Name!"); AddStep(@"change availability", () => info.Availability = RoomAvailability.InviteOnly); AddStep(@"change status", () => info.Status = new RoomStatusOpen()); - AddStep(@"change beatmap", () => info.Beatmap = new BeatmapInfo { StarDifficulty = 4.2, diff --git a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs new file mode 100644 index 0000000000..d6ae07252b --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs @@ -0,0 +1,56 @@ +// 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.Graphics; +using osu.Game.Screens.Multi.Screens.Match; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseMatchParticipants : OsuTestCase + { + public TestCaseMatchParticipants() + { + Participants participants; + Add(participants = new Participants + { + RelativeSizeAxes = Axes.Both, + }); + + AddStep(@"set max to null", () => participants.Max = null); + AddStep(@"set users", () => participants.Users = new[] + { + new User + { + Username = @"Feppla", + Id = 4271601, + Country = new Country { FlagName = @"SE" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", + IsSupporter = true, + }, + new User + { + Username = @"Xilver", + Id = 3099689, + Country = new Country { FlagName = @"IL" }, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", + IsSupporter = true, + }, + new User + { + Username = @"Wucki", + Id = 5287410, + Country = new Country { FlagName = @"FI" }, + CoverUrl = @"https://assets.ppy.sh/user-profile-covers/5287410/5cfeaa9dd41cbce038ecdc9d781396ed4b0108089170bf7f50492ef8eadeb368.jpeg", + IsSupporter = true, + }, + }); + + AddStep(@"set max", () => participants.Max = 10); + AddStep(@"clear users", () => participants.Users = new User[] { }); + AddStep(@"set max to null", () => participants.Max = null); + } + } +} diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Screens/Match/Participants.cs index 11e27c0a18..182aa1e04e 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Participants.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Participants.cs @@ -25,6 +25,7 @@ namespace osu.Game.Screens.Multi.Screens.Match Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Width = 300, + OnLoadComplete = d => d.FadeInFromZero(60), }).ToList(); count.Count = value.Count(); @@ -61,6 +62,8 @@ namespace osu.Game.Screens.Multi.Screens.Match AutoSizeAxes = Axes.Y, Spacing = new Vector2(5), Padding = new MarginPadding { Top = 40 }, + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint, }, }, }, From 9a7e5a3e2c26a8113a3b3182e750ca76d1306a17 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 29 May 2018 04:16:19 -0300 Subject: [PATCH 049/199] Update TestCaseMatch. --- osu.Game.Tests/Visual/TestCaseMatch.cs | 47 +++++++++++++++++++ osu.Game.Tests/Visual/TestCaseMatchInfo.cs | 4 +- osu.Game/Screens/Multi/Screens/Match/Match.cs | 2 +- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMatch.cs b/osu.Game.Tests/Visual/TestCaseMatch.cs index 69c1a6a0b2..bb22358425 100644 --- a/osu.Game.Tests/Visual/TestCaseMatch.cs +++ b/osu.Game.Tests/Visual/TestCaseMatch.cs @@ -89,6 +89,53 @@ namespace osu.Game.Tests.Visual Match match = new Match(room); AddStep(@"show", () => Add(match)); + AddStep(@"null beatmap", () => room.Beatmap.Value = null); + AddStep(@"change name", () => room.Name.Value = @"Two Awesome Rooms"); + AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying()); + AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.FriendsOnly); + AddStep(@"change type", () => room.Type.Value = new GameTypeTag()); + AddStep(@"change beatmap", () => room.Beatmap.Value = new BeatmapInfo + { + StarDifficulty = 4.33, + Ruleset = rulesets.GetRuleset(2), + Metadata = new BeatmapMetadata + { + Title = @"Yasashisa no Riyuu", + Artist = @"ChouCho", + AuthorString = @"celerih", + }, + BeatmapSet = new BeatmapSetInfo + { + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/685391/covers/cover.jpg?1524597970", + }, + }, + }, + }); + + AddStep(@"null max participants", () => room.MaxParticipants.Value = null); + AddStep(@"change participants", () => room.Participants.Value = new[] + { + new User + { + Username = @"Spectator", + Id = 702598, + Country = new Country { FlagName = @"KR" }, + CoverUrl = @"https://assets.ppy.sh/user-profile-covers/702598/3bbf4cb8b8d2cf8b03145000a975ff27e191ab99b0920832e7dd67386280e288.jpeg", + IsSupporter = true, + }, + new User + { + Username = @"celerih", + Id = 4696296, + Country = new Country { FlagName = @"CA" }, + CoverUrl = @"https://assets.ppy.sh/user-profile-covers/4696296/7f8500731d0ac66d5472569d146a7be07d9460273361913f22c038867baddaef.jpeg", + }, + }); + AddStep(@"exit", match.Exit); } } diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs index da5f429363..205da6932f 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchInfo.cs @@ -39,6 +39,8 @@ namespace osu.Game.Tests.Visual AddStep(@"change name", () => info.Name = @"Room Name!"); AddStep(@"change availability", () => info.Availability = RoomAvailability.InviteOnly); AddStep(@"change status", () => info.Status = new RoomStatusOpen()); + AddStep(@"null beatmap", () => info.Beatmap = null); + AddStep(@"change type", () => info.Type = new GameTypeTeamVersus()); AddStep(@"change beatmap", () => info.Beatmap = new BeatmapInfo { StarDifficulty = 4.2, @@ -50,8 +52,6 @@ namespace osu.Game.Tests.Visual AuthorString = @"Someone", }, }); - - AddStep(@"change type", () => info.Type = new GameTypeTeamVersus()); } } } diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 3a2aef2ff4..525682e9c5 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Multi.Screens.Match beatmapBind.ValueChanged += b => { - header.BeatmapSet = b.BeatmapSet; + header.BeatmapSet = b?.BeatmapSet; info.Beatmap = b; }; From 88ac427ba67a216dff3dc654279fa95cac013df4 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 1 Jun 2018 21:06:37 +0300 Subject: [PATCH 050/199] 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 051/199] 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 97b473ef30ce254cadc75c76bc1630bc1c2186e3 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 1 Jun 2018 16:23:11 -0300 Subject: [PATCH 052/199] Expose tabs and hide beatmap select button in Header. --- osu.Game/Screens/Multi/Screens/Match/Header.cs | 12 +++++++++--- osu.Game/Screens/Multi/Screens/Match/Match.cs | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index 1d414e338c..7985ff5fcf 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.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; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -26,18 +27,21 @@ namespace osu.Game.Screens.Multi.Screens.Match private readonly Box tabStrip; private readonly UpdateableBeatmapSetCover cover; - public readonly OsuClickableContainer BeatmapButton; + public readonly PageTabControl Tabs; public BeatmapSetInfo BeatmapSet { set { cover.BeatmapSet = value; } } + public Action OnWantsSelectBeatmap; + public Header() { RelativeSizeAxes = Axes.X; Height = HEIGHT; + BeatmapSelectButton beatmapButton; Children = new Drawable[] { cover = new UpdateableBeatmapSetCover @@ -70,12 +74,12 @@ namespace osu.Game.Screens.Multi.Screens.Match RelativeSizeAxes = Axes.Y, Width = 200, Padding = new MarginPadding { Vertical = 5 }, - Child = BeatmapButton = new BeatmapSelectButton + Child = beatmapButton = new BeatmapSelectButton { RelativeSizeAxes = Axes.Both, }, }, - new PageTabControl + Tabs = new PageTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -84,6 +88,8 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }, }; + + beatmapButton.Action = () => OnWantsSelectBeatmap?.Invoke(); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 525682e9c5..47fe7b9145 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Multi.Screens.Match }, }; - header.BeatmapButton.Action = () => Push(new MatchSongSelect()); + header.OnWantsSelectBeatmap = () => Push(new MatchSongSelect()); nameBind.ValueChanged += n => info.Name = n; statusBind.ValueChanged += s => info.Status = s; availabilityBind.ValueChanged += a => info.Availability = a; From 507305742013cacec3dc54feeeb630fd44971dc2 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 1 Jun 2018 16:34:03 -0300 Subject: [PATCH 053/199] Cleanup. --- osu.Game/Screens/Multi/Screens/Match/Header.cs | 2 +- osu.Game/Screens/Multi/Screens/Match/Participants.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Screens/Match/Header.cs b/osu.Game/Screens/Multi/Screens/Match/Header.cs index 7985ff5fcf..19e9dc4ad4 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Header.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Header.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Multi.Screens.Match public BeatmapSetInfo BeatmapSet { - set { cover.BeatmapSet = value; } + set => cover.BeatmapSet = value; } public Action OnWantsSelectBeatmap; diff --git a/osu.Game/Screens/Multi/Screens/Match/Participants.cs b/osu.Game/Screens/Multi/Screens/Match/Participants.cs index 182aa1e04e..9fa90f8752 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Participants.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Participants.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Multi.Screens.Match public int? Max { - set { count.Max = value; } + set => count.Max = value; } public Participants() From da8b1f996fb127f8b92a34ab90c5c085a7a2a597 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Fri, 1 Jun 2018 17:16:35 -0300 Subject: [PATCH 054/199] Override Type in Match. --- osu.Game/Screens/Multi/Screens/Match/Match.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Multi/Screens/Match/Match.cs b/osu.Game/Screens/Multi/Screens/Match/Match.cs index 47fe7b9145..3c6f141bd3 100644 --- a/osu.Game/Screens/Multi/Screens/Match/Match.cs +++ b/osu.Game/Screens/Multi/Screens/Match/Match.cs @@ -27,6 +27,7 @@ namespace osu.Game.Screens.Multi.Screens.Match protected override Container TransitionContent => participants; + public override string Type => "room"; public override string Title => room.Name.Value; public Match(Room room) From 330ce1904122d4169104ae500ce5338e3ba584e5 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 1 Jun 2018 23:36:25 +0300 Subject: [PATCH 055/199] 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 056/199] 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 057/199] 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 058/199] 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 9f27dd848a8503350ab127cc4d87e02412be2018 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Sun, 3 Jun 2018 15:29:56 +0900 Subject: [PATCH 059/199] HyperDashModifier >= 1 --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 38 +++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 6c3624aa0a..2ae1f7eb7a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using OpenTK.Graphics; +using System.Diagnostics; namespace osu.Game.Rulesets.Catch.UI { @@ -243,14 +244,21 @@ namespace osu.Game.Rulesets.Catch.UI double positionDifference = target.X * CatchPlayfield.BASE_WIDTH - catcherPosition; double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); - HyperDashing = true; - hyperDashModifier = Math.Abs(velocity); - hyperDashDirection = Math.Sign(velocity); - hyperDashTargetPosition = target.X; + // An edge case + if (Math.Abs(velocity) <= 1) + { + HyperDashModifier = 1; + } + else + { + hyperDashDirection = Math.Sign(velocity); + hyperDashTargetPosition = target.X; + HyperDashModifier = Math.Abs(velocity); + } } else { - HyperDashing = false; + HyperDashModifier = 1; } return validCatch; @@ -259,23 +267,27 @@ namespace osu.Game.Rulesets.Catch.UI private double hyperDashModifier = 1; private int hyperDashDirection; private float hyperDashTargetPosition; - private bool hyperDashing; /// /// Whether we are hypderdashing or not. /// - protected bool HyperDashing + public bool HyperDashing => hyperDashModifier != 1; + + /// + /// The modifier multiplied to the catcher speed. + /// It is always not less than 1 and it is greater than 1 if and only if the catcher is hyper-dashing. + /// + protected double HyperDashModifier { - get => hyperDashing; + get => hyperDashModifier; set { - if (hyperDashing == value) return; - - hyperDashing = value; + Trace.Assert(value >= 1); + if (hyperDashModifier == value) return; + hyperDashModifier = value; if (!HyperDashing) { - hyperDashModifier = 1; hyperDashDirection = 0; } @@ -355,7 +367,7 @@ namespace osu.Game.Rulesets.Catch.UI hyperDashDirection < 0 && hyperDashTargetPosition > X) { X = hyperDashTargetPosition; - HyperDashing = false; + HyperDashModifier = 1; } } From 25d3f0ead18bceec90c477fd11a3ed5ea1908e0b Mon Sep 17 00:00:00 2001 From: ekrctb Date: Sun, 3 Jun 2018 15:31:51 +0900 Subject: [PATCH 060/199] Revert TestCaseCatcherArea --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 8 ++++++-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index 9ec39189f8..f239290ed4 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCaseCatcherArea : OsuTestCase { private RulesetInfo catchRuleset; + private TestCatcherArea catcherArea; public override IReadOnlyList RequiredTypes => new[] { @@ -25,6 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests public TestCaseCatcherArea() { AddSliderStep("CircleSize", 0, 8, 5, createCatcher); + AddToggleStep("Hyperdash", t => catcherArea.ToggleHyperDash(t)); } private void createCatcher(float size) @@ -32,10 +34,10 @@ namespace osu.Game.Rulesets.Catch.Tests Child = new CatchInputManager(catchRuleset) { RelativeSizeAxes = Axes.Both, - Child = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) + Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, - Origin = Anchor.TopLeft + Origin = Anchor.BottomLeft }, }; } @@ -52,6 +54,8 @@ namespace osu.Game.Rulesets.Catch.Tests : base(beatmapDifficulty) { } + + public void ToggleHyperDash(bool status) => MovableCatcher.HyperDashModifier = status ? 2 : 1; } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 2ae1f7eb7a..d7d4691ad0 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -277,7 +277,7 @@ namespace osu.Game.Rulesets.Catch.UI /// The modifier multiplied to the catcher speed. /// It is always not less than 1 and it is greater than 1 if and only if the catcher is hyper-dashing. /// - protected double HyperDashModifier + public double HyperDashModifier { get => hyperDashModifier; set From a5c5d11da20febe6f6eeb1772a6955818c0247f3 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Sun, 3 Jun 2018 15:42:27 +0900 Subject: [PATCH 061/199] I think I should learn how to use git --- osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index f239290ed4..5119260c53 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Catch.Tests Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size }) { Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomLeft + Origin = Anchor.TopLeft }, }; } From dd75cd973be81bc6ae960b36fed441f2b0e92891 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 7 Jun 2018 01:13:35 +0900 Subject: [PATCH 062/199] 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 063/199] 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 9b10cc4e0c7596d55abc44cf092a6f940141e531 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 19:53:47 +0900 Subject: [PATCH 064/199] Remove invertability of ManiaStage --- .../TestCaseManiaPlayfield.cs | 4 ---- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 9 --------- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 15 --------------- 3 files changed, 28 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs index b064d82a23..2ae6bc346a 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs @@ -131,8 +131,6 @@ namespace osu.Game.Rulesets.Mania.Tests Origin = Anchor.Centre, }); - playfield.Inverted.Value = inverted; - return playfield; } @@ -158,8 +156,6 @@ namespace osu.Game.Rulesets.Mania.Tests Clock = new FramedClock(rateAdjustClock) }); - playfield.Inverted.Value = inverted; - for (double t = start_time; t <= start_time + duration; t += 100) { var note1 = new Note { StartTime = t, Column = 0 }; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 4b936fc7f9..153d4698e1 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; @@ -19,11 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI { public class ManiaPlayfield : ScrollingPlayfield { - /// - /// Whether this playfield should be inverted. This flips everything inside the playfield. - /// - public readonly Bindable Inverted = new Bindable(true); - public List Columns => stages.SelectMany(x => x.Columns).ToList(); private readonly List stages = new List(); @@ -36,8 +30,6 @@ namespace osu.Game.Rulesets.Mania.UI if (stageDefinitions.Count <= 0) throw new ArgumentException("Can't have zero or fewer stages."); - Inverted.Value = true; - GridContainer playfieldGrid; InternalChild = playfieldGrid = new GridContainer { @@ -52,7 +44,6 @@ namespace osu.Game.Rulesets.Mania.UI { var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); newStage.VisibleTimeRange.BindTo(VisibleTimeRange); - newStage.Inverted.BindTo(Inverted); playfieldGrid.Content[0][i] = newStage; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index cb93613c7d..41af5fef38 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -28,11 +27,6 @@ namespace osu.Game.Rulesets.Mania.UI { public const float HIT_TARGET_POSITION = 50; - /// - /// Whether this playfield should be inverted. This flips everything inside the playfield. - /// - public readonly Bindable Inverted = new Bindable(true); - public IReadOnlyList Columns => columnFlow.Children; private readonly FillFlowContainer columnFlow; @@ -139,15 +133,6 @@ namespace osu.Game.Rulesets.Mania.UI AddColumn(column); } - - Inverted.ValueChanged += invertedChanged; - Inverted.TriggerChange(); - } - - private void invertedChanged(bool newValue) - { - Scale = new Vector2(1, newValue ? -1 : 1); - Judgements.Scale = Scale; } public void AddColumn(Column c) From 2ed978deaa1b32e98ff5616ebd1f2a2988fbbfb5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 19:55:57 +0900 Subject: [PATCH 065/199] Remove TestCaseManiaHitObjects and TestCaseManiaPlayfield --- .../TestCaseManiaHitObjects.cs | 106 ---------- .../TestCaseManiaPlayfield.cs | 181 ------------------ 2 files changed, 287 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs delete mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs deleted file mode 100644 index a4109722d4..0000000000 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaHitObjects.cs +++ /dev/null @@ -1,106 +0,0 @@ -// 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.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Tests.Visual; -using OpenTK; -using OpenTK.Graphics; - -namespace osu.Game.Rulesets.Mania.Tests -{ - [TestFixture] - public class TestCaseManiaHitObjects : OsuTestCase - { - public TestCaseManiaHitObjects() - { - Note note1 = new Note(); - Note note2 = new Note(); - HoldNote holdNote = new HoldNote { StartTime = 1000 }; - - note1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - note2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - Add(new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - // Imagine that the containers containing the drawable notes are the "columns" - Children = new Drawable[] - { - new Container - { - Name = "Normal note column", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 50, - Children = new[] - { - new Container - { - Name = "Timing section", - RelativeSizeAxes = Axes.Both, - RelativeChildSize = new Vector2(1, 10000), - Children = new[] - { - new DrawableNote(note1, ManiaAction.Key1) - { - Y = 5000, - LifetimeStart = double.MinValue, - LifetimeEnd = double.MaxValue, - AccentColour = Color4.Red - }, - new DrawableNote(note2, ManiaAction.Key1) - { - Y = 6000, - LifetimeStart = double.MinValue, - LifetimeEnd = double.MaxValue, - AccentColour = Color4.Red - } - } - } - } - }, - new Container - { - Name = "Hold note column", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Width = 50, - Children = new[] - { - new Container - { - Name = "Timing section", - RelativeSizeAxes = Axes.Both, - RelativeChildSize = new Vector2(1, 10000), - Children = new[] - { - new DrawableHoldNote(holdNote, ManiaAction.Key1) - { - Y = 5000, - Height = 1000, - LifetimeStart = double.MinValue, - LifetimeEnd = double.MaxValue, - AccentColour = Color4.Red, - } - } - } - } - } - } - }); - } - } -} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs deleted file mode 100644 index 2ae6bc346a..0000000000 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseManiaPlayfield.cs +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Configuration; -using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Mania.Configuration; -using osu.Game.Rulesets.Mania.Judgements; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Scoring; -using osu.Game.Tests.Visual; - -namespace osu.Game.Rulesets.Mania.Tests -{ - [TestFixture] - public class TestCaseManiaPlayfield : OsuTestCase - { - private const double start_time = 500; - private const double duration = 500; - - protected override double TimePerAction => 200; - - private RulesetInfo maniaRuleset; - - public TestCaseManiaPlayfield() - { - var rng = new Random(1337); - - AddStep("1 column", () => createPlayfield(1)); - AddStep("4 columns", () => createPlayfield(4)); - AddStep("5 columns", () => createPlayfield(5)); - AddStep("8 columns", () => createPlayfield(8)); - AddStep("4 + 4 columns", () => - { - var stages = new List - { - new StageDefinition { Columns = 4 }, - new StageDefinition { Columns = 4 }, - }; - createPlayfield(stages); - }); - - AddStep("2 + 4 + 2 columns", () => - { - var stages = new List - { - new StageDefinition { Columns = 2 }, - new StageDefinition { Columns = 4 }, - new StageDefinition { Columns = 2 }, - }; - createPlayfield(stages); - }); - - AddStep("1 + 8 + 1 columns", () => - { - var stages = new List - { - new StageDefinition { Columns = 1 }, - new StageDefinition { Columns = 8 }, - new StageDefinition { Columns = 1 }, - }; - createPlayfield(stages); - }); - - AddStep("Reversed", () => createPlayfield(4, true)); - - AddStep("Notes with input", () => createPlayfieldWithNotes()); - AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(true)); - AddStep("Notes with gravity", () => createPlayfieldWithNotes()); - AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true)); - - AddStep("Hit explosion", () => - { - var playfield = createPlayfield(4); - - int col = rng.Next(0, 4); - - var note = new Note { Column = col }; - note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - var drawableNote = new DrawableNote(note, ManiaAction.Key1) - { - AccentColour = playfield.Columns.ElementAt(col).AccentColour - }; - - playfield.OnJudgement(drawableNote, new ManiaJudgement { Result = HitResult.Perfect }); - playfield.Columns[col].OnJudgement(drawableNote, new ManiaJudgement { Result = HitResult.Perfect }); - }); - } - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets, SettingsStore settings) - { - maniaRuleset = rulesets.GetRuleset(3); - - Dependencies.Cache(new ManiaConfigManager(settings, maniaRuleset, 4)); - } - - private ManiaPlayfield createPlayfield(int cols, bool inverted = false) - { - var stages = new List - { - new StageDefinition { Columns = cols }, - }; - - return createPlayfield(stages, inverted); - } - - private ManiaPlayfield createPlayfield(List stages, bool inverted = false) - { - Clear(); - - var inputManager = new ManiaInputManager(maniaRuleset, stages.Sum(g => g.Columns)) { RelativeSizeAxes = Axes.Both }; - Add(inputManager); - - ManiaPlayfield playfield; - - inputManager.Add(playfield = new ManiaPlayfield(stages) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - return playfield; - } - - private void createPlayfieldWithNotes(bool inverted = false) - { - Clear(); - - var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; - - var inputManager = new ManiaInputManager(maniaRuleset, 4) { RelativeSizeAxes = Axes.Both }; - Add(inputManager); - - ManiaPlayfield playfield; - var stages = new List - { - new StageDefinition { Columns = 4 }, - }; - - inputManager.Add(playfield = new ManiaPlayfield(stages) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Clock = new FramedClock(rateAdjustClock) - }); - - for (double t = start_time; t <= start_time + duration; t += 100) - { - var note1 = new Note { StartTime = t, Column = 0 }; - var note2 = new Note { StartTime = t, Column = 3 }; - - note1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - note2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - playfield.Add(new DrawableNote(note1, ManiaAction.Key1)); - playfield.Add(new DrawableNote(note2, ManiaAction.Key4)); - } - - var holdNote1 = new HoldNote { StartTime = start_time, Duration = duration, Column = 1 }; - var holdNote2 = new HoldNote { StartTime = start_time, Duration = duration, Column = 2 }; - - holdNote1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - holdNote2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - - playfield.Add(new DrawableHoldNote(holdNote1, ManiaAction.Key2)); - playfield.Add(new DrawableHoldNote(holdNote2, ManiaAction.Key3)); - } - } -} From 55a5dfa9b6492b1f38aaf6eb608fd48de7a49c8c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:24:33 +0900 Subject: [PATCH 066/199] Add column testcase --- .../ManiaInputTestCase.cs | 45 +++++++++++++++++++ .../TestCaseColumn.cs | 39 ++++++++++++++++ osu.Game/Rulesets/UI/RulesetInputManager.cs | 5 ++- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs new file mode 100644 index 0000000000..75c8fc7e79 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public abstract class ManiaInputTestCase : OsuTestCase + { + private readonly Container content; + protected override Container Content => content ?? base.Content; + + protected ManiaInputTestCase(int keys) + { + base.Content.Add(content = new LocalInputManager(keys)); + } + + private class LocalInputManager : ManiaInputManager + { + public LocalInputManager(int variant) + : base(new ManiaRuleset().RulesetInfo, variant) + { + } + + protected override RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + => new LocalKeyBindingContainer(ruleset, variant, unique); + + private class LocalKeyBindingContainer : RulesetKeyBindingContainer + { + public LocalKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + : base(ruleset, variant, unique) + { + } + + protected override void ReloadMappings() + { + KeyBindings = DefaultKeyBindings; + } + } + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs new file mode 100644 index 0000000000..8960ecb2fd --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Game.Rulesets.Mania.UI; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestCaseColumn : ManiaInputTestCase + { + public TestCaseColumn() + : base(1) + { + } + + [BackgroundDependencyLoader] + private void load() + { + Child = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 1) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Height = 0.85f, + Child = new Column + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AccentColour = Color4.OrangeRed, + Action = ManiaAction.Special1 + } + }; + } + } +} diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index b35616985a..21bd61903c 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.UI protected RulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) { - InternalChild = KeyBindingContainer = new RulesetKeyBindingContainer(ruleset, variant, unique); + InternalChild = KeyBindingContainer = CreateKeyBindingContainer(ruleset, variant, unique); } #region Action mapping (for replays) @@ -247,6 +247,9 @@ namespace osu.Game.Rulesets.UI } #endregion + + protected virtual RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + => new RulesetKeyBindingContainer(ruleset, variant, unique); } /// From 3033294df1a583097d64b0b35f954bba13d3b2b3 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 7 Jun 2018 14:30:11 +0300 Subject: [PATCH 067/199] 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 45dca5646181e3fb1c1c027cf41e171405471443 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:40:27 +0900 Subject: [PATCH 068/199] Cleanup testcase --- osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 8960ecb2fd..0f0258d395 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -20,19 +20,13 @@ namespace osu.Game.Rulesets.Mania.Tests [BackgroundDependencyLoader] private void load() { - Child = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 1) + Child = new Column { Anchor = Anchor.Centre, Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, Height = 0.85f, - Child = new Column - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AccentColour = Color4.OrangeRed, - Action = ManiaAction.Special1 - } + AccentColour = Color4.OrangeRed, + Action = ManiaAction.Special1 }; } } From ab6699b1fb599c7d8d6da4f30afb7bd986c17494 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 7 Jun 2018 14:40:41 +0300 Subject: [PATCH 069/199] 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 4af8baefc15beaf8782f24484b063d168949822f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:49:06 +0900 Subject: [PATCH 070/199] Make the column background follow the scroll direction --- .../TestCaseColumn.cs | 35 +++++- osu.Game.Rulesets.Mania/UI/Column.cs | 32 ++--- .../UI/Components/ColumnBackground.cs | 109 ++++++++++++++++++ 3 files changed, 147 insertions(+), 29 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 0f0258d395..b72dd808f4 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -1,10 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mania.UI.Components; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests @@ -12,22 +18,41 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestCaseColumn : ManiaInputTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Column), + typeof(ColumnBackground) + }; + public TestCaseColumn() - : base(1) + : base(2) { } [BackgroundDependencyLoader] private void load() { - Child = new Column + Child = new FillFlowContainer { + RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Height = 0.85f, - AccentColour = Color4.OrangeRed, - Action = ManiaAction.Special1 + Spacing = new Vector2(20, 0), + Children = new[] + { + createColumn(ScrollingDirection.Up, ManiaAction.Key1), + createColumn(ScrollingDirection.Down, ManiaAction.Key2) + } }; } + + private Column createColumn(ScrollingDirection direction, ManiaAction action) => new Column(direction) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = 0.85f, + AccentColour = Color4.OrangeRed, + Action = action + }; } } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index dee113c82f..b00508eb63 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -14,6 +14,7 @@ using System; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI @@ -32,8 +33,7 @@ namespace osu.Game.Rulesets.Mania.UI public ManiaAction Action; - private readonly Box background; - private readonly Box backgroundOverlay; + private readonly ColumnBackground background; private readonly Container hitTargetBar; private readonly Container keyIcon; @@ -43,8 +43,8 @@ namespace osu.Game.Rulesets.Mania.UI protected override Container Content => content; private readonly Container content; - public Column() - : base(ScrollingDirection.Up) + public Column(ScrollingDirection direction = ScrollingDirection.Up) + : base(direction) { RelativeSizeAxes = Axes.Y; Width = column_width; @@ -54,22 +54,7 @@ namespace osu.Game.Rulesets.Mania.UI InternalChildren = new Drawable[] { - background = new Box - { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Alpha = 0.3f - }, - backgroundOverlay = new Box - { - Name = "Background Gradient Overlay", - RelativeSizeAxes = Axes.Both, - Height = 0.5f, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - Blending = BlendingMode.Additive, - Alpha = 0 - }, + background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }, new Container { Name = "Hit target + hit objects", @@ -192,8 +177,7 @@ namespace osu.Game.Rulesets.Mania.UI return; accentColour = value; - background.Colour = accentColour; - backgroundOverlay.Colour = ColourInfo.GradientVertical(accentColour.Opacity(0.6f), accentColour.Opacity(0)); + background.AccentColour = value; hitTargetBar.EdgeEffect = new EdgeEffectParameters { @@ -235,7 +219,7 @@ namespace osu.Game.Rulesets.Mania.UI { if (action == Action) { - backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); + background.IsLit = true; keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); } @@ -246,7 +230,7 @@ namespace osu.Game.Rulesets.Mania.UI { if (action == Action) { - backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); + background.IsLit = false; keyIcon.ScaleTo(1f, 125, Easing.OutQuint); } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs new file mode 100644 index 0000000000..917d254e3a --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -0,0 +1,109 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI.Components +{ + public class ColumnBackground : CompositeDrawable, IHasAccentColour + { + private readonly ScrollingDirection direction; + + public ColumnBackground(ScrollingDirection direction) + { + this.direction = direction; + } + + private Box background; + private Box backgroundOverlay; + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new[] + { + background = new Box + { + Name = "Background", + RelativeSizeAxes = Axes.Both, + Alpha = 0.3f + }, + backgroundOverlay = new Box + { + Name = "Background Gradient Overlay", + RelativeSizeAxes = Axes.Both, + Height = 0.5f, + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Blending = BlendingMode.Additive, + Alpha = 0 + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateColours(); + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + accentColour = value; + + updateColours(); + } + } + + private void updateColours() + { + if (!IsLoaded) + return; + + background.Colour = AccentColour; + + var brightPoint = AccentColour.Opacity(0.6f); + var dimPoint = AccentColour.Opacity(0); + + backgroundOverlay.Colour = ColourInfo.GradientVertical( + direction == ScrollingDirection.Up ? brightPoint : dimPoint, + direction == ScrollingDirection.Up ? dimPoint : brightPoint); + } + + private bool isLit; + + /// + /// Whether the column lighting should be visible. + /// + public bool IsLit + { + set + { + if (isLit == value) + return; + isLit = value; + + if (isLit) + backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); + else + backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); + } + } + + } +} From 1fdbd2047151f42fb1f59fdb15fabfd423bf78e4 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 7 Jun 2018 14:50:21 +0300 Subject: [PATCH 071/199] 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 d49758d1497a137d486037d4c78d330b2084540e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 20:59:04 +0900 Subject: [PATCH 072/199] Make background handle its own lit state --- osu.Game.Rulesets.Mania/UI/Column.cs | 21 ++++++++---- .../UI/Components/ColumnBackground.cs | 32 ++++++++----------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index b00508eb63..e0ecc9d708 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -31,7 +31,20 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; - public ManiaAction Action; + private ManiaAction action; + + public ManiaAction Action + { + get => action; + set + { + if (action == value) + return; + action = value; + + background.Action = value; + } + } private readonly ColumnBackground background; private readonly Container hitTargetBar; @@ -218,10 +231,7 @@ namespace osu.Game.Rulesets.Mania.UI private bool onPressed(ManiaAction action) { if (action == Action) - { - background.IsLit = true; keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); - } return false; } @@ -229,10 +239,7 @@ namespace osu.Game.Rulesets.Mania.UI private bool onReleased(ManiaAction action) { if (action == Action) - { - background.IsLit = false; keyIcon.ScaleTo(1f, 125, Easing.OutQuint); - } return false; } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 917d254e3a..eeef5afcb0 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -7,14 +7,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Rulesets.UI.Scrolling; using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.UI.Components { - public class ColumnBackground : CompositeDrawable, IHasAccentColour + public class ColumnBackground : CompositeDrawable, IKeyBindingHandler, IHasAccentColour { + public ManiaAction Action; + private readonly ScrollingDirection direction; public ColumnBackground(ScrollingDirection direction) @@ -85,25 +88,18 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction == ScrollingDirection.Up ? dimPoint : brightPoint); } - private bool isLit; - - /// - /// Whether the column lighting should be visible. - /// - public bool IsLit + public bool OnPressed(ManiaAction action) { - set - { - if (isLit == value) - return; - isLit = value; - - if (isLit) - backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); - else - backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); - } + if (action == Action) + backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint); + return false; } + public bool OnReleased(ManiaAction action) + { + if (action == Action) + backgroundOverlay.FadeTo(0, 250, Easing.OutQuint); + return false; + } } } From 11f067d7d6bb3e03fc6666237eddcc76be79c009 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:13:29 +0900 Subject: [PATCH 073/199] Fix background input --- osu.Game.Rulesets.Mania/UI/Column.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e0ecc9d708..e1eb11f5e5 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -65,9 +65,12 @@ namespace osu.Game.Rulesets.Mania.UI Masking = true; CornerRadius = 5; - InternalChildren = new Drawable[] + background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }; + + InternalChildren = new[] { - background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }, + // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements + background.CreateProxy(), new Container { Name = "Hit target + hit objects", @@ -158,6 +161,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, + background, TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both } }; From 207cdbdefe12d29cdd3d38b4c1d36660542e7833 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:13:57 +0900 Subject: [PATCH 074/199] Make the column key area follow the scroll direction --- .../TestCaseColumn.cs | 3 +- osu.Game.Rulesets.Mania/UI/Column.cs | 95 ++------------ .../UI/Components/ColumnKeyArea.cs | 119 ++++++++++++++++++ 3 files changed, 128 insertions(+), 89 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index b72dd808f4..391a30e4c7 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -21,7 +21,8 @@ namespace osu.Game.Rulesets.Mania.Tests public override IReadOnlyList RequiredTypes => new[] { typeof(Column), - typeof(ColumnBackground) + typeof(ColumnBackground), + typeof(ColumnKeyArea) }; public TestCaseColumn() diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e1eb11f5e5..5568869755 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -1,16 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -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.Graphics.Colour; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using System; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; @@ -21,10 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float key_icon_size = 10; - private const float key_icon_corner_radius = 3; - private const float key_icon_border_radius = 2; - private const float hit_target_height = 10; private const float hit_target_bar_height = 2; @@ -43,12 +36,14 @@ namespace osu.Game.Rulesets.Mania.UI action = value; background.Action = value; + keyArea.Action = value; } } private readonly ColumnBackground background; + private readonly ColumnKeyArea keyArea; + private readonly Container hitTargetBar; - private readonly Container keyIcon; internal readonly Container TopLevelContainer; private readonly Container explosionContainer; @@ -112,12 +107,6 @@ namespace osu.Game.Rulesets.Mania.UI Name = "Hit objects", RelativeSizeAxes = Axes.Both, }, - // For column lighting, we need to capture input events before the notes - new InputTarget - { - Pressed = onPressed, - Released = onReleased - }, explosionContainer = new Container { Name = "Hit explosions", @@ -125,41 +114,12 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - new Container + keyArea = new ColumnKeyArea(direction) { - Name = "Key", + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = ManiaStage.HIT_TARGET_POSITION, - Children = new Drawable[] - { - new Box - { - Name = "Key gradient", - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0)), - Alpha = 0.5f - }, - keyIcon = new Container - { - Name = "Key icon", - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(key_icon_size), - Masking = true, - CornerRadius = key_icon_corner_radius, - BorderThickness = 2, - BorderColour = Color4.White, // Not true - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true - } - } - } - } }, background, TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both } @@ -195,6 +155,7 @@ namespace osu.Game.Rulesets.Mania.UI accentColour = value; background.AccentColour = value; + keyArea.AccentColour = value; hitTargetBar.EdgeEffect = new EdgeEffectParameters { @@ -202,13 +163,6 @@ namespace osu.Game.Rulesets.Mania.UI Radius = 5, Colour = accentColour.Opacity(0.5f), }; - - keyIcon.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Radius = 5, - Colour = accentColour.Opacity(0.5f), - }; } } @@ -232,41 +186,6 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer.Add(new HitExplosion(judgedObject)); } - private bool onPressed(ManiaAction action) - { - if (action == Action) - keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); - - return false; - } - - private bool onReleased(ManiaAction action) - { - if (action == Action) - keyIcon.ScaleTo(1f, 125, Easing.OutQuint); - - return false; - } - - /// - /// This is a simple container which delegates various input events that have to be captured before the notes. - /// - private class InputTarget : Container, IKeyBindingHandler - { - public Func Pressed; - public Func Released; - - public InputTarget() - { - RelativeSizeAxes = Axes.Both; - AlwaysPresent = true; - Alpha = 0; - } - - public bool OnPressed(ManiaAction action) => Pressed?.Invoke(action) ?? false; - public bool OnReleased(ManiaAction action) => Released?.Invoke(action) ?? false; - } - public bool OnPressed(ManiaAction action) { if (action != Action) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs new file mode 100644 index 0000000000..f0884f92da --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -0,0 +1,119 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; +using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI.Components +{ + public class ColumnKeyArea : CompositeDrawable, IKeyBindingHandler, IHasAccentColour + { + private const float key_icon_size = 10; + private const float key_icon_corner_radius = 3; + + public ManiaAction Action; + + private readonly ScrollingDirection direction; + + public ColumnKeyArea(ScrollingDirection direction) + { + this.direction = direction; + } + + private Container keyIcon; + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Box + { + Name = "Key gradient", + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical( + direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), + Alpha = 0.5f + }, + keyIcon = new Container + { + Name = "Key icon", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(key_icon_size), + Masking = true, + CornerRadius = key_icon_corner_radius, + BorderThickness = 2, + BorderColour = Color4.White, // Not true + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateColours(); + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + accentColour = value; + + updateColours(); + } + } + + private void updateColours() + { + if (!IsLoaded) + return; + + keyIcon.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = accentColour.Opacity(0.5f), + }; + } + + public bool OnPressed(ManiaAction action) + { + if (action == Action) + keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint); + return false; + } + + public bool OnReleased(ManiaAction action) + { + if (action == Action) + keyIcon.ScaleTo(1f, 125, Easing.OutQuint); + return false; + } + } +} From 0c359088021e5529067b76e56b84798e8ba7e3e5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:19:31 +0900 Subject: [PATCH 075/199] Reorder fields --- osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs | 6 +++--- osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index eeef5afcb0..b71dae035e 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -20,14 +20,14 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly ScrollingDirection direction; + private Box background; + private Box backgroundOverlay; + public ColumnBackground(ScrollingDirection direction) { this.direction = direction; } - private Box background; - private Box backgroundOverlay; - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index f0884f92da..e7fe44171b 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -24,13 +24,13 @@ namespace osu.Game.Rulesets.Mania.UI.Components private readonly ScrollingDirection direction; + private Container keyIcon; + public ColumnKeyArea(ScrollingDirection direction) { this.direction = direction; } - private Container keyIcon; - [BackgroundDependencyLoader] private void load() { From 32037701bfad57592cb39f7b490eda33f9bafce6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 21:40:12 +0900 Subject: [PATCH 076/199] Make the column hitobject area follow the scroll direction --- .../TestCaseColumn.cs | 3 +- osu.Game.Rulesets.Mania/UI/Column.cs | 60 ++---------- .../UI/Components/ColumnHitObjectArea.cs | 96 +++++++++++++++++++ 3 files changed, 107 insertions(+), 52 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 391a30e4c7..05c7e99a18 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -22,7 +22,8 @@ namespace osu.Game.Rulesets.Mania.Tests { typeof(Column), typeof(ColumnBackground), - typeof(ColumnKeyArea) + typeof(ColumnKeyArea), + typeof(ColumnHitObjectArea) }; public TestCaseColumn() diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 5568869755..81607795fe 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -2,10 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System.Linq; @@ -18,9 +16,6 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float hit_target_height = 10; - private const float hit_target_bar_height = 2; - private const float column_width = 45; private const float special_column_width = 70; @@ -42,14 +37,12 @@ namespace osu.Game.Rulesets.Mania.UI private readonly ColumnBackground background; private readonly ColumnKeyArea keyArea; - - private readonly Container hitTargetBar; + private readonly ColumnHitObjectArea hitObjectArea; internal readonly Container TopLevelContainer; private readonly Container explosionContainer; - protected override Container Content => content; - private readonly Container content; + protected override Container Content => hitObjectArea; public Column(ScrollingDirection direction = ScrollingDirection.Up) : base(direction) @@ -70,43 +63,14 @@ namespace osu.Game.Rulesets.Mania.UI { Name = "Hit target + hit objects", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = ManiaStage.HIT_TARGET_POSITION }, + Padding = new MarginPadding + { + Top = direction == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, + Bottom = direction == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, + }, Children = new Drawable[] { - new Container - { - Name = "Hit target", - RelativeSizeAxes = Axes.X, - Height = hit_target_height, - Children = new Drawable[] - { - new Box - { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - hitTargetBar = new Container - { - Name = "Bar", - RelativeSizeAxes = Axes.X, - Height = hit_target_bar_height, - Masking = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both - } - } - } - } - }, - content = new Container - { - Name = "Hit objects", - RelativeSizeAxes = Axes.Both, - }, + hitObjectArea = new ColumnHitObjectArea(direction) { RelativeSizeAxes = Axes.Both }, explosionContainer = new Container { Name = "Hit explosions", @@ -156,13 +120,7 @@ namespace osu.Game.Rulesets.Mania.UI background.AccentColour = value; keyArea.AccentColour = value; - - hitTargetBar.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Radius = 5, - Colour = accentColour.Opacity(0.5f), - }; + hitObjectArea.AccentColour = value; } } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs new file mode 100644 index 0000000000..31df6d5fa3 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -0,0 +1,96 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI.Components +{ + public class ColumnHitObjectArea : Container, IHasAccentColour + { + private const float hit_target_height = 10; + private const float hit_target_bar_height = 2; + + private Container content; + protected override Container Content => content; + + private readonly ScrollingDirection direction; + + private Container hitTargetBar; + + public ColumnHitObjectArea(ScrollingDirection direction) + { + this.direction = direction; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new Box + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = hit_target_height, + Colour = Color4.Black + }, + hitTargetBar = new Container + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = hit_target_bar_height, + Masking = true, + Child = new Box { RelativeSizeAxes = Axes.Both } + }, + content = new Container + { + Name = "Hit objects", + RelativeSizeAxes = Axes.Both, + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateColours(); + } + + private Color4 accentColour; + + public Color4 AccentColour + { + get => accentColour; + set + { + if (accentColour == value) + return; + accentColour = value; + + updateColours(); + } + } + + private void updateColours() + { + if (!IsLoaded) + return; + + hitTargetBar.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 5, + Colour = accentColour.Opacity(0.5f), + }; + } + } +} From ee64760406c6217944475f5f24f3f185fb1affb4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 14:28:27 +0900 Subject: [PATCH 077/199] Add mania stage test case --- .../TestCaseStage.cs | 46 +++++++++++++++++++ osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 6 +-- .../UI/ManiaRulesetContainer.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 6 +-- 5 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs new file mode 100644 index 0000000000..bcdee7b688 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -0,0 +1,46 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestCaseStage : ManiaInputTestCase + { + public TestCaseStage() + : base(4) + { + } + + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Spacing = new Vector2(20, 0), + Children = new[] + { + createStage(ScrollingDirection.Up, ManiaAction.Key1), + createStage(ScrollingDirection.Down, ManiaAction.Key3) + } + }; + } + + private ManiaStage createStage(ScrollingDirection direction, ManiaAction action) + { + var specialAction = ManiaAction.Special1; + return new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 81607795fe..e71a95f3dc 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override Container Content => hitObjectArea; - public Column(ScrollingDirection direction = ScrollingDirection.Up) + public Column(ScrollingDirection direction) : base(direction) { RelativeSizeAxes = Axes.Y; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 153d4698e1..73362ab28f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -21,8 +21,8 @@ namespace osu.Game.Rulesets.Mania.UI public List Columns => stages.SelectMany(x => x.Columns).ToList(); private readonly List stages = new List(); - public ManiaPlayfield(List stageDefinitions) - : base(ScrollingDirection.Up) + public ManiaPlayfield(ScrollingDirection direction, List stageDefinitions) + : base(direction) { if (stageDefinitions == null) throw new ArgumentNullException(nameof(stageDefinitions)); @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI int firstColumnIndex = 0; for (int i = 0; i < stageDefinitions.Count; i++) { - var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); + var newStage = new ManiaStage(direction, firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); newStage.VisibleTimeRange.BindTo(VisibleTimeRange); playfieldGrid.Content[0][i] = newStage; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 7123aab901..b7acd1d5ee 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) + protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(ScrollingDirection.Up, Beatmap.Stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 41af5fef38..822042362f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -43,8 +43,8 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int firstColumnIndex; - public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) - : base(ScrollingDirection.Up) + public ManiaStage(ScrollingDirection direction, int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) + : base(direction) { this.firstColumnIndex = firstColumnIndex; @@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Mania.UI for (int i = 0; i < definition.Columns; i++) { var isSpecial = definition.IsSpecialColumn(i); - var column = new Column + var column = new Column(direction) { IsSpecial = isSpecial, Action = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ From 2a48e0e44a1b299051a57a63d9d807792b40e04e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 14:49:45 +0900 Subject: [PATCH 078/199] Fix sequential speed change visualiser not working with 0 control points --- .../Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs index e353c07e9f..745352a4d3 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs @@ -93,6 +93,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers /// A positive value indicating the position at . private double positionAt(double time, double timeRange) { + if (controlPoints.Count == 0) + return time / timeRange; + double length = 0; // We need to consider all timing points until the specified time and not just the currently-active one, From d6f230f2b03a753249dbde252d73c37776fb9b8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:16:14 +0900 Subject: [PATCH 079/199] Add notes to TestCaseColumn --- .../TestCaseColumn.cs | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index 05c7e99a18..cd1eb43853 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -7,6 +7,10 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; @@ -26,6 +30,8 @@ namespace osu.Game.Rulesets.Mania.Tests typeof(ColumnHitObjectArea) }; + private readonly List columns = new List(); + public TestCaseColumn() : base(2) { @@ -48,13 +54,38 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - private Column createColumn(ScrollingDirection direction, ManiaAction action) => new Column(direction) + protected override void LoadComplete() { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Height = 0.85f, - AccentColour = Color4.OrangeRed, - Action = action - }; + base.LoadComplete(); + + AddStep("note", createNote); + } + + private void createNote() + { + for (int i = 0; i < columns.Count; i++) + { + var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + columns[i].Add(new DrawableNote(obj, columns[i].Action)); + } + } + + private Column createColumn(ScrollingDirection direction, ManiaAction action) + { + var column = new Column(direction) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = 0.85f, + AccentColour = Color4.OrangeRed, + Action = action, + VisibleTimeRange = { Value = 2000 } + }; + + columns.Add(column); + return column; + } } } From 80a577f1823733be9d129d28302810d12205a11c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:16:45 +0900 Subject: [PATCH 080/199] Fix notes not scrolling correctly --- .../Drawables/DrawableManiaHitObject.cs | 23 ++++++++++++++++++- osu.Game.Rulesets.Mania/UI/Column.cs | 7 ++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index fbf1ee8460..61a7f96c91 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -3,10 +3,31 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableHitObject + public abstract class DrawableManiaHitObject : DrawableHitObject + { + protected DrawableManiaHitObject(ManiaHitObject hitObject) + : base(hitObject) + { + } + + /// + /// Sets the scrolling direction. + /// + public virtual ScrollingDirection Direction + { + set + { + Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Origin = Anchor; + } + } + } + + public abstract class DrawableManiaHitObject : DrawableManiaHitObject where TObject : ManiaHitObject { /// diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e71a95f3dc..6f3d82a464 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Objects.Drawables; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; @@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI } } + private readonly ScrollingDirection direction; + private readonly ColumnBackground background; private readonly ColumnKeyArea keyArea; private readonly ColumnHitObjectArea hitObjectArea; @@ -47,6 +50,7 @@ namespace osu.Game.Rulesets.Mania.UI public Column(ScrollingDirection direction) : base(direction) { + this.direction = direction; RelativeSizeAxes = Axes.Y; Width = column_width; @@ -130,6 +134,9 @@ namespace osu.Game.Rulesets.Mania.UI /// The DrawableHitObject to add. public override void Add(DrawableHitObject hitObject) { + var maniaObject = (DrawableManiaHitObject)hitObject; + maniaObject.Direction = direction; + hitObject.AccentColour = AccentColour; hitObject.OnJudgement += OnJudgement; From d73c2a1654a481294158be3c4ebc2184963dc317 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:17:22 +0900 Subject: [PATCH 081/199] Fix various note elements not following the scroll direction --- .../Objects/Drawables/DrawableNote.cs | 13 +++++++++++++ .../Objects/Drawables/Pieces/NotePiece.cs | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 3de0a9c5cc..a8666405cc 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -9,6 +9,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -38,6 +39,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; } + public override ScrollingDirection Direction + { + set + { + base.Direction = value; + + headPiece.Direction = value; + headPiece.Anchor = Anchor; + headPiece.Origin = Origin; + } + } + public override Color4 AccentColour { get { return base.AccentColour; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 9ebeb91e0c..952ddd074e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces { @@ -42,6 +43,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces }; } + public ScrollingDirection Direction + { + set + { + colouredBox.Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Origin = colouredBox.Anchor; + } + } + private Color4 accentColour; public Color4 AccentColour { From 7deaffdb62b0a2247b49fae5fcdf419ad8749fc4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:23:47 +0900 Subject: [PATCH 082/199] Fix hit explosions not following the scroll direction --- osu.Game.Rulesets.Mania/UI/Column.cs | 5 ++++- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 6f3d82a464..26269ff537 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -148,7 +148,10 @@ namespace osu.Game.Rulesets.Mania.UI if (!judgement.IsHit || !judgedObject.DisplayJudgement) return; - explosionContainer.Add(new HitExplosion(judgedObject)); + explosionContainer.Add(new HitExplosion(judgedObject) + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre + }); } public bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index f19c3a811b..e3f0656000 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -21,7 +21,6 @@ namespace osu.Game.Rulesets.Mania.UI { bool isTick = judgedObject is DrawableHoldNoteTick; - Anchor = Anchor.TopCentre; Origin = Anchor.Centre; RelativeSizeAxes = Axes.X; From c933dd4069aec242bcd1450fd2463099788e9fd3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:28:57 +0900 Subject: [PATCH 083/199] Add hold notes to TestCaseColumn --- osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index cd1eb43853..ced64e21e9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -59,6 +59,7 @@ namespace osu.Game.Rulesets.Mania.Tests base.LoadComplete(); AddStep("note", createNote); + AddStep("hold note", createHoldNote); } private void createNote() @@ -72,6 +73,17 @@ namespace osu.Game.Rulesets.Mania.Tests } } + private void createHoldNote() + { + for (int i = 0; i < columns.Count; i++) + { + var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + columns[i].Add(new DrawableHoldNote(obj, columns[i].Action)); + } + } + private Column createColumn(ScrollingDirection direction, ManiaAction action) { var column = new Column(direction) From 5c8bea82f8e53cad4d5d15ffc97bd2dd7ef644df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 15:29:08 +0900 Subject: [PATCH 084/199] Fix scroll direction not applying to nested hitobjects --- .../Objects/Drawables/DrawableManiaHitObject.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 61a7f96c91..89fe0b1945 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.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.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; @@ -23,6 +24,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; Origin = Anchor; + + if (!HasNestedHitObjects) + return; + + foreach (var obj in NestedHitObjects.OfType()) + obj.Direction = value; } } } From c010ea83ca37ed5e8b3b18354cec64cfbe3ca71c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 18:10:07 +0900 Subject: [PATCH 085/199] Add note hitobject testcase --- .../TestCaseNotes.cs | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs new file mode 100644 index 0000000000..bb12bb35db --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -0,0 +1,165 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +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.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Tests.Visual; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestCaseNotes : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableNote), + typeof(DrawableHoldNote) + }; + + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20), + Children = new[] + { + createNoteDisplay(ScrollingDirection.Down), + createNoteDisplay(ScrollingDirection.Up), + createHoldNoteDisplay(ScrollingDirection.Down), + createHoldNoteDisplay(ScrollingDirection.Up), + } + }; + } + + private Drawable createNoteDisplay(ScrollingDirection direction) + { + var note = new Note { StartTime = 999999999 }; + note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + return new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") + { + Child = new DrawableNote(note, ManiaAction.Key1) + { + AccentColour = Color4.OrangeRed, + Direction = direction + } + }; + } + + private Drawable createHoldNoteDisplay(ScrollingDirection direction) + { + var note = new HoldNote { StartTime = 999999999, Duration = 1000 }; + note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + return new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") + { + Child = new DrawableHoldNote(note, ManiaAction.Key1) + { + RelativeSizeAxes = Axes.Both, + AccentColour = Color4.OrangeRed, + Direction = direction + } + }; + } + + private class NoteContainer : Container + { + private readonly Container content; + protected override Container Content => content; + + private readonly ScrollingDirection direction; + + public NoteContainer(ScrollingDirection direction, string description) + { + this.direction = direction; + AutoSizeAxes = Axes.Both; + + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(0, 10), + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 45, + Height = 100, + Children = new Drawable[] + { + new Box + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Both, + Width = 1.25f, + Colour = Color4.Black.Opacity(0.5f) + }, + content = new Container { RelativeSizeAxes = Axes.Both } + } + }, + new SpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextSize = 14, + Text = description + } + } + }; + } + + protected override void Update() + { + base.Update(); + + foreach (var obj in content.OfType()) + { + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + if (!obj.HasNestedHitObjects) + continue; + + foreach (var nested in obj.NestedHitObjects) + { + double finalPosition = (nested.HitObject.StartTime - obj.HitObject.StartTime) / endTime.Duration; + switch (direction) + { + case ScrollingDirection.Up: + nested.Y = (float)(finalPosition * content.DrawHeight); + break; + case ScrollingDirection.Down: + nested.Y = (float)(-finalPosition * content.DrawHeight); + break; + } + } + } + } + } + } +} From 0fb4e6b41b5fba0b9bbb75664d8627f3b85c4fc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 18:16:55 +0900 Subject: [PATCH 086/199] Fix hold note body not following the scroll direction --- .../Objects/Drawables/DrawableHoldNote.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index e008fa952e..6ae78ec4d0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { @@ -75,6 +76,19 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(tail); } + private ScrollingDirection direction; + public override ScrollingDirection Direction + { + set + { + base.Direction = value; + direction = value; + + bodyPiece.Anchor = value == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Origin = bodyPiece.Anchor; + } + } + public override Color4 AccentColour { get { return base.AccentColour; } @@ -100,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.Update(); // Make the body piece not lie under the head note - bodyPiece.Y = head.Height / 2; + bodyPiece.Y = (direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; bodyPiece.Height = DrawHeight - head.Height / 2 + tail.Height / 2; } From ca5103615df1241e7d8aac37678e7d26e4af1fc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 20:13:24 +0900 Subject: [PATCH 087/199] DI the scrolling info rather than pass by ctor --- .../ScrollingTestContainer.cs | 29 +++++++++++++ .../TestCaseColumn.cs | 12 +++++- .../TestCaseNotes.cs | 22 ++++++---- .../TestCaseStage.cs | 12 +++++- .../Objects/Drawables/DrawableHoldNote.cs | 20 ++++----- .../Drawables/DrawableManiaHitObject.cs | 41 +++++-------------- .../Objects/Drawables/DrawableNote.cs | 24 ++++------- .../Objects/Drawables/Pieces/NotePiece.cs | 12 +++--- osu.Game.Rulesets.Mania/UI/Column.cs | 10 ++--- .../UI/Components/ColumnBackground.cs | 19 ++++----- .../UI/Components/ColumnHitObjectArea.cs | 17 +++----- .../UI/Components/ColumnKeyArea.cs | 13 ++---- .../UI/ManiaRulesetContainer.cs | 16 +++++++- osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs | 17 ++++++++ 14 files changed, 146 insertions(+), 118 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs create mode 100644 osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs diff --git a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs new file mode 100644 index 0000000000..2b86c6187b --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs @@ -0,0 +1,29 @@ +// 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.Graphics.Containers; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Tests +{ + /// + /// A container which provides a to children. + /// + public class ScrollingTestContainer : Container + { + private readonly ScrollingInfo scrollingInfo; + + public ScrollingTestContainer(ScrollingInfo scrollingInfo) + { + this.scrollingInfo = scrollingInfo; + } + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + dependencies.Cache(scrollingInfo); + return dependencies; + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index ced64e21e9..d5f43b809e 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Mania.Tests } } - private Column createColumn(ScrollingDirection direction, ManiaAction action) + private Drawable createColumn(ScrollingDirection direction, ManiaAction action) { var column = new Column(direction) { @@ -97,7 +97,15 @@ namespace osu.Game.Rulesets.Mania.Tests }; columns.Add(column); - return column; + + return new ScrollingTestContainer(new ScrollingInfo(direction)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Child = column + }; } } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index bb12bb35db..3342060fe2 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI.Scrolling; @@ -58,12 +59,12 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new Note { StartTime = 999999999 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") + return new ScrollingTestContainer(new ScrollingInfo(direction)) { - Child = new DrawableNote(note, ManiaAction.Key1) + AutoSizeAxes = Axes.Both, + Child = new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") { - AccentColour = Color4.OrangeRed, - Direction = direction + Child = new DrawableNote(note, ManiaAction.Key1) { AccentColour = Color4.OrangeRed } } }; } @@ -73,13 +74,16 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new HoldNote { StartTime = 999999999, Duration = 1000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") + return new ScrollingTestContainer(new ScrollingInfo(direction)) { - Child = new DrawableHoldNote(note, ManiaAction.Key1) + AutoSizeAxes = Axes.Both, + Child = new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") { - RelativeSizeAxes = Axes.Both, - AccentColour = Color4.OrangeRed, - Direction = direction + Child = new DrawableHoldNote(note, ManiaAction.Key1) + { + RelativeSizeAxes = Axes.Both, + AccentColour = Color4.OrangeRed, + } } }; } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index bcdee7b688..2f639494bb 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -37,10 +37,18 @@ namespace osu.Game.Rulesets.Mania.Tests }; } - private ManiaStage createStage(ScrollingDirection direction, ManiaAction action) + private Drawable createStage(ScrollingDirection direction, ManiaAction action) { var specialAction = ManiaAction.Special1; - return new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + + return new ScrollingTestContainer(new ScrollingInfo(direction)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Child = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) + }; } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 6ae78ec4d0..86bbc2c11d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; @@ -9,6 +10,7 @@ using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -36,6 +38,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private bool hasBroken; + private ScrollingInfo scrollingInfo; + private readonly Container tickContainer; public DrawableHoldNote(HoldNote hitObject, ManiaAction action) @@ -76,17 +80,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(tail); } - private ScrollingDirection direction; - public override ScrollingDirection Direction + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) { - set - { - base.Direction = value; - direction = value; + this.scrollingInfo = scrollingInfo; - bodyPiece.Anchor = value == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - bodyPiece.Origin = bodyPiece.Anchor; - } + bodyPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Origin = bodyPiece.Anchor; } public override Color4 AccentColour @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.Update(); // Make the body piece not lie under the head note - bodyPiece.Y = (direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; + bodyPiece.Y = (scrollingInfo.Direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; bodyPiece.Height = DrawHeight - head.Height / 2 + tail.Height / 2; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 89fe0b1945..59f93eb16a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,40 +1,15 @@ // 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 osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableHitObject - { - protected DrawableManiaHitObject(ManiaHitObject hitObject) - : base(hitObject) - { - } - - /// - /// Sets the scrolling direction. - /// - public virtual ScrollingDirection Direction - { - set - { - Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - Origin = Anchor; - - if (!HasNestedHitObjects) - return; - - foreach (var obj in NestedHitObjects.OfType()) - obj.Direction = value; - } - } - } - - public abstract class DrawableManiaHitObject : DrawableManiaHitObject + public abstract class DrawableManiaHitObject : DrawableHitObject where TObject : ManiaHitObject { /// @@ -47,15 +22,19 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; - HitObject = hitObject; if (action != null) Action = action.Value; } + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) + { + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Origin = Anchor; + } + protected override void UpdateState(ArmedState state) { switch (state) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index a8666405cc..7e160befdc 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.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 osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -8,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -29,26 +31,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables CornerRadius = 5; Masking = true; - InternalChildren = new Drawable[] - { - headPiece = new NotePiece - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - } - }; + InternalChild = headPiece = new NotePiece(); } - public override ScrollingDirection Direction + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) { - set - { - base.Direction = value; - - headPiece.Direction = value; - headPiece.Anchor = Anchor; - headPiece.Origin = Origin; - } + headPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + headPiece.Origin = headPiece.Anchor; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 952ddd074e..707d1b5479 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -1,12 +1,14 @@ // 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 OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces @@ -43,13 +45,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces }; } - public ScrollingDirection Direction + [BackgroundDependencyLoader] + private void load(ScrollingInfo scrollingInfo) { - set - { - colouredBox.Anchor = value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - colouredBox.Origin = colouredBox.Anchor; - } + colouredBox.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Origin = colouredBox.Anchor; } private Color4 accentColour; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 26269ff537..f62d91a52b 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Objects.Drawables; using System.Linq; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; @@ -57,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.UI Masking = true; CornerRadius = 5; - background = new ColumnBackground(direction) { RelativeSizeAxes = Axes.Both }; + background = new ColumnBackground { RelativeSizeAxes = Axes.Both }; InternalChildren = new[] { @@ -74,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.UI }, Children = new Drawable[] { - hitObjectArea = new ColumnHitObjectArea(direction) { RelativeSizeAxes = Axes.Both }, + hitObjectArea = new ColumnHitObjectArea { RelativeSizeAxes = Axes.Both }, explosionContainer = new Container { Name = "Hit explosions", @@ -82,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.UI } } }, - keyArea = new ColumnKeyArea(direction) + keyArea = new ColumnKeyArea { Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, @@ -134,9 +133,6 @@ namespace osu.Game.Rulesets.Mania.UI /// The DrawableHitObject to add. public override void Add(DrawableHitObject hitObject) { - var maniaObject = (DrawableManiaHitObject)hitObject; - maniaObject.Direction = direction; - hitObject.AccentColour = AccentColour; hitObject.OnJudgement += OnJudgement; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index b71dae035e..6492380f01 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -18,19 +18,16 @@ namespace osu.Game.Rulesets.Mania.UI.Components { public ManiaAction Action; - private readonly ScrollingDirection direction; - private Box background; private Box backgroundOverlay; - public ColumnBackground(ScrollingDirection direction) - { - this.direction = direction; - } + private ScrollingInfo scrollingInfo; [BackgroundDependencyLoader] - private void load() + private void load(ScrollingInfo scrollingInfo) { + this.scrollingInfo = scrollingInfo; + InternalChildren = new[] { background = new Box @@ -44,8 +41,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components Name = "Background Gradient Overlay", RelativeSizeAxes = Axes.Both, Height = 0.5f, - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, Blending = BlendingMode.Additive, Alpha = 0 } @@ -84,8 +81,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components var dimPoint = AccentColour.Opacity(0); backgroundOverlay.Colour = ColourInfo.GradientVertical( - direction == ScrollingDirection.Up ? brightPoint : dimPoint, - direction == ScrollingDirection.Up ? dimPoint : brightPoint); + scrollingInfo.Direction == ScrollingDirection.Up ? brightPoint : dimPoint, + scrollingInfo.Direction == ScrollingDirection.Up ? dimPoint : brightPoint); } public bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 31df6d5fa3..cdea3870ab 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -20,32 +20,25 @@ namespace osu.Game.Rulesets.Mania.UI.Components private Container content; protected override Container Content => content; - private readonly ScrollingDirection direction; - private Container hitTargetBar; - public ColumnHitObjectArea(ScrollingDirection direction) - { - this.direction = direction; - } - [BackgroundDependencyLoader] - private void load() + private void load(ScrollingInfo scrollingInfo) { InternalChildren = new Drawable[] { new Box { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_height, Colour = Color4.Black }, hitTargetBar = new Container { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, + Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_bar_height, Masking = true, diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index e7fe44171b..56da7bc9b9 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -22,17 +22,10 @@ namespace osu.Game.Rulesets.Mania.UI.Components public ManiaAction Action; - private readonly ScrollingDirection direction; - private Container keyIcon; - public ColumnKeyArea(ScrollingDirection direction) - { - this.direction = direction; - } - [BackgroundDependencyLoader] - private void load() + private void load(ScrollingInfo scrollingInfo) { InternalChildren = new Drawable[] { @@ -41,8 +34,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components Name = "Key gradient", RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical( - direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), - direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), + scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), Alpha = 0.5f }, keyIcon = new Container diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index b7acd1d5ee..54a1b08ea3 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -36,6 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; + private ScrollingInfo scrollingInfo; + public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { @@ -73,7 +75,19 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(ScrollingDirection.Up, Beatmap.Stages) + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + + scrollingInfo = new ScrollingInfo(ScrollingDirection.Up); + dependencies.Cache(scrollingInfo); + + return dependencies; + } + + protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(scrollingInfo.Direction, Beatmap.Stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs b/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs new file mode 100644 index 0000000000..7772485982 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class ScrollingInfo + { + public readonly ScrollingDirection Direction; + + public ScrollingInfo(ScrollingDirection direction) + { + Direction = direction; + } + } +} From baaf431b9ed11bff42b1487d9d6f5ac134d7e1c2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Jun 2018 21:41:20 +0900 Subject: [PATCH 088/199] Make IScrollingInfo and store direction as bindable --- .../ScrollingTestContainer.cs | 18 +++++++---- .../TestCaseColumn.cs | 2 +- .../TestCaseNotes.cs | 5 ++-- .../TestCaseStage.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 13 +++----- .../Drawables/DrawableManiaHitObject.cs | 13 ++++++-- .../Objects/Drawables/DrawableNote.cs | 9 +++--- .../Objects/Drawables/Pieces/NotePiece.cs | 15 ++++++---- .../UI/Components/ColumnBackground.cs | 21 ++++++++----- .../UI/Components/ColumnHitObjectArea.cs | 30 ++++++++++++------- .../UI/Components/ColumnKeyArea.cs | 22 ++++++++++---- osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs | 17 +++++++++++ .../UI/ManiaRulesetContainer.cs | 12 ++++++-- osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs | 17 ----------- 14 files changed, 122 insertions(+), 74 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs delete mode 100644 osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs diff --git a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs index 2b86c6187b..78a98e83e8 100644 --- a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs @@ -2,28 +2,36 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Tests { /// - /// A container which provides a to children. + /// A container which provides a to children. /// public class ScrollingTestContainer : Container { - private readonly ScrollingInfo scrollingInfo; + private readonly ScrollingDirection direction; - public ScrollingTestContainer(ScrollingInfo scrollingInfo) + public ScrollingTestContainer(ScrollingDirection direction) { - this.scrollingInfo = scrollingInfo; + this.direction = direction; } protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - dependencies.Cache(scrollingInfo); + dependencies.CacheAs(new ScrollingInfo { Direction = { Value = direction }}); return dependencies; } + + private class ScrollingInfo : IScrollingInfo + { + public readonly Bindable Direction = new Bindable(); + IBindable IScrollingInfo.Direction => Direction; + } } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index d5f43b809e..72f0b046b6 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Mania.Tests columns.Add(column); - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index 3342060fe2..4fdfac93b7 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -15,7 +15,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI.Scrolling; @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new Note { StartTime = 999999999 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { AutoSizeAxes = Axes.Both, Child = new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLower()}") @@ -74,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Tests var note = new HoldNote { StartTime = 999999999, Duration = 1000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { AutoSizeAxes = Axes.Both, Child = new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLower()}") diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index 2f639494bb..d88896d855 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests { var specialAction = ManiaAction.Special1; - return new ScrollingTestContainer(new ScrollingInfo(direction)) + return new ScrollingTestContainer(direction) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 86bbc2c11d..3448d66ce1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; @@ -10,7 +9,6 @@ using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -38,8 +36,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private bool hasBroken; - private ScrollingInfo scrollingInfo; - private readonly Container tickContainer; public DrawableHoldNote(HoldNote hitObject, ManiaAction action) @@ -80,12 +76,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(tail); } - [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + protected override void OnDirectionChanged(ScrollingDirection direction) { - this.scrollingInfo = scrollingInfo; + base.OnDirectionChanged(direction); - bodyPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; bodyPiece.Origin = bodyPiece.Anchor; } @@ -114,7 +109,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.Update(); // Make the body piece not lie under the head note - bodyPiece.Y = (scrollingInfo.Direction == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; + bodyPiece.Y = (Direction.Value == ScrollingDirection.Up ? 1 : -1) * head.Height / 2; bodyPiece.Height = DrawHeight - head.Height / 2 + tail.Height / 2; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 59f93eb16a..01df4743c7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public new TObject HitObject; + protected readonly IBindable Direction = new Bindable(); + protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { @@ -29,9 +32,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Direction.BindTo(scrollingInfo.Direction); + Direction.BindValueChanged(OnDirectionChanged, true); + } + + protected virtual void OnDirectionChanged(ScrollingDirection direction) + { + Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; Origin = Anchor; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 7e160befdc..b9b3fa7824 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.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 osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -9,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -34,10 +32,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables InternalChild = headPiece = new NotePiece(); } - [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + protected override void OnDirectionChanged(ScrollingDirection direction) { - headPiece.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + base.OnDirectionChanged(direction); + + headPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; headPiece.Origin = headPiece.Anchor; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 707d1b5479..2c36b96f72 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -21,6 +22,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public const float NOTE_HEIGHT = 10; private const float head_colour_height = 6; + private readonly IBindable direction = new Bindable(); + private readonly Box colouredBox; public NotePiece() @@ -36,8 +39,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces }, colouredBox = new Box { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, Height = head_colour_height, Alpha = 0.2f @@ -46,10 +47,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - colouredBox.Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - colouredBox.Origin = colouredBox.Anchor; + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + colouredBox.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Origin = colouredBox.Anchor; + }, true); } private Color4 accentColour; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 6492380f01..50303deda7 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -21,13 +22,11 @@ namespace osu.Game.Rulesets.Mania.UI.Components private Box background; private Box backgroundOverlay; - private ScrollingInfo scrollingInfo; + private readonly IBindable direction = new Bindable(); [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - this.scrollingInfo = scrollingInfo; - InternalChildren = new[] { background = new Box @@ -41,12 +40,18 @@ namespace osu.Game.Rulesets.Mania.UI.Components Name = "Background Gradient Overlay", RelativeSizeAxes = Axes.Both, Height = 0.5f, - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, Blending = BlendingMode.Additive, Alpha = 0 } }; + + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + backgroundOverlay.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + updateColours(); + }, true); } protected override void LoadComplete() @@ -81,8 +86,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components var dimPoint = AccentColour.Opacity(0); backgroundOverlay.Colour = ColourInfo.GradientVertical( - scrollingInfo.Direction == ScrollingDirection.Up ? brightPoint : dimPoint, - scrollingInfo.Direction == ScrollingDirection.Up ? dimPoint : brightPoint); + direction.Value == ScrollingDirection.Up ? brightPoint : dimPoint, + direction.Value == ScrollingDirection.Up ? dimPoint : brightPoint); } public bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index cdea3870ab..4fa8ff4105 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,25 +21,25 @@ namespace osu.Game.Rulesets.Mania.UI.Components private Container content; protected override Container Content => content; - private Container hitTargetBar; + private readonly IBindable direction = new Bindable(); + + private Container hitTargetLine; [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - InternalChildren = new Drawable[] + Drawable hitTargetBar; + + InternalChildren = new[] { - new Box + hitTargetBar = new Box { - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_height, Colour = Color4.Black }, - hitTargetBar = new Container + hitTargetLine = new Container { - Anchor = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = scrollingInfo.Direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = hit_target_bar_height, Masking = true, @@ -50,6 +51,15 @@ namespace osu.Game.Rulesets.Mania.UI.Components RelativeSizeAxes = Axes.Both, }, }; + + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + hitTargetBar.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetBar.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetLine.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetLine.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + }, true); } protected override void LoadComplete() @@ -78,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components if (!IsLoaded) return; - hitTargetBar.EdgeEffect = new EdgeEffectParameters + hitTargetLine.EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, Radius = 5, diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index 56da7bc9b9..4ce1614310 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -22,20 +23,21 @@ namespace osu.Game.Rulesets.Mania.UI.Components public ManiaAction Action; + private readonly IBindable direction = new Bindable(); + private Container keyIcon; [BackgroundDependencyLoader] - private void load(ScrollingInfo scrollingInfo) + private void load(IScrollingInfo scrollingInfo) { - InternalChildren = new Drawable[] + Drawable gradient; + + InternalChildren = new[] { - new Box + gradient = new Box { Name = "Key gradient", RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical( - scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), - scrollingInfo.Direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black), Alpha = 0.5f }, keyIcon = new Container @@ -59,6 +61,14 @@ namespace osu.Game.Rulesets.Mania.UI.Components } } }; + + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => + { + gradient.Colour = ColourInfo.GradientVertical( + direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black); + }, true); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs b/osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs new file mode 100644 index 0000000000..ee65e9f1a5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public interface IScrollingInfo + { + /// + /// The direction s should scroll in. + /// + IBindable Direction { get; } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 54a1b08ea3..1d32ac75eb 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -81,8 +82,9 @@ namespace osu.Game.Rulesets.Mania.UI { dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - scrollingInfo = new ScrollingInfo(ScrollingDirection.Up); - dependencies.Cache(scrollingInfo); + scrollingInfo = new ScrollingInfo { Direction = { Value = ScrollingDirection.Up } }; + + dependencies.CacheAs(scrollingInfo); return dependencies; } @@ -119,5 +121,11 @@ namespace osu.Game.Rulesets.Mania.UI protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay); protected override IRulesetConfigManager CreateConfig(Ruleset ruleset, SettingsStore settings) => new ManiaConfigManager(settings, Ruleset.RulesetInfo, Variant); + + private class ScrollingInfo : IScrollingInfo + { + public readonly Bindable Direction = new Bindable(); + IBindable IScrollingInfo.Direction => Direction; + } } } diff --git a/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs b/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs deleted file mode 100644 index 7772485982..0000000000 --- a/osu.Game.Rulesets.Mania/UI/ScrollingInfo.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.UI.Scrolling; - -namespace osu.Game.Rulesets.Mania.UI -{ - public class ScrollingInfo - { - public readonly ScrollingDirection Direction; - - public ScrollingInfo(ScrollingDirection direction) - { - Direction = direction; - } - } -} From f49b7d6e16407aa5b2d545acbf6bd12ee1ea54cf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 14:36:19 +0900 Subject: [PATCH 089/199] Add mania direction to settings --- .../Configuration/ManiaConfigManager.cs | 5 ++- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 3 ++ .../ManiaSettingsSubsection.cs | 34 +++++++++++++++++++ osu.Game.Rulesets.Mania/UI/Column.cs | 30 +++++++++------- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- .../UI/ManiaRulesetContainer.cs | 13 +++---- .../UI/ManiaScrollingDirection.cs | 13 +++++++ .../UI/ManiaScrollingPlayfield.cs | 26 ++++++++++++++ osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 2 +- osu.Game/Configuration/OsuConfigManager.cs | 2 +- .../Scrolling/ScrollingHitObjectContainer.cs | 13 ++++--- .../UI/Scrolling/ScrollingPlayfield.cs | 11 ++++-- 12 files changed, 121 insertions(+), 33 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs create mode 100644 osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs create mode 100644 osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs index d9e360081d..cb15d55934 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs @@ -4,6 +4,7 @@ using osu.Framework.Configuration.Tracking; using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; +using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Configuration { @@ -19,6 +20,7 @@ namespace osu.Game.Rulesets.Mania.Configuration base.InitialiseDefaults(); Set(ManiaSetting.ScrollTime, 1500.0, 50.0, 10000.0, 50.0); + Set(ManiaSetting.ScrollDirection, ManiaScrollingDirection.Up); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings @@ -29,6 +31,7 @@ namespace osu.Game.Rulesets.Mania.Configuration public enum ManiaSetting { - ScrollTime + ScrollTime, + ScrollDirection } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index e671a3fb14..ccae0b609b 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; @@ -155,6 +156,8 @@ namespace osu.Game.Rulesets.Mania public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new ManiaConfigManager(settings, RulesetInfo); + public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this); + public ManiaRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs new file mode 100644 index 0000000000..54a7bf954d --- /dev/null +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -0,0 +1,34 @@ +// 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.Graphics; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania +{ + public class ManiaSettingsSubsection : RulesetSettingsSubsection + { + protected override string Header => "osu!mania"; + + public ManiaSettingsSubsection(ManiaRuleset ruleset) + : base(ruleset) + { + } + + [BackgroundDependencyLoader] + private void load(ManiaConfigManager config) + { + Children = new Drawable[] + { + new SettingsEnumDropdown + { + LabelText = "Scrolling direction", + Bindable = config.GetBindable(ManiaSetting.ScrollDirection) + } + }; + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index f62d91a52b..6a78143e41 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -14,7 +14,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { - public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour + public class Column : ManiaScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { private const float column_width = 45; private const float special_column_width = 70; @@ -35,8 +35,6 @@ namespace osu.Game.Rulesets.Mania.UI } } - private readonly ScrollingDirection direction; - private readonly ColumnBackground background; private readonly ColumnKeyArea keyArea; private readonly ColumnHitObjectArea hitObjectArea; @@ -49,7 +47,6 @@ namespace osu.Game.Rulesets.Mania.UI public Column(ScrollingDirection direction) : base(direction) { - this.direction = direction; RelativeSizeAxes = Axes.Y; Width = column_width; @@ -58,19 +55,16 @@ namespace osu.Game.Rulesets.Mania.UI background = new ColumnBackground { RelativeSizeAxes = Axes.Both }; + Container hitTargetContainer; + InternalChildren = new[] { // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements background.CreateProxy(), - new Container + hitTargetContainer = new Container { Name = "Hit target + hit objects", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Top = direction == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, - Bottom = direction == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, - }, Children = new Drawable[] { hitObjectArea = new ColumnHitObjectArea { RelativeSizeAxes = Axes.Both }, @@ -83,8 +77,6 @@ namespace osu.Game.Rulesets.Mania.UI }, keyArea = new ColumnKeyArea { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, - Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = ManiaStage.HIT_TARGET_POSITION, }, @@ -93,6 +85,18 @@ namespace osu.Game.Rulesets.Mania.UI }; TopLevelContainer.Add(explosionContainer.CreateProxy()); + + Direction.BindValueChanged(d => + { + hitTargetContainer.Padding = new MarginPadding + { + Top = d == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, + Bottom = d == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, + }; + + keyArea.Anchor = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + keyArea.Origin = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + }, true); } public override Axes RelativeSizeAxes => Axes.Y; @@ -146,7 +150,7 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer.Add(new HitExplosion(judgedObject) { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre + Anchor = Direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre }); } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 73362ab28f..2f8ad7b17e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -16,7 +16,7 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaPlayfield : ScrollingPlayfield + public class ManiaPlayfield : ManiaScrollingPlayfield { public List Columns => stages.SelectMany(x => x.Columns).ToList(); private readonly List stages = new List(); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index eaad787999..fa6fba0cd8 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Handlers; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -34,6 +35,7 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; + private readonly Bindable configDirection = new Bindable(); private ScrollingInfo scrollingInfo; public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) @@ -68,9 +70,12 @@ namespace osu.Game.Rulesets.Mania.UI } [BackgroundDependencyLoader] - private void load() + private void load(ManiaConfigManager config) { BarLines.ForEach(Playfield.Add); + + config.BindWith(ManiaSetting.ScrollDirection, configDirection); + configDirection.BindValueChanged(d => scrollingInfo.Direction.Value = (ScrollingDirection)d, true); } private DependencyContainer dependencies; @@ -78,11 +83,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) { dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - - scrollingInfo = new ScrollingInfo { Direction = { Value = ScrollingDirection.Up } }; - - dependencies.CacheAs(scrollingInfo); - + dependencies.CacheAs(scrollingInfo = new ScrollingInfo()); return dependencies; } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs new file mode 100644 index 0000000000..0fc9c1920a --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public enum ManiaScrollingDirection + { + Up = ScrollingDirection.Up, + Down = ScrollingDirection.Down + } +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs new file mode 100644 index 0000000000..f1ff0665cd --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs @@ -0,0 +1,26 @@ +// 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.Configuration; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class ManiaScrollingPlayfield : ScrollingPlayfield + { + private readonly IBindable direction = new Bindable(); + + public ManiaScrollingPlayfield(ScrollingDirection direction) + : base(direction) + { + } + + [BackgroundDependencyLoader] + private void load(IScrollingInfo scrollingInfo) + { + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(direction => Direction.Value = direction, true); + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 822042362f..3ff14ed0c6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.UI /// /// A collection of s. /// - internal class ManiaStage : ScrollingPlayfield + internal class ManiaStage : ManiaScrollingPlayfield { public const float HIT_TARGET_POSITION = 50; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 597960c352..1bb2ac4678 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -147,6 +147,6 @@ namespace osu.Game.Configuration SongSelectRightMouseScroll, BeatmapSkins, BeatmapHitsounds, - IncreaseFirstObjectVisibility + IncreaseFirstObjectVisibility, } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 36c6b07f54..c64fca6eff 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -29,17 +29,16 @@ namespace osu.Game.Rulesets.UI.Scrolling /// protected readonly SortedList ControlPoints = new SortedList(); - private readonly ScrollingDirection direction; + public readonly Bindable Direction = new Bindable(); private Cached initialStateCache = new Cached(); - public ScrollingHitObjectContainer(ScrollingDirection direction) + public ScrollingHitObjectContainer() { - this.direction = direction; - RelativeSizeAxes = Axes.Both; - TimeRange.ValueChanged += v => initialStateCache.Invalidate(); + TimeRange.ValueChanged += _ => initialStateCache.Invalidate(); + Direction.ValueChanged += _ => initialStateCache.Invalidate(); } private ISpeedChangeVisualiser speedChangeVisualiser; @@ -100,7 +99,7 @@ namespace osu.Game.Rulesets.UI.Scrolling if (!initialStateCache.IsValid) { - speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); + speedChangeVisualiser.ComputeInitialStates(Objects, Direction, TimeRange, DrawSize); initialStateCache.Validate(); } } @@ -110,7 +109,7 @@ namespace osu.Game.Rulesets.UI.Scrolling base.UpdateAfterChildrenLife(); // We need to calculate this as soon as possible after lifetimes so that hitobjects get the final say in their positions - speedChangeVisualiser.UpdatePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); + speedChangeVisualiser.UpdatePositions(AliveObjects, Direction, Time.Current, TimeRange, DrawSize); } } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 6f86d20295..b7f6844245 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -54,7 +54,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; - private readonly ScrollingDirection direction; + protected readonly Bindable Direction = new Bindable(); /// /// Creates a new . @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.UI.Scrolling protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null, float? customHeight = null) : base(customWidth, customHeight) { - this.direction = direction; + Direction.Value = direction; } [BackgroundDependencyLoader] @@ -99,6 +99,11 @@ namespace osu.Game.Rulesets.UI.Scrolling return false; } - protected sealed override HitObjectContainer CreateHitObjectContainer() => new ScrollingHitObjectContainer(direction); + protected sealed override HitObjectContainer CreateHitObjectContainer() + { + var container = new ScrollingHitObjectContainer(); + container.Direction.BindTo(Direction); + return container; + } } } From 162237dc46cf28225a2caa1075d97eefcac5af8c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 15:43:15 +0900 Subject: [PATCH 090/199] Fix bar lines being offset --- .../TestCaseStage.cs | 64 ++++++++++++++++++- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 18 ++++-- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index d88896d855..0f90c1f16b 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -1,11 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using OpenTK; @@ -15,8 +20,12 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestCaseStage : ManiaInputTestCase { + private const int columns = 4; + + private readonly List stages = new List(); + public TestCaseStage() - : base(4) + : base(columns) { } @@ -37,17 +46,68 @@ namespace osu.Game.Rulesets.Mania.Tests }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + AddStep("note", createNote); + AddStep("hold note", createHoldNote); + AddStep("bar line", createBarLine); + } + + private void createNote() + { + foreach (var stage in stages) + { + for (int i = 0; i < stage.Columns.Count; i++) + { + var obj = new Note { Column = i, StartTime = Time.Current + 2000 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + stage.Add(new DrawableNote(obj, stage.Columns[i].Action)); + } + } + } + + private void createHoldNote() + { + foreach (var stage in stages) + { + for (int i = 0; i < stage.Columns.Count; i++) + { + var obj = new HoldNote { Column = i, StartTime = Time.Current + 2000, Duration = 500 }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + stage.Add(new DrawableHoldNote(obj, stage.Columns[i].Action)); + } + } + } + + private void createBarLine() + { + foreach (var stage in stages) + { + var obj = new BarLine { StartTime = Time.Current + 2000, ControlPoint = new TimingControlPoint() }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + stage.Add(obj); + } + } + private Drawable createStage(ScrollingDirection direction, ManiaAction action) { var specialAction = ManiaAction.Special1; + var stage = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + stages.Add(stage); + return new ScrollingTestContainer(direction) { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, - Child = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) + Child = stage }; } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 3ff14ed0c6..7b68582944 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Mania.UI public IReadOnlyList Columns => columnFlow.Children; private readonly FillFlowContainer columnFlow; - protected override Container Content => content; - private readonly Container content; + protected override Container Content => barLineContainer; + private readonly Container barLineContainer; public Container Judgements => judgements; private readonly JudgementContainer judgements; @@ -100,13 +100,12 @@ namespace osu.Game.Rulesets.Mania.UI Width = 1366, // Bar lines should only be masked on the vertical axis BypassAutoSizeAxes = Axes.Both, Masking = true, - Child = content = new Container + Child = barLineContainer = new Container { Name = "Bar lines", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = HIT_TARGET_POSITION } } }, judgements = new JudgementContainer @@ -133,6 +132,15 @@ namespace osu.Game.Rulesets.Mania.UI AddColumn(column); } + + Direction.BindValueChanged(d => + { + barLineContainer.Padding = new MarginPadding + { + Top = d == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0, + Bottom = d == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0, + }; + }, true); } public void AddColumn(Column c) @@ -203,7 +211,7 @@ namespace osu.Game.Rulesets.Mania.UI { // Due to masking differences, it is not possible to get the width of the columns container automatically // While masking on effectively only the Y-axis, so we need to set the width of the bar line container manually - content.Width = columnFlow.Width; + barLineContainer.Width = columnFlow.Width; } } } From b9bf3a1829002036201e96c8359519add545e172 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 15:56:30 +0900 Subject: [PATCH 091/199] Make mania scroll downwards by default --- osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs index cb15d55934..3e9c9feba1 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Configuration base.InitialiseDefaults(); Set(ManiaSetting.ScrollTime, 1500.0, 50.0, 10000.0, 50.0); - Set(ManiaSetting.ScrollDirection, ManiaScrollingDirection.Up); + Set(ManiaSetting.ScrollDirection, ManiaScrollingDirection.Down); } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings From 10d1dfa7cd4ab3a858883f695dfaa921de1c0431 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 16:10:27 +0900 Subject: [PATCH 092/199] A bit of cleanup --- .../Objects/Drawables/DrawableHoldNote.cs | 3 +-- .../Objects/Drawables/DrawableManiaHitObject.cs | 3 +-- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 3 +-- .../Objects/Drawables/Pieces/NotePiece.cs | 3 +-- osu.Game.Rulesets.Mania/UI/Column.cs | 3 +-- osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs | 3 +-- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 5 +---- 7 files changed, 7 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 3448d66ce1..ce0276f759 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -80,8 +80,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { base.OnDirectionChanged(direction); - bodyPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - bodyPiece.Origin = bodyPiece.Anchor; + bodyPiece.Anchor = bodyPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 01df4743c7..1271fae0c1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -40,8 +40,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected virtual void OnDirectionChanged(ScrollingDirection direction) { - Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - Origin = Anchor; + Anchor = Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index b9b3fa7824..fb4aa74ad1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -36,8 +36,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { base.OnDirectionChanged(direction); - headPiece.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - headPiece.Origin = headPiece.Anchor; + headPiece.Anchor = headPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 2c36b96f72..2c74f5b168 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -52,8 +52,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(direction => { - colouredBox.Anchor = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - colouredBox.Origin = colouredBox.Anchor; + colouredBox.Anchor = colouredBox.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 6a78143e41..fafc875706 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -94,8 +94,7 @@ namespace osu.Game.Rulesets.Mania.UI Bottom = d == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; - keyArea.Anchor = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - keyArea.Origin = d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + keyArea.Anchor = keyArea.Origin= d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 50303deda7..9b744bd254 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -48,8 +48,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(direction => { - backgroundOverlay.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + backgroundOverlay.Anchor = backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; updateColours(); }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 4fa8ff4105..6d6edff3f4 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -55,10 +55,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(direction => { - hitTargetBar.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - hitTargetBar.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - hitTargetLine.Anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; - hitTargetLine.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + hitTargetBar.Anchor = hitTargetBar.Origin = hitTargetLine.Anchor = hitTargetLine.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } From a36dab638aec66fe4c50eb7b874a1984910334ce Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 16:12:52 +0900 Subject: [PATCH 093/199] Improve TestCaseStage --- osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index 0f90c1f16b..9aff853ffd 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -52,7 +52,8 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("note", createNote); AddStep("hold note", createHoldNote); - AddStep("bar line", createBarLine); + AddStep("minor bar line", () => createBarLine(false)); + AddStep("major bar line", () => createBarLine(true)); } private void createNote() @@ -83,11 +84,17 @@ namespace osu.Game.Rulesets.Mania.Tests } } - private void createBarLine() + private void createBarLine(bool major) { foreach (var stage in stages) { - var obj = new BarLine { StartTime = Time.Current + 2000, ControlPoint = new TimingControlPoint() }; + var obj = new BarLine + { + StartTime = Time.Current + 2000, + ControlPoint = new TimingControlPoint(), + BeatIndex = major ? 0 : 1 + }; + obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); stage.Add(obj); @@ -98,7 +105,7 @@ namespace osu.Game.Rulesets.Mania.Tests { var specialAction = ManiaAction.Special1; - var stage = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction); + var stage = new ManiaStage(direction, 0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) { VisibleTimeRange = { Value = 2000 } }; stages.Add(stage); return new ScrollingTestContainer(direction) From 3bad319dd2995c242ddc74c433a039699928f78e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 16:19:57 +0900 Subject: [PATCH 094/199] Fix filename --- .../UI/{IScrollinginfo.cs => IScrollingInfo.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Mania/UI/{IScrollinginfo.cs => IScrollingInfo.cs} (100%) diff --git a/osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs b/osu.Game.Rulesets.Mania/UI/IScrollingInfo.cs similarity index 100% rename from osu.Game.Rulesets.Mania/UI/IScrollinginfo.cs rename to osu.Game.Rulesets.Mania/UI/IScrollingInfo.cs From 8f3215f5a0b251f29e4863e50b396e91624e33e3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 20:42:04 +0900 Subject: [PATCH 095/199] Make sure taiko hitexplosions expire and get removed --- osu.Game.Rulesets.Taiko/UI/HitExplosion.cs | 4 +++- osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs index ee2c1d5ad5..4dd0ba4d3d 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Taiko.UI /// internal class HitExplosion : CircularContainer { + public override bool RemoveWhenNotAlive => true; + public readonly DrawableHitObject JudgedObject; private readonly Box innerFill; @@ -66,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.UI this.ScaleTo(3f, 1000, Easing.OutQuint); this.FadeOut(500); - Expire(); + Expire(true); } /// diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index ac3cf8305a..287d59972a 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -14,6 +14,8 @@ namespace osu.Game.Rulesets.Taiko.UI { public class KiaiHitExplosion : CircularContainer { + public override bool RemoveWhenNotAlive => true; + public readonly DrawableHitObject JudgedObject; private readonly bool isRim; @@ -62,7 +64,7 @@ namespace osu.Game.Rulesets.Taiko.UI this.ScaleTo(new Vector2(1, 3f), 500, Easing.OutQuint); this.FadeOut(250); - Expire(); + Expire(true); } } } From b6fb01440b407e62a88852e5f9331e27d9816fba Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 20:44:26 +0900 Subject: [PATCH 096/199] Fix taiko hit states not being reverted on rewind --- .../Objects/Drawables/DrawableHit.cs | 3 +++ .../Objects/Drawables/DrawableHitStrong.cs | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index d923b2dcdf..ad361b66bc 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -86,6 +86,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (State.Value) { case ArmedState.Idle: + SecondHitAllowed = false; + validKeyPressed = false; + this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); break; case ArmedState.Miss: diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs index c416d50062..b431d35e16 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; @@ -46,6 +47,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables AddJudgement(new TaikoStrongHitJudgement { Result = HitResult.Great }); } + protected override void UpdateState(ArmedState state) + { + base.UpdateState(state); + + switch (state) + { + case ArmedState.Idle: + firstHitTime = 0; + firstKeyHeld = false; + break; + } + } + public override bool OnReleased(TaikoAction action) { if (action == firstHitAction) From 22dfe46572b2f73a0fbb790688d41a8a78d873d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 21:45:19 +0900 Subject: [PATCH 097/199] Make taiko hitobject properly unproxy when rewound --- .../Objects/Drawables/DrawableHit.cs | 4 ++ .../Objects/Drawables/DrawableSwell.cs | 20 +++---- .../Drawables/DrawableTaikoHitObject.cs | 60 +++++++++++++++++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 20 +------ 4 files changed, 70 insertions(+), 34 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index d923b2dcdf..cca2753524 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -86,6 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (State.Value) { case ArmedState.Idle: + UnproxyContent(); this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); break; case ArmedState.Miss: @@ -93,6 +94,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables .Expire(); break; case ArmedState.Hit: + if (X >= -0.05f) + ProxyContent(); + var flash = circlePiece?.FlashBox; if (flash != null) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 33cc29bccf..1f571544d8 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -20,12 +20,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableSwell : DrawableTaikoHitObject { - /// - /// Invoked when the swell has reached the hit target, i.e. when CurrentTime >= StartTime. - /// This is only ever invoked once. - /// - public event Action OnStart; - private const float target_ring_thick_border = 1.4f; private const float target_ring_thin_border = 1f; private const float target_ring_scale = 5f; @@ -40,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private int userHits; - private bool hasStarted; + private bool hasProxied; private readonly SwellSymbolPiece symbol; public DrawableSwell(Swell swell) @@ -48,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { FillMode = FillMode.Fit; - AddInternal(bodyContainer = new Container + Content.Add(bodyContainer = new Container { RelativeSizeAxes = Axes.Both, Depth = 1, @@ -177,6 +171,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { + case ArmedState.Idle: + hasProxied = false; + UnproxyContent(); + break; case ArmedState.Hit: bodyContainer.Delay(untilJudgement).ScaleTo(1.4f, out_transition_time); break; @@ -195,10 +193,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables X = Math.Max(0, X); double t = Math.Min(HitObject.StartTime, Time.Current); - if (t == HitObject.StartTime && !hasStarted) + if (t == HitObject.StartTime && !hasProxied) { - OnStart?.Invoke(); - hasStarted = true; + ProxyContent(); + hasProxied = true; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 971fd8854d..c07ee3a0fd 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -9,10 +9,62 @@ using OpenTK; using System.Linq; using osu.Game.Audio; using System.Collections.Generic; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler + public abstract class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler + { + protected readonly Container Content; + public readonly Container ProxiedContent; + + private readonly Container nonProxiedContent; + + protected DrawableTaikoHitObject(TaikoHitObject hitObject) + : base(hitObject) + { + InternalChildren = new[] + { + nonProxiedContent = new Container + { + RelativeSizeAxes = Axes.Both, + Child = Content = new Container { RelativeSizeAxes = Axes.Both } + }, + ProxiedContent = new Container { RelativeSizeAxes = Axes.Both } + }; + } + + /// + /// is proxied into an upper layer. We don't want to get masked away otherwise would too. + /// + protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; + + /// + /// Moves to a layer proxied above the playfield. + /// + protected void ProxyContent() + { + nonProxiedContent.Remove(Content); + ProxiedContent.Remove(Content); + ProxiedContent.Add(Content); + } + + /// + /// Moves to the normal hitobject layer. + /// + protected void UnproxyContent() + { + ProxiedContent.Remove(Content); + nonProxiedContent.Remove(Content); + nonProxiedContent.Add(Content); + } + + public abstract bool OnPressed(TaikoAction action); + public virtual bool OnReleased(TaikoAction action) => false; + } + + public abstract class DrawableTaikoHitObject : DrawableTaikoHitObject where TaikoHitType : TaikoHitObject { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); @@ -34,7 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Both; Size = BaseSize = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE); - InternalChild = MainPiece = CreateMainPiece(); + Content.Add(MainPiece = CreateMainPiece()); MainPiece.KiaiMode = HitObject.Kiai; } @@ -44,9 +96,5 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override string SampleNamespace => "Taiko"; protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); - - public abstract bool OnPressed(TaikoAction action); - - public virtual bool OnReleased(TaikoAction action) => false; } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 417a7c2581..c638f807fe 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -216,10 +216,9 @@ namespace osu.Game.Rulesets.Taiko.UI if (barline != null) barlineContainer.Add(barline.CreateProxy()); - // Swells should be moved at the very top of the playfield when they reach the hit target - var swell = h as DrawableSwell; - if (swell != null) - swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy()); + var taikoObject = h as DrawableTaikoHitObject; + if (taikoObject != null) + topLevelHitContainer.Add(taikoObject.ProxiedContent.CreateProxy()); } internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) @@ -244,19 +243,6 @@ namespace osu.Game.Rulesets.Taiko.UI hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == judgedObject)?.VisualiseSecondHit(); else { - if (judgedObject.X >= -0.05f && judgedObject is DrawableHit) - { - // If we're far enough away from the left stage, we should bring outselves in front of it - // Todo: The following try-catch is temporary for replay rewinding support - try - { - topLevelHitContainer.Add(judgedObject.CreateProxy()); - } - catch - { - } - } - hitExplosionContainer.Add(new HitExplosion(judgedObject, isRim)); if (judgedObject.HitObject.Kiai) From 1b12820de9e8529df794cc3d1396ba9e4d954c29 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 11 Jun 2018 21:54:11 +0900 Subject: [PATCH 098/199] Restore a removed comment --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index cca2753524..519b56a3ed 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -94,6 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables .Expire(); break; case ArmedState.Hit: + // If we're far enough away from the left stage, we should bring outselves in front of it if (X >= -0.05f) ProxyContent(); From 0f9c05d1e6dee534dbae0bcfb91c43fa3bcc7fdd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 22:32:08 +0900 Subject: [PATCH 099/199] Fix taiko swells not properly rewinding --- .../TaikoIntermediateSwellJudgement.cs | 26 +++++++++++++ .../Objects/Drawables/DrawableSwell.cs | 38 +++++++++---------- 2 files changed, 45 insertions(+), 19 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs new file mode 100644 index 0000000000..608f1f9be2 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Judgements +{ + public class TaikoIntermediateSwellJudgement : TaikoJudgement + { + public override HitResult MaxResult => HitResult.Perfect; + + public override bool AffectsCombo => false; + + public TaikoIntermediateSwellJudgement() + { + Final = false; + } + + /// + /// Computes the numeric result value for the combo portion of the score. + /// + /// The result to compute the value for. + /// The numeric result value. + protected override int NumericResultFor(HitResult result) => 0; + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 33cc29bccf..5c3f8601b4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -26,6 +25,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// public event Action OnStart; + /// + /// A judgement is only displayed when the user has complete the swell (either a hit or miss). + /// + public override bool DisplayJudgement => AllJudged; + private const float target_ring_thick_border = 1.4f; private const float target_ring_thin_border = 1f; private const float target_ring_scale = 5f; @@ -35,11 +39,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private readonly CircularContainer targetRing; private readonly CircularContainer expandingRing; - /// - /// The amount of times the user has hit this swell. - /// - private int userHits; - private bool hasStarted; private readonly SwellSymbolPiece symbol; @@ -136,9 +135,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { if (userTriggered) { - userHits++; + AddJudgement(new TaikoIntermediateSwellJudgement()); - var completion = (float)userHits / HitObject.RequiredHits; + var completion = (float)Judgements.Count / HitObject.RequiredHits; expandingRing .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) @@ -149,7 +148,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); - if (userHits == HitObject.RequiredHits) + if (Judgements.Count == HitObject.RequiredHits) AddJudgement(new TaikoJudgement { Result = HitResult.Great }); } else @@ -158,7 +157,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return; //TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP - AddJudgement(userHits > HitObject.RequiredHits / 2 + AddJudgement(Judgements.Count > HitObject.RequiredHits / 2 ? new TaikoJudgement { Result = HitResult.Good } : new TaikoJudgement { Result = HitResult.Miss }); } @@ -169,20 +168,21 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables const float preempt = 100; const float out_transition_time = 300; - double untilStartTime = HitObject.StartTime - Time.Current; - double untilJudgement = untilStartTime + (Judgements.FirstOrDefault()?.TimeOffset ?? 0) + HitObject.Duration; - - targetRing.Delay(untilStartTime - preempt).ScaleTo(target_ring_scale, preempt * 4, Easing.OutQuint); - this.Delay(untilJudgement).FadeOut(out_transition_time, Easing.Out); - switch (state) { + case ArmedState.Idle: + expandingRing.FadeTo(0); + using (BeginAbsoluteSequence(HitObject.StartTime - preempt, true)) + targetRing.ScaleTo(target_ring_scale, preempt * 4, Easing.OutQuint); + break; + case ArmedState.Miss: case ArmedState.Hit: - bodyContainer.Delay(untilJudgement).ScaleTo(1.4f, out_transition_time); + this.FadeOut(out_transition_time, Easing.Out); + bodyContainer.ScaleTo(1.4f, out_transition_time); + + Expire(); break; } - - Expire(); } protected override void Update() From 7651819fb0ea29f7f636cdd4e4e42fcfa680e24b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 12:53:53 +0900 Subject: [PATCH 100/199] Add same change to mania's hit explosions --- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index f19c3a811b..bf8db63137 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -15,6 +15,8 @@ namespace osu.Game.Rulesets.Mania.UI { internal class HitExplosion : CompositeDrawable { + public override bool RemoveWhenNotAlive => true; + private readonly CircularContainer circle; public HitExplosion(DrawableHitObject judgedObject) From b90cdfbfd166aeb8fc26ad1bf8f51ff8d1c9b3d1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 14:33:33 +0900 Subject: [PATCH 101/199] Remove unused variable --- osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index 0a2e549509..c0557982fb 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -19,8 +19,6 @@ namespace osu.Game.Tests.Visual public TestCaseEditorComposeTimeline() { - TimelineArea timelineArea; - Children = new Drawable[] { new MusicController From 6ceac8ab0a316437d1dfed2c133927e2496c71f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 24 May 2018 15:23:59 +0900 Subject: [PATCH 102/199] Add a centre marker to the timeline --- .../Visual/TestCaseEditorComposeTimeline.cs | 9 +++- .../Screens/Compose/Timeline/CentreMarker.cs | 52 +++++++++++++++++++ .../Edit/Screens/Compose/Timeline/Timeline.cs | 6 +++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Screens/Edit/Screens/Compose/Timeline/CentreMarker.cs diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index c0557982fb..d731ef973a 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -15,7 +15,14 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseEditorComposeTimeline : EditorClockTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineArea), typeof(Timeline), typeof(TimelineButton) }; + public override IReadOnlyList RequiredTypes => new[] + { + typeof(TimelineArea), + typeof(Timeline), + typeof(BeatmapWaveformGraph), + typeof(TimelineButton), + typeof(CentreMarker) + }; public TestCaseEditorComposeTimeline() { diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/CentreMarker.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/CentreMarker.cs new file mode 100644 index 0000000000..8e932f307d --- /dev/null +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/CentreMarker.cs @@ -0,0 +1,52 @@ +// 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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using OpenTK; + +namespace osu.Game.Screens.Edit.Screens.Compose.Timeline +{ + public class CentreMarker : CompositeDrawable + { + private const float triangle_width = 20; + private const float triangle_height = 10; + private const float bar_width = 2; + + public CentreMarker() + { + RelativeSizeAxes = Axes.Y; + Size = new Vector2(20, 1); + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + InternalChildren = new Drawable[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = bar_width, + }, + new Triangle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(triangle_width, triangle_height), + Scale = new Vector2(1, -1) + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Red; + } + } +} diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index daf67ed7f0..d5f47f5e04 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -41,6 +41,12 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline Depth = float.MaxValue }; + // We don't want the centre marker to scroll + AddInternal(new CentreMarker()); + + // Make sure that the scrollbar is above the centre marker + ChangeInternalChildDepth(Scrollbar, -1); + WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); Beatmap.BindTo(beatmap); From 7dfe171869ed7b0596c30620f55ea834636628c2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 14:31:12 +0900 Subject: [PATCH 103/199] Fix rebase error --- osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index d731ef973a..a89c5767fc 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -19,7 +19,6 @@ namespace osu.Game.Tests.Visual { typeof(TimelineArea), typeof(Timeline), - typeof(BeatmapWaveformGraph), typeof(TimelineButton), typeof(CentreMarker) }; From aaf2f66594527f0d912bedaf72e79c22e4916b5c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 15:49:42 +0900 Subject: [PATCH 104/199] Make scrolling only zoom the timeline --- .../Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index 035e6a0804..ed26c28c80 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -99,10 +99,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline protected override bool OnScroll(InputState state) { - if (!state.Keyboard.ControlPressed) + if (state.Mouse.HasPreciseScroll) return base.OnScroll(state); - - setZoomTarget(zoomTarget + state.Mouse.ScrollDelta.X, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); + setZoomTarget(zoomTarget + state.Mouse.ScrollDelta.Y, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); return true; } From 3b396e38caf1211eb3b6645f81b22e86092b7904 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 15:51:48 +0900 Subject: [PATCH 105/199] Hide the scrollbar --- .../Edit/Screens/Compose/Timeline/Timeline.cs | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index daf67ed7f0..3bd7a0b96b 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -25,6 +25,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline ZoomDuration = 200; ZoomEasing = Easing.OutQuint; Zoom = 10; + ScrollbarVisible = false; } private WaveformGraph waveform; @@ -150,35 +151,5 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline if (trackWasPlaying) adjustableClock.Start(); } - - protected override ScrollbarContainer CreateScrollbar(Direction direction) => new TimelineScrollbar(this, direction); - - private class TimelineScrollbar : ScrollbarContainer - { - private readonly Timeline timeline; - - public TimelineScrollbar(Timeline timeline, Direction scrollDir) - : base(scrollDir) - { - this.timeline = timeline; - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - if (base.OnMouseDown(state, args)) - { - timeline.beginUserDrag(); - return true; - } - - return false; - } - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) - { - timeline.endUserDrag(); - return base.OnMouseUp(state, args); - } - } } } From 34f23359bb773c8997e8e34a1e65d31374e679d9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 16:20:31 +0900 Subject: [PATCH 106/199] Fix unit tests --- .../Visual/TestCaseZoomableScrollContainer.cs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs index 70dd67cdbd..0d6526b637 100644 --- a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs @@ -77,16 +77,12 @@ namespace osu.Game.Tests.Visual // Scroll in at 0.25 AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y))); - AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); - AddStep("Scroll by 3", () => InputManager.ScrollBy(new Vector2(3, 0))); - AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddStep("Scroll by 3", () => InputManager.ScrollBy(new Vector2(0, 3))); AddAssert("Box not at 0", () => !Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); AddAssert("Box 1/4 at 1/4", () => Precision.AlmostEquals(boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X)); // Scroll out at 0.25 - AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); - AddStep("Scroll by -3", () => InputManager.ScrollBy(new Vector2(-3, 0))); - AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddStep("Scroll by -3", () => InputManager.ScrollBy(new Vector2(0, -3))); AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); AddAssert("Box 1/4 at 1/4", () => Precision.AlmostEquals(boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X)); } @@ -98,15 +94,11 @@ namespace osu.Game.Tests.Visual // Scroll in at 0.25 AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y))); - AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); - AddStep("Scroll by 1", () => InputManager.ScrollBy(new Vector2(1, 0))); - AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddStep("Scroll by 1", () => InputManager.ScrollBy(new Vector2(0, 1))); // Scroll in at 0.6 AddStep("Move mouse to 0.75x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.75f * scrollQuad.Size.X, scrollQuad.Centre.Y))); - AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); - AddStep("Scroll by 1", () => InputManager.ScrollBy(new Vector2(1, 0))); - AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddStep("Scroll by 1", () => InputManager.ScrollBy(new Vector2(0, 1))); AddAssert("Box not at 0", () => !Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); // Very hard to determine actual position, so approximate @@ -115,15 +107,11 @@ namespace osu.Game.Tests.Visual AddAssert("Box at correct position (3)", () => Precision.DefinitelyBigger(boxQuad.TopLeft.X + 0.6f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.6f * scrollQuad.Size.X)); // Scroll out at 0.6 - AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); - AddStep("Scroll by -1", () => InputManager.ScrollBy(new Vector2(-1, 0))); - AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddStep("Scroll by -1", () => InputManager.ScrollBy(new Vector2(0, -1))); // Scroll out at 0.25 AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y))); - AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); - AddStep("Scroll by -1", () => InputManager.ScrollBy(new Vector2(-1, 0))); - AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddStep("Scroll by -1", () => InputManager.ScrollBy(new Vector2(0, -1))); AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); } From 93d2b5c4dea32f93186e877697cb95cf806e902b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 16:20:38 +0900 Subject: [PATCH 107/199] Adjust precision for failing test --- osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs index 0d6526b637..7fe59979a1 100644 --- a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual { reset(); AddStep("Set zoom = 10", () => scrollContainer.Zoom = 10); - AddAssert("Box at 1/2", () => Precision.AlmostEquals(boxQuad.Centre, scrollQuad.Centre)); + AddAssert("Box at 1/2", () => Precision.AlmostEquals(boxQuad.Centre, scrollQuad.Centre, 1)); AddAssert("Box width = 10x", () => Precision.AlmostEquals(boxQuad.Size.X, 10 * scrollQuad.Size.X)); } From ac1990c093a9f69eabdbe49af90182794466ee3c Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Tue, 12 Jun 2018 16:36:46 +0900 Subject: [PATCH 108/199] Remove unused using --- osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs index 7fe59979a1..8bd1b79a84 100644 --- a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs @@ -13,7 +13,6 @@ using osu.Game.Graphics.Cursor; using osu.Game.Screens.Edit.Screens.Compose.Timeline; using OpenTK; using OpenTK.Graphics; -using OpenTK.Input; namespace osu.Game.Tests.Visual { From ca3186f34c7b2507fef6e0900e61e5c7e9746c82 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Jun 2018 19:51:35 +0900 Subject: [PATCH 109/199] Create dependencies before children are loaded --- osu.Game/Tests/Visual/EditorClockTestCase.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs index 08dc6a3bbd..521b51529e 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs @@ -25,13 +25,20 @@ namespace osu.Game.Tests.Visual Clock = new EditorClock(new ControlPointInfo(), 5000, BeatDivisor) { IsCoupled = false }; } + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + + dependencies.Cache(BeatDivisor); + dependencies.CacheAs(Clock); + dependencies.CacheAs(Clock); + + return dependencies; + } + [BackgroundDependencyLoader] private void load() { - Dependencies.Cache(BeatDivisor); - Dependencies.CacheAs(Clock); - Dependencies.CacheAs(Clock); - Beatmap.BindValueChanged(beatmapChanged, true); } From 2a18625b2c95f2f2fda8981365f177417e339969 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 16:46:27 +0900 Subject: [PATCH 110/199] 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 111/199] 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 112/199] 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 113/199] 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 b318b770d4ea82efdb6f24b11f1cf131af77d2bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Jun 2018 19:18:11 +0900 Subject: [PATCH 114/199] Fix pixellation of volume meter progress bars --- osu.Game.Tests/Visual/TestCaseVolumePieces.cs | 13 +- osu.Game/Overlays/Volume/VolumeMeter.cs | 200 +++++++++++------- 2 files changed, 139 insertions(+), 74 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseVolumePieces.cs b/osu.Game.Tests/Visual/TestCaseVolumePieces.cs index 449f48b7d7..3c5b91ccd2 100644 --- a/osu.Game.Tests/Visual/TestCaseVolumePieces.cs +++ b/osu.Game.Tests/Visual/TestCaseVolumePieces.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Overlays.Volume; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Tests.Visual @@ -17,13 +18,21 @@ namespace osu.Game.Tests.Visual { VolumeMeter meter; MuteButton mute; - Add(meter = new VolumeMeter("MASTER", 125, Color4.Blue)); + Add(meter = new VolumeMeter("MASTER", 125, Color4.Blue) { Position = new Vector2(10) }); + AddSliderStep("master volume", 0, 10, 0, i => meter.Bindable.Value = i * 0.1); + + Add(new VolumeMeter("BIG", 250, Color4.Red) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Position = new Vector2(10), + }); + Add(mute = new MuteButton { Margin = new MarginPadding { Top = 200 } }); - AddSliderStep("master volume", 0, 10, 0, i => meter.Bindable.Value = i * 0.1); AddToggleStep("mute", b => mute.Current.Value = b); } } diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index b2cf43704b..0e43945f8c 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -24,6 +24,8 @@ namespace osu.Game.Overlays.Volume public class VolumeMeter : Container, IKeyBindingHandler { private CircularProgress volumeCircle; + private CircularProgress volumeCircleGlow; + public BindableDouble Bindable { get; } = new BindableDouble { MinValue = 0, MaxValue = 1 }; private readonly float circleSize; private readonly Color4 meterColour; @@ -44,90 +46,143 @@ namespace osu.Game.Overlays.Volume [BackgroundDependencyLoader] private void load(OsuColour colours) { - Add(new Container - { - Size = new Vector2(120, 20), - CornerRadius = 10, - Masking = true, - Margin = new MarginPadding { Left = circleSize + 10 }, - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray1, - Alpha = 0.9f, - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = "Exo2.0-Bold", - Text = name - } - } - }); + Color4 backgroundColour = colours.Gray1; CircularProgress bgProgress; - Add(new CircularContainer + const float progress_start_radius = 0.75f; + const float progress_size = 0.03f; + const float progress_end_radius = progress_start_radius + progress_size; + + const float blur_amount = 5; + + Children = new Drawable[] { - Masking = true, - Size = new Vector2(circleSize), - Children = new Drawable[] + new Container { - new Box + Size = new Vector2(circleSize), + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = colours.Gray1, - Alpha = 0.9f, - }, - bgProgress = new CircularProgress - { - RelativeSizeAxes = Axes.Both, - InnerRadius = 0.05f, - Rotation = 180, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = colours.Gray2, - Size = new Vector2(0.8f) - }, - new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.8f), - Padding = new MarginPadding(-Blur.KernelSize(5)), - Rotation = 180, - Child = (volumeCircle = new CircularProgress + new BufferedContainer { + Alpha = 0.9f, RelativeSizeAxes = Axes.Both, - InnerRadius = 0.05f, + Children = new Drawable[] + { + new Circle + { + RelativeSizeAxes = Axes.Both, + Colour = backgroundColour, + }, + new CircularContainer + { + Masking = true, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(progress_end_radius), + Children = new Drawable[] + { + bgProgress = new CircularProgress + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Rotation = 180, + Colour = backgroundColour, + }, + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Name = "Progress under covers for smoothing", + RelativeSizeAxes = Axes.Both, + Rotation = 180, + Child = volumeCircle = new CircularProgress + { + RelativeSizeAxes = Axes.Both, + } + }, + } + }, + new Circle + { + Name = "Inner Cover", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = backgroundColour, + Size = new Vector2(progress_start_radius), + }, + new Container + { + Name = "Progress overlay for glow", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(progress_start_radius + progress_size / 1.5f), + Rotation = 180, + Padding = new MarginPadding(-Blur.KernelSize(blur_amount)), + Child = (volumeCircleGlow = new CircularProgress + { + RelativeSizeAxes = Axes.Both, + InnerRadius = progress_size * 0.8f, + }).WithEffect(new GlowEffect + { + Colour = meterColour, + BlurSigma = new Vector2(blur_amount), + Strength = 5, + PadExtent = true + }), + }, + }, + }, + maxGlow = (text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = "Venera", + TextSize = 0.16f * circleSize }).WithEffect(new GlowEffect { - Colour = meterColour, - Strength = 2, - PadExtent = true - }), - }, - maxGlow = (text = new OsuSpriteText + Colour = Color4.Transparent, + PadExtent = true, + }) + } + }, + new Container + { + Size = new Vector2(120, 20), + CornerRadius = 10, + Masking = true, + Margin = new MarginPadding { Left = circleSize + 10 }, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = "Venera", - TextSize = 0.16f * circleSize - }).WithEffect(new GlowEffect - { - Colour = Color4.Transparent, - PadExtent = true, - }) + new Box + { + Alpha = 0.9f, + RelativeSizeAxes = Axes.Both, + Colour = backgroundColour, + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = "Exo2.0-Bold", + Text = name + } + } } - }); - - Bindable.ValueChanged += newVolume => { this.TransformTo("DisplayVolume", newVolume, 400, Easing.OutQuint); }; + }; + Bindable.ValueChanged += newVolume => + { + this.TransformTo("DisplayVolume", + newVolume, + 400, + Easing.OutQuint); + }; bgProgress.Current.Value = 0.75f; } @@ -158,6 +213,7 @@ namespace osu.Game.Overlays.Volume } volumeCircle.Current.Value = displayVolume * 0.75f; + volumeCircleGlow.Current.Value = displayVolume * 0.75f; } } From 1431ee1867f6f4ca4f648158a316853f3c580d16 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 14:46:25 +0900 Subject: [PATCH 115/199] Remove unused method --- osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 31cd9dc6f5..a9bf5b1797 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -33,10 +33,6 @@ namespace osu.Game.Rulesets.Difficulty TimeRate = clock.Rate; } - protected virtual void PreprocessHitObjects() - { - } - /// /// Creates all combinations which adjust the difficulty. /// From b7a06b95944fdde0083c7f3f14bfed2132bcc074 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 15:32:07 +0900 Subject: [PATCH 116/199] Restructure of DifficultyCalculator to cleanup mod + attribute handling --- .../Difficulty/DifficultyAttributes.cs | 19 +++++++ .../Difficulty/DifficultyCalculator.cs | 51 ++++++++++++++----- osu.Game/Rulesets/Ruleset.cs | 2 +- 3 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs new file mode 100644 index 0000000000..1fdebd586f --- /dev/null +++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Difficulty +{ + public class DifficultyAttributes + { + public readonly Mod[] Mods; + public readonly double StarRating; + + public DifficultyAttributes(Mod[] mods, double starRating) + { + Mods = mods; + StarRating = starRating; + } + } +} diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index a9bf5b1797..8f9651ab09 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -13,24 +13,44 @@ namespace osu.Game.Rulesets.Difficulty { public abstract class DifficultyCalculator { - protected readonly IBeatmap Beatmap; - protected readonly Mod[] Mods; + private readonly Ruleset ruleset; + private readonly WorkingBeatmap beatmap; - protected double TimeRate { get; private set; } = 1; - - protected DifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) + protected DifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) { - Beatmap = beatmap; - Mods = mods ?? new Mod[0]; - - ApplyMods(Mods); + this.ruleset = ruleset; + this.beatmap = beatmap; } - protected virtual void ApplyMods(Mod[] mods) + /// + /// Calculates the difficulty of the beatmap using a specific mod combination. + /// + /// The mods that should be applied to the beatmap. + /// A structure describing the difficulty of the beatmap. + public DifficultyAttributes Calculate(params Mod[] mods) { + beatmap.Mods.Value = mods; + IBeatmap playableBeatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo); + var clock = new StopwatchClock(); mods.OfType().ForEach(m => m.ApplyToClock(clock)); - TimeRate = clock.Rate; + + return Calculate(playableBeatmap, mods, clock.Rate); + } + + /// + /// Calculates the difficulty of the beatmap using all mod combinations applicable to the beatmap. + /// + /// A collection of structures describing the difficulty of the beatmap for each mod combination. + public IEnumerable CalculateAll() + { + foreach (var combination in CreateDifficultyAdjustmentModCombinations()) + { + if (combination is MultiMod multi) + yield return Calculate(multi.Mods); + else + yield return Calculate(combination); + } } /// @@ -71,6 +91,13 @@ namespace osu.Game.Rulesets.Difficulty /// protected virtual Mod[] DifficultyAdjustmentMods => Array.Empty(); - public abstract double Calculate(Dictionary categoryDifficulty = null); + /// + /// Calculates the difficulty of a using a specific combination. + /// + /// The to compute the difficulty for. + /// The s that should be applied. + /// The rate of time in . + /// A structure containing the difficulty attributes. + protected abstract DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate); } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index a39e8bb8d4..cdc1c44306 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets public virtual IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => null; - public abstract DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null); + public abstract DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap); public virtual PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => null; From 47fc18d7c48bc7e5b5f4dce262fc76ee28626372 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 15:36:49 +0900 Subject: [PATCH 117/199] Adjust OsuDifficultyCalculator in-line with changes --- .../Difficulty/OsuDifficultyAttributes.cs | 19 ++++++++++++ .../Difficulty/OsuDifficultyCalculator.cs | 30 +++++++------------ osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- 3 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs new file mode 100644 index 0000000000..5650bc395a --- /dev/null +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Difficulty +{ + public class OsuDifficultyAttributes : DifficultyAttributes + { + public double AimStrain { get; set; } + public double SpeedStrain { get; set; } + + public OsuDifficultyAttributes(Mod[] mods, double starRating) + : base(mods, starRating) + { + } + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 94d2afbf45..400afbc043 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -18,31 +18,26 @@ namespace osu.Game.Rulesets.Osu.Difficulty private const int section_length = 400; private const double difficulty_multiplier = 0.0675; - public OsuDifficultyCalculator(IBeatmap beatmap) - : base(beatmap) + public OsuDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } - public OsuDifficultyCalculator(IBeatmap beatmap, Mod[] mods) - : base(beatmap, mods) + protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) { - } - - public override double Calculate(Dictionary categoryDifficulty = null) - { - OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap((List)Beatmap.HitObjects, TimeRate); + OsuDifficultyBeatmap difficultyBeatmap = new OsuDifficultyBeatmap(beatmap.HitObjects.Cast().ToList(), timeRate); Skill[] skills = { new Aim(), new Speed() }; - double sectionLength = section_length * TimeRate; + double sectionLength = section_length * timeRate; // The first object doesn't generate a strain, so we begin with an incremented section end double currentSectionEnd = 2 * sectionLength; - foreach (OsuDifficultyHitObject h in beatmap) + foreach (OsuDifficultyHitObject h in difficultyBeatmap) { while (h.BaseObject.StartTime > currentSectionEnd) { @@ -61,16 +56,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; - double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; - if (categoryDifficulty != null) + return new OsuDifficultyAttributes(mods, starRating) { - categoryDifficulty.Add("Aim", aimRating); - categoryDifficulty.Add("Speed", speedRating); - } - - return starRating; + AimStrain = aimRating, + SpeedStrain = speedRating + }; } protected override Mod[] DifficultyAdjustmentMods => new Mod[] diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6ab75d008f..49468392f5 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o }; - public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods); + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap); public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); From 33c7ce1bec1a51a70b9a2da9629ef3182132bc32 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 15:47:42 +0900 Subject: [PATCH 118/199] Adjust TaikoDifficultyCalculator in-line with changes --- .../Difficulty/TaikoDifficultyCalculator.cs | 59 ++++++++----------- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index bb666eb528..473c205293 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -27,54 +27,33 @@ namespace osu.Game.Rulesets.Taiko.Difficulty /// private const double decay_weight = 0.9; - /// - /// HitObjects are stored as a member variable. - /// - private readonly List difficultyHitObjects = new List(); - - public TaikoDifficultyCalculator(IBeatmap beatmap) - : base(beatmap) + public TaikoDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } - public TaikoDifficultyCalculator(IBeatmap beatmap, Mod[] mods) - : base(beatmap, mods) + protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) { - } + var difficultyHitObjects = new List(); - public override double Calculate(Dictionary categoryDifficulty = null) - { - // Fill our custom DifficultyHitObject class, that carries additional information - difficultyHitObjects.Clear(); - - foreach (var hitObject in Beatmap.HitObjects) + foreach (var hitObject in beatmap.HitObjects) difficultyHitObjects.Add(new TaikoHitObjectDifficulty((TaikoHitObject)hitObject)); // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); - if (!calculateStrainValues()) return 0; + if (!calculateStrainValues(difficultyHitObjects, timeRate)) + return new DifficultyAttributes(mods, 0); - double starRating = calculateDifficulty() * star_scaling_factor; + double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - if (categoryDifficulty != null) - categoryDifficulty["Strain"] = starRating; - - return starRating; + return new DifficultyAttributes(mods, starRating); } - protected override Mod[] DifficultyAdjustmentMods => new Mod[] - { - new TaikoModDoubleTime(), - new TaikoModHalfTime(), - new TaikoModEasy(), - new TaikoModHardRock(), - }; - - private bool calculateStrainValues() + private bool calculateStrainValues(List objects, double timeRate) { // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - using (List.Enumerator hitObjectsEnumerator = difficultyHitObjects.GetEnumerator()) + using (var hitObjectsEnumerator = objects.GetEnumerator()) { if (!hitObjectsEnumerator.MoveNext()) return false; @@ -84,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty while (hitObjectsEnumerator.MoveNext()) { var next = hitObjectsEnumerator.Current; - next?.CalculateStrains(current, TimeRate); + next?.CalculateStrains(current, timeRate); current = next; } @@ -92,9 +71,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty } } - private double calculateDifficulty() + private double calculateDifficulty(List objects, double timeRate) { - double actualStrainStep = strain_step * TimeRate; + double actualStrainStep = strain_step * timeRate; // Find the highest strain value within each strain step List highestStrains = new List(); @@ -102,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval TaikoHitObjectDifficulty previousHitObject = null; - foreach (var hitObject in difficultyHitObjects) + foreach (var hitObject in objects) { // While we are beyond the current interval push the currently available maximum to our strain list while (hitObject.BaseHitObject.StartTime > intervalEndTime) @@ -144,5 +123,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty return difficulty; } + + protected override Mod[] DifficultyAdjustmentMods => new Mod[] + { + new TaikoModDoubleTime(), + new TaikoModHalfTime(), + new TaikoModEasy(), + new TaikoModHardRock(), + }; } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 225461fd6f..1b34ab68bd 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Taiko public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o }; - public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap, mods); + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap); public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new TaikoPerformanceCalculator(this, beatmap, score); From 6ff06d4757f4bb00f94bb7870235b4b18bd9b920 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 15:48:56 +0900 Subject: [PATCH 119/199] Adjust CatchDifficultyCalculator in-line with changes --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Difficulty/CatchDifficultyCalculator.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index d0180f1791..fc6e23c884 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Catch public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o }; - public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap); + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap); public override int? LegacyID => 2; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index f8351b7519..562374087e 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -1,18 +1,19 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchDifficultyCalculator : DifficultyCalculator { - public CatchDifficultyCalculator(IBeatmap beatmap) : base(beatmap) + public CatchDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } - public override double Calculate(Dictionary categoryDifficulty = null) => 0; + protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) => new DifficultyAttributes(mods, 0); } } From 966099fabc209b34f2ac2bcc7881b0639eb465f0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 15:54:05 +0900 Subject: [PATCH 120/199] Adjust ManiaDifficultyCalculator in-line with changes --- .../Difficulty/ManiaDifficultyCalculator.cs | 47 +++++++------------ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index ca2002b7c9..9c091ac31a 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -29,47 +29,33 @@ namespace osu.Game.Rulesets.Mania.Difficulty /// private const double decay_weight = 0.9; - /// - /// HitObjects are stored as a member variable. - /// - private readonly List difficultyHitObjects = new List(); - - public ManiaDifficultyCalculator(IBeatmap beatmap) - : base(beatmap) + public ManiaDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) { } - public ManiaDifficultyCalculator(IBeatmap beatmap, Mod[] mods) - : base(beatmap, mods) + protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) { - } + var difficultyHitObjects = new List(); - public override double Calculate(Dictionary categoryDifficulty = null) - { - // Fill our custom DifficultyHitObject class, that carries additional information - difficultyHitObjects.Clear(); - - int columnCount = (Beatmap as ManiaBeatmap)?.TotalColumns ?? 7; + int columnCount = ((ManiaBeatmap)beatmap).TotalColumns; // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. // Note: Stable sort is done so that the ordering of hitobjects with equal start times doesn't change - difficultyHitObjects.AddRange(Beatmap.HitObjects.Select(h => new ManiaHitObjectDifficulty((ManiaHitObject)h, columnCount)).OrderBy(h => h.BaseHitObject.StartTime)); + difficultyHitObjects.AddRange(beatmap.HitObjects.Select(h => new ManiaHitObjectDifficulty((ManiaHitObject)h, columnCount)).OrderBy(h => h.BaseHitObject.StartTime)); - if (!calculateStrainValues()) - return 0; + if (!calculateStrainValues(difficultyHitObjects, timeRate)) + return new DifficultyAttributes(mods, 0); - double starRating = calculateDifficulty() * star_scaling_factor; + double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - if (categoryDifficulty != null) - categoryDifficulty["Strain"] = starRating; - - return starRating; + return new DifficultyAttributes(mods, starRating); } - private bool calculateStrainValues() + private bool calculateStrainValues(List objects, double timeRate) { // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - using (List.Enumerator hitObjectsEnumerator = difficultyHitObjects.GetEnumerator()) + using (var hitObjectsEnumerator = objects.GetEnumerator()) { if (!hitObjectsEnumerator.MoveNext()) return false; @@ -80,7 +66,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty while (hitObjectsEnumerator.MoveNext()) { var next = hitObjectsEnumerator.Current; - next?.CalculateStrains(current, TimeRate); + next?.CalculateStrains(current, timeRate); current = next; } @@ -88,9 +74,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty } } - private double calculateDifficulty() + private double calculateDifficulty(List objects, double timeRate) { - double actualStrainStep = strain_step * TimeRate; + double actualStrainStep = strain_step * timeRate; // Find the highest strain value within each strain step List highestStrains = new List(); @@ -98,7 +84,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval ManiaHitObjectDifficulty previousHitObject = null; - foreach (var hitObject in difficultyHitObjects) + foreach (var hitObject in objects) { // While we are beyond the current interval push the currently available maximum to our strain list while (hitObject.BaseHitObject.StartTime > intervalEndTime) @@ -159,5 +145,6 @@ namespace osu.Game.Rulesets.Mania.Difficulty new ManiaModKey8(), new ManiaModKey9(), }; + } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index e671a3fb14..1b7a8f77b3 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -147,7 +147,7 @@ namespace osu.Game.Rulesets.Mania public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o }; - public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods); + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(this, beatmap); public override int? LegacyID => 3; From 540b43313eba0932a1be122c2469d586409b3d1c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 15:57:06 +0900 Subject: [PATCH 121/199] Remove PP test cases (osu-tools/osu-server should be used instead) --- .../TestCasePerformancePoints.cs | 16 - .../TestCasePerformancePoints.cs | 16 - .../TestCasePerformancePoints.cs | 16 - .../TestCasePerformancePoints.cs | 16 - .../Tests/Visual/TestCasePerformancePoints.cs | 403 ------------------ 5 files changed, 467 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch.Tests/TestCasePerformancePoints.cs delete mode 100644 osu.Game.Rulesets.Mania.Tests/TestCasePerformancePoints.cs delete mode 100644 osu.Game.Rulesets.Osu.Tests/TestCasePerformancePoints.cs delete mode 100644 osu.Game.Rulesets.Taiko.Tests/TestCasePerformancePoints.cs delete mode 100644 osu.Game/Tests/Visual/TestCasePerformancePoints.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Catch.Tests/TestCasePerformancePoints.cs deleted file mode 100644 index 9512cf2061..0000000000 --- a/osu.Game.Rulesets.Catch.Tests/TestCasePerformancePoints.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; - -namespace osu.Game.Rulesets.Catch.Tests -{ - [TestFixture] - public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints - { - public TestCasePerformancePoints() - : base(new CatchRuleset()) - { - } - } -} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Mania.Tests/TestCasePerformancePoints.cs deleted file mode 100644 index c15a6dd688..0000000000 --- a/osu.Game.Rulesets.Mania.Tests/TestCasePerformancePoints.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; - -namespace osu.Game.Rulesets.Mania.Tests -{ - [TestFixture] - public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints - { - public TestCasePerformancePoints() - : base(new ManiaRuleset()) - { - } - } -} diff --git a/osu.Game.Rulesets.Osu.Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Osu.Tests/TestCasePerformancePoints.cs deleted file mode 100644 index 63026fe316..0000000000 --- a/osu.Game.Rulesets.Osu.Tests/TestCasePerformancePoints.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; - -namespace osu.Game.Rulesets.Osu.Tests -{ - [TestFixture] - public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints - { - public TestCasePerformancePoints() - : base(new OsuRuleset()) - { - } - } -} diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Taiko.Tests/TestCasePerformancePoints.cs deleted file mode 100644 index 2fd9161d13..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests/TestCasePerformancePoints.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; - -namespace osu.Game.Rulesets.Taiko.Tests -{ - [TestFixture] - public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints - { - public TestCasePerformancePoints() - : base(new TaikoRuleset()) - { - } - } -} diff --git a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs deleted file mode 100644 index dfae8fbc1d..0000000000 --- a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using System.Linq; -using OpenTK; -using OpenTK.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Caching; -using osu.Framework.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Game.Beatmaps; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Tests.Visual -{ - public abstract class TestCasePerformancePoints : OsuTestCase - { - protected TestCasePerformancePoints(Ruleset ruleset) - { - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.5f, - }, - new ScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = new BeatmapList(ruleset, Beatmap) - } - } - }, - null, - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.5f, - }, - new ScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = new StarRatingGrid() - } - } - }, - null, - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.5f, - }, - new ScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = new PerformanceList() - } - } - }, - } - }, - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 20), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 20) - } - }; - } - - private class BeatmapList : CompositeDrawable - { - private readonly Container beatmapDisplays; - private readonly Ruleset ruleset; - private readonly BindableBeatmap beatmapBindable; - - public BeatmapList(Ruleset ruleset, BindableBeatmap beatmapBindable) - { - this.ruleset = ruleset; - this.beatmapBindable = beatmapBindable; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - InternalChild = beatmapDisplays = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 4) - }; - } - - [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps) - { - var sets = beatmaps.GetAllUsableBeatmapSets(); - var allBeatmaps = sets.SelectMany(s => s.Beatmaps).Where(b => ruleset.LegacyID == null || b.RulesetID == ruleset.LegacyID); - - allBeatmaps.ForEach(b => beatmapDisplays.Add(new BeatmapDisplay(b, beatmapBindable))); - } - - private class BeatmapDisplay : CompositeDrawable, IHasTooltip - { - private readonly OsuSpriteText text; - private readonly BeatmapInfo beatmap; - - private readonly BindableBeatmap beatmapBindable; - - private BeatmapManager beatmaps; - - private bool isSelected; - - public string TooltipText => text.Text; - - public BeatmapDisplay(BeatmapInfo beatmap, BindableBeatmap beatmapBindable) - { - this.beatmap = beatmap; - this.beatmapBindable = beatmapBindable; - - AutoSizeAxes = Axes.Both; - InternalChild = text = new OsuSpriteText(); - - this.beatmapBindable.ValueChanged += beatmapChanged; - } - - [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps) - { - this.beatmaps = beatmaps; - - var working = beatmaps.GetWorkingBeatmap(beatmap); - text.Text = $"{working.Metadata.Artist} - {working.Metadata.Title} ({working.Metadata.AuthorString}) [{working.BeatmapInfo.Version}]"; - } - - private void beatmapChanged(WorkingBeatmap newBeatmap) - { - if (isSelected) - this.FadeColour(Color4.White, 100); - isSelected = false; - } - - protected override bool OnClick(InputState state) - { - if (beatmapBindable.Value.BeatmapInfo.ID == beatmap.ID) - return false; - - beatmapBindable.Value = beatmaps.GetWorkingBeatmap(beatmap); - isSelected = true; - return true; - } - - protected override bool OnHover(InputState state) - { - if (isSelected) - return false; - this.FadeColour(Color4.Yellow, 100); - return true; - } - - protected override void OnHoverLost(InputState state) - { - if (isSelected) - return; - this.FadeColour(Color4.White, 100); - } - } - } - - private class PerformanceList : CompositeDrawable - { - private readonly FillFlowContainer scores; - private APIAccess api; - - private readonly IBindable currentBeatmap = new Bindable(); - - public PerformanceList() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - InternalChild = scores = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 4) - }; - } - - [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, APIAccess api) - { - this.api = api; - - if (!api.IsLoggedIn) - { - InternalChild = new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "Please sign in to see online scores", - }; - } - - currentBeatmap.ValueChanged += beatmapChanged; - currentBeatmap.BindTo(beatmap); - } - - private GetScoresRequest lastRequest; - private void beatmapChanged(WorkingBeatmap newBeatmap) - { - if (!IsAlive) return; - - lastRequest?.Cancel(); - scores.Clear(); - - if (!api.IsLoggedIn) - return; - - lastRequest = new GetScoresRequest(newBeatmap.BeatmapInfo, newBeatmap.BeatmapInfo.Ruleset); - lastRequest.Success += res => res.Scores.ForEach(s => scores.Add(new PerformanceDisplay(s, newBeatmap.Beatmap))); - api.Queue(lastRequest); - } - - private class PerformanceDisplay : CompositeDrawable - { - private readonly OsuSpriteText text; - - private readonly Score score; - private readonly IBeatmap beatmap; - - public PerformanceDisplay(Score score, IBeatmap beatmap) - { - this.score = score; - this.beatmap = beatmap; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - InternalChild = text = new OsuSpriteText(); - } - - [BackgroundDependencyLoader] - private void load() - { - var ruleset = beatmap.BeatmapInfo.Ruleset.CreateInstance(); - var calculator = ruleset.CreatePerformanceCalculator(beatmap, score); - if (calculator == null) - return; - - var attributes = new Dictionary(); - double performance = calculator.Calculate(attributes); - - text.Text = $"{score.User.Username} -> online: {score.PP:n2}pp | local: {performance:n2}pp"; - } - } - } - - private class StarRatingGrid : CompositeDrawable - { - private readonly FillFlowContainer modFlow; - private readonly OsuSpriteText totalText; - private readonly FillFlowContainer categoryTexts; - - public StarRatingGrid() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - InternalChild = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - modFlow = new FillFlowContainer - { - Name = "Checkbox flow", - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(4, 4) - }, - new FillFlowContainer - { - Name = "Information display", - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0, 4), - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - totalText = new OsuSpriteText { TextSize = 24 }, - categoryTexts = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical - } - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap) - { - beatmap.ValueChanged += beatmapChanged; - } - - private Cached informationCache = new Cached(); - - private Ruleset ruleset; - private WorkingBeatmap beatmap; - - private void beatmapChanged(WorkingBeatmap newBeatmap) - { - beatmap = newBeatmap; - - modFlow.Clear(); - - ruleset = newBeatmap.BeatmapInfo.Ruleset.CreateInstance(); - foreach (var mod in ruleset.GetAllMods()) - { - var checkBox = new OsuCheckbox - { - RelativeSizeAxes = Axes.None, - Width = 50, - LabelText = mod.ShortenedName - }; - - checkBox.Current.ValueChanged += v => informationCache.Invalidate(); - modFlow.Add(checkBox); - } - - informationCache.Invalidate(); - } - - protected override void Update() - { - base.Update(); - - if (ruleset == null) - return; - - if (!informationCache.IsValid) - { - totalText.Text = string.Empty; - categoryTexts.Clear(); - - var allMods = ruleset.GetAllMods().ToList(); - Mod[] activeMods = modFlow.Where(c => c.Current.Value).Select(c => allMods.First(m => m.ShortenedName == c.LabelText)).ToArray(); - - var diffCalc = ruleset.CreateDifficultyCalculator(beatmap.Beatmap, activeMods); - if (diffCalc != null) - { - var categories = new Dictionary(); - double totalSr = diffCalc.Calculate(categories); - - totalText.Text = $"Star rating: {totalSr:n2}"; - foreach (var kvp in categories) - categoryTexts.Add(new OsuSpriteText { Text = $"{kvp.Key}: {kvp.Value:n2}" }); - } - - informationCache.Validate(); - } - } - } - } -} From 8f7334874ca3ff149c6e2cc10f0e0cd667f8c40e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:04:48 +0900 Subject: [PATCH 122/199] Fix up performance calculators --- .../Difficulty/ManiaPerformanceCalculator.cs | 4 ++-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Difficulty/OsuPerformanceCalculator.cs | 8 +++++--- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Difficulty/TaikoPerformanceCalculator.cs | 6 +++--- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- .../DifficultyAdjustmentModCombinationsTest.cs | 8 ++++---- osu.Game/Beatmaps/BeatmapManager.cs | 3 +-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- .../Rulesets/Difficulty/PerformanceCalculator.cs | 12 ++++++------ osu.Game/Rulesets/Ruleset.cs | 2 +- 11 files changed, 26 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 93652f7610..b6089b830b 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty private int countMeh; private int countMiss; - public ManiaPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) + public ManiaPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) : base(ruleset, beatmap, score) { } @@ -82,7 +82,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeStrainValue() { // Obtain strain difficulty - double strainValue = Math.Pow(5 * Math.Max(1, Attributes["Strain"] / 0.2) - 4.0, 2.2) / 135.0; + double strainValue = Math.Pow(5 * Math.Max(1, Attributes.StarRating / 0.2) - 4.0, 2.2) / 135.0; // Longer maps are worth more strainValue *= 1.0 + 0.1 * Math.Min(1.0, totalHits / 1500.0); diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 1b7a8f77b3..ac5fbfdde0 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new ManiaPerformanceCalculator(this, beatmap, score); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new ManiaPerformanceCalculator(this, beatmap, score); public override IEnumerable ConvertLegacyMods(LegacyMods mods) { diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 57cf962fa7..3ab3cc879a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -15,6 +15,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty { public class OsuPerformanceCalculator : PerformanceCalculator { + public new OsuDifficultyAttributes Attributes => (OsuDifficultyAttributes)base.Attributes; + private readonly int countHitCircles; private readonly int beatmapMaxCombo; @@ -37,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty private int countMeh; private int countMiss; - public OsuPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) + public OsuPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) : base(ruleset, beatmap, score) { countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); @@ -102,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty private double computeAimValue() { - double aimValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes["Aim"] / 0.0675f) - 4.0f, 3.0f) / 100000.0f; + double aimValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes.AimStrain / 0.0675f) - 4.0f, 3.0f) / 100000.0f; // Longer maps are worth more double lengthBonus = 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + @@ -151,7 +153,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty private double computeSpeedValue() { - double speedValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes["Speed"] / 0.0675f) - 4.0f, 3.0f) / 100000.0f; + double speedValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes.SpeedStrain / 0.0675f) - 4.0f, 3.0f) / 100000.0f; // Longer maps are worth more speedValue *= 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 49468392f5..ce80537b93 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Osu public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this); diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 6b1a25d667..53cfb4fd0f 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -22,10 +22,10 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private int countMeh; private int countMiss; - public TaikoPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) + public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) : base(ruleset, beatmap, score) { - beatmapMaxCombo = beatmap.HitObjects.Count(h => h is Hit); + beatmapMaxCombo = Beatmap.HitObjects.Count(h => h is Hit); } public override double Calculate(Dictionary categoryDifficulty = null) @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private double computeStrainValue() { - double strainValue = Math.Pow(5.0 * Math.Max(1.0, Attributes["Strain"] / 0.0075) - 4.0, 2.0) / 100000.0; + double strainValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0075) - 4.0, 2.0) / 100000.0; // Longer maps are worth more double lengthBonus = 1 + 0.1f * Math.Min(1.0, totalHits / 1500.0); diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 1b34ab68bd..7b4978694b 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Taiko public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap); - public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new TaikoPerformanceCalculator(this, beatmap, score); + public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new TaikoPerformanceCalculator(this, beatmap, score); public override int? LegacyID => 1; diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index fd697ba3d3..49494b65b9 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -2,8 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using NUnit.Framework; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -139,14 +139,14 @@ namespace osu.Game.Tests.NonVisual private class TestDifficultyCalculator : DifficultyCalculator { public TestDifficultyCalculator(params Mod[] mods) - : base(null) + : base(null, null) { DifficultyAdjustmentMods = mods; } - public override double Calculate(Dictionary categoryDifficulty = null) => throw new NotImplementedException(); - protected override Mod[] DifficultyAdjustmentMods { get; } + + protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) => throw new NotImplementedException(); } } } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 895b47d62b..5e3b66646b 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -366,8 +366,7 @@ namespace osu.Game.Beatmaps if (ruleset != null) { // TODO: this should be done in a better place once we actually need to dynamically update it. - var converted = new DummyConversionBeatmap(beatmap).GetPlayableBeatmap(ruleset); - beatmap.BeatmapInfo.StarDifficulty = ruleset.CreateInstance().CreateDifficultyCalculator(converted).Calculate(); + beatmap.BeatmapInfo.StarDifficulty = ruleset.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating; } else beatmap.BeatmapInfo.StarDifficulty = 0; diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index ee1fc6aec3..265c6832b2 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -62,7 +62,7 @@ namespace osu.Game.Beatmaps public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new DummyBeatmapConverter { Beatmap = beatmap }; - public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => null; + public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => null; public override string Description => "dummy"; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 07d9c80061..ba783ee87b 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -13,8 +13,7 @@ namespace osu.Game.Rulesets.Difficulty { public abstract class PerformanceCalculator { - private readonly Dictionary attributes = new Dictionary(); - protected IDictionary Attributes => attributes; + protected readonly DifficultyAttributes Attributes; protected readonly Ruleset Ruleset; protected readonly IBeatmap Beatmap; @@ -22,14 +21,15 @@ namespace osu.Game.Rulesets.Difficulty protected double TimeRate { get; private set; } = 1; - protected PerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score) + protected PerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) { Ruleset = ruleset; - Beatmap = beatmap; Score = score; - var diffCalc = ruleset.CreateDifficultyCalculator(beatmap, score.Mods); - diffCalc.Calculate(attributes); + beatmap.Mods.Value = score.Mods; + Beatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo); + + Attributes = ruleset.CreateDifficultyCalculator(beatmap).Calculate(score.Mods); ApplyMods(score.Mods); } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index cdc1c44306..f818523a3d 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets public abstract DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap); - public virtual PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => null; + public virtual PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => null; public virtual HitObjectComposer CreateHitObjectComposer() => null; From af218b3d8dd16b6ae9762c122b6fcd757ec44d8f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:13:21 +0900 Subject: [PATCH 123/199] No need to use properties --- osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index 5650bc395a..50a259ae55 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -8,8 +8,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty { public class OsuDifficultyAttributes : DifficultyAttributes { - public double AimStrain { get; set; } - public double SpeedStrain { get; set; } + public double AimStrain; + public double SpeedStrain; public OsuDifficultyAttributes(Mod[] mods, double starRating) : base(mods, starRating) From 22add2abc5a443ee63fc711a27af2e7dc60c8313 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:25:44 +0900 Subject: [PATCH 124/199] Move mania difficulty attributes to ManiaDifficultyCalculator --- .../Difficulty/ManiaDifficultyAttributes.cs | 18 ++++++++++++++++++ .../Difficulty/ManiaDifficultyCalculator.cs | 7 ++++++- .../Difficulty/ManiaPerformanceCalculator.cs | 8 ++++---- 3 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs new file mode 100644 index 0000000000..c7f6890b93 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Difficulty +{ + public class ManiaDifficultyAttributes : DifficultyAttributes + { + public double GreatHitWindow; + + public ManiaDifficultyAttributes(Mod[] mods, double starRating) + : base(mods, starRating) + { + } + } +} diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 9c091ac31a..525426df2d 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -47,9 +47,14 @@ namespace osu.Game.Rulesets.Mania.Difficulty if (!calculateStrainValues(difficultyHitObjects, timeRate)) return new DifficultyAttributes(mods, 0); + double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - return new DifficultyAttributes(mods, starRating); + return new ManiaDifficultyAttributes(mods, starRating) + { + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate + }; } private bool calculateStrainValues(List objects, double timeRate) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index b6089b830b..1f26bda1b2 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -13,6 +13,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty { public class ManiaPerformanceCalculator : PerformanceCalculator { + protected new ManiaDifficultyAttributes Attributes => (ManiaDifficultyAttributes)base.Attributes; + private Mod[] mods; // Score after being scaled by non-difficulty-increasing mods @@ -105,14 +107,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty private double computeAccuracyValue(double strainValue) { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; - if (hitWindowGreat <= 0) + if (Attributes.GreatHitWindow <= 0) return 0; // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Max(0.0, 0.2 - (hitWindowGreat - 34) * 0.006667) + double accuracyValue = Math.Max(0.0, 0.2 - (Attributes.GreatHitWindow - 34) * 0.006667) * strainValue * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); From 01dd2d79198202216c439f5827cf436957bbf1a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:26:51 +0900 Subject: [PATCH 125/199] Move taiko difficulty attributes to TaikoDifficultyCalculator --- .../Difficulty/TaikoDifficultyAttributes.cs | 19 +++++++++++++++++++ .../Difficulty/TaikoDifficultyCalculator.cs | 8 +++++++- .../Difficulty/TaikoPerformanceCalculator.cs | 14 +++++--------- 3 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs new file mode 100644 index 0000000000..d18d03b1db --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Difficulty +{ + public class TaikoDifficultyAttributes : DifficultyAttributes + { + public double GreatHitWindow; + public int MaxCombo; + + public TaikoDifficultyAttributes(Mod[] mods, double starRating) + : base(mods, starRating) + { + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 473c205293..190717e024 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -47,7 +48,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - return new DifficultyAttributes(mods, starRating); + return new TaikoDifficultyAttributes(mods, starRating) + { + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate, + MaxCombo = beatmap.HitObjects.Count(h => h is Hit) + }; } private bool calculateStrainValues(List objects, double timeRate) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 53cfb4fd0f..f530b6725c 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -8,13 +8,12 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Difficulty { public class TaikoPerformanceCalculator : PerformanceCalculator { - private readonly int beatmapMaxCombo; + protected new TaikoDifficultyAttributes Attributes => (TaikoDifficultyAttributes)base.Attributes; private Mod[] mods; private int countGreat; @@ -25,7 +24,6 @@ namespace osu.Game.Rulesets.Taiko.Difficulty public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) : base(ruleset, beatmap, score) { - beatmapMaxCombo = Beatmap.HitObjects.Count(h => h is Hit); } public override double Calculate(Dictionary categoryDifficulty = null) @@ -78,8 +76,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty strainValue *= Math.Pow(0.985, countMiss); // Combo scaling - if (beatmapMaxCombo > 0) - strainValue *= Math.Min(Math.Pow(Score.MaxCombo, 0.5) / Math.Pow(beatmapMaxCombo, 0.5), 1.0); + if (Attributes.MaxCombo > 0) + strainValue *= Math.Min(Math.Pow(Score.MaxCombo, 0.5) / Math.Pow(Attributes.MaxCombo, 0.5), 1.0); if (mods.Any(m => m is ModHidden)) strainValue *= 1.025; @@ -94,14 +92,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private double computeAccuracyValue() { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; - if (hitWindowGreat <= 0) + if (Attributes.GreatHitWindow <= 0) return 0; // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accValue = Math.Pow(150.0 / hitWindowGreat, 1.1) * Math.Pow(Score.Accuracy, 15) * 22.0; + double accValue = Math.Pow(150.0 / Attributes.GreatHitWindow, 1.1) * Math.Pow(Score.Accuracy, 15) * 22.0; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer return accValue * Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); From 41abd5990cc9adcf6e3865b7149fcf9b7f1747a9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 16:27:05 +0900 Subject: [PATCH 126/199] Move osu! difficulty attributes to OsuDifficultyCalculator --- .../Difficulty/OsuDifficultyAttributes.cs | 3 ++ .../Difficulty/OsuDifficultyCalculator.cs | 13 ++++++- .../Difficulty/OsuPerformanceCalculator.cs | 39 ++++++------------- 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index 50a259ae55..2b42eed0c5 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -10,6 +10,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty { public double AimStrain; public double SpeedStrain; + public double ApproachRate; + public double OverallDifficulty; + public int MaxCombo; public OsuDifficultyAttributes(Mod[] mods, double starRating) : base(mods, starRating) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 400afbc043..4386004e30 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -58,10 +58,21 @@ namespace osu.Game.Rulesets.Osu.Difficulty double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; + // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future + double hitWindowGreat = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate; + double preEmpt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / timeRate; + + int maxCombo = beatmap.HitObjects.Count(); + // Add the ticks + tail of the slider. 1 is subtracted because the "headcircle" would be counted twice (once for the slider itself in the line above) + maxCombo += beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count - 1); + return new OsuDifficultyAttributes(mods, starRating) { AimStrain = aimRating, - SpeedStrain = speedRating + SpeedStrain = speedRating, + ApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5, + OverallDifficulty = (80 - hitWindowGreat) / 6, + MaxCombo = maxCombo }; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 3ab3cc879a..d4a60dd52f 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -22,16 +22,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty private Mod[] mods; - /// - /// Approach rate adjusted by mods. - /// - private double realApproachRate; - - /// - /// Overall difficulty adjusted by mods. - /// - private double realOverallDifficulty; - private double accuracy; private int scoreMaxCombo; private int countGreat; @@ -63,13 +53,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(m => !m.Ranked)) return 0; - // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate; - double preEmpt = (int)BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate; - - realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5; - realOverallDifficulty = (80 - hitWindowGreat) / 6; - // Custom multipliers for NoFail and SpunOut. double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things @@ -94,8 +77,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty categoryRatings.Add("Aim", aimValue); categoryRatings.Add("Speed", speedValue); categoryRatings.Add("Accuracy", accuracyValue); - categoryRatings.Add("OD", realOverallDifficulty); - categoryRatings.Add("AR", realApproachRate); + categoryRatings.Add("OD", Attributes.OverallDifficulty); + categoryRatings.Add("AR", Attributes.ApproachRate); categoryRatings.Add("Max Combo", beatmapMaxCombo); } @@ -120,22 +103,22 @@ namespace osu.Game.Rulesets.Osu.Difficulty aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); double approachRateFactor = 1.0f; - if (realApproachRate > 10.33f) - approachRateFactor += 0.45f * (realApproachRate - 10.33f); - else if (realApproachRate < 8.0f) + if (Attributes.ApproachRate > 10.33f) + approachRateFactor += 0.45f * (Attributes.ApproachRate - 10.33f); + else if (Attributes.ApproachRate < 8.0f) { // HD is worth more with lower ar! if (mods.Any(h => h is OsuModHidden)) - approachRateFactor += 0.02f * (8.0f - realApproachRate); + approachRateFactor += 0.02f * (8.0f - Attributes.ApproachRate); else - approachRateFactor += 0.01f * (8.0f - realApproachRate); + approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate); } aimValue *= approachRateFactor; // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) - aimValue *= 1.02 + (11.0f - realApproachRate) / 50.0; // Gives a 1.04 bonus for AR10, a 1.06 bonus for AR9, a 1.02 bonus for AR11. + aimValue *= 1.02 + (11.0f - Attributes.ApproachRate) / 50.0; // Gives a 1.04 bonus for AR10, a 1.06 bonus for AR9, a 1.02 bonus for AR11. if (mods.Any(h => h is OsuModFlashlight)) { @@ -146,7 +129,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Scale the aim value with accuracy _slightly_ aimValue *= 0.5f + accuracy / 2.0f; // It is important to also consider accuracy difficulty when doing that - aimValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500; + aimValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; return aimValue; } @@ -172,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Scale the speed value with accuracy _slightly_ speedValue *= 0.5f + accuracy / 2.0f; // It is important to also consider accuracy difficulty when doing that - speedValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500; + speedValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; return speedValue; } @@ -194,7 +177,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Pow(1.52163f, realOverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; + double accuracyValue = Math.Pow(1.52163f, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f)); From 08b9cf75e964fd3665d3aa67ccb8e4ceff5b7e6b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 17:04:31 +0900 Subject: [PATCH 127/199] Don't compute keymod difficulties for mania-specific beatmaps These don't affect the number of keys in the beatmap at all for mania-specific beatmaps. --- .../Difficulty/ManiaDifficultyCalculator.cs | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 9c091ac31a..520b9c1152 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -29,9 +29,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty /// private const double decay_weight = 0.9; + private readonly bool isForCurrentRuleset; + public ManiaDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { + isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo); } protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) @@ -129,22 +132,38 @@ namespace osu.Game.Rulesets.Mania.Difficulty return difficulty; } - protected override Mod[] DifficultyAdjustmentMods => new Mod[] + protected override Mod[] DifficultyAdjustmentMods { - new ManiaModDoubleTime(), - new ManiaModHalfTime(), - new ManiaModEasy(), - new ManiaModHardRock(), - new ManiaModKey1(), - new ManiaModKey2(), - new ManiaModKey3(), - new ManiaModKey4(), - new ManiaModKey5(), - new ManiaModKey6(), - new ManiaModKey7(), - new ManiaModKey8(), - new ManiaModKey9(), - }; + get + { + if (isForCurrentRuleset) + { + return new Mod[] + { + new ManiaModDoubleTime(), + new ManiaModHalfTime(), + new ManiaModEasy(), + new ManiaModHardRock(), + }; + } + return new Mod[] + { + new ManiaModDoubleTime(), + new ManiaModHalfTime(), + new ManiaModEasy(), + new ManiaModHardRock(), + new ManiaModKey1(), + new ManiaModKey2(), + new ManiaModKey3(), + new ManiaModKey4(), + new ManiaModKey5(), + new ManiaModKey6(), + new ManiaModKey7(), + new ManiaModKey8(), + new ManiaModKey9(), + }; + } + } } } From b25a6a33ccdde95af2a05739661b211cf0d7a3fd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 19:37:21 +0900 Subject: [PATCH 128/199] Fix 1K breaking hitcircle / slider conversions --- .../Patterns/Legacy/DistanceObjectPatternGenerator.cs | 7 +++++++ .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index afa9bdbbd7..f60958d581 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -58,6 +58,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy public override Pattern Generate() { + if (TotalColumns == 1) + { + var pattern = new Pattern(); + addToPattern(pattern, 0, HitObject.StartTime, endTime); + return pattern; + } + if (spanCount > 1) { if (segmentDuration <= 90) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index cec3e18ad6..c72005e3ad 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -81,6 +81,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy public override Pattern Generate() { + if (TotalColumns == 1) + { + var pattern = new Pattern(); + addToPattern(pattern, 0); + return pattern; + } + int lastColumn = PreviousPattern.HitObjects.FirstOrDefault()?.Column ?? 0; if ((convertType & PatternType.Reverse) > 0 && PreviousPattern.HitObjects.Any()) From a3bf16e481bc5489ba809ef97e6326c565b0fc97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 19:37:32 +0900 Subject: [PATCH 129/199] Fix missing convert type --- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index c72005e3ad..339a1b4e77 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -77,6 +77,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } else convertType |= PatternType.LowProbability; + + if ((convertType & PatternType.KeepSingle) == 0) + { + if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && TotalColumns != 8) + convertType |= PatternType.Mirror; + else + convertType |= PatternType.Gathered; + } } public override Pattern Generate() From fd84afb89bfa052f9a13139721d74b8932fe1c0e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 Jun 2018 19:38:48 +0900 Subject: [PATCH 130/199] Fix non-inverted calculation --- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 339a1b4e77..b4160dc98b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -361,7 +361,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy addToCentre = false; if ((convertType & PatternType.ForceNotStack) > 0) - return getRandomNoteCount(p2 / 2, p2, (p2 + p3) / 2, p3); + return getRandomNoteCount(1 / 2f + p2 / 2, p2, (p2 + p3) / 2, p3); switch (TotalColumns) { From 4a19f22b3d798201734ac71859204cddb815fc37 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jun 2018 13:38:42 +0900 Subject: [PATCH 131/199] Remove custom migration exception This was hiding the true error message from ever hitting logs. Made to help disagnose #2711. --- osu.Game/Database/OsuDbContext.cs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 4b0de57c4c..bf57644caf 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -181,24 +181,6 @@ namespace osu.Game.Database } } - public void Migrate() - { - try - { - Database.Migrate(); - } - catch (Exception e) - { - throw new MigrationFailedException(e); - } - } - } - - public class MigrationFailedException : Exception - { - public MigrationFailedException(Exception exception) - : base("sqlite-net migration failed", exception) - { - } + public void Migrate() => Database.Migrate(); } } From 149d94116bef6b2cbe96aba8901922fb2de7c53c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jun 2018 15:44:47 +0900 Subject: [PATCH 132/199] Fix droplets not bouncing off catcher's plate immediately --- .../Drawable/DrawableCatchHitObject.cs | 2 + .../Objects/Drawable/DrawableDroplet.cs | 2 + osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 63 +++++++++++-------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 3dbda708e5..e3564b5967 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -42,6 +42,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { public virtual bool CanBePlated => false; + public virtual bool StaysOnPlate => CanBePlated; + protected DrawableCatchHitObject(CatchHitObject hitObject) : base(hitObject) { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index a19d67ebbe..5c8a7c4a7c 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -13,6 +13,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { private Pulp pulp; + public override bool StaysOnPlate => false; + public DrawableDroplet(Droplet h) : base(h) { diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index d8c7b5130d..b62e9997d4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -48,6 +48,16 @@ namespace osu.Game.Rulesets.Catch.UI public void OnJudgement(DrawableCatchHitObject fruit, Judgement judgement) { + void runAfterLoaded(Action action) + { + // this is required to make this run after the last caught fruit runs UpdateState at least once. + // TODO: find a better alternative + if (lastPlateableFruit.IsLoaded) + action(); + else + lastPlateableFruit.OnLoadComplete = _ => action(); + } + if (judgement.IsHit && fruit.CanBePlated) { var caughtFruit = (DrawableCatchHitObject)GetVisualRepresentation?.Invoke(fruit.HitObject); @@ -63,21 +73,17 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruit.LifetimeEnd = double.MaxValue; MovableCatcher.Add(caughtFruit); - lastPlateableFruit = caughtFruit; + + if (!fruit.StaysOnPlate) + runAfterLoaded(() => MovableCatcher.Explode(caughtFruit)); + } if (fruit.HitObject.LastInCombo) { if (judgement.IsHit) - { - // this is required to make this run after the last caught fruit runs UpdateState at least once. - // TODO: find a better alternative - if (lastPlateableFruit.IsLoaded) - MovableCatcher.Explode(); - else - lastPlateableFruit.OnLoadComplete = _ => { MovableCatcher.Explode(); }; - } + runAfterLoaded(() => MovableCatcher.Explode()); else MovableCatcher.Drop(); } @@ -378,28 +384,31 @@ namespace osu.Game.Rulesets.Catch.UI var fruit = caughtFruit.ToArray(); foreach (var f in fruit) + Explode(f); + } + + public void Explode(DrawableHitObject fruit) + { + var originalX = fruit.X * Scale.X; + + if (ExplodingFruitTarget != null) { - var originalX = f.X * Scale.X; + fruit.Anchor = Anchor.TopLeft; + fruit.Position = caughtFruit.ToSpaceOfOtherDrawable(fruit.DrawPosition, ExplodingFruitTarget); - if (ExplodingFruitTarget != null) - { - f.Anchor = Anchor.TopLeft; - f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget); + caughtFruit.Remove(fruit); - caughtFruit.Remove(f); - - ExplodingFruitTarget.Add(f); - } - - f.MoveToY(f.Y - 50, 250, Easing.OutSine) - .Then() - .MoveToY(f.Y + 50, 500, Easing.InSine); - - f.MoveToX(f.X + originalX * 6, 1000); - f.FadeOut(750); - - f.Expire(); + ExplodingFruitTarget.Add(fruit); } + + fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine) + .Then() + .MoveToY(fruit.Y + 50, 500, Easing.InSine); + + fruit.MoveToX(fruit.X + originalX * 6, 1000); + fruit.FadeOut(750); + + fruit.Expire(); } private class CatcherSprite : Sprite From 1c27ef644a53340f8d3883128789ae71bbc6cb8a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jun 2018 16:12:11 +0900 Subject: [PATCH 133/199] Fix music controller drag activating from anywhere on the screen --- osu.Game/Overlays/MusicController.cs | 61 +++++++++++++++------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index d96bb40165..a57d5fd183 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -66,34 +66,6 @@ namespace osu.Game.Overlays AlwaysPresent = true; } - private Vector2 dragStart; - - protected override bool OnDragStart(InputState state) - { - base.OnDragStart(state); - dragStart = state.Mouse.Position; - return true; - } - - protected override bool OnDrag(InputState state) - { - if (base.OnDrag(state)) return true; - - Vector2 change = state.Mouse.Position - dragStart; - - // Diminish the drag distance as we go further to simulate "rubber band" feeling. - change *= change.Length <= 0 ? 0 : (float)Math.Pow(change.Length, 0.7f) / change.Length; - - dragContainer.MoveTo(change); - return true; - } - - protected override bool OnDragEnd(InputState state) - { - dragContainer.MoveTo(Vector2.Zero, 800, Easing.OutElastic); - return base.OnDragEnd(state); - } - [BackgroundDependencyLoader] private void load(BindableBeatmap beatmap, BeatmapManager beatmaps, OsuColour colours, LocalisationEngine localisation) { @@ -103,7 +75,7 @@ namespace osu.Game.Overlays Children = new Drawable[] { - dragContainer = new Container + dragContainer = new DragContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -470,5 +442,36 @@ namespace osu.Game.Overlays sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4"); } } + + private class DragContainer : Container + { + private Vector2 dragStart; + + protected override bool OnDragStart(InputState state) + { + base.OnDragStart(state); + dragStart = state.Mouse.Position; + return true; + } + + protected override bool OnDrag(InputState state) + { + if (base.OnDrag(state)) return true; + + Vector2 change = state.Mouse.Position - dragStart; + + // Diminish the drag distance as we go further to simulate "rubber band" feeling. + change *= change.Length <= 0 ? 0 : (float)Math.Pow(change.Length, 0.7f) / change.Length; + + this.MoveTo(change); + return true; + } + + protected override bool OnDragEnd(InputState state) + { + this.MoveTo(Vector2.Zero, 800, Easing.OutElastic); + return base.OnDragEnd(state); + } + } } } From a2950b1d80d6efeece366c6be4b807a88d434dc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jun 2018 16:12:18 +0900 Subject: [PATCH 134/199] Fix incorrect comment --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 0186a170c9..062f8d27aa 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.Containers /// /// Whether mouse input should be blocked screen-wide while this overlay is visible. - /// Performing mouse actions outside of the valid extents will hide the overlay but pass the events through. + /// Performing mouse actions outside of the valid extents will hide the overlay and block the input. /// public virtual bool BlockScreenWideMouse => BlockPassThroughMouse; From aaf3ef240e4e40a49768bf051ed8157ad1e5894e Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Fri, 15 Jun 2018 17:07:07 +0900 Subject: [PATCH 135/199] Remove easily-confused comment --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 062f8d27aa..0528f7b3ae 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.Containers /// /// Whether mouse input should be blocked screen-wide while this overlay is visible. - /// Performing mouse actions outside of the valid extents will hide the overlay and block the input. + /// Performing mouse actions outside of the valid extents will hide the overlay. /// public virtual bool BlockScreenWideMouse => BlockPassThroughMouse; From 5d105cd08d036d78009733546c80711c1503e592 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jun 2018 17:15:04 +0900 Subject: [PATCH 136/199] 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 4eda017fa55824d12e9eac8c52894cea8e9c32ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 17 Jun 2018 17:54:05 +0900 Subject: [PATCH 137/199] Fix CI error --- osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 8f90b6d87e..9b48ec17bd 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -114,7 +114,7 @@ namespace osu.Game.Tests.Visual private class TestPlayfield : ScrollingPlayfield { - public readonly ScrollingDirection Direction; + public new readonly ScrollingDirection Direction; public TestPlayfield(ScrollingDirection direction) : base(direction) From 457531910294897c15cdfbc5337672d138c0ef1d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 17 Jun 2018 17:56:46 +0900 Subject: [PATCH 138/199] Privatise the proxied content --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 17 +++++++++++------ osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index c07ee3a0fd..e712d62a26 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public abstract class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler { protected readonly Container Content; - public readonly Container ProxiedContent; + private readonly Container proxiedContent; private readonly Container nonProxiedContent; @@ -31,12 +31,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Both, Child = Content = new Container { RelativeSizeAxes = Axes.Both } }, - ProxiedContent = new Container { RelativeSizeAxes = Axes.Both } + proxiedContent = new Container { RelativeSizeAxes = Axes.Both } }; } /// - /// is proxied into an upper layer. We don't want to get masked away otherwise would too. + /// is proxied into an upper layer. We don't want to get masked away otherwise would too. /// protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; @@ -46,8 +46,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected void ProxyContent() { nonProxiedContent.Remove(Content); - ProxiedContent.Remove(Content); - ProxiedContent.Add(Content); + proxiedContent.Remove(Content); + proxiedContent.Add(Content); } /// @@ -55,11 +55,16 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// protected void UnproxyContent() { - ProxiedContent.Remove(Content); + proxiedContent.Remove(Content); nonProxiedContent.Remove(Content); nonProxiedContent.Add(Content); } + /// + /// Creates a proxy for the content of this . + /// + public Drawable CreateProxiedContent() => proxiedContent.CreateProxy(); + public abstract bool OnPressed(TaikoAction action); public virtual bool OnReleased(TaikoAction action) => false; } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index c638f807fe..7fdd3cd1e2 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -218,7 +218,7 @@ namespace osu.Game.Rulesets.Taiko.UI var taikoObject = h as DrawableTaikoHitObject; if (taikoObject != null) - topLevelHitContainer.Add(taikoObject.ProxiedContent.CreateProxy()); + topLevelHitContainer.Add(taikoObject.CreateProxiedContent()); } internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) From 0a99d21938a252071189eab06d40f909d098e138 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 17 Jun 2018 18:01:28 +0900 Subject: [PATCH 139/199] Use the passed-in ruleset --- osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 520b9c1152..5d5adb8e66 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty public ManiaDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { - isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo); + isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); } protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) From 6c100caba763b333cd099e37033c70e02cac224b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 15:09:03 +0900 Subject: [PATCH 140/199] Use existing instance of beatmap rather than adding more resources --- .../Beatmaps/IO/ImportBeatmapTest.cs | 4 +- osu.Game.Tests/Visual/TestCaseWaveform.cs | 16 +----- osu.Game.Tests/WaveformTestBeatmap.cs | 55 +++++++++++++++++++ 3 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 osu.Game.Tests/WaveformTestBeatmap.cs diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 1c9696901c..616ba132fd 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Beatmaps.IO [TestFixture] public class ImportBeatmapTest { - private const string osz_path = @"../../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz"; + public const string TEST_OSZ_PATH = @"../../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz"; [Test] public void TestImportWhenClosed() @@ -265,7 +265,7 @@ namespace osu.Game.Tests.Beatmaps.IO private string createTemporaryBeatmap() { var temp = Path.GetTempFileName() + ".osz"; - File.Copy(osz_path, temp, true); + File.Copy(TEST_OSZ_PATH, temp, true); Assert.IsTrue(File.Exists(temp)); return temp; } diff --git a/osu.Game.Tests/Visual/TestCaseWaveform.cs b/osu.Game.Tests/Visual/TestCaseWaveform.cs index 983b98016e..46d46863ad 100644 --- a/osu.Game.Tests/Visual/TestCaseWaveform.cs +++ b/osu.Game.Tests/Visual/TestCaseWaveform.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays; namespace osu.Game.Tests.Visual { @@ -20,22 +19,14 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { + Beatmap.Value = new WaveformTestBeatmap(); + FillFlowContainer flow; Child = flow = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Spacing = new Vector2(0, 10), - Children = new Drawable[] - { - new MusicController - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Y = 100, - State = Visibility.Visible - }, - } }; for (int i = 1; i <= 16; i *= 2) @@ -44,10 +35,9 @@ namespace osu.Game.Tests.Visual { RelativeSizeAxes = Axes.Both, Resolution = 1f / i, + Waveform = Beatmap.Value.Waveform, }; - Beatmap.ValueChanged += b => newDisplay.Waveform = b.Waveform; - flow.Add(new Container { RelativeSizeAxes = Axes.X, diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs new file mode 100644 index 0000000000..17aa7db14d --- /dev/null +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.IO; +using System.Linq; +using osu.Framework.Audio.Track; +using osu.Framework.Graphics.Textures; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; +using osu.Game.IO.Archives; +using osu.Game.Tests.Beatmaps.IO; + +namespace osu.Game.Tests +{ + /// + /// A that is used for testcases that include waveforms. + /// + public class WaveformTestBeatmap : WorkingBeatmap + { + private readonly ZipArchiveReader reader; + private readonly FileStream stream; + + public WaveformTestBeatmap() + : base(new BeatmapInfo()) + { + stream = File.OpenRead(ImportBeatmapTest.TEST_OSZ_PATH); + reader = new ZipArchiveReader(stream); + } + + public override void Dispose() + { + base.Dispose(); + stream?.Dispose(); + reader?.Dispose(); + } + + protected override IBeatmap GetBeatmap() => createTestBeatmap(); + + protected override Texture GetBackground() => null; + + protected override Waveform GetWaveform() => new Waveform(getAudioStream()); + + protected override Track GetTrack() => new TrackBass(getAudioStream()); + + private Stream getAudioStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".mp3"))); + private Stream getBeatmapStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".osu"))); + + private Beatmap createTestBeatmap() + { + using (var beatmapStream = getBeatmapStream()) + using (var beatmapReader = new StreamReader(beatmapStream)) + return Decoder.GetDecoder(beatmapReader).Decode(beatmapReader); + } + } +} From 0695615c6a21ff53e11c6e53ef52147841304b66 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Jun 2018 15:10:08 +0900 Subject: [PATCH 141/199] Remove MusicController from compose timeline testcase --- .../Visual/TestCaseEditorComposeTimeline.cs | 104 +++++++++++++++++- 1 file changed, 98 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index c0557982fb..bb0e6156f6 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -4,11 +4,17 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Configuration; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Overlays; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Screens.Edit.Screens.Compose.Timeline; +using OpenTK.Graphics; namespace osu.Game.Tests.Visual { @@ -17,15 +23,23 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineArea), typeof(Timeline), typeof(TimelineButton) }; - public TestCaseEditorComposeTimeline() + [BackgroundDependencyLoader] + private void load() { + Beatmap.Value = new WaveformTestBeatmap(); + Children = new Drawable[] { - new MusicController + new FillFlowContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - State = Visibility.Visible + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + new StartStopButton(), + new AudioVisualiser(), + } }, new TimelineArea { @@ -36,5 +50,83 @@ namespace osu.Game.Tests.Visual } }; } + + private class AudioVisualiser : CompositeDrawable + { + private readonly Drawable marker; + + private readonly IBindable beatmap = new Bindable(); + private IAdjustableClock adjustableClock; + + public AudioVisualiser() + { + Size = new Vector2(250, 25); + + InternalChildren = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.25f, + }, + marker = new Box + { + RelativePositionAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Width = 2, + } + }; + } + + [BackgroundDependencyLoader] + private void load(IAdjustableClock adjustableClock, IBindableBeatmap beatmap) + { + this.adjustableClock = adjustableClock; + this.beatmap.BindTo(beatmap); + } + + protected override void Update() + { + base.Update(); + marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length); + } + } + + private class StartStopButton : Button + { + private IAdjustableClock adjustableClock; + private bool started; + + public StartStopButton() + { + BackgroundColour = Color4.SlateGray; + Size = new Vector2(100, 50); + Text = "Start"; + + Action = onClick; + } + + [BackgroundDependencyLoader] + private void load(IAdjustableClock adjustableClock) + { + this.adjustableClock = adjustableClock; + } + + private void onClick() + { + if (started) + { + adjustableClock.Stop(); + Text = "Start"; + } + else + { + adjustableClock.Start(); + Text = "Stop"; + } + + started = !started; + } + } } } From 08f172ba982f8c4880a516dc565e373b3f7d0ab0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Jun 2018 15:38:19 +0900 Subject: [PATCH 142/199] Make testcase work on appveyor (no BASS) --- osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index bb0e6156f6..5aa17bca7d 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -88,7 +88,9 @@ namespace osu.Game.Tests.Visual protected override void Update() { base.Update(); - marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length); + + if (beatmap.Value.Track.IsLoaded) + marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length); } } From 5b344525e1889e6c4fbd8a5cedccc812827a314e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jun 2018 00:27:18 +0900 Subject: [PATCH 143/199] Move proxy state check to base class --- .../Objects/Drawables/DrawableSwell.cs | 7 +------ .../Objects/Drawables/DrawableTaikoHitObject.cs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 1f571544d8..df36a475d6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -34,7 +34,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private int userHits; - private bool hasProxied; private readonly SwellSymbolPiece symbol; public DrawableSwell(Swell swell) @@ -172,7 +171,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Idle: - hasProxied = false; UnproxyContent(); break; case ArmedState.Hit: @@ -193,11 +191,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables X = Math.Max(0, X); double t = Math.Min(HitObject.StartTime, Time.Current); - if (t == HitObject.StartTime && !hasProxied) - { + if (t == HitObject.StartTime) ProxyContent(); - hasProxied = true; - } } private bool? lastWasCentre; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index e712d62a26..a6d61f1a5a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -40,23 +40,31 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; + private bool isProxied; + /// /// Moves to a layer proxied above the playfield. + /// Does nothing is content is already proxied. /// protected void ProxyContent() { + if (isProxied) return; + isProxied = true; + nonProxiedContent.Remove(Content); - proxiedContent.Remove(Content); proxiedContent.Add(Content); } /// /// Moves to the normal hitobject layer. + /// Does nothing is content is not currently proxied. /// protected void UnproxyContent() { + if (!isProxied) return; + isProxied = false; + proxiedContent.Remove(Content); - nonProxiedContent.Remove(Content); nonProxiedContent.Add(Content); } From 6fa72c510f2b0229267053a4d7e460f69ce0f309 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jun 2018 00:48:35 +0900 Subject: [PATCH 144/199] Avoid listing the base mods twice --- .../Difficulty/ManiaDifficultyCalculator.cs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 5d5adb8e66..5fa113224d 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -136,23 +136,20 @@ namespace osu.Game.Rulesets.Mania.Difficulty { get { - if (isForCurrentRuleset) - { - return new Mod[] - { - new ManiaModDoubleTime(), - new ManiaModHalfTime(), - new ManiaModEasy(), - new ManiaModHardRock(), - }; - } - - return new Mod[] + var mods = new Mod[] { new ManiaModDoubleTime(), new ManiaModHalfTime(), new ManiaModEasy(), new ManiaModHardRock(), + }; + + if (isForCurrentRuleset) + return mods; + + // if we are a convert, we can be played in any key mod. + return mods.Concat(new Mod[] + { new ManiaModKey1(), new ManiaModKey2(), new ManiaModKey3(), @@ -162,7 +159,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty new ManiaModKey7(), new ManiaModKey8(), new ManiaModKey9(), - }; + }).ToArray(); } } } From 31f9d0161df4b9f2fd19e6a7e9304f52766d2154 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jun 2018 03:03:09 +0900 Subject: [PATCH 145/199] Add a comment about precision scroll behaviour --- .../Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index ed26c28c80..0bfea68e50 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -100,7 +100,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline protected override bool OnScroll(InputState state) { if (state.Mouse.HasPreciseScroll) + // for now, we don't support zoom when using a precision scroll device. this needs gesture support. return base.OnScroll(state); + setZoomTarget(zoomTarget + state.Mouse.ScrollDelta.Y, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); return true; } From bec6e3083ec27fd25205a343470f0c9c6ad7a43b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jun 2018 03:19:21 +0900 Subject: [PATCH 146/199] Remove scrollbar depth change as scrollbar is hidden now --- osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index 489233e256..36f76b013a 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -45,9 +45,6 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline // We don't want the centre marker to scroll AddInternal(new CentreMarker()); - // Make sure that the scrollbar is above the centre marker - ChangeInternalChildDepth(Scrollbar, -1); - WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); Beatmap.BindTo(beatmap); From b1d059a67dbe34b17d6389b3a97b33a463ecc0ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jun 2018 04:31:47 +0900 Subject: [PATCH 147/199] Add some colours to the compose-mode timeline --- .../Screens/Edit/Screens/Compose/Timeline/Timeline.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index 36f76b013a..e993d36551 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -4,6 +4,7 @@ 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.Audio; using osu.Framework.Input; @@ -31,14 +32,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline private WaveformGraph waveform; [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, IAdjustableClock adjustableClock) + private void load(IBindableBeatmap beatmap, IAdjustableClock adjustableClock, OsuColour colours) { this.adjustableClock = adjustableClock; Child = waveform = new WaveformGraph { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("222"), + Colour = colours.Blue.Opacity(0.2f), + LowColour = colours.BlueLighter, + MidColour = colours.BlueDark, + HighColour = colours.BlueDarker, Depth = float.MaxValue }; From 8c671f93fc9476439b4e306a0c0c7ba2299603be Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Jun 2018 19:32:04 +0900 Subject: [PATCH 148/199] Always perform non-seeked scroll in the editor while audio is playing --- osu.Game/Screens/Edit/Editor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index d4f66c2f09..379484bae6 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -181,9 +181,9 @@ namespace osu.Game.Screens.Edit protected override bool OnScroll(InputState state) { if (state.Mouse.ScrollDelta.X + state.Mouse.ScrollDelta.Y > 0) - clock.SeekBackward(true); + clock.SeekBackward(!clock.IsRunning); else - clock.SeekForward(true); + clock.SeekForward(!clock.IsRunning); return true; } From 4aa89de2d76d38af34f2f19b9ef6ad7858d3c974 Mon Sep 17 00:00:00 2001 From: Tom Arrow Date: Mon, 18 Jun 2018 17:22:01 +0200 Subject: [PATCH 149/199] Fix reverse arrow displayed with incorrect angle --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index b3bc2930d8..26f3ee6bb4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using osu.Game.Graphics; @@ -89,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // find the next vector2 in the curve which is not equal to our current position to infer a rotation. for (int i = searchStart; i >= 0 && i < curve.Count; i += direction) { - if (curve[i] == Position) + if (Precision.AlmostEquals(curve[i], Position)) continue; Rotation = MathHelper.RadiansToDegrees((float)Math.Atan2(curve[i].Y - Position.Y, curve[i].X - Position.X)); From a0f1143287c884d41a67338382e96d5c077df838 Mon Sep 17 00:00:00 2001 From: Michael Manis Date: Mon, 18 Jun 2018 19:14:44 -0400 Subject: [PATCH 150/199] Add padding to 'show more' button --- osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 1e0406c125..b1b5e3a075 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -64,6 +64,7 @@ namespace osu.Game.Overlays.Profile.Sections { TextSize = 14, Text = "show more", + Padding = new MarginPadding {Top = 10, Bottom = 10, Left = 15, Right = 15 }, } }, ShowMoreLoading = new LoadingAnimation From 15f3a05c831f637c94fc33a958c0eb6c5963e8b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jun 2018 19:28:21 +0900 Subject: [PATCH 151/199] Update rider configuration names --- .../{VisualTests__netcoreapp2_1_.xml => VisualTests.xml} | 5 ++--- .../runConfigurations/{osu___netcoreapp2_1_.xml => osu_.xml} | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) rename .idea/.idea.osu/.idea/runConfigurations/{VisualTests__netcoreapp2_1_.xml => VisualTests.xml} (85%) rename .idea/.idea.osu/.idea/runConfigurations/{osu___netcoreapp2_1_.xml => osu_.xml} (86%) diff --git a/.idea/.idea.osu/.idea/runConfigurations/VisualTests__netcoreapp2_1_.xml b/.idea/.idea.osu/.idea/runConfigurations/VisualTests.xml similarity index 85% rename from .idea/.idea.osu/.idea/runConfigurations/VisualTests__netcoreapp2_1_.xml rename to .idea/.idea.osu/.idea/runConfigurations/VisualTests.xml index 2d3a848922..bf5a1f64e0 100644 --- a/.idea/.idea.osu/.idea/runConfigurations/VisualTests__netcoreapp2_1_.xml +++ b/.idea/.idea.osu/.idea/runConfigurations/VisualTests.xml @@ -1,12 +1,11 @@ - +