From 2a0b1f36157d9768fa7d894d7787bdd6cf91383a Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 3 Jul 2018 19:13:42 +0530 Subject: [PATCH 01/48] Update direct panel download button for new design - Add a download failed event to BeatmapManager - Make DownloadButton aware of all 3 possible download states - Change button appearance based on each state --- osu.Game/Beatmaps/BeatmapManager.cs | 7 ++ .../Drawables/BeatmapSetDownloader.cs | 52 ++++++--- .../BeatmapSet/Buttons/DownloadButton.cs | 11 +- osu.Game/Overlays/Direct/DirectGridPanel.cs | 7 +- osu.Game/Overlays/Direct/DirectPanel.cs | 8 ++ osu.Game/Overlays/Direct/DownloadButton.cs | 100 +++++++++++++++--- 6 files changed, 149 insertions(+), 36 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e488dacf80..f9bbe7b972 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -45,6 +45,11 @@ namespace osu.Game.Beatmaps /// public event Action BeatmapDownloadBegan; + /// + /// Fired when a beatmap download is interrupted, due to user cancellation or other failures. + /// + public event Action BeatmapDownloadFailed; + /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// @@ -175,6 +180,8 @@ namespace osu.Game.Beatmaps request.Failure += error => { + BeatmapDownloadFailed?.Invoke(request); + if (error is OperationCanceledException) return; downloadNotification.State = ProgressNotificationState.Cancelled; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index 6acb58e165..6f4d4c0d6f 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -5,6 +5,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Game.Online.API.Requests; namespace osu.Game.Beatmaps.Drawables { @@ -19,9 +20,9 @@ namespace osu.Game.Beatmaps.Drawables private BeatmapManager beatmaps; /// - /// Whether the associated beatmap set has been downloading (by this instance or any other instance). + /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded. /// - public readonly BindableBool Downloaded = new BindableBool(); + public readonly Bindable DownloadState = new Bindable(); public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false) { @@ -36,10 +37,16 @@ namespace osu.Game.Beatmaps.Drawables beatmaps.ItemAdded += setAdded; beatmaps.ItemRemoved += setRemoved; + beatmaps.BeatmapDownloadBegan += downloadBegan; + beatmaps.BeatmapDownloadFailed += downloadFailed; // initial value - if (set.OnlineBeatmapSetID != null) - Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any(); + if (set.OnlineBeatmapSetID != null && beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any()) + DownloadState.Value = DownloadStatus.Downloaded; + else if (beatmaps.GetExistingDownload(set) != null) + DownloadState.Value = DownloadStatus.Downloading; + else + DownloadState.Value = DownloadStatus.NotDownloaded; } protected override void Dispose(bool isDisposing) @@ -50,6 +57,8 @@ namespace osu.Game.Beatmaps.Drawables { beatmaps.ItemAdded -= setAdded; beatmaps.ItemRemoved -= setRemoved; + beatmaps.BeatmapDownloadBegan -= downloadBegan; + beatmaps.BeatmapDownloadFailed -= downloadFailed; } } @@ -57,28 +66,45 @@ namespace osu.Game.Beatmaps.Drawables /// Begin downloading the associated beatmap set. /// /// True if downloading began. False if an existing download is active or completed. - public bool Download() + public void Download() { - if (Downloaded.Value) - return false; - - if (beatmaps.GetExistingDownload(set) != null) - return false; + if (DownloadState.Value > DownloadStatus.NotDownloaded) + return; beatmaps.Download(set, noVideo); - return true; + + DownloadState.Value = DownloadStatus.Downloading; } private void setAdded(BeatmapSetInfo s) { if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - Downloaded.Value = true; + DownloadState.Value = DownloadStatus.Downloaded; } private void setRemoved(BeatmapSetInfo s) { if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - Downloaded.Value = false; + DownloadState.Value = DownloadStatus.NotDownloaded; + } + + private void downloadBegan(DownloadBeatmapSetRequest d) + { + if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID) + DownloadState.Value = DownloadStatus.Downloading; + } + + private void downloadFailed(DownloadBeatmapSetRequest d) + { + if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID) + DownloadState.Value = DownloadStatus.NotDownloaded; + } + + public enum DownloadStatus + { + NotDownloaded, + Downloading, + Downloaded, } } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 4fce6a49fb..7a227f4bfa 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -61,20 +61,23 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Action = () => { - if (!downloader.Download()) + if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloading) { Content.MoveToX(-5, 50, Easing.OutSine).Then() .MoveToX(5, 100, Easing.InOutSine).Then() .MoveToX(-5, 100, Easing.InOutSine).Then() .MoveToX(0, 50, Easing.InSine); + return; } + + downloader.Download(); }; - downloader.Downloaded.ValueChanged += d => + downloader.DownloadState.ValueChanged += d => { - if (d) + if (d == BeatmapSetDownloader.DownloadStatus.Downloaded) this.FadeOut(200); - else + else if (d == BeatmapSetDownloader.DownloadStatus.NotDownloaded) this.FadeIn(200); }; } diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index e286837746..48963a91e8 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -168,11 +168,10 @@ namespace osu.Game.Overlays.Direct }, new DownloadButton(SetInfo) { - Size = new Vector2(30), + Size = new Vector2(50, 30), Margin = new MarginPadding(horizontal_padding), - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Colour = colours.Gray5, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, }, }, }, diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index e63c290ce5..76da4b61b0 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -99,6 +99,7 @@ namespace osu.Game.Overlays.Direct attachDownload(downloadRequest); beatmaps.BeatmapDownloadBegan += attachDownload; + beatmaps.ItemAdded += setAdded; } public override bool DisposeOnDeathRemoval => true; @@ -107,6 +108,7 @@ namespace osu.Game.Overlays.Direct { base.Dispose(isDisposing); beatmaps.BeatmapDownloadBegan -= attachDownload; + beatmaps.ItemAdded -= setAdded; } protected override void Update() @@ -171,6 +173,12 @@ namespace osu.Game.Overlays.Direct }; } + private void setAdded(BeatmapSetInfo s) + { + if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID) + progressBar.FadeOut(500); + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 1ffa8dbd35..68380b951c 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -1,76 +1,146 @@ // 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.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays.Direct { public class DownloadButton : OsuClickableContainer { private readonly SpriteIcon icon; + private readonly SpriteIcon checkmark; + private readonly BeatmapSetDownloader downloader; + private readonly Box background; + + private OsuColour colours; public DownloadButton(BeatmapSetInfo set, bool noVideo = false) { - BeatmapSetDownloader downloader; Children = new Drawable[] { downloader = new BeatmapSetDownloader(set, noVideo), + new Container + { + RelativeSizeAxes = Axes.Both, + CornerRadius = 17, + Masking = true, + Child = background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + }, icon = new SpriteIcon { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(30), - Icon = FontAwesome.fa_osu_chevron_down_o, + Size = new Vector2(13), + Icon = FontAwesome.fa_download, }, + checkmark = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + X = 8, + Size = Vector2.Zero, + Icon = FontAwesome.fa_check, + } }; Action = () => { - if (!downloader.Download()) + if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloading) { Content.MoveToX(-5, 50, Easing.OutSine).Then() .MoveToX(5, 100, Easing.InOutSine).Then() .MoveToX(-5, 100, Easing.InOutSine).Then() .MoveToX(0, 50, Easing.InSine); } + else if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloaded) + { + // TODO: Jump to song select with this set when the capability is implemented + } + else + { + downloader.Download(); + } }; - downloader.Downloaded.ValueChanged += d => - { - if (d) - this.FadeOut(200); - else - this.FadeIn(200); - }; + downloader.DownloadState.ValueChanged += _ => updateState(); + + Colour = Color4.White; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + updateState(); + } + + [BackgroundDependencyLoader(permitNulls:true)] + private void load(OsuColour colours) + { + this.colours = colours; } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - icon.ScaleTo(0.9f, 1000, Easing.Out); + Content.ScaleTo(0.9f, 1000, Easing.Out); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - icon.ScaleTo(1f, 500, Easing.OutElastic); + Content.ScaleTo(1f, 500, Easing.OutElastic); return base.OnMouseUp(state, args); } protected override bool OnHover(InputState state) { - icon.ScaleTo(1.1f, 500, Easing.OutElastic); + Content.ScaleTo(1.1f, 500, Easing.OutElastic); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - icon.ScaleTo(1f, 500, Easing.OutElastic); + Content.ScaleTo(1f, 500, Easing.OutElastic); + } + + private void updateState() + { + if (!IsLoaded) + return; + + switch (downloader.DownloadState.Value) + { + case BeatmapSetDownloader.DownloadStatus.NotDownloaded: + background.FadeColour(colours.Gray4, 500, Easing.InOutExpo); + icon.MoveToX(0, 500, Easing.InOutExpo); + checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); + break; + + case BeatmapSetDownloader.DownloadStatus.Downloading: + background.FadeColour(colours.Blue, 500, Easing.InOutExpo); + icon.MoveToX(0, 500, Easing.InOutExpo); + checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); + break; + + case BeatmapSetDownloader.DownloadStatus.Downloaded: + background.FadeColour(colours.Green, 500, Easing.InOutExpo); + icon.MoveToX(-8, 500, Easing.InOutExpo); + checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo); + break; + } } } } From 6ea6a10defeafddd5e698b5f6d41af42653d9335 Mon Sep 17 00:00:00 2001 From: naoey Date: Tue, 3 Jul 2018 20:26:49 +0530 Subject: [PATCH 02/48] Reduce size of download button in list view to fit hover effect --- osu.Game/Overlays/Direct/DirectListPanel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 812a0e2073..17c5153dab 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -120,8 +120,8 @@ namespace osu.Game.Overlays.Direct Alpha = 0, Child = new DownloadButton(SetInfo) { - Size = new Vector2(height - vertical_padding * 2), - Margin = new MarginPadding { Left = vertical_padding }, + Size = new Vector2(height - vertical_padding * 3), + Margin = new MarginPadding { Left = vertical_padding, Right = vertical_padding }, }, }, new FillFlowContainer From e28a6107578ae52d17298a6fc929d49ce17e5ca1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Jul 2018 12:40:55 +0900 Subject: [PATCH 03/48] Fix mods not correctly resetting when changing ruleset at song select --- .../ManiaSettingsSubsection.cs | 5 ++- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 7 +++- .../Settings/RulesetSettingsSubsection.cs | 9 +++-- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 4 +- osu.Game/Screens/Select/SongSelect.cs | 38 +++++++++++++------ osu.Game/osu.Game.csproj | 2 +- 7 files changed, 46 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index 54a7bf954d..8d1fad8a82 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; @@ -19,14 +20,14 @@ namespace osu.Game.Rulesets.Mania } [BackgroundDependencyLoader] - private void load(ManiaConfigManager config) + private void load() { Children = new Drawable[] { new SettingsEnumDropdown { LabelText = "Scrolling direction", - Bindable = config.GetBindable(ManiaSetting.ScrollDirection) + Bindable = (Config as RulesetConfigManager)?.GetBindable(ManiaSetting.ScrollDirection) } }; } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index c584a32a82..98cf111ba0 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -44,6 +44,8 @@ namespace osu.Game.Overlays.Mods private void rulesetChanged(RulesetInfo newRuleset) { + if (newRuleset == null) return; + var instance = newRuleset.CreateInstance(); foreach (ModSection section in ModSectionsContainer.Children) @@ -173,7 +175,10 @@ namespace osu.Game.Overlays.Mods refreshSelectedMods(); } - private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); + private void refreshSelectedMods() + { + SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); + } public ModSelectOverlay() { diff --git a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs index 05104018cd..5340a01743 100644 --- a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Game.Rulesets; +using osu.Game.Rulesets.Configuration; namespace osu.Game.Overlays.Settings { @@ -14,6 +15,8 @@ namespace osu.Game.Overlays.Settings { private readonly Ruleset ruleset; + protected IRulesetConfigManager Config; + protected RulesetSettingsSubsection(Ruleset ruleset) { this.ruleset = ruleset; @@ -25,9 +28,9 @@ namespace osu.Game.Overlays.Settings { dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - var config = dependencies.Get().GetConfigFor(ruleset); - if (config != null) - dependencies.Cache(config); + Config = dependencies.Get().GetConfigFor(ruleset); + if (Config != null) + dependencies.Cache(Config); return dependencies; } diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 7058d1bed6..8f73ff4c2d 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mods { - public class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer + public abstract class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer where T : HitObject { protected virtual Score CreateReplayScore(Beatmap beatmap) => new Score { Replay = new Replay() }; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 8ce40fcfa0..a346911ca2 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -84,10 +84,10 @@ namespace osu.Game.Screens.Select protected override void UpdateBeatmap(WorkingBeatmap beatmap) { - base.UpdateBeatmap(beatmap); - beatmap.Mods.BindTo(SelectedMods); + base.UpdateBeatmap(beatmap); + BeatmapDetails.Beatmap = beatmap; if (beatmap.Track != null) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 94c16f1797..e940cac419 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using OpenTK; using OpenTK.Input; using osu.Framework.Allocation; @@ -19,6 +20,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Edit; using osu.Game.Screens.Menu; @@ -67,8 +69,17 @@ namespace osu.Game.Screens.Select protected new readonly Bindable Ruleset = new Bindable(); private DependencyContainer dependencies; + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) - => dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + { + dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + + dependencies.CacheAs(this); + dependencies.CacheAs(Ruleset); + dependencies.CacheAs>(Ruleset); + + return dependencies; + } protected SongSelect() { @@ -183,11 +194,9 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) { - dependencies.CacheAs(this); - dependencies.CacheAs(Ruleset); - dependencies.CacheAs>(Ruleset); - + // manual binding to parent ruleset to allow for delayed load in the incoming direction. base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce); + Ruleset.ValueChanged += r => base.Ruleset.Value = r; if (Footer != null) { @@ -263,7 +272,7 @@ namespace osu.Game.Screens.Select // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value) { - Ruleset.Value = beatmap.BeatmapInfo.Ruleset; + base.Ruleset.Value = beatmap.BeatmapInfo.Ruleset; Carousel.SelectBeatmap(beatmap.BeatmapInfo); } } @@ -281,16 +290,22 @@ namespace osu.Game.Screens.Select void performLoad() { + WorkingBeatmap working = Beatmap.Value; + bool preview = false; + // We may be arriving here due to another component changing the bindable Beatmap. // In these cases, the other component has already loaded the beatmap, so we don't need to do so again. if (beatmap?.Equals(Beatmap.Value.BeatmapInfo) != true) { - bool preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID; - - Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); - ensurePlayingSelected(preview); + preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID; + working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); } + ensurePlayingSelected(preview); + + working.Mods.Value = Enumerable.Empty(); + + Beatmap.Value = working; Ruleset.Value = ruleset; UpdateBeatmap(Beatmap.Value); @@ -464,7 +479,8 @@ namespace osu.Game.Screens.Select private void carouselBeatmapsLoaded() { - if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false && Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false)) + if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false + && Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false)) return; if (Carousel.SelectedBeatmapSet == null && !Carousel.SelectNextRandom()) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 56c33c47af..74da553bfe 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 1418d1369fe76c5e76a0cfaeda57b331334d090f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Jul 2018 01:32:10 +0900 Subject: [PATCH 04/48] Add the ability to click completed download notifications to select beatmap Closes #2731. --- osu.Game/Beatmaps/BeatmapManager.cs | 15 ++++++++++++++- osu.Game/OsuGame.cs | 27 +++++++++++++++++++++++++++ osu.Game/Screens/Menu/MainMenu.cs | 6 +++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index fd24e4297b..e63f70610e 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -45,6 +45,11 @@ namespace osu.Game.Beatmaps /// public event Action BeatmapDownloadBegan; + /// + /// Fired when a beatmap load is requested (into the interactive game UI). + /// + public Action PresentBeatmap; + /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// @@ -163,12 +168,20 @@ namespace osu.Game.Beatmaps Task.Factory.StartNew(() => { + BeatmapSetInfo importedBeatmap; + // This gets scheduled back to the update thread, but we want the import to run in the background. using (var stream = new MemoryStream(data)) using (var archive = new ZipArchiveReader(stream, beatmapSetInfo.ToString())) - Import(archive); + importedBeatmap = Import(archive); + downloadNotification.CompletionClickAction = () => + { + PresentBeatmap?.Invoke(importedBeatmap); + return true; + }; downloadNotification.State = ProgressNotificationState.Completed; + currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); }; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 922d228701..f8fdaf368c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -23,6 +23,7 @@ using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Platform; using osu.Framework.Threading; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Notifications; @@ -33,6 +34,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Skinning; using OpenTK.Graphics; using osu.Game.Overlays.Volume; +using osu.Game.Screens.Select; namespace osu.Game { @@ -178,6 +180,30 @@ namespace osu.Game /// The set to display. public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); + /// + /// Present a beatmap at song select. + /// + /// The beatmap to select. + public void PresentBeatmap(BeatmapSetInfo beatmap) + { + CloseAllOverlays(); + + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); + + switch (currentScreen) + { + case SongSelect _: + break; + default: + // navigate to song select if we are not already there. + var menu = (MainMenu)intro.ChildScreen; + + menu.MakeCurrent(); + menu.LoadToSolo(); + break; + } + } + /// /// Show a user's profile as an overlay. /// @@ -244,6 +270,7 @@ namespace osu.Game BeatmapManager.PostNotification = n => notifications?.Post(n); BeatmapManager.GetStableStorage = GetStorageForStableInstall; + BeatmapManager.PresentBeatmap = PresentBeatmap; AddRange(new Drawable[] { diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index d922f49ce3..4790996833 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Menu OnChart = delegate { Push(new ChartListing()); }, OnDirect = delegate { Push(new OnlineListing()); }, OnEdit = delegate { Push(new Editor()); }, - OnSolo = delegate { Push(consumeSongSelect()); }, + OnSolo = onSolo, OnMulti = delegate { Push(new Multiplayer()); }, OnExit = Exit, } @@ -85,6 +85,10 @@ namespace osu.Game.Screens.Menu LoadComponentAsync(songSelect = new PlaySongSelect()); } + public void LoadToSolo() => Schedule(onSolo); + + private void onSolo() => Push(consumeSongSelect()); + private Screen consumeSongSelect() { var s = songSelect; From 1e48582dc2eb7582938385be546a4916039c3576 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Wed, 11 Jul 2018 13:49:37 +0200 Subject: [PATCH 05/48] Instantly hide pause menu for quick retry --- osu.Game/Screens/Play/Player.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b406bda411..48a398a209 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -222,6 +222,7 @@ namespace osu.Game.Screens.Play //we want to hide the hitrenderer immediately (looks better). //we may be able to remove this once the mouse cursor trail is improved. RulesetContainer?.Hide(); + pauseContainer?.Hide(); Restart(); }, } From a9f8c2acb8560b30f03d6aa3606680324d65da25 Mon Sep 17 00:00:00 2001 From: Criminalllz Date: Thu, 12 Jul 2018 20:36:57 +0200 Subject: [PATCH 06/48] Use Regex to only care about colors and commas when parsing a color. --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index c8874c3bc7..c2ab156637 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text.RegularExpressions; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; @@ -73,10 +74,12 @@ namespace osu.Game.Beatmaps.Formats bool isCombo = pair.Key.StartsWith(@"Combo"); - string[] split = pair.Value.Split(','); + line = Regex.Replace(pair.Value, "[^0-9,]", ""); + + string[] split = line.Split(','); if (split.Length != 3) - throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {pair.Value}"); + throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {line}"); if (!byte.TryParse(split[0], out var r) || !byte.TryParse(split[1], out var g) || !byte.TryParse(split[2], out var b)) throw new InvalidOperationException(@"Color must be specified with 8-bit integer components"); From 0676919496463b4dacd4e5e6782398cb689e30ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 14:56:44 +0900 Subject: [PATCH 07/48] Fix incorrect corner radius --- osu.Game/Overlays/Direct/DownloadButton.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 68380b951c..2d678c572c 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -29,10 +29,9 @@ namespace osu.Game.Overlays.Direct Children = new Drawable[] { downloader = new BeatmapSetDownloader(set, noVideo), - new Container + new CircularContainer { RelativeSizeAxes = Axes.Both, - CornerRadius = 17, Masking = true, Child = background = new Box { From ee2c7c50adc0160648a8c097b9fd688d056ffcef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 16:28:18 +0900 Subject: [PATCH 08/48] Tidy up button hierarchy --- osu.Game.Tests/Visual/TestCaseIconButton.cs | 15 ++- osu.Game/Graphics/UserInterface/IconButton.cs | 111 +++--------------- .../UserInterface/OsuAnimatedButton.cs | 109 +++++++++++++++++ osu.Game/Overlays/Direct/DownloadButton.cs | 62 ++-------- osu.Game/Overlays/MusicController.cs | 18 ++- .../Compose/Timeline/TimelineButton.cs | 24 ++-- 6 files changed, 175 insertions(+), 164 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseIconButton.cs b/osu.Game.Tests/Visual/TestCaseIconButton.cs index 16363da527..14cba71ec8 100644 --- a/osu.Game.Tests/Visual/TestCaseIconButton.cs +++ b/osu.Game.Tests/Visual/TestCaseIconButton.cs @@ -25,11 +25,7 @@ namespace osu.Game.Tests.Visual Children = new[] { new NamedIconButton("No change", new IconButton()), - new NamedIconButton("Background colours", new IconButton - { - FlashColour = Color4.DarkGreen, - HoverColour = Color4.Green, - }), + new NamedIconButton("Background colours", new ColouredIconButton()), new NamedIconButton("Full-width", new IconButton { ButtonSize = new Vector2(200, 30) }), new NamedIconButton("Unchanging size", new IconButton(), false), new NamedIconButton("Icon colours", new IconButton @@ -41,6 +37,15 @@ namespace osu.Game.Tests.Visual }; } + private class ColouredIconButton : IconButton + { + public ColouredIconButton() + { + FlashColour = Color4.DarkGreen; + HoverColour = Color4.Green; + } + } + private class NamedIconButton : Container { public NamedIconButton(string name, IconButton button, bool allowSizeChange = true) diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 5a25fe641d..eca7bf57c8 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -3,31 +3,17 @@ 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.Input; -using osu.Game.Graphics.Containers; namespace osu.Game.Graphics.UserInterface { - public class IconButton : OsuClickableContainer + public class IconButton : OsuAnimatedButton { public const float BUTTON_SIZE = 30; - private Color4? flashColour; - /// - /// The colour that should be flashed when the is clicked. - /// - public Color4 FlashColour - { - get { return flashColour ?? Color4.White; } - set { flashColour = value; } - } - private Color4? iconColour; + /// /// The icon colour. This does not affect . /// @@ -42,6 +28,7 @@ namespace osu.Game.Graphics.UserInterface } private Color4? iconHoverColour; + /// /// The icon colour while the is hovered. /// @@ -51,20 +38,6 @@ namespace osu.Game.Graphics.UserInterface set { iconHoverColour = value; } } - private Color4? hoverColour; - /// - /// The background colour of the while it is hovered. - /// - public Color4 HoverColour - { - get { return hoverColour ?? Color4.White; } - set - { - hoverColour = value; - hover.Colour = value; - } - } - /// /// The icon. /// @@ -88,93 +61,39 @@ namespace osu.Game.Graphics.UserInterface /// public Vector2 ButtonSize { - get { return content.Size; } - set { content.Size = value; } + get => Content.Size; + set + { + Content.RelativeSizeAxes = Axes.None; + Content.Size = value; + } } - private readonly Container content; private readonly SpriteIcon icon; - private readonly Box hover; public IconButton() { AutoSizeAxes = Axes.Both; + ButtonSize = new Vector2(BUTTON_SIZE); - Children = new Drawable[] + Add(icon = new SpriteIcon { - content = new Container - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(BUTTON_SIZE), - CornerRadius = 5, - Masking = true, - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0.04f), - Type = EdgeEffectType.Shadow, - Radius = 5, - }, - Children = new Drawable[] - { - hover = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - icon = new SpriteIcon - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Size = new Vector2(18), - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - if (hoverColour == null) - HoverColour = colours.Yellow.Opacity(0.6f); - - if (flashColour == null) - FlashColour = colours.Yellow; - - Enabled.ValueChanged += enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint); + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(18), + }); } protected override bool OnHover(InputState state) { - hover.FadeIn(500, Easing.OutQuint); icon.FadeColour(IconHoverColour, 500, Easing.OutQuint); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - hover.FadeOut(500, Easing.OutQuint); icon.FadeColour(IconColour, 500, Easing.OutQuint); base.OnHoverLost(state); } - - protected override bool OnClick(InputState state) - { - hover.FlashColour(FlashColour, 800, Easing.OutQuint); - return base.OnClick(state); - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - content.ScaleTo(0.75f, 2000, Easing.OutQuint); - return base.OnMouseDown(state, args); - } - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) - { - content.ScaleTo(1, 1000, Easing.OutElastic); - return base.OnMouseUp(state, args); - } } } diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs new file mode 100644 index 0000000000..990a2f20a9 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.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.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Graphics.Containers; +using OpenTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// Highlight on hover, bounce on click. + /// + public class OsuAnimatedButton : OsuClickableContainer + { + /// + /// The colour that should be flashed when the is clicked. + /// + protected Color4 FlashColour = Color4.White.Opacity(0.3f); + + private Color4 hoverColour = Color4.White.Opacity(0.1f); + + /// + /// The background colour of the while it is hovered. + /// + protected Color4 HoverColour + { + get => hoverColour; + set + { + hoverColour = value; + hover.Colour = value; + } + } + + protected override Container Content => content; + + private readonly Container content; + private readonly Box hover; + + public OsuAnimatedButton() + { + base.Content.Add(content = new Container + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + CornerRadius = 5, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.04f), + Type = EdgeEffectType.Shadow, + Radius = 5, + }, + Children = new Drawable[] + { + hover = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = HoverColour, + Blending = BlendingMode.Additive, + Alpha = 0, + }, + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Enabled.BindValueChanged(enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true); + } + + protected override bool OnHover(InputState state) + { + hover.FadeIn(500, Easing.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + hover.FadeOut(500, Easing.OutQuint); + base.OnHoverLost(state); + } + + protected override bool OnClick(InputState state) + { + hover.FlashColour(FlashColour, 800, Easing.OutQuint); + return base.OnClick(state); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + Content.ScaleTo(0.75f, 2000, Easing.OutQuint); + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + Content.ScaleTo(1, 1000, Easing.OutElastic); + return base.OnMouseUp(state, args); + } + } +} diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 2d678c572c..5c5e4907ed 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -3,19 +3,16 @@ using osu.Framework.Allocation; 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.UserInterface; using OpenTK; -using OpenTK.Graphics; namespace osu.Game.Overlays.Direct { - public class DownloadButton : OsuClickableContainer + public class DownloadButton : OsuAnimatedButton { private readonly SpriteIcon icon; private readonly SpriteIcon checkmark; @@ -26,17 +23,13 @@ namespace osu.Game.Overlays.Direct public DownloadButton(BeatmapSetInfo set, bool noVideo = false) { - Children = new Drawable[] + AddRange(new Drawable[] { downloader = new BeatmapSetDownloader(set, noVideo), - new CircularContainer + background = new Box { RelativeSizeAxes = Axes.Both, - Masking = true, - Child = background = new Box - { - RelativeSizeAxes = Axes.Both, - }, + Depth = float.MaxValue }, icon = new SpriteIcon { @@ -53,18 +46,19 @@ namespace osu.Game.Overlays.Direct Size = Vector2.Zero, Icon = FontAwesome.fa_check, } - }; + }); Action = () => { - if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloading) + if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloading) { + // todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged. Content.MoveToX(-5, 50, Easing.OutSine).Then() .MoveToX(5, 100, Easing.InOutSine).Then() .MoveToX(-5, 100, Easing.InOutSine).Then() .MoveToX(0, 50, Easing.InSine); } - else if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloaded) + else if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloaded) { // TODO: Jump to song select with this set when the capability is implemented } @@ -73,54 +67,24 @@ namespace osu.Game.Overlays.Direct downloader.Download(); } }; - - downloader.DownloadState.ValueChanged += _ => updateState(); - - Colour = Color4.White; } protected override void LoadComplete() { base.LoadComplete(); - updateState(); + downloader.DownloadState.BindValueChanged(updateState, true); } - [BackgroundDependencyLoader(permitNulls:true)] + [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuColour colours) { this.colours = colours; } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + private void updateState(BeatmapSetDownloader.DownloadStatus state) { - Content.ScaleTo(0.9f, 1000, Easing.Out); - return base.OnMouseDown(state, args); - } - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) - { - Content.ScaleTo(1f, 500, Easing.OutElastic); - return base.OnMouseUp(state, args); - } - - protected override bool OnHover(InputState state) - { - Content.ScaleTo(1.1f, 500, Easing.OutElastic); - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - Content.ScaleTo(1f, 500, Easing.OutElastic); - } - - private void updateState() - { - if (!IsLoaded) - return; - - switch (downloader.DownloadState.Value) + switch (state) { case BeatmapSetDownloader.DownloadStatus.NotDownloaded: background.FadeColour(colours.Gray4, 500, Easing.InOutExpo); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index a57d5fd183..56af04c498 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -142,14 +142,14 @@ namespace osu.Game.Overlays Anchor = Anchor.Centre, Children = new[] { - prevButton = new IconButton + prevButton = new MusicIconButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, Action = prev, Icon = FontAwesome.fa_step_backward, }, - playButton = new IconButton + playButton = new MusicIconButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -158,7 +158,7 @@ namespace osu.Game.Overlays Action = play, Icon = FontAwesome.fa_play_circle_o, }, - nextButton = new IconButton + nextButton = new MusicIconButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -167,7 +167,7 @@ namespace osu.Game.Overlays }, } }, - playlistButton = new IconButton + playlistButton = new MusicIconButton { Origin = Anchor.Centre, Anchor = Anchor.CentreRight, @@ -405,6 +405,16 @@ namespace osu.Game.Overlays Prev } + private class MusicIconButton : IconButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + HoverColour = colours.YellowDark.Opacity(0.6f); + FlashColour = colours.Yellow; + } + } + private class Background : BufferedContainer { private readonly Sprite sprite; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs index f46cc7ef9d..5928fbaa1b 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs @@ -27,16 +27,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline public TimelineButton() { - InternalChild = button = new IconButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - IconColour = OsuColour.Gray(0.35f), - IconHoverColour = Color4.White, - HoverColour = OsuColour.Gray(0.25f), - FlashColour = OsuColour.Gray(0.5f), - Action = () => Action?.Invoke() - }; + InternalChild = button = new TimelineIconButton { Action = () => Action?.Invoke() }; button.Enabled.BindTo(Enabled); Width = button.ButtonSize.X; @@ -48,5 +39,18 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline button.ButtonSize = new Vector2(button.ButtonSize.X, DrawHeight); } + + private class TimelineIconButton : IconButton + { + public TimelineIconButton() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + IconColour = OsuColour.Gray(0.35f); + IconHoverColour = Color4.White; + HoverColour = OsuColour.Gray(0.25f); + FlashColour = OsuColour.Gray(0.5f); + } + } } } From bbb11a4066f0742d17636f7c7528b61deb4a3df9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 19:53:29 +0900 Subject: [PATCH 09/48] Fix regression in drawable rank first display --- osu.Game/Screens/Select/Leaderboards/DrawableRank.cs | 2 +- osu.Game/Users/Country.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs index 228633a41f..0c4b369f36 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Select.Leaderboards { Rank = newRank; - if (IsLoaded) + if (LoadState >= LoadState.Ready) updateTexture(); } } diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index 98b3a2df0c..80039eadad 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -43,7 +43,7 @@ namespace osu.Game.Users country = value; - if (IsLoaded) + if (LoadState >= LoadState.Ready) sprite.Texture = getFlagTexture(); } } From b33a0f772e585d77d8aaaeb59fbc57dd59341d07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:00:52 +0900 Subject: [PATCH 10/48] Don't close toolbar --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f8fdaf368c..bed4c98b53 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -186,7 +186,7 @@ namespace osu.Game /// The beatmap to select. public void PresentBeatmap(BeatmapSetInfo beatmap) { - CloseAllOverlays(); + CloseAllOverlays(false); Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); From 95f314d9499dce6ae165d8c206bb6481756428a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:04:10 +0900 Subject: [PATCH 11/48] Fix crash when clicking notification from player --- osu.Game/OsuGame.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index bed4c98b53..a96768629e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -188,17 +188,19 @@ namespace osu.Game { CloseAllOverlays(false); - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); + void setBeatmap() => Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); switch (currentScreen) { case SongSelect _: + setBeatmap(); break; default: // navigate to song select if we are not already there. var menu = (MainMenu)intro.ChildScreen; menu.MakeCurrent(); + setBeatmap(); menu.LoadToSolo(); break; } From 6d8923a37cc1a14772538d455cbc819332d3b423 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:08:41 +0900 Subject: [PATCH 12/48] Use better logic --- osu.Game/OsuGame.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 17c8ad8aa0..e2b93d0599 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -189,22 +189,31 @@ namespace osu.Game { CloseAllOverlays(false); - void setBeatmap() => Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); + void setBeatmap() + { + if (Beatmap.Disabled) + { + Schedule(setBeatmap); + return; + } + + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); + }; switch (currentScreen) { case SongSelect _: - setBeatmap(); break; default: // navigate to song select if we are not already there. var menu = (MainMenu)intro.ChildScreen; menu.MakeCurrent(); - setBeatmap(); menu.LoadToSolo(); break; } + + setBeatmap(); } /// From fc3aff66896f146e48eb14df7e2d298ed1eff945 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:19:10 +0900 Subject: [PATCH 13/48] Fix initial colour --- osu.Game/Overlays/Direct/DownloadButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 5c5e4907ed..7758e171c5 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -72,8 +72,8 @@ namespace osu.Game.Overlays.Direct protected override void LoadComplete() { base.LoadComplete(); - downloader.DownloadState.BindValueChanged(updateState, true); + FinishTransforms(true); } [BackgroundDependencyLoader(permitNulls: true)] From ac4f25c5bc55c1bdc92977c18b9bd19913bee806 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:25:08 +0900 Subject: [PATCH 14/48] Make notifications less noisy --- osu.Desktop/Overlays/VersionManager.cs | 2 ++ osu.Game/Database/ArchiveModelManager.cs | 7 ++++++- osu.Game/Overlays/NotificationOverlay.cs | 3 ++- osu.Game/Overlays/Notifications/Notification.cs | 5 +++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 1129969694..0c564f8113 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -111,6 +111,8 @@ namespace osu.Desktop.Overlays private class UpdateCompleteNotification : SimpleNotification { + public override bool IsImportant => true; + public UpdateCompleteNotification(string version, Action openUrl = null) { Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index cbf0df3227..c5591c00dc 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -116,7 +116,7 @@ namespace osu.Game.Database /// One or more archive locations on disk. public void Import(params string[] paths) { - var notification = new ProgressNotification + var notification = new ImportNotification { Text = "Import is initialising...", Progress = 0, @@ -407,5 +407,10 @@ namespace osu.Game.Database return new LegacyFilesystemReader(path); throw new InvalidFormatException($"{path} is not a valid archive"); } + + private class ImportNotification : ProgressNotification + { + public override bool IsImportant => true; + } } } diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 3dc8f5ec15..d891cd96e8 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -128,7 +128,8 @@ namespace osu.Game.Overlays var section = sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType))); section?.Add(notification, notification.DisplayOnTop ? -runningDepth : runningDepth); - State = Visibility.Visible; + if (notification.IsImportant) + State = Visibility.Visible; updateCounts(); }); diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index d2b5ae1829..c98ac3b2cd 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -23,6 +23,11 @@ namespace osu.Game.Overlays.Notifications /// public event Action Closed; + /// + /// Whether this notification should forcefully display itself. + /// + public virtual bool IsImportant => false; + /// /// Run on user activating the notification. Return true to close. /// From ac35e8bd9939fd3d227915213dca699565e7ef38 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:27:09 +0900 Subject: [PATCH 15/48] Remove redundant empty statement --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e2b93d0599..18a1d018d0 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -198,7 +198,7 @@ namespace osu.Game } Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); - }; + } switch (currentScreen) { From 63c40e9051c0125aa41cdb50902873d65aca98a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:45:42 +0900 Subject: [PATCH 16/48] Remove unnecessary cache operations --- osu.Game/Screens/Select/SongSelect.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index a695aedda7..e6f33a7d29 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -202,10 +202,6 @@ namespace osu.Game.Screens.Select base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce); Ruleset.ValueChanged += r => base.Ruleset.Value = r; - dependencies.CacheAs(this); - dependencies.CacheAs(Ruleset); - dependencies.CacheAs>(Ruleset); - if (Footer != null) { Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2); From 4f5578245efc81f29a81a86b178150ad036ba2e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Jul 2018 21:45:49 +0900 Subject: [PATCH 17/48] Fix regression causing previews to not play --- osu.Game/Screens/Select/SongSelect.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index e6f33a7d29..234508a195 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -315,13 +315,14 @@ namespace osu.Game.Screens.Select working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); } - ensurePlayingSelected(preview); working.Mods.Value = Enumerable.Empty(); Beatmap.Value = working; Ruleset.Value = ruleset; + ensurePlayingSelected(preview); + UpdateBeatmap(Beatmap.Value); } From 81e5a37d6d5c0a324ef864d498a80872c41b3142 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Jul 2018 03:31:19 +0900 Subject: [PATCH 18/48] Enlist a few more important notifications --- osu.Desktop/Updater/SimpleUpdateManager.cs | 7 ++++++- .../Notifications/ProgressCompletionNotification.cs | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Desktop/Updater/SimpleUpdateManager.cs index 6c363422f7..5b62298010 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Desktop/Updater/SimpleUpdateManager.cs @@ -48,7 +48,7 @@ namespace osu.Desktop.Updater if (latest.TagName != version) { - notificationOverlay.Post(new SimpleNotification + notificationOverlay.Post(new UpdateNotification { Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" + "Click here to download the new version, which can be installed over the top of your existing installation", @@ -62,6 +62,11 @@ namespace osu.Desktop.Updater } } + private class UpdateNotification : SimpleNotification + { + public override bool IsImportant => true; + } + private string getBestUrl(GitHubRelease release) { GitHubAsset bestAsset = null; diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index 0711e49608..cd72049702 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -9,6 +9,8 @@ namespace osu.Game.Overlays.Notifications { public class ProgressCompletionNotification : SimpleNotification { + public override bool IsImportant => true; + public ProgressCompletionNotification() { Icon = FontAwesome.fa_check; From 730eb2daa2e19d7c3c3fa3c7ef9eea8823166d08 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Jul 2018 03:47:56 +0900 Subject: [PATCH 19/48] Reduce osu!direct panel width to allow three panels displayed at 16:9 resolutions --- osu.Game/Overlays/Direct/DirectGridPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index e286837746..4060f26008 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Direct public DirectGridPanel(BeatmapSetInfo beatmap) : base(beatmap) { - Width = 400; + Width = 380; Height = 140 + vertical_padding; //full height of all the elements plus vertical padding (autosize uses the image) } From 453d58bcbd7be12fbc9e6f7ff85c37e6223776d6 Mon Sep 17 00:00:00 2001 From: HoutarouOreki Date: Sun, 15 Jul 2018 01:10:05 +0200 Subject: [PATCH 20/48] Hide Content instead of particular overlays --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 48a398a209..3992ebc6ee 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Play //we want to hide the hitrenderer immediately (looks better). //we may be able to remove this once the mouse cursor trail is improved. RulesetContainer?.Hide(); - pauseContainer?.Hide(); + Content.Hide(); Restart(); }, } From 6c861a16385d88340768f0a29c88f4b0cbf26b84 Mon Sep 17 00:00:00 2001 From: morguldir Date: Mon, 16 Jul 2018 01:04:41 +0200 Subject: [PATCH 21/48] Strip comments from everything except metadata --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 16 +++++++++------- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 15 +++++++++++---- .../Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 ++ osu.Game/Skinning/LegacySkinDecoder.cs | 2 ++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index c79938e613..641cdc4fd6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -62,32 +62,34 @@ namespace osu.Game.Beatmaps.Formats protected override void ParseLine(Beatmap beatmap, Section section, string line) { + var stripped_line = StripComments(line); + switch (section) { case Section.General: - handleGeneral(line); + handleGeneral(stripped_line); return; case Section.Editor: - handleEditor(line); + handleEditor(stripped_line); return; case Section.Metadata: handleMetadata(line); return; case Section.Difficulty: - handleDifficulty(line); + handleDifficulty(stripped_line); return; case Section.Events: - handleEvent(line); + handleEvent(stripped_line); return; case Section.TimingPoints: - handleTimingPoint(line); + handleTimingPoint(stripped_line); return; case Section.HitObjects: - handleHitObject(line); + handleHitObject(stripped_line); return; } - base.ParseLine(beatmap, section, line); + base.ParseLine(beatmap, section, stripped_line); } private void handleGeneral(string line) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index c2ab156637..7a97281c76 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -58,6 +58,8 @@ namespace osu.Game.Beatmaps.Formats protected virtual void ParseLine(T output, Section section, string line) { + line = StripComments(line); + switch (section) { case Section.Colours: @@ -65,6 +67,13 @@ namespace osu.Game.Beatmaps.Formats return; } } + internal string StripComments(string line) + { + var index = line.IndexOf("//"); + if (index > 0) + return line.Substring(0, index); + return line; + } private bool hasComboColours; @@ -74,12 +83,10 @@ namespace osu.Game.Beatmaps.Formats bool isCombo = pair.Key.StartsWith(@"Combo"); - line = Regex.Replace(pair.Value, "[^0-9,]", ""); - - string[] split = line.Split(','); + string[] split = pair.Value.Split(','); if (split.Length != 3) - throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {line}"); + throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {pair.Value}"); if (!byte.TryParse(split[0], out var r) || !byte.TryParse(split[1], out var g) || !byte.TryParse(split[2], out var b)) throw new InvalidOperationException(@"Color must be specified with 8-bit integer components"); diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 868ae5206a..b418cbd5ec 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -42,6 +42,8 @@ namespace osu.Game.Beatmaps.Formats protected override void ParseLine(Storyboard storyboard, Section section, string line) { + line = StripComments(line); + switch (section) { case Section.Events: diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 0ef54c7310..d4f1c5c6f1 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -14,6 +14,8 @@ namespace osu.Game.Skinning protected override void ParseLine(SkinConfiguration skin, Section section, string line) { + line = StripComments(line); + switch (section) { case Section.General: From 87a4bf3d92f143a737b1ef45ae75b19608846cab Mon Sep 17 00:00:00 2001 From: morguldir Date: Mon, 16 Jul 2018 01:08:30 +0200 Subject: [PATCH 22/48] Remove using directive for regex in LegacyDecoder --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 7a97281c76..7ceb78c30d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text.RegularExpressions; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; From 429306aa876ef9bbe24aa16412d366124fd2c72d Mon Sep 17 00:00:00 2001 From: morguldir Date: Mon, 16 Jul 2018 01:54:20 +0200 Subject: [PATCH 23/48] Fix casing, use ordinal string comparison when stripping comments --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 16 ++++++++-------- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 641cdc4fd6..7664a4cea3 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -62,34 +62,34 @@ namespace osu.Game.Beatmaps.Formats protected override void ParseLine(Beatmap beatmap, Section section, string line) { - var stripped_line = StripComments(line); + var strippedLine = StripComments(line); switch (section) { case Section.General: - handleGeneral(stripped_line); + handleGeneral(strippedLine); return; case Section.Editor: - handleEditor(stripped_line); + handleEditor(strippedLine); return; case Section.Metadata: handleMetadata(line); return; case Section.Difficulty: - handleDifficulty(stripped_line); + handleDifficulty(strippedLine); return; case Section.Events: - handleEvent(stripped_line); + handleEvent(strippedLine); return; case Section.TimingPoints: - handleTimingPoint(stripped_line); + handleTimingPoint(strippedLine); return; case Section.HitObjects: - handleHitObject(stripped_line); + handleHitObject(strippedLine); return; } - base.ParseLine(beatmap, section, stripped_line); + base.ParseLine(beatmap, section, strippedLine); } private void handleGeneral(string line) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 7ceb78c30d..0698954bb6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -68,7 +68,7 @@ namespace osu.Game.Beatmaps.Formats } internal string StripComments(string line) { - var index = line.IndexOf("//"); + var index = line.IndexOf("//", StringComparison.Ordinal); if (index > 0) return line.Substring(0, index); return line; From a12c47536b4158561d26315e004ad2476c748523 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Jul 2018 13:00:21 +0900 Subject: [PATCH 24/48] Change default to being important --- osu.Desktop/Overlays/VersionManager.cs | 2 -- osu.Desktop/Updater/SimpleUpdateManager.cs | 7 +------ osu.Game/Beatmaps/BeatmapManager.cs | 18 +++++++++++++++++- osu.Game/Database/ArchiveModelManager.cs | 7 +------ .../Overlays/Notifications/Notification.cs | 2 +- .../ProgressCompletionNotification.cs | 2 -- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 0c564f8113..1129969694 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -111,8 +111,6 @@ namespace osu.Desktop.Overlays private class UpdateCompleteNotification : SimpleNotification { - public override bool IsImportant => true; - public UpdateCompleteNotification(string version, Action openUrl = null) { Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Desktop/Updater/SimpleUpdateManager.cs index 5b62298010..6c363422f7 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Desktop/Updater/SimpleUpdateManager.cs @@ -48,7 +48,7 @@ namespace osu.Desktop.Updater if (latest.TagName != version) { - notificationOverlay.Post(new UpdateNotification + notificationOverlay.Post(new SimpleNotification { Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n" + "Click here to download the new version, which can be installed over the top of your existing installation", @@ -62,11 +62,6 @@ namespace osu.Desktop.Updater } } - private class UpdateNotification : SimpleNotification - { - public override bool IsImportant => true; - } - private string getBestUrl(GitHubRelease release) { GitHubAsset bestAsset = null; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index fc4d43080e..49aa4eca28 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -143,7 +143,7 @@ namespace osu.Game.Beatmaps return; } - var downloadNotification = new ProgressNotification + var downloadNotification = new DownloadNotification { CompletionText = $"Imported {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}!", Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}", @@ -453,5 +453,21 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => null; protected override Track GetTrack() => null; } + + private class DownloadNotification : ProgressNotification + { + public override bool IsImportant => false; + + protected override Notification CreateCompletionNotification() => new SilencedProgressCompletionNotification + { + Activated = CompletionClickAction, + Text = CompletionText + }; + + private class SilencedProgressCompletionNotification : ProgressCompletionNotification + { + public override bool IsImportant => false; + } + } } } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index c5591c00dc..cbf0df3227 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -116,7 +116,7 @@ namespace osu.Game.Database /// One or more archive locations on disk. public void Import(params string[] paths) { - var notification = new ImportNotification + var notification = new ProgressNotification { Text = "Import is initialising...", Progress = 0, @@ -407,10 +407,5 @@ namespace osu.Game.Database return new LegacyFilesystemReader(path); throw new InvalidFormatException($"{path} is not a valid archive"); } - - private class ImportNotification : ProgressNotification - { - public override bool IsImportant => true; - } } } diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index c98ac3b2cd..3a3fcb54e0 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Notifications /// /// Whether this notification should forcefully display itself. /// - public virtual bool IsImportant => false; + public virtual bool IsImportant => true; /// /// Run on user activating the notification. Return true to close. diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index cd72049702..0711e49608 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -9,8 +9,6 @@ namespace osu.Game.Overlays.Notifications { public class ProgressCompletionNotification : SimpleNotification { - public override bool IsImportant => true; - public ProgressCompletionNotification() { Icon = FontAwesome.fa_check; From dbc538abbe5806b5f8a273cffbae1e200fc90a78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Jul 2018 16:17:22 +0900 Subject: [PATCH 25/48] Use Enum.HasFlag With .NET core 2.0+ this is as efficient as the ugly code we've been using. --- .../Legacy/DistanceObjectPatternGenerator.cs | 16 ++++----- .../Legacy/HitObjectPatternGenerator.cs | 35 ++++++++++--------- .../Objects/Drawables/Pieces/BodyPiece.cs | 2 +- .../Replays/ManiaReplayFrame.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 4 +-- osu.Game/Graphics/SpriteIcon.cs | 2 +- osu.Game/Graphics/UserInterface/BarGraph.cs | 8 ++--- osu.Game/Graphics/UserInterface/LineGraph.cs | 2 +- .../Graphics/UserInterface/TwoLayerButton.cs | 10 +++--- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 4 +-- .../Objects/Legacy/ConvertHitObjectParser.cs | 14 ++++---- .../Replays/Legacy/LegacyReplayFrame.cs | 8 ++--- osu.Game/Screens/Play/SquareGraph.cs | 2 +- 13 files changed, 55 insertions(+), 54 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 280c2f45d4..8d0d78120a 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -133,26 +133,26 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (ConversionDifficulty > 6.5) { - if ((convertType & PatternType.LowProbability) > 0) + if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.78, 0.3, 0); return generateNRandomNotes(HitObject.StartTime, 0.85, 0.36, 0.03); } if (ConversionDifficulty > 4) { - if ((convertType & PatternType.LowProbability) > 0) + if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.43, 0.08, 0); return generateNRandomNotes(HitObject.StartTime, 0.56, 0.18, 0); } if (ConversionDifficulty > 2.5) { - if ((convertType & PatternType.LowProbability) > 0) + if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.3, 0, 0); return generateNRandomNotes(HitObject.StartTime, 0.37, 0.08, 0); } - if ((convertType & PatternType.LowProbability) > 0) + if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.17, 0, 0); return generateNRandomNotes(HitObject.StartTime, 0.27, 0, 0); } @@ -209,7 +209,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); - if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns) + if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) { while (PreviousPattern.ColumnHasObject(nextColumn)) nextColumn = Random.Next(RandomStart, TotalColumns); @@ -361,7 +361,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy bool isDoubleSample(SampleInfo sample) => sample.Name == SampleInfo.HIT_CLAP || sample.Name == SampleInfo.HIT_FINISH; - bool canGenerateTwoNotes = (convertType & PatternType.LowProbability) == 0; + bool canGenerateTwoNotes = !convertType.HasFlag(PatternType.LowProbability); canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample); if (canGenerateTwoNotes) @@ -391,7 +391,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int columnRepeat = Math.Min(spanCount, TotalColumns); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); - if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns) + if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) { while (PreviousPattern.ColumnHasObject(nextColumn)) nextColumn = Random.Next(RandomStart, TotalColumns); @@ -425,7 +425,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); - if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns) + if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) { while (PreviousPattern.ColumnHasObject(holdColumn)) holdColumn = Random.Next(RandomStart, TotalColumns); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 0e839d87a2..84ebfdb839 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -21,7 +21,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private readonly PatternType convertType; - public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, IBeatmap originalBeatmap) + public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, + PatternType lastStair, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime)); @@ -79,7 +80,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy else convertType |= PatternType.LowProbability; - if ((convertType & PatternType.KeepSingle) == 0) + if (!convertType.HasFlag(PatternType.KeepSingle)) { if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && TotalColumns != 8) convertType |= PatternType.Mirror; @@ -107,7 +108,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int lastColumn = PreviousPattern.HitObjects.FirstOrDefault()?.Column ?? 0; - if ((convertType & PatternType.Reverse) > 0 && PreviousPattern.HitObjects.Any()) + if (convertType.HasFlag(PatternType.Reverse) && PreviousPattern.HitObjects.Any()) { // Generate a new pattern by copying the last hit objects in reverse-column order for (int i = RandomStart; i < TotalColumns; i++) @@ -117,7 +118,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy return pattern; } - if ((convertType & PatternType.Cycle) > 0 && PreviousPattern.HitObjects.Count() == 1 + if (convertType.HasFlag(PatternType.Cycle) && PreviousPattern.HitObjects.Count() == 1 // If we convert to 7K + 1, let's not overload the special key && (TotalColumns != 8 || lastColumn != 0) // Make sure the last column was not the centre column @@ -130,7 +131,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy return pattern; } - if ((convertType & PatternType.ForceStack) > 0 && PreviousPattern.HitObjects.Any()) + if (convertType.HasFlag(PatternType.ForceStack) && PreviousPattern.HitObjects.Any()) { // Generate a new pattern by placing on the already filled columns for (int i = RandomStart; i < TotalColumns; i++) @@ -142,7 +143,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (PreviousPattern.HitObjects.Count() == 1) { - if ((convertType & PatternType.Stair) > 0) + if (convertType.HasFlag(PatternType.Stair)) { // Generate a new pattern by placing on the next column, cycling back to the start if there is no "next" int targetColumn = lastColumn + 1; @@ -153,7 +154,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy return pattern; } - if ((convertType & PatternType.ReverseStair) > 0) + if (convertType.HasFlag(PatternType.ReverseStair)) { // Generate a new pattern by placing on the previous column, cycling back to the end if there is no "previous" int targetColumn = lastColumn - 1; @@ -165,10 +166,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } } - if ((convertType & PatternType.KeepSingle) > 0) + if (convertType.HasFlag(PatternType.KeepSingle)) return pattern = generateRandomNotes(1); - if ((convertType & PatternType.Mirror) > 0) + if (convertType.HasFlag(PatternType.Mirror)) { if (ConversionDifficulty > 6.5) return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); @@ -179,21 +180,21 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (ConversionDifficulty > 6.5) { - if ((convertType & PatternType.LowProbability) > 0) + if (convertType.HasFlag(PatternType.LowProbability)) return pattern = generateRandomPattern(0.78, 0.42, 0, 0); return pattern = generateRandomPattern(1, 0.62, 0, 0); } if (ConversionDifficulty > 4) { - if ((convertType & PatternType.LowProbability) > 0) + if (convertType.HasFlag(PatternType.LowProbability)) return pattern = generateRandomPattern(0.35, 0.08, 0, 0); return pattern = generateRandomPattern(0.52, 0.15, 0, 0); } if (ConversionDifficulty > 2) { - if ((convertType & PatternType.LowProbability) > 0) + if (convertType.HasFlag(PatternType.LowProbability)) return pattern = generateRandomPattern(0.18, 0, 0, 0); return pattern = generateRandomPattern(0.45, 0, 0, 0); } @@ -204,9 +205,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { foreach (var obj in pattern.HitObjects) { - if ((convertType & PatternType.Stair) > 0 && obj.Column == TotalColumns - 1) + if (convertType.HasFlag(PatternType.Stair) && obj.Column == TotalColumns - 1) StairType = PatternType.ReverseStair; - if ((convertType & PatternType.ReverseStair) > 0 && obj.Column == RandomStart) + if (convertType.HasFlag(PatternType.ReverseStair) && obj.Column == RandomStart) StairType = PatternType.Stair; } } @@ -225,7 +226,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { var pattern = new Pattern(); - bool allowStacking = (convertType & PatternType.ForceNotStack) == 0; + bool allowStacking = !convertType.HasFlag(PatternType.ForceNotStack); if (!allowStacking) noteCount = Math.Min(noteCount, TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects); @@ -235,7 +236,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn) && !allowStacking) { - if ((convertType & PatternType.Gathered) > 0) + if (convertType.HasFlag(PatternType.Gathered)) { nextColumn++; if (nextColumn == TotalColumns) @@ -367,7 +368,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { addToCentre = false; - if ((convertType & PatternType.ForceNotStack) > 0) + if (convertType.HasFlag(PatternType.ForceNotStack)) return getRandomNoteCount(1 / 2f + p2 / 2, p2, (p2 + p3) / 2, p3); switch (TotalColumns) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 4ab2da208a..dbba56501e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if ((invalidation & Invalidation.DrawSize) > 0) + if (invalidation.HasFlag(Invalidation.DrawSize)) subtractionCache.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index bc9fd6e06f..e2dc2d6a03 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Replays { var isSpecial = stage.IsSpecialColumn(counter); - if ((activeColumns & 1) > 0) + if (activeColumns.HasFlag(1)) Actions.Add(isSpecial ? specialAction : normalAction); if (isSpecial) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index c79938e613..81f1e056fb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -306,8 +306,8 @@ namespace osu.Game.Beatmaps.Formats if (split.Length >= 8) { int effectFlags = int.Parse(split[7]); - kiaiMode = (effectFlags & 1) > 0; - omitFirstBarSignature = (effectFlags & 8) > 0; + kiaiMode = effectFlags.HasFlag(1); + omitFirstBarSignature = effectFlags.HasFlag(8); } string stringSampleSet = sampleSet.ToString().ToLower(); diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index 6acd20719e..244844f6d5 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -84,7 +84,7 @@ namespace osu.Game.Graphics public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if ((invalidation & Invalidation.Colour) > 0 && Shadow) + if (invalidation.HasFlag(Invalidation.Colour) && Shadow) layout.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); } diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index d065ecdd5f..0ba49929e9 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -26,10 +26,10 @@ namespace osu.Game.Graphics.UserInterface set { direction = value; - base.Direction = (direction & BarDirection.Horizontal) > 0 ? FillDirection.Vertical : FillDirection.Horizontal; + base.Direction = direction.HasFlag(BarDirection.Horizontal) ? FillDirection.Vertical : FillDirection.Horizontal; foreach (var bar in Children) { - bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / Children.Count) : new Vector2(1.0f / Children.Count, 1); + bar.Size = direction.HasFlag(BarDirection.Horizontal) ? new Vector2(1, 1.0f / Children.Count) : new Vector2(1.0f / Children.Count, 1); bar.Direction = direction; } } @@ -56,14 +56,14 @@ namespace osu.Game.Graphics.UserInterface if (bar.Bar != null) { bar.Bar.Length = length; - bar.Bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, size) : new Vector2(size, 1); + bar.Bar.Size = direction.HasFlag(BarDirection.Horizontal) ? new Vector2(1, size) : new Vector2(size, 1); } else { Add(new Bar { RelativeSizeAxes = Axes.Both, - Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, size) : new Vector2(size, 1), + Size = direction.HasFlag(BarDirection.Horizontal) ? new Vector2(1, size) : new Vector2(size, 1), Length = length, Direction = Direction, }); diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index 3cb2446acc..c4e1e1d283 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -75,7 +75,7 @@ namespace osu.Game.Graphics.UserInterface public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if ((invalidation & Invalidation.DrawSize) > 0) + if (invalidation.HasFlag(Invalidation.DrawSize)) pathCached.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index f490306acf..dd5454314d 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -56,15 +56,15 @@ namespace osu.Game.Graphics.UserInterface set { base.Origin = value; - c1.Origin = c1.Anchor = (value & Anchor.x2) > 0 ? Anchor.TopLeft : Anchor.TopRight; - c2.Origin = c2.Anchor = (value & Anchor.x2) > 0 ? Anchor.TopRight : Anchor.TopLeft; + c1.Origin = c1.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopLeft : Anchor.TopRight; + c2.Origin = c2.Anchor = value.HasFlag(Anchor.x2) ? Anchor.TopRight : Anchor.TopLeft; - X = (value & Anchor.x2) > 0 ? SIZE_RETRACTED.X * shear * 0.5f : 0; + X = value.HasFlag(Anchor.x2) ? SIZE_RETRACTED.X * shear * 0.5f : 0; Remove(c1); Remove(c2); - c1.Depth = (value & Anchor.x2) > 0 ? 0 : 1; - c2.Depth = (value & Anchor.x2) > 0 ? 1 : 0; + c1.Depth = value.HasFlag(Anchor.x2) ? 0 : 1; + c2.Depth = value.HasFlag(Anchor.x2) ? 1 : 0; Add(c1); Add(c2); } diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index c7870a72de..4514f3c33c 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -118,9 +118,9 @@ namespace osu.Game.Overlays.Toolbar { Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.Both, //stops us being considered in parent's autosize - Anchor = (TooltipAnchor & Anchor.x0) > 0 ? Anchor.BottomLeft : Anchor.BottomRight, + Anchor = TooltipAnchor.HasFlag(Anchor.x0) ? Anchor.BottomLeft : Anchor.BottomRight, Origin = TooltipAnchor, - Position = new Vector2((TooltipAnchor & Anchor.x0) > 0 ? 5 : -5, 5), + Position = new Vector2(TooltipAnchor.HasFlag(Anchor.x0) ? 5 : -5, 5), Alpha = 0, Children = new[] { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 95589d8953..48512a71c2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -39,14 +39,14 @@ namespace osu.Game.Rulesets.Objects.Legacy HitObject result = null; - if ((type & ConvertHitObjectType.Circle) > 0) + if (type.HasFlag(ConvertHitObjectType.Circle)) { result = CreateHit(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo); if (split.Length > 5) readCustomSampleBanks(split[5], bankInfo); } - else if ((type & ConvertHitObjectType.Slider) > 0) + else if (type.HasFlag(ConvertHitObjectType.Slider)) { var pos = new Vector2(int.Parse(split[0]), int.Parse(split[1])); @@ -150,14 +150,14 @@ namespace osu.Game.Rulesets.Objects.Legacy result = CreateSlider(pos, combo, points, length, curveType, repeatCount, nodeSamples); } - else if ((type & ConvertHitObjectType.Spinner) > 0) + else if (type.HasFlag(ConvertHitObjectType.Spinner)) { result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + offset); if (split.Length > 6) readCustomSampleBanks(split[6], bankInfo); } - else if ((type & ConvertHitObjectType.Hold) > 0) + else if (type.HasFlag(ConvertHitObjectType.Hold)) { // Note: Hold is generated by BMS converts @@ -266,7 +266,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } }; - if ((type & LegacySoundType.Finish) > 0) + if (type.HasFlag(LegacySoundType.Finish)) { soundTypes.Add(new SampleInfo { @@ -276,7 +276,7 @@ namespace osu.Game.Rulesets.Objects.Legacy }); } - if ((type & LegacySoundType.Whistle) > 0) + if (type.HasFlag(LegacySoundType.Whistle)) { soundTypes.Add(new SampleInfo { @@ -286,7 +286,7 @@ namespace osu.Game.Rulesets.Objects.Legacy }); } - if ((type & LegacySoundType.Clap) > 0) + if (type.HasFlag(LegacySoundType.Clap)) { soundTypes.Add(new SampleInfo { diff --git a/osu.Game/Rulesets/Replays/Legacy/LegacyReplayFrame.cs b/osu.Game/Rulesets/Replays/Legacy/LegacyReplayFrame.cs index d39d765bfe..5bd56e0cc0 100644 --- a/osu.Game/Rulesets/Replays/Legacy/LegacyReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Legacy/LegacyReplayFrame.cs @@ -15,10 +15,10 @@ namespace osu.Game.Rulesets.Replays.Legacy public bool MouseLeft => MouseLeft1 || MouseLeft2; public bool MouseRight => MouseRight1 || MouseRight2; - public bool MouseLeft1 => (ButtonState & ReplayButtonState.Left1) > 0; - public bool MouseRight1 => (ButtonState & ReplayButtonState.Right1) > 0; - public bool MouseLeft2 => (ButtonState & ReplayButtonState.Left2) > 0; - public bool MouseRight2 => (ButtonState & ReplayButtonState.Right2) > 0; + public bool MouseLeft1 => ButtonState.HasFlag(ReplayButtonState.Left1); + public bool MouseRight1 => ButtonState.HasFlag(ReplayButtonState.Right1); + public bool MouseLeft2 => ButtonState.HasFlag(ReplayButtonState.Left2); + public bool MouseRight2 => ButtonState.HasFlag(ReplayButtonState.Right2); public ReplayButtonState ButtonState; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 8ffd04b35c..1d13b4548d 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Play public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if ((invalidation & Invalidation.DrawSize) > 0) + if (invalidation.HasFlag(Invalidation.DrawSize)) layout.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); } From 98cddc0c04ef451e3fffcdc393ab628086a7f121 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Jul 2018 16:26:37 +0900 Subject: [PATCH 26/48] Fix some legacy cases --- .../Replays/ManiaReplayFrame.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index e2dc2d6a03..bc9fd6e06f 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Replays { var isSpecial = stage.IsSpecialColumn(counter); - if (activeColumns.HasFlag(1)) + if ((activeColumns & 1) > 0) Actions.Add(isSpecial ? specialAction : normalAction); if (isSpecial) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 81f1e056fb..770dab9eeb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -305,9 +305,9 @@ namespace osu.Game.Beatmaps.Formats bool omitFirstBarSignature = false; if (split.Length >= 8) { - int effectFlags = int.Parse(split[7]); - kiaiMode = effectFlags.HasFlag(1); - omitFirstBarSignature = effectFlags.HasFlag(8); + EffectFlags effectFlags = (EffectFlags)int.Parse(split[7]); + kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai); + omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); } string stringSampleSet = sampleSet.ToString().ToLower(); @@ -405,5 +405,13 @@ namespace osu.Game.Beatmaps.Formats private double getOffsetTime() => ApplyOffsets ? offset : 0; private double getOffsetTime(double time) => time + (ApplyOffsets ? offset : 0); + + [Flags] + internal enum EffectFlags + { + None = 0, + Kiai = 1, + OmitFirstBarLine = 8 + } } } From 58fe434dd01d0953586bbe7a1b9f00111502effe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Jul 2018 16:39:52 +0900 Subject: [PATCH 27/48] Don't use in invalidation logic to avoid incorrect execution --- osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs | 2 +- osu.Game/Graphics/SpriteIcon.cs | 2 +- osu.Game/Graphics/UserInterface/LineGraph.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index dbba56501e..4ab2da208a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if (invalidation.HasFlag(Invalidation.DrawSize)) + if ((invalidation & Invalidation.DrawSize) > 0) subtractionCache.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index 244844f6d5..6acd20719e 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -84,7 +84,7 @@ namespace osu.Game.Graphics public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if (invalidation.HasFlag(Invalidation.Colour) && Shadow) + if ((invalidation & Invalidation.Colour) > 0 && Shadow) layout.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); } diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index c4e1e1d283..3cb2446acc 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -75,7 +75,7 @@ namespace osu.Game.Graphics.UserInterface public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if (invalidation.HasFlag(Invalidation.DrawSize)) + if ((invalidation & Invalidation.DrawSize) > 0) pathCached.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 1d13b4548d..8ffd04b35c 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Play public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { - if (invalidation.HasFlag(Invalidation.DrawSize)) + if ((invalidation & Invalidation.DrawSize) > 0) layout.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); } From fc77e01ba980a03ed366820f5a7b645ff11ba0ff Mon Sep 17 00:00:00 2001 From: morguldir Date: Mon, 16 Jul 2018 16:35:55 +0200 Subject: [PATCH 28/48] Fix formatting, make StripComments protected Don't strip comments when calling ParseLine --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 7664a4cea3..d1b47b449b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -89,7 +89,7 @@ namespace osu.Game.Beatmaps.Formats return; } - base.ParseLine(beatmap, section, strippedLine); + base.ParseLine(beatmap, section, line); } private void handleGeneral(string line) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 0698954bb6..91c1c98438 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -66,7 +66,8 @@ namespace osu.Game.Beatmaps.Formats return; } } - internal string StripComments(string line) + + protected string StripComments(string line) { var index = line.IndexOf("//", StringComparison.Ordinal); if (index > 0) From da300baff156caf2a6c02f7921daf2ee096bd65b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Jul 2018 00:06:51 +0900 Subject: [PATCH 29/48] Update hide logic --- osu.Game/Screens/Play/Player.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f97ee27ced..49a180902b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -219,10 +219,7 @@ namespace osu.Game.Screens.Play { if (!IsCurrentScreen) return; - //we want to hide the hitrenderer immediately (looks better). - //we may be able to remove this once the mouse cursor trail is improved. - RulesetContainer?.Hide(); - Content.Hide(); + pauseContainer.Hide(); Restart(); }, } From b967fe714b8ef7b13c6266efe52043ad94a488d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Jul 2018 14:29:22 +0900 Subject: [PATCH 30/48] Fix lead-in time now being long enough in many cases --- osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs | 10 ++++++++++ osu.Game/Rulesets/UI/RulesetContainer.cs | 6 ++++++ osu.Game/Screens/Play/Player.cs | 7 +++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 33d4e16662..c18d180783 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.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.Cursor; using osu.Framework.Input; using OpenTK; @@ -46,6 +47,15 @@ namespace osu.Game.Rulesets.Osu.UI protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuReplayInputHandler(replay); + public override double GameplayStartTime + { + get + { + var first = (OsuHitObject)Objects.First(); + return first.StartTime - first.TimePreempt; + } + } + protected override Vector2 GetAspectAdjustedSize() { var aspectSize = DrawSize.X * 0.75f < DrawSize.Y ? new Vector2(DrawSize.X, DrawSize.X * 0.75f) : new Vector2(DrawSize.Y * 4f / 3f, DrawSize.Y); diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 0bfde148e7..d68afdfedc 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -56,6 +56,12 @@ namespace osu.Game.Rulesets.UI public abstract IEnumerable Objects { get; } + /// + /// The point in time at which gameplay starts, including any required lead-in for display purposes. + /// Defaults to two seconds before the first . Override as necessary. + /// + public virtual double GameplayStartTime => Objects.First().StartTime - 2000; + private readonly Lazy playfield; /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 49a180902b..fc439a48c5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -138,10 +138,9 @@ namespace osu.Game.Screens.Play sourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock(); adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; - var firstObjectTime = RulesetContainer.Objects.First().StartTime; adjustableClock.Seek(AllowLeadIn - ? Math.Min(0, firstObjectTime - Math.Max(beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, beatmap.BeatmapInfo.AudioLeadIn)) - : firstObjectTime); + ? Math.Min(RulesetContainer.GameplayStartTime, beatmap.HitObjects.First().StartTime - beatmap.BeatmapInfo.AudioLeadIn) + : RulesetContainer.GameplayStartTime); adjustableClock.ProcessFrame(); @@ -199,7 +198,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre }, - new SkipOverlay(firstObjectTime) + new SkipOverlay(RulesetContainer.GameplayStartTime) { Clock = Clock, // skip button doesn't want to use the audio clock directly ProcessCustomClock = false, From 825941aff11aecbeae4666f6a9e46e8bac08c0ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Jul 2018 14:35:09 +0900 Subject: [PATCH 31/48] Use switch with type matching in place of if-else where possible --- .../CatchBeatmapConversionTest.cs | 22 ++++--- .../Difficulty/CatchDifficultyCalculator.cs | 13 ++-- .../Legacy/EndTimeObjectPatternGenerator.cs | 14 ++-- .../Replays/ManiaAutoGenerator.cs | 13 ++-- .../Replays/OsuAutoGenerator.cs | 65 ++++++++++--------- .../UI/OsuRulesetContainer.cs | 16 +++-- .../Scoring/TaikoScoreProcessor.cs | 40 ++++++------ osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 16 +++-- .../UI/TaikoRulesetContainer.cs | 32 ++++----- .../BeatmapSet/Buttons/DownloadButton.cs | 15 +++-- osu.Game/Overlays/OnScreenDisplay.cs | 19 +++--- .../Difficulty/DifficultyCalculator.cs | 16 +++-- 12 files changed, 150 insertions(+), 131 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 4b95a6754e..162624da57 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -28,18 +28,20 @@ namespace osu.Game.Rulesets.Catch.Tests protected override IEnumerable CreateConvertValue(HitObject hitObject) { - if (hitObject is JuiceStream stream) + switch (hitObject) { - foreach (var nested in stream.NestedHitObjects) - yield return new ConvertValue((CatchHitObject)nested); + case JuiceStream stream: + foreach (var nested in stream.NestedHitObjects) + yield return new ConvertValue((CatchHitObject)nested); + break; + case BananaShower shower: + foreach (var nested in shower.NestedHitObjects) + yield return new ConvertValue((CatchHitObject)nested); + break; + default: + yield return new ConvertValue((CatchHitObject)hitObject); + break; } - else if (hitObject is BananaShower shower) - { - foreach (var nested in shower.NestedHitObjects) - yield return new ConvertValue((CatchHitObject)nested); - } - else - yield return new ConvertValue((CatchHitObject)hitObject); } protected override Ruleset CreateRuleset() => new CatchRuleset(); diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 31c56c37c4..978b71576e 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -46,13 +46,16 @@ namespace osu.Game.Rulesets.Catch.Difficulty 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) + switch (hitObject) { - difficultyHitObjects.Add(new CatchDifficultyHitObject((CatchHitObject)hitObject, halfCatchWidth)); + // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. + case Fruit _: + difficultyHitObjects.Add(new CatchDifficultyHitObject((CatchHitObject)hitObject, halfCatchWidth)); + break; + case JuiceStream _: + difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth))); + break; } - if (hitObject is JuiceStream) - difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth))); } difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index b902ee63c6..06b4b8a27e 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -33,15 +33,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy bool generateHold = endTime - HitObject.StartTime >= 100; - if (TotalColumns == 8) + switch (TotalColumns) { - if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000) + case 8 when HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000: addToPattern(pattern, 0, generateHold); - else + break; + case 8: addToPattern(pattern, getNextRandomColumn(RandomStart), generateHold); + break; + default: + if (TotalColumns > 0) + addToPattern(pattern, getNextRandomColumn(0), generateHold); + break; } - else if (TotalColumns > 0) - addToPattern(pattern, getNextRandomColumn(0), generateHold); return pattern; } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index d006a3e1c7..0eef540d97 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -56,10 +56,15 @@ namespace osu.Game.Rulesets.Mania.Replays { foreach (var point in group) { - if (point is HitPoint) - actions.Add(columnActions[point.Column]); - if (point is ReleasePoint) - actions.Remove(columnActions[point.Column]); + switch (point) + { + case HitPoint _: + actions.Add(columnActions[point.Column]); + break; + case ReleasePoint _: + actions.Remove(columnActions[point.Column]); + break; + } } Replay.Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray())); diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index ad4ea343d2..7322f65066 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -285,44 +285,45 @@ namespace osu.Game.Rulesets.Osu.Replays AddFrameToReplay(startFrame); - // We add intermediate frames for spinning / following a slider here. - if (h is Spinner) + switch (h) { - Spinner s = h as Spinner; - - Vector2 difference = startPosition - SPINNER_CENTRE; - - float radius = difference.Length; - float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X); - - double t; - - for (double j = h.StartTime + FrameDelay; j < s.EndTime; j += FrameDelay) + // We add intermediate frames for spinning / following a slider here. + case Spinner spinner: { - t = ApplyModsToTime(j - h.StartTime) * spinnerDirection; + Vector2 difference = startPosition - SPINNER_CENTRE; - Vector2 pos = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS); - AddFrameToReplay(new OsuReplayFrame((int)j, new Vector2(pos.X, pos.Y), action)); + float radius = difference.Length; + float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X); + + double t; + + for (double j = h.StartTime + FrameDelay; j < spinner.EndTime; j += FrameDelay) + { + t = ApplyModsToTime(j - h.StartTime) * spinnerDirection; + + Vector2 pos = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS); + AddFrameToReplay(new OsuReplayFrame((int)j, new Vector2(pos.X, pos.Y), action)); + } + + t = ApplyModsToTime(spinner.EndTime - h.StartTime) * spinnerDirection; + Vector2 endPosition = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS); + + AddFrameToReplay(new OsuReplayFrame(spinner.EndTime, new Vector2(endPosition.X, endPosition.Y), action)); + + endFrame.Position = endPosition; + break; } - - t = ApplyModsToTime(s.EndTime - h.StartTime) * spinnerDirection; - Vector2 endPosition = SPINNER_CENTRE + CirclePosition(t / 20 + angle, SPIN_RADIUS); - - AddFrameToReplay(new OsuReplayFrame(s.EndTime, new Vector2(endPosition.X, endPosition.Y), action)); - - endFrame.Position = endPosition; - } - else if (h is Slider) - { - Slider s = h as Slider; - - for (double j = FrameDelay; j < s.Duration; j += FrameDelay) + case Slider slider: { - Vector2 pos = s.StackedPositionAt(j / s.Duration); - AddFrameToReplay(new OsuReplayFrame(h.StartTime + j, new Vector2(pos.X, pos.Y), action)); - } + for (double j = FrameDelay; j < slider.Duration; j += FrameDelay) + { + Vector2 pos = slider.StackedPositionAt(j / slider.Duration); + AddFrameToReplay(new OsuReplayFrame(h.StartTime + j, new Vector2(pos.X, pos.Y), action)); + } - AddFrameToReplay(new OsuReplayFrame(s.EndTime, new Vector2(s.StackedEndPosition.X, s.StackedEndPosition.Y), action)); + AddFrameToReplay(new OsuReplayFrame(slider.EndTime, new Vector2(slider.StackedEndPosition.X, slider.StackedEndPosition.Y), action)); + break; + } } // We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed! diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 33d4e16662..3558c347a9 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -33,14 +33,16 @@ namespace osu.Game.Rulesets.Osu.UI protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { - if (h is HitCircle circle) - return new DrawableHitCircle(circle); + switch (h) + { + case HitCircle circle: + return new DrawableHitCircle(circle); + case Slider slider: + return new DrawableSlider(slider); + case Spinner spinner: + return new DrawableSpinner(spinner); + } - if (h is Slider slider) - return new DrawableSlider(slider); - - if (h is Spinner spinner) - return new DrawableSpinner(spinner); return null; } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index c7f75e44fa..6347cf9da2 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -80,30 +80,30 @@ namespace osu.Game.Rulesets.Taiko.Scoring foreach (var obj in beatmap.HitObjects) { - if (obj is Hit) + switch (obj) { - AddJudgement(new TaikoJudgement { Result = HitResult.Great }); - if (obj.IsStrong) - AddJudgement(new TaikoStrongHitJudgement()); - } - else if (obj is DrumRoll) - { - for (int i = 0; i < ((DrumRoll)obj).NestedHitObjects.OfType().Count(); i++) - { - AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great }); + case Hit _: + AddJudgement(new TaikoJudgement { Result = HitResult.Great }); + if (obj.IsStrong) + AddJudgement(new TaikoStrongHitJudgement()); + break; + case DrumRoll _: + for (int i = 0; i < ((DrumRoll)obj).NestedHitObjects.OfType().Count(); i++) + { + AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great }); + + if (obj.IsStrong) + AddJudgement(new TaikoStrongHitJudgement()); + } + + AddJudgement(new TaikoJudgement { Result = HitResult.Great }); if (obj.IsStrong) AddJudgement(new TaikoStrongHitJudgement()); - } - - AddJudgement(new TaikoJudgement { Result = HitResult.Great }); - - if (obj.IsStrong) - AddJudgement(new TaikoStrongHitJudgement()); - } - else if (obj is Swell) - { - AddJudgement(new TaikoJudgement { Result = HitResult.Great }); + break; + case Swell _: + AddJudgement(new TaikoJudgement { Result = HitResult.Great }); + break; } } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 7fdd3cd1e2..8cb260776a 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -212,13 +212,15 @@ namespace osu.Game.Rulesets.Taiko.UI base.Add(h); - var barline = h as DrawableBarLine; - if (barline != null) - barlineContainer.Add(barline.CreateProxy()); - - var taikoObject = h as DrawableTaikoHitObject; - if (taikoObject != null) - topLevelHitContainer.Add(taikoObject.CreateProxiedContent()); + switch (h) + { + case DrawableBarLine barline: + barlineContainer.Add(barline.CreateProxy()); + break; + case DrawableTaikoHitObject taikoObject: + topLevelHitContainer.Add(taikoObject.CreateProxiedContent()); + break; + } } internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index e04b4d45f6..2fa4627bde 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -98,32 +98,22 @@ namespace osu.Game.Rulesets.Taiko.UI protected override DrawableHitObject GetVisualRepresentation(TaikoHitObject h) { - var centreHit = h as CentreHit; - if (centreHit != null) + switch (h) { - if (h.IsStrong) + case CentreHit centreHit when h.IsStrong: return new DrawableCentreHitStrong(centreHit); - return new DrawableCentreHit(centreHit); - } - - var rimHit = h as RimHit; - if (rimHit != null) - { - if (h.IsStrong) + case CentreHit centreHit: + return new DrawableCentreHit(centreHit); + case RimHit rimHit when h.IsStrong: return new DrawableRimHitStrong(rimHit); - return new DrawableRimHit(rimHit); + case RimHit rimHit: + return new DrawableRimHit(rimHit); + case DrumRoll drumRoll: + return new DrawableDrumRoll(drumRoll); + case Swell swell: + return new DrawableSwell(swell); } - var drumRoll = h as DrumRoll; - if (drumRoll != null) - { - return new DrawableDrumRoll(drumRoll); - } - - var swell = h as Swell; - if (swell != null) - return new DrawableSwell(swell); - return null; } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 7a227f4bfa..223ca1c904 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -73,12 +73,17 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons downloader.Download(); }; - downloader.DownloadState.ValueChanged += d => + downloader.DownloadState.ValueChanged += state => { - if (d == BeatmapSetDownloader.DownloadStatus.Downloaded) - this.FadeOut(200); - else if (d == BeatmapSetDownloader.DownloadStatus.NotDownloaded) - this.FadeIn(200); + switch (state) + { + case BeatmapSetDownloader.DownloadStatus.Downloaded: + this.FadeOut(200); + break; + case BeatmapSetDownloader.DownloadStatus.NotDownloaded: + this.FadeIn(200); + break; + } }; } } diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 753cd33cc6..5a5b90ee25 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -188,16 +188,17 @@ namespace osu.Game.Overlays int optionCount = 0; int selectedOption = -1; - if (description.RawValue is bool) + switch (description.RawValue) { - optionCount = 1; - if ((bool)description.RawValue) selectedOption = 0; - } - else if (description.RawValue is Enum) - { - var values = Enum.GetValues(description.RawValue.GetType()); - optionCount = values.Length; - selectedOption = Convert.ToInt32(description.RawValue); + case bool val: + optionCount = 1; + if (val) selectedOption = 0; + break; + case Enum _: + var values = Enum.GetValues(description.RawValue.GetType()); + optionCount = values.Length; + selectedOption = Convert.ToInt32(description.RawValue); + break; } textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre; diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 8f9651ab09..0c9e03cedd 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -62,12 +62,16 @@ namespace osu.Game.Rulesets.Difficulty IEnumerable createDifficultyAdjustmentModCombinations(IEnumerable currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0) { - // Initial-case: Empty current set - if (currentSetCount == 0) - yield return new NoModMod(); - - if (currentSetCount == 1) - yield return currentSet.Single(); + switch (currentSetCount) + { + case 0: + // Initial-case: Empty current set + yield return new NoModMod(); + break; + case 1: + yield return currentSet.Single(); + break; + } if (currentSetCount > 1) yield return new MultiMod(currentSet.ToArray()); From 827c5c4939e1a2abbcc5888fe9754f2a9fd1e086 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 15:14:03 +0900 Subject: [PATCH 32/48] Remove scroll direction from ScrolingPlayfield constructor --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 +++- osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs | 2 +- osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs | 2 +- osu.Game.Rulesets.Mania/UI/Column.cs | 3 +-- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 6 ++---- osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs | 5 ----- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 5 ++--- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 3 ++- osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 1 - osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 7 ++++--- 11 files changed, 17 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 9eca8f6871..ea3b6fb0e0 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -23,8 +23,10 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; public CatchPlayfield(BeatmapDifficulty difficulty, Func> getVisualRepresentation) - : base(ScrollingDirection.Down, BASE_WIDTH) + : base(BASE_WIDTH) { + Direction.Value = ScrollingDirection.Down; + Container explodingFruitContainer; Anchor = Anchor.TopCentre; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index de2bfaed9c..cceee718ca 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createColumn(ScrollingDirection direction, ManiaAction action) { - var column = new Column(direction) + var column = new Column { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index 8046c46fc1..b1bb7f5187 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -105,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) { VisibleTimeRange = { Value = 2000 } }; + var stage = new ManiaStage(0, new StageDefinition { Columns = 2 }, ref action, ref specialAction) { VisibleTimeRange = { Value = 2000 } }; stages.Add(stage); return new ScrollingTestContainer(direction) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 8465258055..063531da45 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -32,8 +32,7 @@ namespace osu.Game.Rulesets.Mania.UI protected override Container Content => hitObjectArea; - public Column(ScrollingDirection direction) - : base(direction) + public Column() { RelativeSizeAxes = Axes.Y; Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 2f8ad7b17e..d6781a6e8f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -12,7 +12,6 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Configuration; -using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { @@ -21,8 +20,7 @@ namespace osu.Game.Rulesets.Mania.UI public List Columns => stages.SelectMany(x => x.Columns).ToList(); private readonly List stages = new List(); - public ManiaPlayfield(ScrollingDirection direction, List stageDefinitions) - : base(direction) + public ManiaPlayfield(List stageDefinitions) { if (stageDefinitions == null) throw new ArgumentNullException(nameof(stageDefinitions)); @@ -42,7 +40,7 @@ namespace osu.Game.Rulesets.Mania.UI int firstColumnIndex = 0; for (int i = 0; i < stageDefinitions.Count; i++) { - var newStage = new ManiaStage(direction, firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); + var newStage = new ManiaStage(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 abc9705119..aaa4505b5e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.UI return dependencies; } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(scrollingInfo.Direction, Beatmap.Stages) + protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs index f1ff0665cd..4d6c5a747a 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingPlayfield.cs @@ -11,11 +11,6 @@ namespace osu.Game.Rulesets.Mania.UI { private readonly IBindable direction = new Bindable(); - public ManiaScrollingPlayfield(ScrollingDirection direction) - : base(direction) - { - } - [BackgroundDependencyLoader] private void load(IScrollingInfo scrollingInfo) { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 4c7deb4567..a0ff8780ad 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -43,8 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int firstColumnIndex; - public ManiaStage(ScrollingDirection direction, int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) - : base(direction) + public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) { this.firstColumnIndex = firstColumnIndex; @@ -124,7 +123,7 @@ namespace osu.Game.Rulesets.Mania.UI for (int i = 0; i < definition.Columns; i++) { var isSpecial = definition.IsSpecialColumn(i); - var column = new Column(direction) + var column = new Column { IsSpecial = isSpecial, Action = { Value = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 7fdd3cd1e2..a47c433631 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -58,8 +58,9 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Box background; public TaikoPlayfield(ControlPointInfo controlPoints) - : base(ScrollingDirection.Left) { + Direction.Value = ScrollingDirection.Left; + AddRangeInternal(new Drawable[] { backgroundContainer = new Container diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 9b48ec17bd..bbc9d2b860 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -117,7 +117,6 @@ namespace osu.Game.Tests.Visual public new readonly ScrollingDirection Direction; public TestPlayfield(ScrollingDirection direction) - : base(direction) { Direction = direction; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index cfcfca157b..7146ad8064 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -57,22 +57,23 @@ namespace osu.Game.Rulesets.UI.Scrolling /// public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + /// + /// The direction in which s in this should scroll. + /// protected readonly Bindable Direction = new Bindable(); /// /// Creates a new . /// - /// The direction in which s in this container should scroll. /// The width to scale the internal coordinate space to. /// May be null if scaling based on is desired. If is also null, no scaling will occur. /// /// The height to scale the internal coordinate space to. /// May be null if scaling based on is desired. If is also null, no scaling will occur. /// - protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null, float? customHeight = null) + protected ScrollingPlayfield(float? customWidth = null, float? customHeight = null) : base(customWidth, customHeight) { - Direction.Value = direction; } [BackgroundDependencyLoader] From 9f933187e9cc071d5ad269287ecebc5467b37b36 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Jul 2018 16:33:08 +0900 Subject: [PATCH 33/48] Apply review feedback --- .../Difficulty/CatchDifficultyCalculator.cs | 4 ++-- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 4 ++-- osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 978b71576e..a763989750 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty switch (hitObject) { // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. - case Fruit _: - difficultyHitObjects.Add(new CatchDifficultyHitObject((CatchHitObject)hitObject, halfCatchWidth)); + case Fruit fruit: + difficultyHitObjects.Add(new CatchDifficultyHitObject(fruit, halfCatchWidth)); break; case JuiceStream _: difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth))); diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 6347cf9da2..cea59c3fea 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -87,8 +87,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring if (obj.IsStrong) AddJudgement(new TaikoStrongHitJudgement()); break; - case DrumRoll _: - for (int i = 0; i < ((DrumRoll)obj).NestedHitObjects.OfType().Count(); i++) + case DrumRoll drumRoll: + for (int i = 0; i < drumRoll.NestedHitObjects.OfType().Count(); i++) { AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great }); diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 0c9e03cedd..0de0a620e3 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -71,11 +71,11 @@ namespace osu.Game.Rulesets.Difficulty case 1: yield return currentSet.Single(); break; + default: + yield return new MultiMod(currentSet.ToArray()); + break; } - if (currentSetCount > 1) - yield return new MultiMod(currentSet.ToArray()); - // Apply mods in the adjustment set recursively. Using the entire adjustment set would result in duplicate multi-mod mod // combinations in further recursions, so a moving subset is used to eliminate this effect for (int i = adjustmentSetStart; i < adjustmentSet.Length; i++) From c6816a6cf3f638b5ee031280f6be7b1c9e79c4e9 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 17 Jul 2018 17:00:28 +0900 Subject: [PATCH 34/48] Fix potential quadratic complexity in taiko autoplay --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index cea59c3fea..7dd50ab8b8 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -88,7 +88,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring AddJudgement(new TaikoStrongHitJudgement()); break; case DrumRoll drumRoll: - for (int i = 0; i < drumRoll.NestedHitObjects.OfType().Count(); i++) + var count = drumRoll.NestedHitObjects.OfType().Count(); + for (int i = 0; i < count; i++) { AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great }); From e3fb781a5a712883a83380b2023e2e09f11d4b83 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jul 2018 12:58:28 +0900 Subject: [PATCH 35/48] Fix ArchiveModelManager's model import method not running import logic --- osu.Game/Beatmaps/BeatmapManager.cs | 3 +- osu.Game/Database/ArchiveModelManager.cs | 42 ++++++++++++-------- osu.Game/Database/SingletonContextFactory.cs | 2 +- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 78042349d1..4ff16b604a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -91,7 +91,8 @@ namespace osu.Game.Beatmaps protected override void Populate(BeatmapSetInfo model, ArchiveReader archive) { - model.Beatmaps = createBeatmapDifficulties(archive); + if (archive != null) + model.Beatmaps = createBeatmapDifficulties(archive); foreach (BeatmapInfo b in model.Beatmaps) { diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index cbf0df3227..0465c0ad73 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework.IO.File; using osu.Framework.Logging; @@ -175,7 +176,24 @@ namespace osu.Game.Database /// The archive to be imported. public TModel Import(ArchiveReader archive) { - TModel item = null; + try + { + return Import(CreateModel(archive), archive); + } + catch (Exception e) + { + Logger.Error(e, $"Model creation of {archive.Name} failed.", LoggingTarget.Database); + return null; + } + } + + /// + /// Import an item from a . + /// + /// The model to be imported. + /// An optional archive to use for model population. + public TModel Import(TModel item, ArchiveReader archive = null) + { delayEvents(); try @@ -186,18 +204,16 @@ namespace osu.Game.Database { if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}"); - // create a new model (don't yet add to database) - item = CreateModel(archive); - var existing = CheckForExisting(item); if (existing != null) { - Logger.Log($"Found existing {typeof(TModel)} for {archive.Name} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); return existing; } - item.Files = createFileInfos(archive, Files); + if (archive != null) + item.Files = createFileInfos(archive, Files); Populate(item, archive); @@ -211,11 +227,11 @@ namespace osu.Game.Database } } - Logger.Log($"Import of {archive.Name} successfully completed!", LoggingTarget.Database); + Logger.Log($"Import of {item} successfully completed!", LoggingTarget.Database); } catch (Exception e) { - Logger.Error(e, $"Import of {archive.Name} failed and has been rolled back.", LoggingTarget.Database); + Logger.Error(e, $"Import of {item} failed and has been rolled back.", LoggingTarget.Database); item = null; } finally @@ -227,12 +243,6 @@ namespace osu.Game.Database return item; } - /// - /// Import an item from a . - /// - /// The model to be imported. - public void Import(TModel item) => ModelStore.Add(item); - /// /// Perform an update of the specified item. /// TODO: Support file changes. @@ -385,8 +395,8 @@ namespace osu.Game.Database /// After this method, the model should be in a state ready to commit to a store. /// /// The model to populate. - /// The archive to use as a reference for population. - protected virtual void Populate(TModel model, ArchiveReader archive) + /// The archive to use as a reference for population. May be null. + protected virtual void Populate(TModel model, [CanBeNull] ArchiveReader archive) { } diff --git a/osu.Game/Database/SingletonContextFactory.cs b/osu.Game/Database/SingletonContextFactory.cs index ce3fbf6881..a7158c0583 100644 --- a/osu.Game/Database/SingletonContextFactory.cs +++ b/osu.Game/Database/SingletonContextFactory.cs @@ -14,6 +14,6 @@ namespace osu.Game.Database public OsuDbContext Get() => context; - public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null); + public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null) { IsTransactionLeader = true }; } } From 0c242443400529b107b567c318198210f2a846f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jul 2018 16:43:46 +0900 Subject: [PATCH 36/48] Remove SingletonContextFactory It is dangerous to use this as it doesn't correctly handle contexts and can cause issues that will never actually arise in normal execution. # Conflicts: # osu.Game/Database/SingletonContextFactory.cs --- .../Visual/TestCasePlaySongSelect.cs | 7 ++++++- osu.Game/Database/DatabaseContextFactory.cs | 10 +++++----- osu.Game/Database/SingletonContextFactory.cs | 19 ------------------- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Tests/Platform/TestStorage.cs | 8 +++----- 5 files changed, 15 insertions(+), 31 deletions(-) delete mode 100644 osu.Game/Database/SingletonContextFactory.cs diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index dab7f7e037..4afb76a7e2 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -62,7 +62,12 @@ namespace osu.Game.Tests.Visual var storage = new TestStorage(@"TestCasePlaySongSelect"); // this is by no means clean. should be replacing inside of OsuGameBase somehow. - IDatabaseContextFactory factory = new SingletonContextFactory(new OsuDbContext()); + DatabaseContextFactory factory = new DatabaseContextFactory(storage); + + factory.ResetDatabase(); + + using (var usage = factory.Get()) + usage.Migrate(); Dependencies.Cache(rulesets = new RulesetStore(factory)); Dependencies.Cache(manager = new BeatmapManager(storage, factory, rulesets, null, null) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 5160239c38..c20d4569f6 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -11,7 +11,7 @@ namespace osu.Game.Database { public class DatabaseContextFactory : IDatabaseContextFactory { - private readonly GameHost host; + private readonly Storage storage; private const string database_name = @"client"; @@ -26,9 +26,9 @@ namespace osu.Game.Database private IDbContextTransaction currentWriteTransaction; - public DatabaseContextFactory(GameHost host) + public DatabaseContextFactory(Storage storage) { - this.host = host; + this.storage = storage; recycleThreadContexts(); } @@ -117,7 +117,7 @@ namespace osu.Game.Database private void recycleThreadContexts() => threadContexts = new ThreadLocal(CreateContext); - protected virtual OsuDbContext CreateContext() => new OsuDbContext(host.Storage.GetDatabaseConnectionString(database_name)) + protected virtual OsuDbContext CreateContext() => new OsuDbContext(storage.GetDatabaseConnectionString(database_name)) { Database = { AutoTransactionsEnabled = false } }; @@ -129,7 +129,7 @@ namespace osu.Game.Database recycleThreadContexts(); GC.Collect(); GC.WaitForPendingFinalizers(); - host.Storage.DeleteDatabase(database_name); + storage.DeleteDatabase(database_name); } } } diff --git a/osu.Game/Database/SingletonContextFactory.cs b/osu.Game/Database/SingletonContextFactory.cs deleted file mode 100644 index ce3fbf6881..0000000000 --- a/osu.Game/Database/SingletonContextFactory.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Database -{ - public class SingletonContextFactory : IDatabaseContextFactory - { - private readonly OsuDbContext context; - - public SingletonContextFactory(OsuDbContext context) - { - this.context = context; - } - - public OsuDbContext Get() => context; - - public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null); - } -} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index a9b74d6740..63cc883844 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -107,7 +107,7 @@ namespace osu.Game { Resources.AddStore(new DllResourceStore(@"osu.Game.Resources.dll")); - dependencies.Cache(contextFactory = new DatabaseContextFactory(Host)); + dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); diff --git a/osu.Game/Tests/Platform/TestStorage.cs b/osu.Game/Tests/Platform/TestStorage.cs index 5b31c7b4d0..a6b6b5530d 100644 --- a/osu.Game/Tests/Platform/TestStorage.cs +++ b/osu.Game/Tests/Platform/TestStorage.cs @@ -7,13 +7,11 @@ namespace osu.Game.Tests.Platform { public class TestStorage : DesktopStorage { - public TestStorage(string baseName) : base(baseName, null) + public TestStorage(string baseName) + : base(baseName, null) { } - public override string GetDatabaseConnectionString(string name) - { - return "DataSource=:memory:"; - } + public override string GetDatabaseConnectionString(string name) => "Data Source=" + GetUsablePathFor($"{(object)name}.db", true); } } From ffd3040fe2da3de865f3b28b9e10c43a9835144d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Jul 2018 14:41:07 +0900 Subject: [PATCH 37/48] Fix GameplayCursor state not restoring correctly after Show/Hide --- osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs index 35146dfe29..4d6722b61b 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs @@ -39,6 +39,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private int downCount; + private const float pressed_scale = 1.2f; + private const float released_scale = 1f; + + private float targetScale => downCount > 0 ? pressed_scale : released_scale; + public bool OnPressed(OsuAction action) { switch (action) @@ -46,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor case OsuAction.LeftButton: case OsuAction.RightButton: downCount++; - ActiveCursor.ScaleTo(1).ScaleTo(1.2f, 100, Easing.OutQuad); + ActiveCursor.ScaleTo(released_scale).ScaleTo(targetScale, 100, Easing.OutQuad); break; } @@ -60,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor case OsuAction.LeftButton: case OsuAction.RightButton: if (--downCount == 0) - ActiveCursor.ScaleTo(1, 200, Easing.OutQuad); + ActiveCursor.ScaleTo(targetScale, 200, Easing.OutQuad); break; } @@ -72,13 +77,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor protected override void PopIn() { fadeContainer.FadeTo(1, 300, Easing.OutQuint); - ActiveCursor.ScaleTo(1, 400, Easing.OutQuint); + ActiveCursor.ScaleTo(targetScale, 400, Easing.OutQuint); } protected override void PopOut() { fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); - ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint); + ActiveCursor.ScaleTo(targetScale * 0.8f, 450, Easing.OutQuint); } public class OsuCursor : Container From c2cdf12986a1e879a700b4a411b345df8a3f92ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Jul 2018 17:01:27 +0900 Subject: [PATCH 38/48] Better pause logic --- osu.Game/Rulesets/UI/RulesetContainer.cs | 13 +++++++++++++ osu.Game/Screens/Play/PauseContainer.cs | 12 ++++-------- osu.Game/Screens/Play/Player.cs | 8 ++------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index d68afdfedc..ee34e2df04 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -89,6 +89,14 @@ namespace osu.Game.Rulesets.UI Ruleset = ruleset; playfield = new Lazy(CreatePlayfield); + IsPaused.ValueChanged += paused => + { + if (HasReplayLoaded) + return; + + KeyBindingInputManager.UseParentInput = !paused; + }; + Cursor = CreateCursor(); } @@ -120,6 +128,11 @@ namespace osu.Game.Rulesets.UI public Replay Replay { get; private set; } + /// + /// Whether the game is paused. Used to block user input. + /// + public readonly BindableBool IsPaused = new BindableBool(); + /// /// Sets a replay to be used, overriding local input. /// diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index e2f133dde3..d9677e5daf 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; @@ -18,7 +19,7 @@ namespace osu.Game.Screens.Play /// public class PauseContainer : Container { - public bool IsPaused { get; private set; } + public readonly BindableBool IsPaused = new BindableBool(); public Func CheckCanPause; @@ -39,9 +40,6 @@ namespace osu.Game.Screens.Play public Action OnRetry; public Action OnQuit; - public Action OnResume; - public Action OnPause; - private readonly FramedClock framedClock; private readonly DecoupleableInterpolatingFramedClock decoupledClock; @@ -84,9 +82,8 @@ namespace osu.Game.Screens.Play // stop the seekable clock (stops the audio eventually) decoupledClock.Stop(); - IsPaused = true; + IsPaused.Value = true; - OnPause?.Invoke(); pauseOverlay.Show(); lastPauseActionTime = Time.Current; @@ -96,7 +93,7 @@ namespace osu.Game.Screens.Play { if (!IsPaused) return; - IsPaused = false; + IsPaused.Value = false; IsResuming = false; lastPauseActionTime = Time.Current; @@ -105,7 +102,6 @@ namespace osu.Game.Screens.Play decoupledClock.Seek(decoupledClock.CurrentTime); decoupledClock.Start(); - OnResume?.Invoke(); pauseOverlay.Hide(); } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fc439a48c5..e92805bf57 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -165,12 +165,6 @@ namespace osu.Game.Screens.Play OnRetry = Restart, OnQuit = Exit, CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, - OnPause = () => - { - pauseContainer.Retries = RestartCount; - hudOverlay.KeyCounter.IsCounting = !pauseContainer.IsPaused; - }, - OnResume = () => hudOverlay.KeyCounter.IsCounting = true, Children = new[] { storyboardContainer = new Container @@ -227,6 +221,8 @@ namespace osu.Game.Screens.Play hudOverlay.HoldToQuit.Action = Exit; hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded); + RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); + if (ShowStoryboard) initializeStoryboard(false); From a01361f8334f0bf2cfdfb4c76a7abf38f7a46428 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jul 2018 22:05:24 +0900 Subject: [PATCH 39/48] Set restart count --- osu.Game/Screens/Play/Player.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e92805bf57..f28ddb09a2 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -162,6 +162,7 @@ namespace osu.Game.Screens.Play { pauseContainer = new PauseContainer(offsetClock, adjustableClock) { + Retries = RestartCount, OnRetry = Restart, OnQuit = Exit, CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, From 8414fe9d05ff2e948a25e6e46d551bc0d4a92a21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jul 2018 22:19:32 +0900 Subject: [PATCH 40/48] Add key counter exceptions for paused state --- osu.Game/Screens/Play/Player.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index f28ddb09a2..28ae77a53c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -223,6 +223,7 @@ namespace osu.Game.Screens.Play hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded); RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); + RulesetContainer.IsPaused.ValueChanged += paused => hudOverlay.KeyCounter.IsCounting = !paused; if (ShowStoryboard) initializeStoryboard(false); From 41441771ae2d4cb0bc95ecceef32b3a8d2b19593 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Jul 2018 22:22:28 +0900 Subject: [PATCH 41/48] Remove unnecessary cast --- osu.Game/Tests/Platform/TestStorage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Platform/TestStorage.cs b/osu.Game/Tests/Platform/TestStorage.cs index a6b6b5530d..8391de3405 100644 --- a/osu.Game/Tests/Platform/TestStorage.cs +++ b/osu.Game/Tests/Platform/TestStorage.cs @@ -12,6 +12,6 @@ namespace osu.Game.Tests.Platform { } - public override string GetDatabaseConnectionString(string name) => "Data Source=" + GetUsablePathFor($"{(object)name}.db", true); + public override string GetDatabaseConnectionString(string name) => "Data Source=" + GetUsablePathFor($"{name}.db", true); } } From 82ddbb3f5d1126cb570110e9226d3498fd7668f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Jul 2018 01:18:07 +0900 Subject: [PATCH 42/48] Delay key count stop --- osu.Game/Screens/Play/Player.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 28ae77a53c..427519bff8 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -223,7 +223,9 @@ namespace osu.Game.Screens.Play hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded); RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); - RulesetContainer.IsPaused.ValueChanged += paused => hudOverlay.KeyCounter.IsCounting = !paused; + + // schedule to ensure we count any key presses from the current frame (which may affect gameplay). + RulesetContainer.IsPaused.ValueChanged += paused => Schedule(() => hudOverlay.KeyCounter.IsCounting = !paused); if (ShowStoryboard) initializeStoryboard(false); From 68614f1512e2becfb23b2845e90265a1d54540e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Jul 2018 13:41:09 +0900 Subject: [PATCH 43/48] Ensure online IDs are validated for imports that don't have an associated archive too --- osu.Game/Beatmaps/BeatmapManager.cs | 73 ++++++++++++----------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 4ff16b604a..3bd5c440c1 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -89,34 +89,46 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; } - protected override void Populate(BeatmapSetInfo model, ArchiveReader archive) + protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive) { if (archive != null) - model.Beatmaps = createBeatmapDifficulties(archive); + beatmapSet.Beatmaps = createBeatmapDifficulties(archive); - foreach (BeatmapInfo b in model.Beatmaps) + foreach (BeatmapInfo b in beatmapSet.Beatmaps) { // remove metadata from difficulties where it matches the set - if (model.Metadata.Equals(b.Metadata)) + if (beatmapSet.Metadata.Equals(b.Metadata)) b.Metadata = null; - // by setting the model here, we can update the noline set id below. - b.BeatmapSet = model; - - fetchAndPopulateOnlineIDs(b, model.Beatmaps); + b.BeatmapSet = beatmapSet; } // check if a set already exists with the same online id, delete if it does. - if (model.OnlineBeatmapSetID != null) + if (beatmapSet.OnlineBeatmapSetID != null) { - var existingOnlineId = beatmaps.ConsumableItems.FirstOrDefault(b => b.OnlineBeatmapSetID == model.OnlineBeatmapSetID); + var existingOnlineId = beatmaps.ConsumableItems.FirstOrDefault(b => b.OnlineBeatmapSetID == beatmapSet.OnlineBeatmapSetID); if (existingOnlineId != null) { Delete(existingOnlineId); beatmaps.PurgeDeletable(s => s.ID == existingOnlineId.ID); - Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({model.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database); + Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({beatmapSet.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database); } } + + validateOnlineIds(beatmapSet.Beatmaps); + + foreach (BeatmapInfo b in beatmapSet.Beatmaps) + fetchAndPopulateOnlineIDs(b, beatmapSet.Beatmaps); + } + + private void validateOnlineIds(List beatmaps) + { + var beatmapIds = beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID); + + // ensure all IDs are unique in this set and none match existing IDs in the local beatmap store. + if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1) || QueryBeatmaps(b => beatmapIds.Contains(b.OnlineBeatmapID)).Any()) + // remove all online IDs if any problems were found. + beatmaps.ForEach(b => b.OnlineBeatmapID = null); } protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo model) @@ -297,7 +309,7 @@ namespace osu.Game.Beatmaps /// /// The query. /// Results from the provided query. - public IEnumerable QueryBeatmaps(Expression> query) => beatmaps.Beatmaps.AsNoTracking().Where(query); + public IQueryable QueryBeatmaps(Expression> query) => beatmaps.Beatmaps.AsNoTracking().Where(query); /// /// Denotes whether an osu-stable installation is present to perform automated imports from. @@ -360,8 +372,6 @@ namespace osu.Game.Beatmaps { var beatmapInfos = new List(); - bool invalidateOnlineIDs = false; - foreach (var name in reader.Filenames.Where(f => f.EndsWith(".osu"))) { using (var raw = reader.GetStream(name)) @@ -378,38 +388,15 @@ namespace osu.Game.Beatmaps beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash(); - if (beatmap.BeatmapInfo.OnlineBeatmapID.HasValue) - { - var ourId = beatmap.BeatmapInfo.OnlineBeatmapID; - - // check that no existing beatmap in database exists that is imported with the same online beatmap ID. if so, give it precedence. - if (QueryBeatmap(b => b.OnlineBeatmapID.Value == ourId) != null) - beatmap.BeatmapInfo.OnlineBeatmapID = null; - - // check that no other beatmap in this imported set has a conflicting online beatmap ID. If so, presume *all* are incorrect. - if (beatmapInfos.Any(b => b.OnlineBeatmapID == ourId)) - invalidateOnlineIDs = true; - } - - RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); - + var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.Ruleset = ruleset; - - if (ruleset != null) - { - // TODO: this should be done in a better place once we actually need to dynamically update it. - beatmap.BeatmapInfo.StarDifficulty = ruleset.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating; - } - else - beatmap.BeatmapInfo.StarDifficulty = 0; + // TODO: this should be done in a better place once we actually need to dynamically update it. + beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; beatmapInfos.Add(beatmap.BeatmapInfo); } } - if (invalidateOnlineIDs) - beatmapInfos.ForEach(b => b.OnlineBeatmapID = null); - return beatmapInfos; } @@ -422,12 +409,12 @@ namespace osu.Game.Beatmaps /// True if population was successful. private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, IEnumerable otherBeatmaps, bool force = false) { + if (api?.State != APIState.Online) + return false; + 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 7be3a5d466bafa64a4e462a5c1ec0ca70f6d5d7b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Jul 2018 14:07:55 +0900 Subject: [PATCH 44/48] Centralise test storage logic --- osu.Game.Tests/Visual/TestCasePlaySongSelect.cs | 10 +++------- osu.Game/Tests/Platform/TestStorage.cs | 17 ----------------- osu.Game/Tests/Visual/OsuTestCase.cs | 13 +++++++++++++ 3 files changed, 16 insertions(+), 24 deletions(-) delete mode 100644 osu.Game/Tests/Platform/TestStorage.cs diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index 4afb76a7e2..b94fb42bf0 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -16,7 +16,6 @@ using osu.Game.Rulesets; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; -using osu.Game.Tests.Platform; namespace osu.Game.Tests.Visual { @@ -28,6 +27,7 @@ namespace osu.Game.Tests.Visual private RulesetStore rulesets; private WorkingBeatmap defaultBeatmap; + private DatabaseContextFactory factory; public override IReadOnlyList RequiredTypes => new[] { @@ -59,18 +59,14 @@ namespace osu.Game.Tests.Visual { TestSongSelect songSelect = null; - var storage = new TestStorage(@"TestCasePlaySongSelect"); - - // this is by no means clean. should be replacing inside of OsuGameBase somehow. - DatabaseContextFactory factory = new DatabaseContextFactory(storage); - + factory = new DatabaseContextFactory(LocalStorage); factory.ResetDatabase(); using (var usage = factory.Get()) usage.Migrate(); Dependencies.Cache(rulesets = new RulesetStore(factory)); - Dependencies.Cache(manager = new BeatmapManager(storage, factory, rulesets, null, null) + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null) { DefaultBeatmap = defaultBeatmap = Beatmap.Default }); diff --git a/osu.Game/Tests/Platform/TestStorage.cs b/osu.Game/Tests/Platform/TestStorage.cs deleted file mode 100644 index 8391de3405..0000000000 --- a/osu.Game/Tests/Platform/TestStorage.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.Framework.Platform; - -namespace osu.Game.Tests.Platform -{ - public class TestStorage : DesktopStorage - { - public TestStorage(string baseName) - : base(baseName, null) - { - } - - public override string GetDatabaseConnectionString(string name) => "Data Source=" + GetUsablePathFor($"{name}.db", true); - } -} diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index fcbab5b8f5..8e09ec849c 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -1,10 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // 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.Audio; using osu.Framework.Configuration; +using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -20,6 +22,9 @@ namespace osu.Game.Tests.Visual protected DependencyContainer Dependencies { get; private set; } + private readonly Lazy localStorage; + protected Storage LocalStorage => localStorage.Value; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -33,6 +38,11 @@ namespace osu.Game.Tests.Visual return Dependencies; } + protected OsuTestCase() + { + localStorage = new Lazy(() => new DesktopStorage($"{GetType().Name}-{Guid.NewGuid()}", null)); + } + [BackgroundDependencyLoader] private void load(AudioManager audioManager, RulesetStore rulesets) { @@ -50,6 +60,9 @@ namespace osu.Game.Tests.Visual beatmap.Disabled = true; beatmap.Value.Track.Stop(); } + + if (localStorage.IsValueCreated) + localStorage.Value.DeleteDirectory("."); } protected override ITestCaseTestRunner CreateRunner() => new OsuTestCaseTestRunner(); From 4e72794101d75c52b93acd1659d52079d5128b2b Mon Sep 17 00:00:00 2001 From: David V Date: Thu, 19 Jul 2018 15:55:38 +0200 Subject: [PATCH 45/48] Converts float to int. --- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 48512a71c2..1b6c6f5ce8 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -41,14 +41,14 @@ namespace osu.Game.Rulesets.Objects.Legacy if (type.HasFlag(ConvertHitObjectType.Circle)) { - result = CreateHit(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo); + result = CreateHit(new Vector2((int)float.Parse(split[0]), (int)float.Parse(split[1])), combo); if (split.Length > 5) readCustomSampleBanks(split[5], bankInfo); } else if (type.HasFlag(ConvertHitObjectType.Slider)) { - var pos = new Vector2(int.Parse(split[0]), int.Parse(split[1])); + var pos = new Vector2((int)float.Parse(split[0]), (int)float.Parse(split[1])); CurveType curveType = CurveType.Catmull; double length = 0; @@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Objects.Legacy readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo); } - result = CreateHold(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo, endTime + offset); + result = CreateHold(new Vector2((int)float.Parse(split[0]), (int)float.Parse(split[1])), combo, endTime + offset); } if (result == null) From 9eb69a1e768848ab304b5134d8f3ca8fcfde098a Mon Sep 17 00:00:00 2001 From: David V Date: Thu, 19 Jul 2018 17:47:55 +0200 Subject: [PATCH 46/48] Restructure + corrects converting to support all systems --- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 1b6c6f5ce8..dc1cd5ed3b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Objects.Legacy { string[] split = text.Split(','); + Vector2 pos = new Vector2((int)Convert.ToSingle(split[0], CultureInfo.InvariantCulture), (int)Convert.ToSingle(split[1], CultureInfo.InvariantCulture)); + ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]) & ~ConvertHitObjectType.ColourHax; bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); type &= ~ConvertHitObjectType.NewCombo; @@ -41,15 +43,13 @@ namespace osu.Game.Rulesets.Objects.Legacy if (type.HasFlag(ConvertHitObjectType.Circle)) { - result = CreateHit(new Vector2((int)float.Parse(split[0]), (int)float.Parse(split[1])), combo); + result = CreateHit(pos, combo); if (split.Length > 5) readCustomSampleBanks(split[5], bankInfo); } else if (type.HasFlag(ConvertHitObjectType.Slider)) { - var pos = new Vector2((int)float.Parse(split[0]), (int)float.Parse(split[1])); - CurveType curveType = CurveType.Catmull; double length = 0; var points = new List { Vector2.Zero }; @@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Objects.Legacy readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo); } - result = CreateHold(new Vector2((int)float.Parse(split[0]), (int)float.Parse(split[1])), combo, endTime + offset); + result = CreateHold(pos, combo, endTime + offset); } if (result == null) From 7fea2b3a8b683e433451c7a504de0569bfd06de8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Jul 2018 16:38:02 +0900 Subject: [PATCH 47/48] Add ToList --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 3bd5c440c1..67f02c8ac4 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -123,7 +123,7 @@ namespace osu.Game.Beatmaps private void validateOnlineIds(List beatmaps) { - var beatmapIds = beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID); + var beatmapIds = beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList(); // ensure all IDs are unique in this set and none match existing IDs in the local beatmap store. if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1) || QueryBeatmaps(b => beatmapIds.Contains(b.OnlineBeatmapID)).Any()) From 241437c819e89db8b6e06d45405d6d8fef30b689 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 20 Jul 2018 17:08:25 +0900 Subject: [PATCH 48/48] Remove unnecessary counting change logic --- osu.Game.Tests/Visual/TestCaseKeyCounter.cs | 1 - osu.Game/Screens/Play/HUDOverlay.cs | 1 - osu.Game/Screens/Play/KeyCounter.cs | 2 +- osu.Game/Screens/Play/KeyCounterCollection.cs | 3 +-- osu.Game/Screens/Play/Player.cs | 3 --- 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs index a20f67e336..b98875cd6a 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs @@ -18,7 +18,6 @@ namespace osu.Game.Tests.Visual { Origin = Anchor.Centre, Anchor = Anchor.Centre, - IsCounting = true, Children = new KeyCounter[] { new KeyCounterKeyboard(Key.Z), diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index f920b20649..4f3fe15211 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -195,7 +195,6 @@ namespace osu.Game.Screens.Play protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection { - IsCounting = true, FadeTime = 50, Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 2a0587133b..2c31e61114 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Play private Container textLayer; private SpriteText countSpriteText; - public bool IsCounting { get; set; } + public bool IsCounting { get; set; } = true; private int countPresses; public int CountPresses { diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 114ea83ba6..721d925d63 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -53,8 +53,7 @@ namespace osu.Game.Screens.Play configVisibility.BindValueChanged(_ => updateVisibility(), true); } - //further: change default values here and in KeyCounter if needed, instead of passing them in every constructor - private bool isCounting; + private bool isCounting = true; public bool IsCounting { get { return isCounting; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 427519bff8..f28ddb09a2 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -224,9 +224,6 @@ namespace osu.Game.Screens.Play RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); - // schedule to ensure we count any key presses from the current frame (which may affect gameplay). - RulesetContainer.IsPaused.ValueChanged += paused => Schedule(() => hudOverlay.KeyCounter.IsCounting = !paused); - if (ShowStoryboard) initializeStoryboard(false);