From 651706b10e4ba85bea3faba3ccf70c2736cbf5aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 16:17:20 +0900 Subject: [PATCH 001/503] Account for user/system offsets when deciding on an initial seek time Closes #3043 Remove "AllowLeadIn" flag --- osu.Game/Screens/Play/GameplayClockContainer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index c151e598f7..f6a23575e9 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -26,6 +26,10 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; + private readonly bool allowLeadIn; + + private readonly double gameplayStartTime; + /// /// The original source (usually a 's track). /// @@ -60,6 +64,8 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; + private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) { this.beatmap = beatmap; @@ -93,6 +99,9 @@ namespace osu.Game.Screens.Play userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); + adjustableClock.Seek(Math.Min(0, gameplayStartTime - totalOffset - (allowLeadIn ? beatmap.BeatmapInfo.AudioLeadIn : 0))); + adjustableClock.ProcessFrame(); + UserPlaybackRate.ValueChanged += _ => updateRate(); Seek(Math.Min(-beatmap.BeatmapInfo.AudioLeadIn, gameplayStartTime)); From d1d1c4ee7a5df46e20330b28b293dc700c9da7e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 16:13:58 +0900 Subject: [PATCH 002/503] Add lead-in tests --- .../Visual/Gameplay/TestCaseLeadIn.cs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs new file mode 100644 index 0000000000..0186ba1da1 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs @@ -0,0 +1,88 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestCaseLeadIn : RateAdjustedBeatmapTestCase + { + private Ruleset ruleset; + + private LeadInPlayer player; + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + Add(new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Depth = int.MaxValue + }); + + ruleset = rulesets.AvailableRulesets.First().CreateInstance(); + } + + [Test] + public void TestShortLeadIn() + { + AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 1000 } })); + AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == 0); + } + + [Test] + public void TestLongLeadIn() + { + AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 10000 } })); + AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); + } + + private void loadPlayerWithBeatmap(IBeatmap beatmap) + { + Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); + + LoadScreen(player = new LeadInPlayer + { + AllowPause = false, + AllowResults = false, + }); + } + + private class LeadInPlayer : Player + { + public double? FirstFrameClockTime; + + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; + + public double GameplayStartTime => DrawableRuleset.GameplayStartTime; + + public double GameplayClockTime => GameplayClockContainer.GameplayClock.CurrentTime; + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + if (!FirstFrameClockTime.HasValue) + { + FirstFrameClockTime = GameplayClockContainer.GameplayClock.CurrentTime; + AddInternal(new OsuSpriteText + { + Text = $"GameplayStartTime: {DrawableRuleset.GameplayStartTime} " + + $"LeadInTime: {Beatmap.Value.BeatmapInfo.AudioLeadIn} " + + $"FirstFrameClockTime: {FirstFrameClockTime}" + }); + } + } + } + } +} From e03a664970e39158396b478dfef1f6aa7e0574b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Mar 2019 16:18:15 +0900 Subject: [PATCH 003/503] Fix lead-in logic to match stable Also adds storyboard event priority support. --- osu.Game/Screens/Play/GameplayClock.cs | 1 - osu.Game/Screens/Play/GameplayClockContainer.cs | 8 +++++++- osu.Game/Storyboards/Storyboard.cs | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index b1948d02d5..6c9dacfc39 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -34,7 +34,6 @@ namespace osu.Game.Screens.Play public void ProcessFrame() { // we do not want to process the underlying clock. - // this is handled by PauseContainer. } public double ElapsedFrameTime => underlyingClock.ElapsedFrameTime; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index f6a23575e9..7abdc8ef66 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -99,7 +99,13 @@ namespace osu.Game.Screens.Play userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); - adjustableClock.Seek(Math.Min(0, gameplayStartTime - totalOffset - (allowLeadIn ? beatmap.BeatmapInfo.AudioLeadIn : 0))); + double startTime = -beatmap.BeatmapInfo.AudioLeadIn; + + startTime = Math.Min(startTime, beatmap.Storyboard.FirstEventTime); + startTime = Math.Min(startTime, gameplayStartTime); + startTime = Math.Min(startTime, 0); + + Seek(startTime); adjustableClock.ProcessFrame(); UserPlaybackRate.ValueChanged += _ => updateRate(); diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 3d988c5fe3..401a7ce25a 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -17,6 +17,8 @@ namespace osu.Game.Storyboards public bool HasDrawable => Layers.Any(l => l.Elements.Any(e => e.IsDrawable)); + public double FirstEventTime => Layers.Min(l => l.Elements.FirstOrDefault()?.StartTime ?? 0); + public Storyboard() { layers.Add("Background", new StoryboardLayer("Background", 3)); From a2fbcb2bd39e756503d6e98a9cf25fb57dba021e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 May 2019 15:58:46 +0900 Subject: [PATCH 004/503] Fix rebase regressions --- osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs | 14 ++++++++------ osu.Game/Screens/Play/GameplayClockContainer.cs | 6 ------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs index 0186ba1da1..33f1e4062f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCaseLeadIn : RateAdjustedBeatmapTestCase + public class TestCaseLeadIn : RateAdjustedBeatmapTestScene { private Ruleset ruleset; @@ -52,15 +52,16 @@ namespace osu.Game.Tests.Visual.Gameplay { Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); - LoadScreen(player = new LeadInPlayer - { - AllowPause = false, - AllowResults = false, - }); + LoadScreen(player = new LeadInPlayer()); } private class LeadInPlayer : Player { + public LeadInPlayer() + : base(false, false) + { + } + public double? FirstFrameClockTime; public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; @@ -72,6 +73,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); + if (!FirstFrameClockTime.HasValue) { FirstFrameClockTime = GameplayClockContainer.GameplayClock.CurrentTime; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 7abdc8ef66..d718424b29 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -26,10 +26,6 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private readonly IReadOnlyList mods; - private readonly bool allowLeadIn; - - private readonly double gameplayStartTime; - /// /// The original source (usually a 's track). /// @@ -91,8 +87,6 @@ namespace osu.Game.Screens.Play GameplayClock.IsPaused.BindTo(IsPaused); } - private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From 1b5a9aecffdef0b307c3712d0d85992928b0d894 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Fri, 2 Aug 2019 23:34:25 +0800 Subject: [PATCH 005/503] Add iOS URL Scheme support --- .../Graphics/Containers/LinkFlowContainer.cs | 47 +--------------- osu.Game/Online/Chat/MessageFormatter.cs | 54 ++++++++++++++++++- osu.Game/OsuGame.cs | 22 ++++++++ osu.iOS/AppDelegate.cs | 7 ++- osu.iOS/Info.plist | 14 +++++ 5 files changed, 93 insertions(+), 51 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 15068d81c0..51a842fc84 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -86,52 +86,7 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => - { - switch (linkType) - { - case LinkAction.OpenBeatmap: - // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) - game?.ShowBeatmap(beatmapId); - break; - - case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) - game?.ShowBeatmapSet(setId); - break; - - case LinkAction.OpenChannel: - try - { - channelManager?.OpenChannel(linkArgument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); - } - - break; - - case LinkAction.OpenEditorTimestamp: - case LinkAction.JoinMultiplayerMatch: - case LinkAction.Spectate: - showNotImplementedError?.Invoke(); - break; - - case LinkAction.External: - game?.OpenUrlExternally(url); - break; - - case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) - game?.ShowUser(userId); - break; - - default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); - } - }), + Action = action ?? (() => LinkUtils.HandleLink(url, linkType, linkArgument, game, channelManager, showNotImplementedError)), }); return drawables; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 4aaffdd161..ee8f45803b 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; +using osu.Framework.Logging; namespace osu.Game.Online.Chat { @@ -98,7 +100,7 @@ namespace osu.Game.Online.Chat } } - private static LinkDetails getLinkDetails(string url) + public static LinkDetails getLinkDetails(string url) { var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); @@ -288,4 +290,54 @@ namespace osu.Game.Online.Chat public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; } + + public static class LinkUtils + { + public static void HandleLink(string url, LinkAction linkType, string linkArgument, OsuGame game, ChannelManager channelManager = null, Action showNotImplementedError = null) + { + switch (linkType) + { + case LinkAction.OpenBeatmap: + // TODO: proper query params handling + if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) + game?.ShowBeatmap(beatmapId); + break; + + case LinkAction.OpenBeatmapSet: + if (int.TryParse(linkArgument, out int setId)) + game?.ShowBeatmapSet(setId); + break; + + case LinkAction.OpenChannel: + try + { + channelManager?.OpenChannel(linkArgument); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); + } + + break; + + case LinkAction.OpenEditorTimestamp: + case LinkAction.JoinMultiplayerMatch: + case LinkAction.Spectate: + showNotImplementedError?.Invoke(); + break; + + case LinkAction.External: + game?.OpenUrlExternally(url); + break; + + case LinkAction.OpenUserProfile: + if (long.TryParse(linkArgument, out long userId)) + game?.ShowUser(userId); + break; + + default: + throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); + } + } + } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e71dd67bf2..5dea67253d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -43,6 +43,7 @@ using osu.Game.Scoring; using osu.Game.Screens.Select; using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; +using static osu.Game.Online.Chat.MessageFormatter; namespace osu.Game { @@ -90,6 +91,8 @@ namespace osu.Game private IntroScreen introScreen; + private bool loaded = false; + private Bindable configRuleset; private Bindable configSkin; @@ -190,10 +193,29 @@ namespace osu.Game Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); Beatmap.BindValueChanged(beatmapChanged, true); + + loaded = true; } private ExternalLinkOpener externalLinkOpener; + public void HandleUrl(string url) + { + Logger.Log($"Request to handle url: {url}"); + if (loaded) + { + Action showNotImplementedError = () => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + }); + LinkDetails linkDetails = getLinkDetails(url); + Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); + } + else + Scheduler.AddDelayed(() => HandleUrl(url), 1000); + } + public void OpenUrlExternally(string url) { if (url.StartsWith("/")) diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 9ef21e014c..e727305997 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Threading.Tasks; using Foundation; using osu.Framework.iOS; -using osu.Game; +using osu.Framework.Threading; using UIKit; namespace osu.iOS @@ -16,9 +15,9 @@ namespace osu.iOS protected override Framework.Game CreateGame() => game = new OsuGameIOS(); - public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) + public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) { - Task.Run(() => game.Import(url.Path)); + game.HandleUrl(url.AbsoluteString); return true; } } diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 4fbc67e27b..5fe8cd6d5b 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -107,5 +107,19 @@ + UIFileSharingEnabled + + CFBundleURLTypes + + + CFBundleURLSchemes + + osu + osump + + CFBundleTypeRole + Editor + + From 471103fd101180e78f2d54fc34d96cb5198dcada Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Sat, 3 Aug 2019 00:00:22 +0800 Subject: [PATCH 006/503] Fix code format --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 1 - osu.Game/Online/Chat/MessageFormatter.cs | 2 +- osu.Game/OsuGame.cs | 8 +++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 51a842fc84..ab4629cfff 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Framework.Logging; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Users; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index ee8f45803b..347139975e 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -100,7 +100,7 @@ namespace osu.Game.Online.Chat } } - public static LinkDetails getLinkDetails(string url) + public static LinkDetails GetLinkDetails(string url) { var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5dea67253d..fa68142fea 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -91,7 +91,7 @@ namespace osu.Game private IntroScreen introScreen; - private bool loaded = false; + private bool loaded; private Bindable configRuleset; @@ -193,8 +193,6 @@ namespace osu.Game Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); Beatmap.BindValueChanged(beatmapChanged, true); - - loaded = true; } private ExternalLinkOpener externalLinkOpener; @@ -202,6 +200,7 @@ namespace osu.Game public void HandleUrl(string url) { Logger.Log($"Request to handle url: {url}"); + if (loaded) { Action showNotImplementedError = () => notifications?.Post(new SimpleNotification @@ -402,6 +401,8 @@ namespace osu.Game protected override void LoadComplete() { + loaded = false; + base.LoadComplete(); // The next time this is updated is in UpdateAfterChildren, which occurs too late and results @@ -597,6 +598,7 @@ namespace osu.Game settings.State.ValueChanged += _ => updateScreenOffset(); notifications.State.ValueChanged += _ => updateScreenOffset(); + loaded = true; } public class GameIdleTracker : IdleTracker From c9e14c8f063afae562789111864fc094601a9202 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Sat, 3 Aug 2019 19:46:57 +0800 Subject: [PATCH 007/503] Fix typo --- osu.Game/Online/Chat/MessageFormatter.cs | 4 ++-- osu.Game/OsuGame.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 347139975e..73396ce4d2 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -78,7 +78,7 @@ namespace osu.Game.Online.Chat //since we just changed the line display text, offset any already processed links. result.Links.ForEach(l => l.Index -= l.Index > index ? m.Length - displayText.Length : 0); - var details = getLinkDetails(linkText); + var details = GetLinkDetails(linkText); result.Links.Add(new Link(linkText, index, displayText.Length, linkActionOverride ?? details.Action, details.Argument)); //adjust the offset for processing the current matches group. @@ -95,7 +95,7 @@ namespace osu.Game.Online.Chat var link = m.Groups["link"].Value; var indexLength = link.Length; - var details = getLinkDetails(link); + var details = GetLinkDetails(link); result.Links.Add(new Link(link, index, indexLength, details.Action, details.Argument)); } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fa68142fea..c478ad0a57 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -208,7 +208,7 @@ namespace osu.Game Text = @"This link type is not yet supported!", Icon = FontAwesome.Solid.LifeRing, }); - LinkDetails linkDetails = getLinkDetails(url); + LinkDetails linkDetails = GetLinkDetails(url); Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); } else From 0fe6585975a7efdf6b00a73f7be41593c7ea6e20 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Mon, 5 Aug 2019 22:30:35 +0800 Subject: [PATCH 008/503] Fix iOS importing --- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.Game/OsuGame.cs | 24 ++++++++---------------- osu.iOS/AppDelegate.cs | 6 +++++- osu.iOS/Info.plist | 2 ++ osu.iOS/OsuGameIOS.cs | 2 ++ 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index efb76deff8..37ea7b2ca9 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -54,7 +54,7 @@ namespace osu.Game.Database public virtual string[] HandledExtensions => new[] { ".zip" }; - public virtual bool SupportsImportFromStable => RuntimeInfo.IsDesktop; + public virtual bool SupportsImportFromStable => (RuntimeInfo.IsDesktop || RuntimeInfo.OS == RuntimeInfo.Platform.iOS); protected readonly FileStore Files; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b64f04de2a..846677a0a9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -91,8 +91,6 @@ namespace osu.Game private IntroScreen introScreen; - private bool loaded; - private Bindable configRuleset; private Bindable configSkin; @@ -201,18 +199,15 @@ namespace osu.Game { Logger.Log($"Request to handle url: {url}"); - if (loaded) + Action showNotImplementedError = () => notifications?.Post(new SimpleNotification { - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); - LinkDetails linkDetails = GetLinkDetails(url); - Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); - } - else - Scheduler.AddDelayed(() => HandleUrl(url), 1000); + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + }); + + LinkDetails linkDetails = GetLinkDetails(url); + + Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); } public void OpenUrlExternally(string url) @@ -403,8 +398,6 @@ namespace osu.Game protected override void LoadComplete() { - loaded = false; - base.LoadComplete(); // The next time this is updated is in UpdateAfterChildren, which occurs too late and results @@ -600,7 +593,6 @@ namespace osu.Game settings.State.ValueChanged += _ => updateScreenOffset(); notifications.State.ValueChanged += _ => updateScreenOffset(); - loaded = true; } public class GameIdleTracker : IdleTracker diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index e727305997..07e0245195 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading.Tasks; using Foundation; using osu.Framework.iOS; using osu.Framework.Threading; @@ -17,7 +18,10 @@ namespace osu.iOS public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) { - game.HandleUrl(url.AbsoluteString); + if (url.IsFileUrl) + Task.Run(() => game.Import(url.Path)); + else + Task.Run(() => game.HandleUrl(url.AbsoluteString)); return true; } } diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index f3067bdcec..5fe8cd6d5b 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -14,6 +14,8 @@ 0.1.0 LSRequiresIPhoneOS + LSSupportsOpeningDocumentsInPlace + MinimumOSVersion 10.0 UIDeviceFamily diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index 6cf18df9a6..ac66357fc9 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -3,12 +3,14 @@ using System; using Foundation; +using osu.Framework.Platform; using osu.Game; namespace osu.iOS { public class OsuGameIOS : OsuGame { + public override Storage GetStorageForStableInstall() => Storage; public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); } } From 87974850ddcfdbd55cb332b72016c21f880c91a6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 7 Aug 2019 08:42:43 +0300 Subject: [PATCH 009/503] Initial implementation --- .../Online/TestSceneLeaderboardModSelector.cs | 63 ++++++++ .../BeatmapSet/LeaderboardModSelector.cs | 136 ++++++++++++++++++ osu.Game/Overlays/Mods/ModButton.cs | 2 +- osu.Game/Rulesets/Mods/ModType.cs | 3 +- osu.Game/Rulesets/UI/ModIcon.cs | 27 ++-- 5 files changed, 213 insertions(+), 18 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs create mode 100644 osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs new file mode 100644 index 0000000000..eb7fe5591d --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Overlays.BeatmapSet; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Bindables; +using osu.Game.Rulesets; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneLeaderboardModSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(LeaderboardModSelector), + }; + + public TestSceneLeaderboardModSelector() + { + LeaderboardModSelector modSelector; + FillFlowContainer selectedMods; + Bindable ruleset = new Bindable(); + + Add(selectedMods = new FillFlowContainer + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + + Add(modSelector = new LeaderboardModSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Ruleset = { BindTarget = ruleset } + }); + + modSelector.SelectedMods.BindValueChanged(mods => + { + selectedMods.Clear(); + + foreach (var mod in mods.NewValue) + selectedMods.Add(new SpriteText + { + Text = mod.Acronym, + }); + }); + + AddStep("osu mods", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania mods", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko mods", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch mods", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("Deselect all", () => modSelector.DeselectAll()); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs new file mode 100644 index 0000000000..99c51813c5 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -0,0 +1,136 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Framework.Bindables; +using System.Collections.Generic; +using osu.Game.Rulesets; +using osuTK; +using osu.Game.Rulesets.UI; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; +using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class LeaderboardModSelector : Container + { + public readonly Bindable> SelectedMods = new Bindable>(); + public readonly Bindable Ruleset = new Bindable(); + + private readonly FillFlowContainer modsContainer; + + public LeaderboardModSelector() + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + Child = modsContainer = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Full, + Spacing = new Vector2(4), + }; + + Ruleset.BindValueChanged(onRulesetChanged); + } + + private void onRulesetChanged(ValueChangedEvent ruleset) + { + SelectedMods.Value = new List(); + + modsContainer.Clear(); + + if (ruleset.NewValue == null) + return; + + modsContainer.Add(new ModButton(new NoMod())); + + foreach (var mod in ruleset.NewValue.CreateInstance().GetAllMods()) + if (mod.Ranked) + modsContainer.Add(new ModButton(mod)); + + foreach (var mod in modsContainer) + mod.OnSelectionChanged += selectionChanged; + } + + private void selectionChanged(Mod mod, bool selected) + { + var mods = SelectedMods.Value.ToList(); + + if (selected) + mods.Add(mod); + else + mods.Remove(mod); + + SelectedMods.Value = mods; + } + + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + + private class ModButton : ModIcon + { + private const float mod_scale = 0.4f; + private const int duration = 200; + + public readonly BindableBool Selected = new BindableBool(); + public Action OnSelectionChanged; + + public ModButton(Mod mod) + : base(mod) + { + Scale = new Vector2(mod_scale); + Add(new HoverClickSounds()); + + Selected.BindValueChanged(selected => + { + updateState(); + OnSelectionChanged?.Invoke(mod, selected.NewValue); + }, true); + } + + protected override bool OnClick(ClickEvent e) + { + Selected.Value = !Selected.Value; + return base.OnClick(e); + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateState(); + } + + private void updateState() + { + this.FadeColour(IsHovered || Selected.Value ? Color4.White : Color4.Gray, duration, Easing.OutQuint); + } + } + + private class NoMod : Mod + { + public override string Name => "NoMod"; + + public override string Acronym => "NM"; + + public override double ScoreMultiplier => 1; + + public override IconUsage Icon => FontAwesome.Solid.Ban; + + public override ModType Type => ModType.Custom; + } + } +} diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index fa1ee500a8..7b8745cf42 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Mods } } - foregroundIcon.Highlighted = Selected; + foregroundIcon.Highlighted.Value = Selected; SelectionChanged?.Invoke(SelectedMod); return true; diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index e3c82e42f5..1cdc4415ac 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods Conversion, Automation, Fun, - System + System, + Custom } } diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 86feea09a8..962263adba 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -11,11 +11,14 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osuTK; +using osu.Framework.Bindables; namespace osu.Game.Rulesets.UI { public class ModIcon : Container, IHasTooltip { + public readonly BindableBool Highlighted = new BindableBool(); + private readonly SpriteIcon modIcon; private readonly SpriteIcon background; @@ -96,27 +99,19 @@ namespace osu.Game.Rulesets.UI backgroundColour = colours.Pink; highlightedColour = colours.PinkLight; break; - } - applyStyle(); - } - - private bool highlighted; - - public bool Highlighted - { - get => highlighted; - - set - { - highlighted = value; - applyStyle(); + case ModType.Custom: + backgroundColour = colours.Gray6; + highlightedColour = colours.Gray7; + modIcon.Colour = colours.Yellow; + break; } } - private void applyStyle() + protected override void LoadComplete() { - background.Colour = highlighted ? highlightedColour : backgroundColour; + base.LoadComplete(); + Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); } } } From 411916d4a31b39725b58cbc549fd0a9001e691f5 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 7 Aug 2019 19:32:48 +0800 Subject: [PATCH 010/503] Move static method to Game class --- .../Graphics/Containers/LinkFlowContainer.cs | 2 +- osu.Game/Online/Chat/MessageFormatter.cs | 52 ------------------ osu.Game/OsuGame.cs | 55 +++++++++++++++++-- 3 files changed, 52 insertions(+), 57 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index ab4629cfff..ca9ffd06c6 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -85,7 +85,7 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => LinkUtils.HandleLink(url, linkType, linkArgument, game, channelManager, showNotImplementedError)), + Action = action ?? (() => game.HandleLink(url, linkType, linkArgument)), }); return drawables; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 73396ce4d2..c875150091 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -3,9 +3,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text.RegularExpressions; -using osu.Framework.Logging; namespace osu.Game.Online.Chat { @@ -290,54 +288,4 @@ namespace osu.Game.Online.Chat public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; } - - public static class LinkUtils - { - public static void HandleLink(string url, LinkAction linkType, string linkArgument, OsuGame game, ChannelManager channelManager = null, Action showNotImplementedError = null) - { - switch (linkType) - { - case LinkAction.OpenBeatmap: - // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) - game?.ShowBeatmap(beatmapId); - break; - - case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) - game?.ShowBeatmapSet(setId); - break; - - case LinkAction.OpenChannel: - try - { - channelManager?.OpenChannel(linkArgument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); - } - - break; - - case LinkAction.OpenEditorTimestamp: - case LinkAction.JoinMultiplayerMatch: - case LinkAction.Spectate: - showNotImplementedError?.Invoke(); - break; - - case LinkAction.External: - game?.OpenUrlExternally(url); - break; - - case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) - game?.ShowUser(userId); - break; - - default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); - } - } - } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 846677a0a9..43f3f1f5b5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -195,19 +195,66 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleUrl(string url) + public void HandleLink(string url, LinkAction linkType, string linkArgument) { - Logger.Log($"Request to handle url: {url}"); - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification { Text = @"This link type is not yet supported!", Icon = FontAwesome.Solid.LifeRing, }); + switch (linkType) + { + case LinkAction.OpenBeatmap: + // TODO: proper query params handling + if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) + ShowBeatmap(beatmapId); + break; + + case LinkAction.OpenBeatmapSet: + if (int.TryParse(linkArgument, out int setId)) + ShowBeatmapSet(setId); + break; + + case LinkAction.OpenChannel: + try + { + channelManager.OpenChannel(linkArgument); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); + } + + break; + + case LinkAction.OpenEditorTimestamp: + case LinkAction.JoinMultiplayerMatch: + case LinkAction.Spectate: + showNotImplementedError?.Invoke(); + break; + + case LinkAction.External: + OpenUrlExternally(url); + break; + + case LinkAction.OpenUserProfile: + if (long.TryParse(linkArgument, out long userId)) + ShowUser(userId); + break; + + default: + throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); + } + } + + public void HandleUrl(string url) + { + Logger.Log($"Request to handle url: {url}"); + LinkDetails linkDetails = GetLinkDetails(url); - Schedule(() => LinkUtils.HandleLink(url, linkDetails.Action, linkDetails.Argument, this, channelManager, showNotImplementedError)); + Schedule(() => HandleLink(url, linkDetails.Action, linkDetails.Argument)); } public void OpenUrlExternally(string url) From 37e430177384e047ce2ce932b280a22583c7d223 Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 7 Aug 2019 20:16:22 +0800 Subject: [PATCH 011/503] Fix code format --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 11 +---------- osu.Game/OsuGame.cs | 2 +- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index ca9ffd06c6..b03bc4e3aa 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -22,21 +22,12 @@ namespace osu.Game.Graphics.Containers } private OsuGame game; - private ChannelManager channelManager; - private Action showNotImplementedError; [BackgroundDependencyLoader(true)] - private void load(OsuGame game, NotificationOverlay notifications, ChannelManager channelManager) + private void load(OsuGame game) { // will be null in tests this.game = game; - this.channelManager = channelManager; - - showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); } public void AddLinks(string text, List links) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 43f3f1f5b5..82bf8abf94 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -231,7 +231,7 @@ namespace osu.Game case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - showNotImplementedError?.Invoke(); + showNotImplementedError.Invoke(); break; case LinkAction.External: From 9f72e92e0e35dc4c71ba7d6d184334fbd5b732ca Mon Sep 17 00:00:00 2001 From: DTSDAO Date: Wed, 7 Aug 2019 20:27:39 +0800 Subject: [PATCH 012/503] Fix code format --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index b03bc4e3aa..66911d9615 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -8,8 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osu.Game.Users; namespace osu.Game.Graphics.Containers From e3d52d8d7171076a28ddb67feaf130cf62a7ea3a Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 12:22:45 +0200 Subject: [PATCH 013/503] Add NewsOverlay class --- osu.Game/Overlays/NewsOverlay.cs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 osu.Game/Overlays/NewsOverlay.cs diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs new file mode 100644 index 0000000000..76040a6086 --- /dev/null +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -0,0 +1,23 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; + +namespace osu.Game.Overlays +{ + public class NewsOverlay : FullscreenOverlay + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.PurpleLightAlternative + } + }; + } + } +} From 4b0ac381b7372a0ba2f6238e2890509c158debb2 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 12:26:54 +0200 Subject: [PATCH 014/503] Add visual tests. --- .../Visual/Online/TestSceneNewsOverlay.cs | 17 +++++++++++++++++ osu.Game/Overlays/NewsOverlay.cs | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs new file mode 100644 index 0000000000..3362d4700f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -0,0 +1,17 @@ +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneNewsOverlay : OsuTestScene + { + private NewsOverlay news; + + protected override void LoadComplete() + { + base.LoadComplete(); + Add(news = new NewsOverlay()); + AddStep(@"Show", news.Show); + AddStep(@"Hide", news.Hide); + } + } +} diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 76040a6086..76b917b65d 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.PurpleLightAlternative + Colour = colours.PurpleDarkAlternative } }; } From b19c378fc8a7e5b571ed0e288b79c6e2ac628941 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 12:53:34 +0200 Subject: [PATCH 015/503] Add NewsHeader class --- osu.Game/Overlays/News/NewsHeader.cs | 71 ++++++++++++++++++++++++++++ osu.Game/Overlays/NewsOverlay.cs | 21 +++++++- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Overlays/News/NewsHeader.cs diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs new file mode 100644 index 0000000000..43a514cdc6 --- /dev/null +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -0,0 +1,71 @@ +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.News +{ + public class NewsHeader : OverlayHeader + { + private const string front_page_string = "Front Page"; + + private NewsHeaderTitle title; + + public NewsHeader() + { + TabControl.AddItem(front_page_string); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + TabControl.AccentColour = colour.Violet; + } + + protected override Drawable CreateBackground() => new NewsHeaderBackground(); + + protected override Drawable CreateContent() => new Container(); + + protected override ScreenTitle CreateTitle() => title = new NewsHeaderTitle(); + + private class NewsHeaderBackground : Sprite + { + public NewsHeaderBackground() + { + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fill; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Headers/changelog"); //using changelog bg until corresponding osu-resources pr is merged. + } + } + + private class NewsHeaderTitle : ScreenTitle + { + private const string article_string = "Article"; + + public bool IsReadingArticle + { + set => Section = value ? article_string : front_page_string; + } + + public NewsHeaderTitle() + { + Title = "News"; + IsReadingArticle = false; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Violet; + } + } + } +} diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 76b917b65d..80088a25bc 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -1,12 +1,17 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Overlays.News; namespace osu.Game.Overlays { public class NewsOverlay : FullscreenOverlay { + private NewsHeader header; + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -16,7 +21,21 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, Colour = colours.PurpleDarkAlternative - } + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + header = new NewsHeader() + }, + }, + }, }; } } From 0e5561c783344856d751338f32e876cb373cb4a0 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 16:12:42 +0200 Subject: [PATCH 016/503] Use News overlay resources --- osu.Game/Overlays/News/NewsHeader.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 43a514cdc6..fb02f7f105 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.News [BackgroundDependencyLoader] private void load(TextureStore textures) { - Texture = textures.Get(@"Headers/changelog"); //using changelog bg until corresponding osu-resources pr is merged. + Texture = textures.Get(@"Headers/news"); } } @@ -61,6 +61,8 @@ namespace osu.Game.Overlays.News IsReadingArticle = false; } + protected override Drawable CreateIcon() => new ScreenTitleIcon(@"Icons/news"); + [BackgroundDependencyLoader] private void load(OsuColour colours) { From b92e331730f2971c5fbe7b5afe0031e781c2c494 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 10 Aug 2019 17:06:52 +0200 Subject: [PATCH 017/503] Add tabcontrol logic to news overlay --- .../Visual/Online/TestSceneNewsOverlay.cs | 3 ++ osu.Game/Overlays/News/NewsHeader.cs | 35 ++++++++++++++++++- osu.Game/Overlays/NewsOverlay.cs | 13 +++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index 3362d4700f..d5273801d8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -12,6 +12,9 @@ namespace osu.Game.Tests.Visual.Online Add(news = new NewsOverlay()); AddStep(@"Show", news.Show); AddStep(@"Hide", news.Hide); + + AddStep(@"Show front page", () => news.ShowFrontPage()); + AddStep(@"Custom article", () => news.Current.Value = "Test Article 101"); } } } diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index fb02f7f105..e887d48456 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -1,10 +1,12 @@ using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using System; namespace osu.Game.Overlays.News { @@ -14,9 +16,21 @@ namespace osu.Game.Overlays.News private NewsHeaderTitle title; + public readonly Bindable Current = new Bindable(null); + + public Action ShowFrontPage; + public NewsHeader() { TabControl.AddItem(front_page_string); + + TabControl.Current.ValueChanged += e => + { + if (e.NewValue == front_page_string) + ShowFrontPage?.Invoke(); + }; + + Current.ValueChanged += showArticle; } [BackgroundDependencyLoader] @@ -25,6 +39,25 @@ namespace osu.Game.Overlays.News TabControl.AccentColour = colour.Violet; } + private void showArticle(ValueChangedEvent e) + { + if (e.OldValue != null) + TabControl.RemoveItem(e.OldValue); + + if (e.NewValue != null) + { + TabControl.AddItem(e.NewValue); + TabControl.Current.Value = e.NewValue; + + title.IsReadingArticle = true; + } + else + { + TabControl.Current.Value = front_page_string; + title.IsReadingArticle = false; + } + } + protected override Drawable CreateBackground() => new NewsHeaderBackground(); protected override Drawable CreateContent() => new Container(); @@ -52,7 +85,7 @@ namespace osu.Game.Overlays.News public bool IsReadingArticle { - set => Section = value ? article_string : front_page_string; + set => Section = value ? article_string : front_page_string; } public NewsHeaderTitle() diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 80088a25bc..1506cbb288 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -1,4 +1,5 @@ using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -12,6 +13,8 @@ namespace osu.Game.Overlays { private NewsHeader header; + public readonly Bindable Current = new Bindable(null); + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -37,6 +40,16 @@ namespace osu.Game.Overlays }, }, }; + + header.Current.BindTo(Current); + header.ShowFrontPage = ShowFrontPage; + Current.TriggerChange(); + } + + public void ShowFrontPage() + { + Current.Value = null; + Show(); } } } From 0070f6b26072b391e3989eb880261bc632ce41fb Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 14:49:08 +0300 Subject: [PATCH 018/503] Use CompositeDrawable as a parent class --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 99c51813c5..399cd4a49a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -19,7 +19,7 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardModSelector : Container + public class LeaderboardModSelector : CompositeDrawable { public readonly Bindable> SelectedMods = new Bindable>(); public readonly Bindable Ruleset = new Bindable(); @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.BeatmapSet { AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; - Child = modsContainer = new FillFlowContainer + InternalChild = modsContainer = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 21af39032749fdb8da92fd773a5063f03ab955c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 14:57:16 +0300 Subject: [PATCH 019/503] Move binding to LoadComplete --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 399cd4a49a..99c1b54467 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -38,8 +38,12 @@ namespace osu.Game.Overlays.BeatmapSet Direction = FillDirection.Full, Spacing = new Vector2(4), }; + } - Ruleset.BindValueChanged(onRulesetChanged); + protected override void LoadComplete() + { + base.LoadComplete(); + Ruleset.BindValueChanged(onRulesetChanged, true); } private void onRulesetChanged(ValueChangedEvent ruleset) From 62a91e4aaab46c458152233ef4208278dc635e4b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 15:20:21 +0300 Subject: [PATCH 020/503] Add the ability to override Highlighted action to the ModIcon --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 14 ++++++++++++-- osu.Game/Rulesets/UI/ModIcon.cs | 13 +++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 99c1b54467..03d2e6ce4b 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -92,11 +92,16 @@ namespace osu.Game.Overlays.BeatmapSet { Scale = new Vector2(mod_scale); Add(new HoverClickSounds()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); Selected.BindValueChanged(selected => { updateState(); - OnSelectionChanged?.Invoke(mod, selected.NewValue); + OnSelectionChanged?.Invoke(Mod, selected.NewValue); }, true); } @@ -120,7 +125,12 @@ namespace osu.Game.Overlays.BeatmapSet private void updateState() { - this.FadeColour(IsHovered || Selected.Value ? Color4.White : Color4.Gray, duration, Easing.OutQuint); + Highlighted.Value = (IsHovered || Selected.Value) ? true : false; + } + + protected override void OnHighlightedChange(ValueChangedEvent highlighted) + { + this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } } diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 962263adba..e713216f35 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -34,9 +34,11 @@ namespace osu.Game.Rulesets.UI public virtual string TooltipText { get; } + protected Mod Mod { get; private set; } + public ModIcon(Mod mod) { - if (mod == null) throw new ArgumentNullException(nameof(mod)); + Mod = mod ?? throw new ArgumentNullException(nameof(mod)); type = mod.Type; @@ -106,12 +108,19 @@ namespace osu.Game.Rulesets.UI modIcon.Colour = colours.Yellow; break; } + + background.Colour = backgroundColour; } protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Highlighted.BindValueChanged(OnHighlightedChange, true); + } + + protected virtual void OnHighlightedChange(ValueChangedEvent highlighted) + { + background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; } } } From b71c776e65c291df39a45a175bc8301d6e3661d7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:20:36 +0300 Subject: [PATCH 021/503] Add web-like hover behavior --- .../BeatmapSet/LeaderboardModSelector.cs | 39 +++++++++++++++++-- osu.Game/Rulesets/UI/ModIcon.cs | 2 +- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 03d2e6ce4b..1e10c41478 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -57,12 +57,13 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Add(new ModButton(new NoMod())); - foreach (var mod in ruleset.NewValue.CreateInstance().GetAllMods()) + ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => + { if (mod.Ranked) modsContainer.Add(new ModButton(mod)); + }); - foreach (var mod in modsContainer) - mod.OnSelectionChanged += selectionChanged; + modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); } private void selectionChanged(Mod mod, bool selected) @@ -74,11 +75,39 @@ namespace osu.Game.Overlays.BeatmapSet else mods.Remove(mod); + if (!mods.Any() && !IsHovered) + modsContainer.ForEach(button => button.Highlighted.Value = true); + SelectedMods.Value = mods; } + protected override bool OnHover(HoverEvent e) + { + if (!SelectedMods.Value.Any()) + dehighlightAll(); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (!SelectedMods.Value.Any()) + modsContainer.ForEach(mod => mod.Highlighted.Value = true); + } + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + private void dehighlightAll() + { + modsContainer.ForEach(button => + { + if (!button.IsHovered) + button.Highlighted.Value = false; + }); + } + private class ModButton : ModIcon { private const float mod_scale = 0.4f; @@ -98,11 +127,13 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); + Highlighted.Value = true; + Selected.BindValueChanged(selected => { updateState(); OnSelectionChanged?.Invoke(Mod, selected.NewValue); - }, true); + }); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index e713216f35..1bcd2dc780 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(OnHighlightedChange, true); + Highlighted.BindValueChanged(OnHighlightedChange); } protected virtual void OnHighlightedChange(ValueChangedEvent highlighted) From 86c9d5251faea12d24347dc68ae1c94ea3c738db Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:28:53 +0300 Subject: [PATCH 022/503] Remove unused function --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 1e10c41478..fffbc400b1 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -84,7 +84,11 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnHover(HoverEvent e) { if (!SelectedMods.Value.Any()) - dehighlightAll(); + modsContainer.ForEach(button => + { + if (!button.IsHovered) + button.Highlighted.Value = false; + }); return base.OnHover(e); } @@ -99,15 +103,6 @@ namespace osu.Game.Overlays.BeatmapSet public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); - private void dehighlightAll() - { - modsContainer.ForEach(button => - { - if (!button.IsHovered) - button.Highlighted.Value = false; - }); - } - private class ModButton : ModIcon { private const float mod_scale = 0.4f; From cf92d6b1b01174666b484580242ad99891a839e0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:32:04 +0300 Subject: [PATCH 023/503] Add highlightAll function to avoid duplication --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index fffbc400b1..1489907589 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.BeatmapSet mods.Remove(mod); if (!mods.Any() && !IsHovered) - modsContainer.ForEach(button => button.Highlighted.Value = true); + highlightAll(); SelectedMods.Value = mods; } @@ -98,11 +98,13 @@ namespace osu.Game.Overlays.BeatmapSet base.OnHoverLost(e); if (!SelectedMods.Value.Any()) - modsContainer.ForEach(mod => mod.Highlighted.Value = true); + highlightAll(); } public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + private void highlightAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = true); + private class ModButton : ModIcon { private const float mod_scale = 0.4f; From 1bfb87fcdd01536874269a16ffcf13d6e7ffcc7c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 12 Aug 2019 16:41:35 +0300 Subject: [PATCH 024/503] Remove redundant conditional ternary expression --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 1489907589..66d78f927a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -28,8 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet public LeaderboardModSelector() { - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Both; InternalChild = modsContainer = new FillFlowContainer { Anchor = Anchor.Centre, @@ -151,10 +150,7 @@ namespace osu.Game.Overlays.BeatmapSet updateState(); } - private void updateState() - { - Highlighted.Value = (IsHovered || Selected.Value) ? true : false; - } + private void updateState() => Highlighted.Value = IsHovered || Selected.Value; protected override void OnHighlightedChange(ValueChangedEvent highlighted) { From 87811afade5abfdbf6dc3a2503242f2be4be076b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Mon, 12 Aug 2019 20:16:41 +0200 Subject: [PATCH 025/503] Add missing licence headers to added files. --- osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs | 5 ++++- osu.Game/Overlays/News/NewsHeader.cs | 5 ++++- osu.Game/Overlays/NewsOverlay.cs | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index d5273801d8..546f6ac182 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -1,4 +1,7 @@ -using osu.Game.Overlays; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Overlays; namespace osu.Game.Tests.Visual.Online { diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index e887d48456..6a14828473 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 1506cbb288..b509204c58 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -1,4 +1,7 @@ -using osu.Framework.Allocation; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From 840d4741daf285b0c2541997f39b6fda309a492b Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 14 Aug 2019 20:24:36 +0200 Subject: [PATCH 026/503] Add NewsContent class and fix broken reference. --- osu.Game/Overlays/News/NewsContent.cs | 16 ++++++++++++++++ osu.Game/Overlays/News/NewsHeader.cs | 2 +- osu.Game/Overlays/NewsOverlay.cs | 10 +++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Overlays/News/NewsContent.cs diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs new file mode 100644 index 0000000000..f0763285eb --- /dev/null +++ b/osu.Game/Overlays/News/NewsContent.cs @@ -0,0 +1,16 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Overlays.News +{ + public abstract class NewsContent : FillFlowContainer + { + public NewsContent() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Padding = new MarginPadding { Bottom = 100 }; + } + } +} diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 6a14828473..27620ab523 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.News IsReadingArticle = false; } - protected override Drawable CreateIcon() => new ScreenTitleIcon(@"Icons/news"); + protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/news"); [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index b509204c58..b341321a46 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -15,6 +15,7 @@ namespace osu.Game.Overlays public class NewsOverlay : FullscreenOverlay { private NewsHeader header; + private Container content; public readonly Bindable Current = new Bindable(null); @@ -39,13 +40,20 @@ namespace osu.Game.Overlays Children = new Drawable[] { header = new NewsHeader() + { + ShowFrontPage = ShowFrontPage + }, + content = new Container() + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } }, }, }, }; header.Current.BindTo(Current); - header.ShowFrontPage = ShowFrontPage; Current.TriggerChange(); } From 46e71e9ead75227f63080ed4751e3f61228d1f40 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 14 Aug 2019 21:34:29 +0200 Subject: [PATCH 027/503] Add missing licence header --- osu.Game/Overlays/News/NewsContent.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs index f0763285eb..26f92b3825 100644 --- a/osu.Game/Overlays/News/NewsContent.cs +++ b/osu.Game/Overlays/News/NewsContent.cs @@ -1,4 +1,7 @@ -using osu.Framework.Graphics; +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; namespace osu.Game.Overlays.News From 4d1b1a4022d530d5c7fff5ceec3d04ffca641543 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 14 Aug 2019 21:52:36 +0200 Subject: [PATCH 028/503] Fix CI inspections --- osu.Game/Overlays/News/NewsContent.cs | 2 +- osu.Game/Overlays/NewsOverlay.cs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs index 26f92b3825..16a8ed84b8 100644 --- a/osu.Game/Overlays/News/NewsContent.cs +++ b/osu.Game/Overlays/News/NewsContent.cs @@ -8,7 +8,7 @@ namespace osu.Game.Overlays.News { public abstract class NewsContent : FillFlowContainer { - public NewsContent() + protected NewsContent() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index b341321a46..aadca8883e 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -15,6 +15,8 @@ namespace osu.Game.Overlays public class NewsOverlay : FullscreenOverlay { private NewsHeader header; + + //ReSharper disable NotAccessedField.Local private Container content; public readonly Bindable Current = new Bindable(null); @@ -39,11 +41,11 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new Drawable[] { - header = new NewsHeader() + header = new NewsHeader { ShowFrontPage = ShowFrontPage }, - content = new Container() + content = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, From af2ffac03a5fe99a4d62e0508e3e0f1e215d2be3 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 18 Aug 2019 14:52:26 +0200 Subject: [PATCH 029/503] Add global Top and Horizontal padding to NewsContent --- osu.Game/Overlays/News/NewsContent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/NewsContent.cs b/osu.Game/Overlays/News/NewsContent.cs index 16a8ed84b8..5ff210f9f5 100644 --- a/osu.Game/Overlays/News/NewsContent.cs +++ b/osu.Game/Overlays/News/NewsContent.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.News RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding { Bottom = 100 }; + Padding = new MarginPadding { Bottom = 100, Top = 20, Horizontal = 50 }; } } } From 0cf4db899ff94292bac6945e8296c93931f64769 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 19 Sep 2019 17:03:52 +0300 Subject: [PATCH 030/503] Few cleanups --- .../Visual/Online/TestSceneLeaderboardModSelector.cs | 9 +++++---- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 11 ++++------- osu.Game/Rulesets/UI/ModIcon.cs | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index eb7fe5591d..3a64ac79f6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -53,11 +53,12 @@ namespace osu.Game.Tests.Visual.Online }); }); - AddStep("osu mods", () => ruleset.Value = new OsuRuleset().RulesetInfo); - AddStep("mania mods", () => ruleset.Value = new ManiaRuleset().RulesetInfo); - AddStep("taiko mods", () => ruleset.Value = new TaikoRuleset().RulesetInfo); - AddStep("catch mods", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); + AddStep("null ruleset", () => ruleset.Value = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 66d78f927a..d09464aba6 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -74,10 +74,10 @@ namespace osu.Game.Overlays.BeatmapSet else mods.Remove(mod); + SelectedMods.Value = mods; + if (!mods.Any() && !IsHovered) highlightAll(); - - SelectedMods.Value = mods; } protected override bool OnHover(HoverEvent e) @@ -116,6 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet : base(mod) { Scale = new Vector2(mod_scale); + Highlighted.Value = true; Add(new HoverClickSounds()); } @@ -123,8 +124,6 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); - Highlighted.Value = true; - Selected.BindValueChanged(selected => { updateState(); @@ -152,10 +151,8 @@ namespace osu.Game.Overlays.BeatmapSet private void updateState() => Highlighted.Value = IsHovered || Selected.Value; - protected override void OnHighlightedChange(ValueChangedEvent highlighted) - { + protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); - } } private class NoMod : Mod diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index d3607757ab..b54ddf8f12 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -114,10 +114,10 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(OnHighlightedChange); + Highlighted.BindValueChanged(OnHighlightedChanged, true); } - protected virtual void OnHighlightedChange(ValueChangedEvent highlighted) + protected virtual void OnHighlightedChanged(ValueChangedEvent highlighted) { background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; } From e7118a9272600b7e4ac2ffddef8bbecab336d12d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 20 Sep 2019 23:47:21 +0300 Subject: [PATCH 031/503] Use System mod type for NoMod --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- osu.Game/Rulesets/Mods/ModType.cs | 3 +-- osu.Game/Rulesets/UI/ModIcon.cs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index d09464aba6..4b6fd5bfc2 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -165,7 +165,7 @@ namespace osu.Game.Overlays.BeatmapSet public override IconUsage Icon => FontAwesome.Solid.Ban; - public override ModType Type => ModType.Custom; + public override ModType Type => ModType.System; } } } diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index 1cdc4415ac..e3c82e42f5 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -10,7 +10,6 @@ namespace osu.Game.Rulesets.Mods Conversion, Automation, Fun, - System, - Custom + System } } diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index b54ddf8f12..19211e0c80 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.UI highlightedColour = colours.PinkLight; break; - case ModType.Custom: + case ModType.System: backgroundColour = colours.Gray6; highlightedColour = colours.Gray7; modIcon.Colour = colours.Yellow; From b8d147a3b41586c2e10556145a04aea69193e57a Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 17:42:06 +0800 Subject: [PATCH 032/503] introduce main menu background modes --- osu.Game/Configuration/BackgroundMode.cs | 12 +++++++ osu.Game/Configuration/OsuConfigManager.cs | 5 ++- .../Graphics/Backgrounds/BeatmapBackground.cs | 28 ++++++++++++++++ .../Sections/Audio/MainMenuSettings.cs | 6 ++++ .../Backgrounds/BackgroundScreenBeatmap.cs | 17 ---------- .../Backgrounds/BackgroundScreenDefault.cs | 33 +++++++++++++++++-- 6 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Configuration/BackgroundMode.cs create mode 100644 osu.Game/Graphics/Backgrounds/BeatmapBackground.cs diff --git a/osu.Game/Configuration/BackgroundMode.cs b/osu.Game/Configuration/BackgroundMode.cs new file mode 100644 index 0000000000..21554891ca --- /dev/null +++ b/osu.Game/Configuration/BackgroundMode.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Configuration +{ + public enum BackgroundMode + { + Default, + Seasonal, + Beatmap + } +} diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 64b1f2d7bc..9b964e8893 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -117,6 +117,8 @@ namespace osu.Game.Configuration Set(OsuSetting.UIHoldActivationDelay, 200, 0, 500); Set(OsuSetting.IntroSequence, IntroSequence.Triangles); + + Set(OsuSetting.BackgroundMode, BackgroundMode.Default); } public OsuConfigManager(Storage storage) @@ -186,6 +188,7 @@ namespace osu.Game.Configuration UIScale, IntroSequence, UIHoldActivationDelay, - HitLighting + HitLighting, + BackgroundMode } } diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs new file mode 100644 index 0000000000..40c6dae43c --- /dev/null +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -0,0 +1,28 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics.Textures; +using osu.Game.Beatmaps; + +namespace osu.Game.Graphics.Backgrounds +{ + public class BeatmapBackground : Background + { + public readonly WorkingBeatmap Beatmap; + + private readonly string fallbackTextureName; + + public BeatmapBackground(WorkingBeatmap beatmap, string fallbackTextureName = @"Backgrounds/bg1") + { + Beatmap = beatmap; + this.fallbackTextureName = fallbackTextureName; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName); + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs index 5ccdc952ba..76a6aafe45 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs @@ -34,6 +34,12 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Bindable = config.GetBindable(OsuSetting.IntroSequence), Items = Enum.GetValues(typeof(IntroSequence)).Cast() }, + new SettingsDropdown + { + LabelText = "Background", + Bindable = config.GetBindable(OsuSetting.BackgroundMode), + Items = Enum.GetValues(typeof(BackgroundMode)).Cast() + } }; } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 2730b0b90d..3de0ab191c 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -6,7 +6,6 @@ using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.Backgrounds; @@ -107,22 +106,6 @@ namespace osu.Game.Screens.Backgrounds return base.Equals(other) && beatmap == otherBeatmapBackground.Beatmap; } - protected class BeatmapBackground : Background - { - public readonly WorkingBeatmap Beatmap; - - public BeatmapBackground(WorkingBeatmap beatmap) - { - Beatmap = beatmap; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Sprite.Texture = Beatmap?.Background ?? textures.Get(@"Backgrounds/bg1"); - } - } - public class DimmableBackground : UserDimContainer { /// diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 2d7fe6a6a3..a8ba17ef49 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -6,6 +6,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Framework.Threading; +using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics.Backgrounds; using osu.Game.Online.API; using osu.Game.Skinning; @@ -24,6 +26,10 @@ namespace osu.Game.Screens.Backgrounds private Bindable user; private Bindable skin; + private Bindable mode; + + [Resolved] + private IBindable beatmap { get; set; } public BackgroundScreenDefault(bool animateOnEnter = true) : base(animateOnEnter) @@ -31,13 +37,15 @@ namespace osu.Game.Screens.Backgrounds } [BackgroundDependencyLoader] - private void load(IAPIProvider api, SkinManager skinManager) + private void load(IAPIProvider api, SkinManager skinManager, OsuConfigManager config) { user = api.LocalUser.GetBoundCopy(); skin = skinManager.CurrentSkin.GetBoundCopy(); + mode = config.GetBindable(OsuSetting.BackgroundMode); user.ValueChanged += _ => Next(); skin.ValueChanged += _ => Next(); + mode.ValueChanged += _ => Next(); currentDisplay = RNG.Next(0, background_count); @@ -66,9 +74,28 @@ namespace osu.Game.Screens.Backgrounds Background newBackground; if (user.Value?.IsSupporter ?? false) - newBackground = new SkinnedBackground(skin.Value, backgroundName); + { + switch (mode.Value) + { + case BackgroundMode.Beatmap: + newBackground = new BeatmapBackground(beatmap.Value, backgroundName); + break; + + default: + newBackground = new SkinnedBackground(skin.Value, backgroundName); + break; + } + } else - newBackground = new Background(backgroundName); + { + switch (mode.Value) + { + case BackgroundMode.Seasonal: + default: + newBackground = new Background(backgroundName); + break; + } + } newBackground.Depth = currentDisplay; From 03947e5b8532b21f52dcc73f755b2d31c64c000b Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 19:49:46 +0800 Subject: [PATCH 033/503] change background for ScalingContainer --- osu.Game/Graphics/Containers/ScalingContainer.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 8f07c3a656..84053ee5d9 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; @@ -154,6 +155,15 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { + private Bindable beatmap; + + [BackgroundDependencyLoader] + private void load(IBindable beatmap) + { + this.beatmap = (Bindable)beatmap; + this.beatmap.ValueChanged += _ => Next(); + } + public override void OnEntering(IScreen last) { this.FadeInFromZero(4000, Easing.OutQuint); From 0bc59e17dc30cfd240407cc3d9fc4928c55b6daa Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 21:56:32 +0800 Subject: [PATCH 034/503] remove Seasonal and apply suggestions --- osu.Game/Configuration/BackgroundMode.cs | 1 - osu.Game/Graphics/Containers/ScalingContainer.cs | 4 +--- .../Screens/Backgrounds/BackgroundScreenDefault.cs | 10 +--------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/osu.Game/Configuration/BackgroundMode.cs b/osu.Game/Configuration/BackgroundMode.cs index 21554891ca..50d54f1eb2 100644 --- a/osu.Game/Configuration/BackgroundMode.cs +++ b/osu.Game/Configuration/BackgroundMode.cs @@ -6,7 +6,6 @@ namespace osu.Game.Configuration public enum BackgroundMode { Default, - Seasonal, Beatmap } } diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 84053ee5d9..1701223f44 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -155,13 +155,11 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { - private Bindable beatmap; [BackgroundDependencyLoader] private void load(IBindable beatmap) { - this.beatmap = (Bindable)beatmap; - this.beatmap.ValueChanged += _ => Next(); + beatmap.ValueChanged += _ => Next(); } public override void OnEntering(IScreen last) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index a8ba17ef49..93590b0543 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -87,15 +87,7 @@ namespace osu.Game.Screens.Backgrounds } } else - { - switch (mode.Value) - { - case BackgroundMode.Seasonal: - default: - newBackground = new Background(backgroundName); - break; - } - } + newBackground = new Background(backgroundName); newBackground.Depth = currentDisplay; From 851e42a444d642ed08e3505f5314398db8401a67 Mon Sep 17 00:00:00 2001 From: LeNitrous Date: Tue, 24 Sep 2019 22:57:29 +0800 Subject: [PATCH 035/503] avoid memory leak --- osu.Game/Graphics/Containers/ScalingContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 1701223f44..023d295b08 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -155,11 +155,13 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { + private IBindable beatmap; [BackgroundDependencyLoader] private void load(IBindable beatmap) { - beatmap.ValueChanged += _ => Next(); + this.beatmap = beatmap.GetBoundCopy(); + this.beatmap.ValueChanged += _ => Next(); } public override void OnEntering(IScreen last) From 2d707b2b65bb4baa189e4cb68c3e9d3bbbfeff54 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 15:36:23 +0300 Subject: [PATCH 036/503] Implement PostBeatmapFavouriteRequest --- .../Requests/PostBeatmapFavouriteRequest.cs | 36 +++++++++++++++++++ .../BeatmapSet/Buttons/FavouriteButton.cs | 24 ++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs diff --git a/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs new file mode 100644 index 0000000000..f3724230cb --- /dev/null +++ b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.IO.Network; +using System.Net.Http; + +namespace osu.Game.Online.API.Requests +{ + public class PostBeatmapFavouriteRequest : APIRequest + { + private readonly int id; + private readonly BeatmapFavouriteAction action; + + public PostBeatmapFavouriteRequest(int id, BeatmapFavouriteAction action) + { + this.id = id; + this.action = action; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Post; + req.AddParameter(@"action", action.ToString().ToLowerInvariant()); + return req; + } + + protected override string Target => $@"beatmapsets/{id}/favourites"; + } + + public enum BeatmapFavouriteAction + { + Favourite, + UnFavourite + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 11f56bc163..23325b8765 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -10,6 +10,9 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons @@ -20,8 +23,11 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private readonly Bindable favourited = new Bindable(); + private PostBeatmapFavouriteRequest request; + private DimmedLoadingLayer loading; + [BackgroundDependencyLoader] - private void load() + private void load(IAPIProvider api) { Container pink; SpriteIcon icon; @@ -55,6 +61,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Size = new Vector2(18), Shadow = false, }, + loading = new DimmedLoadingLayer(), }); BeatmapSet.BindValueChanged(setInfo => @@ -67,6 +74,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons favourited.ValueChanged += favourited => { + loading.Hide(); + if (favourited.NewValue) { pink.FadeIn(200); @@ -78,6 +87,19 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons icon.Icon = FontAwesome.Regular.Heart; } }; + + Action = () => + { + if (loading.State.Value == Visibility.Visible) + return; + + loading.Show(); + + request?.Cancel(); + request = new PostBeatmapFavouriteRequest(BeatmapSet.Value?.OnlineBeatmapSetID ?? 0, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); + request.Success += () => favourited.Value = !favourited.Value; + api.Queue(request); + }; } protected override void UpdateAfterChildren() From a7dc9bb582682c0b87ea047f1da9aa6b40a45ea0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 7 Oct 2019 15:41:05 +0300 Subject: [PATCH 037/503] Add tooltip and remove pink layer --- .../BeatmapSet/Buttons/FavouriteButton.cs | 40 +++---------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 23325b8765..fcea20ef11 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -5,11 +5,9 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -17,7 +15,7 @@ using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class FavouriteButton : HeaderButton + public class FavouriteButton : HeaderButton, IHasTooltip { public readonly Bindable BeatmapSet = new Bindable(); @@ -26,33 +24,14 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private PostBeatmapFavouriteRequest request; private DimmedLoadingLayer loading; + public string TooltipText => (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; + [BackgroundDependencyLoader] private void load(IAPIProvider api) { - Container pink; SpriteIcon icon; AddRange(new Drawable[] { - pink = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0f, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"9f015f"), - }, - new Triangles - { - RelativeSizeAxes = Axes.Both, - ColourLight = OsuColour.FromHex(@"cb2187"), - ColourDark = OsuColour.FromHex(@"9f015f"), - TriangleScale = 1.5f, - }, - }, - }, icon = new SpriteIcon { Anchor = Anchor.Centre, @@ -76,16 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { loading.Hide(); - if (favourited.NewValue) - { - pink.FadeIn(200); - icon.Icon = FontAwesome.Solid.Heart; - } - else - { - pink.FadeOut(200); - icon.Icon = FontAwesome.Regular.Heart; - } + icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; }; Action = () => From 003af19e3f039985ec73565cee3d3ad7345e0e9b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:04:34 +0300 Subject: [PATCH 038/503] Introduce legacy skin configuration --- osu.Game/Skinning/LegacySkin.cs | 18 ++++++++++++++++-- osu.Game/Skinning/LegacySkinConfiguration.cs | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Skinning/LegacySkinConfiguration.cs diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index fea15458e4..25703b30dc 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,6 +26,8 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; + protected new LegacySkinConfiguration Configuration => (LegacySkinConfiguration)base.Configuration; + public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") { @@ -37,9 +39,9 @@ namespace osu.Game.Skinning Stream stream = storage?.GetStream(filename); if (stream != null) using (LineBufferedReader reader = new LineBufferedReader(stream)) - Configuration = new LegacySkinDecoder().Decode(reader); + base.Configuration = new LegacySkinDecoder().Decode(reader); else - Configuration = new DefaultSkinConfiguration(); + base.Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION }; if (storage != null) { @@ -71,6 +73,18 @@ namespace osu.Game.Skinning case GlobalSkinColour colour: return SkinUtils.As(getCustomColour(colour.ToString())); + case LegacySkinConfigurations legacy: + switch (legacy) + { + case LegacySkinConfigurations.Version: + if (Configuration.LegacyVersion.HasValue) + return SkinUtils.As(new BindableDouble(Configuration.LegacyVersion.Value)); + + break; + } + + break; + case SkinCustomColourLookup customColour: return SkinUtils.As(getCustomColour(customColour.Lookup.ToString())); diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs new file mode 100644 index 0000000000..022f613562 --- /dev/null +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Skinning +{ + public class LegacySkinConfiguration : DefaultSkinConfiguration + { + public const double LATEST_VERSION = 2.5; + + /// + /// Legacy version of this skin. + /// + public double? LegacyVersion { get; internal set; } + } + + public enum LegacySkinConfigurations + { + Version, + } +} From 7f6541672c9c3d3e30673e47c7d7a1b0ab630f1b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:05:50 +0300 Subject: [PATCH 039/503] Parse legacy version of decoded skin to numerical --- osu.Game/Skinning/LegacySkinDecoder.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index e97664e75e..75cd0a666d 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -5,14 +5,14 @@ using osu.Game.Beatmaps.Formats; namespace osu.Game.Skinning { - public class LegacySkinDecoder : LegacyDecoder + public class LegacySkinDecoder : LegacyDecoder { public LegacySkinDecoder() : base(1) { } - protected override void ParseLine(DefaultSkinConfiguration skin, Section section, string line) + protected override void ParseLine(LegacySkinConfiguration skin, Section section, string line) { if (section != Section.Colours) { @@ -32,6 +32,14 @@ namespace osu.Game.Skinning case @"Author": skin.SkinInfo.Creator = pair.Value; return; + + case @"Version": + if (pair.Value == "latest" || pair.Value == "User") + skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; + else if (double.TryParse(pair.Value, out var version)) + skin.LegacyVersion = version; + + return; } break; From 01ac19fdbb96cea3f36da3ce4b5ed39d1994658a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:06:32 +0300 Subject: [PATCH 040/503] Set legacy version of osu!classic skin to 2.0 --- osu.Game/Skinning/DefaultLegacySkin.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 4b6eea6b6e..4c68ee938f 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -20,6 +20,8 @@ namespace osu.Game.Skinning new Color4(18, 124, 255, 255), new Color4(242, 24, 57, 255), }); + + Configuration.LegacyVersion = 2.0; } public static SkinInfo Info { get; } = new SkinInfo From d15db378ce2598a66f5bdad3958d964dbd1b869b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:06:53 +0300 Subject: [PATCH 041/503] Add tests for legacy skin decoding --- osu.Game.Tests/Resources/skin-20.ini | 2 ++ osu.Game.Tests/Resources/skin-latest.ini | 2 ++ osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 11 +++++++++++ 3 files changed, 15 insertions(+) create mode 100644 osu.Game.Tests/Resources/skin-20.ini create mode 100644 osu.Game.Tests/Resources/skin-latest.ini diff --git a/osu.Game.Tests/Resources/skin-20.ini b/osu.Game.Tests/Resources/skin-20.ini new file mode 100644 index 0000000000..947b56b2f9 --- /dev/null +++ b/osu.Game.Tests/Resources/skin-20.ini @@ -0,0 +1,2 @@ +[General] +Version: 2 \ No newline at end of file diff --git a/osu.Game.Tests/Resources/skin-latest.ini b/osu.Game.Tests/Resources/skin-latest.ini new file mode 100644 index 0000000000..32f500263f --- /dev/null +++ b/osu.Game.Tests/Resources/skin-latest.ini @@ -0,0 +1,2 @@ +[General] +Version: latest \ No newline at end of file diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 0d96dd08da..8c85074456 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -56,5 +56,16 @@ namespace osu.Game.Tests.Skins Assert.AreEqual("TestValue", config.ConfigDictionary["TestLookup"]); } } + + [TestCase("skin-20.ini", 2.0)] + [TestCase("skin-latest.ini", LegacySkinConfiguration.LATEST_VERSION)] + [TestCase("skin-empty.ini", null)] + public void TestDecodeVersion(string filename, double? expected) + { + var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource(filename)) + using (var stream = new LineBufferedReader(resStream)) + Assert.AreEqual(expected, decoder.Decode(stream).LegacyVersion); + } } } From 2cf17e0bf38455d465d2f59e7c9552255dde2766 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 9 Oct 2019 23:33:25 +0300 Subject: [PATCH 042/503] Use decimal data type instead --- osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 28 +++++++++++++++---- osu.Game/Skinning/DefaultLegacySkin.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Skinning/LegacySkinConfiguration.cs | 4 +-- osu.Game/Skinning/LegacySkinDecoder.cs | 2 +- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 8c85074456..4fee6942d0 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -57,15 +57,31 @@ namespace osu.Game.Tests.Skins } } - [TestCase("skin-20.ini", 2.0)] - [TestCase("skin-latest.ini", LegacySkinConfiguration.LATEST_VERSION)] - [TestCase("skin-empty.ini", null)] - public void TestDecodeVersion(string filename, double? expected) + [Test] + public void TestDecodeSpecifiedVersion() { var decoder = new LegacySkinDecoder(); - using (var resStream = TestResources.OpenResource(filename)) + using (var resStream = TestResources.OpenResource("skin-20.ini")) using (var stream = new LineBufferedReader(resStream)) - Assert.AreEqual(expected, decoder.Decode(stream).LegacyVersion); + Assert.AreEqual(2.0m, decoder.Decode(stream).LegacyVersion); + } + + [Test] + public void TestDecodeLatestVersion() + { + var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource("skin-latest.ini")) + using (var stream = new LineBufferedReader(resStream)) + Assert.AreEqual(LegacySkinConfiguration.LATEST_VERSION, decoder.Decode(stream).LegacyVersion); + } + + [Test] + public void TestDecodeNoVersion() + { + var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource("skin-empty.ini")) + using (var stream = new LineBufferedReader(resStream)) + Assert.IsNull(decoder.Decode(stream).LegacyVersion); } } } diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 4c68ee938f..0caf2d19e9 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -21,7 +21,7 @@ namespace osu.Game.Skinning new Color4(242, 24, 57, 255), }); - Configuration.LegacyVersion = 2.0; + Configuration.LegacyVersion = 2.0m; } public static SkinInfo Info { get; } = new SkinInfo diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 25703b30dc..f6a366b21d 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -78,7 +78,7 @@ namespace osu.Game.Skinning { case LegacySkinConfigurations.Version: if (Configuration.LegacyVersion.HasValue) - return SkinUtils.As(new BindableDouble(Configuration.LegacyVersion.Value)); + return SkinUtils.As(new Bindable(Configuration.LegacyVersion.Value)); break; } diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 022f613562..051d10747b 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -5,12 +5,12 @@ namespace osu.Game.Skinning { public class LegacySkinConfiguration : DefaultSkinConfiguration { - public const double LATEST_VERSION = 2.5; + public const decimal LATEST_VERSION = 2.5m; /// /// Legacy version of this skin. /// - public double? LegacyVersion { get; internal set; } + public decimal? LegacyVersion { get; internal set; } } public enum LegacySkinConfigurations diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 75cd0a666d..ea087353a0 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -36,7 +36,7 @@ namespace osu.Game.Skinning case @"Version": if (pair.Value == "latest" || pair.Value == "User") skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; - else if (double.TryParse(pair.Value, out var version)) + else if (decimal.TryParse(pair.Value, out var version)) skin.LegacyVersion = version; return; From 937dbb7bf690c22fff07cade2d4cadd6c8c9128a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 9 Oct 2019 16:06:16 +0900 Subject: [PATCH 043/503] Initial layout for timing screen --- .../Visual/Editor/TestSceneTimingScreen.cs | 21 ++++ osu.Game/Screens/Edit/Timing/TimingScreen.cs | 97 ++++++++++++++++++- 2 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs new file mode 100644 index 0000000000..be84ae2cf9 --- /dev/null +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Edit.Timing; + +namespace osu.Game.Tests.Visual.Editor +{ + [TestFixture] + public class TestSceneTimingScreen : EditorClockTestScene + { + [BackgroundDependencyLoader] + private void load() + { + Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + Child = new TimingScreen(); + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 9ded4207e5..b723ffac9a 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,13 +1,104 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; + namespace osu.Game.Screens.Edit.Timing { - public class TimingScreen : EditorScreen + public class TimingScreen : EditorScreenWithTimeline { - public TimingScreen() + protected override Drawable CreateMainContent() => new GridContainer { - Child = new ScreenWhiteBox.UnderConstructionMessage("Timing mode"); + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Absolute, 200), + }, + Content = new[] + { + new Drawable[] + { + new ControlPointList(), + new ControlPointSettings(), + }, + } + }; + + public class ControlPointList : CompositeDrawable + { + [Resolved] + protected IBindable Beatmap { get; private set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = colours.Gray0, + RelativeSizeAxes = Axes.Both, + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new ControlPointRow(), + new ControlPointRow(), + new ControlPointRow(), + new ControlPointRow(), + new ControlPointRow(), + new ControlPointRow(), + } + }, + } + }; + } + + private class ControlPointRow : CompositeDrawable + { + public ControlPointRow() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + InternalChildren = new Drawable[] + { + new OsuSpriteText { Text = "sample row" }, + }; + } + } + } + + public class ControlPointSettings : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new Box + { + Colour = colours.Gray3, + RelativeSizeAxes = Axes.Both, + }; + } } } } From de13320a2debb7c48d46691ea5a34a0b09d722a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Oct 2019 18:46:05 +0900 Subject: [PATCH 044/503] Add initial table display --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 187 ++++++++++++++++--- 1 file changed, 160 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index b723ffac9a..be7058ae08 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,12 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Globalization; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -15,6 +21,9 @@ namespace osu.Game.Screens.Edit.Timing { public class TimingScreen : EditorScreenWithTimeline { + [Cached] + private readonly Bindable controlPoint = new Bindable(); + protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, @@ -53,37 +62,13 @@ namespace osu.Game.Screens.Edit.Timing new OsuScrollContainer { RelativeSizeAxes = Axes.Both, - Child = new FillFlowContainer + Child = new ControlPointTable { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - new ControlPointRow(), - } - }, + ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints + } } }; } - - private class ControlPointRow : CompositeDrawable - { - public ControlPointRow() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - InternalChildren = new Drawable[] - { - new OsuSpriteText { Text = "sample row" }, - }; - } - } } public class ControlPointSettings : CompositeDrawable @@ -101,4 +86,152 @@ namespace osu.Game.Screens.Edit.Timing } } } + + public class ControlPointTable : TableContainer + { + private const float horizontal_inset = 20; + private const float row_height = 25; + private const int text_size = 14; + + private readonly FillFlowContainer backgroundFlow; + + [Resolved] + private Bindable controlPoint { get; set; } + + public ControlPointTable() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Padding = new MarginPadding { Horizontal = horizontal_inset }; + RowSize = new Dimension(GridSizeMode.Absolute, row_height); + + AddInternal(backgroundFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Depth = 1f, + Padding = new MarginPadding { Horizontal = -horizontal_inset }, + Margin = new MarginPadding { Top = row_height } + }); + } + + public IReadOnlyList ControlPoints + { + set + { + Content = null; + backgroundFlow.Clear(); + + if (value?.Any() != true) + return; + + for (int i = 0; i < value.Count; i++) + { + var cp = value[i]; + backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = cp }); + } + + Columns = createHeaders(); + Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + } + } + + private TableColumn[] createHeaders() + { + var columns = new List + { + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("offset", Anchor.Centre), + new TableColumn("BPM", Anchor.Centre), + new TableColumn("Meter", Anchor.Centre), + new TableColumn("Sample Set", Anchor.Centre), + new TableColumn("Volume", Anchor.Centre), + }; + + return columns.ToArray(); + } + + private Drawable[] createContent(int index, ControlPoint controlPoint) + { + return new Drawable[] + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = $"{controlPoint.Time}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = $"{(controlPoint as TimingControlPoint)?.BeatLength.ToString(CultureInfo.InvariantCulture) ?? "-"}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = $"{(controlPoint as TimingControlPoint)?.TimeSignature.ToString() ?? "-"}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + }; + } + + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); + + private class HeaderText : OsuSpriteText + { + public HeaderText(string text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); + } + } + + public class RowBackground : OsuClickableContainer + { + private const int fade_duration = 100; + + private readonly Box hoveredBackground; + + public RowBackground() + { + RelativeSizeAxes = Axes.X; + Height = 25; + + AlwaysPresent = true; + + CornerRadius = 3; + Masking = true; + + Children = new Drawable[] + { + hoveredBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoveredBackground.Colour = colours.Blue; + } + + protected override bool OnHover(HoverEvent e) + { + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } + } } From 2dac3a6efe89934faa8cc354e5581a83bd182bd3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 16 Oct 2019 13:58:29 +0300 Subject: [PATCH 045/503] Handle hitting the maximum allowed number of favourited beatmaps --- .../BeatmapSet/Buttons/FavouriteButton.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index fcea20ef11..e2bc1ee008 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -11,6 +11,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Overlays.Notifications; using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons @@ -26,8 +27,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons public string TooltipText => (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; - [BackgroundDependencyLoader] - private void load(IAPIProvider api) + [BackgroundDependencyLoader(true)] + private void load(IAPIProvider api, NotificationOverlay notifications) { SpriteIcon icon; AddRange(new Drawable[] @@ -68,6 +69,18 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons request?.Cancel(); request = new PostBeatmapFavouriteRequest(BeatmapSet.Value?.OnlineBeatmapSetID ?? 0, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); request.Success += () => favourited.Value = !favourited.Value; + request.Failure += exception => + { + if (exception.Message == "UnprocessableEntity") + { + notifications.Post(new SimpleNotification + { + Text = @"You have too many favourited beatmaps! Please unfavourite some before trying again.", + Icon = FontAwesome.Solid.Times, + }); + loading.Hide(); + } + }; api.Queue(request); }; } From 71d45d41d1f85125dfae1171e3b5a2f954f4053d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Oct 2019 17:46:39 +0900 Subject: [PATCH 046/503] Add basic visualisation of different control point types --- .../ControlPoints/ControlPointInfo.cs | 6 + osu.Game/Screens/Edit/Timing/TimingScreen.cs | 133 +++++++++++++----- 2 files changed, 105 insertions(+), 34 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 855084ad02..68eb0ec6d1 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -36,6 +36,12 @@ namespace osu.Game.Beatmaps.ControlPoints [JsonProperty] public SortedList EffectPoints { get; private set; } = new SortedList(Comparer.Default); + public IReadOnlyList AllControlPoints => + TimingPoints + .Concat((IEnumerable)DifficultyPoints) + .Concat(SamplePoints) + .Concat(EffectPoints).ToArray(); + /// /// Finds the difficulty control point that is active at . /// diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index be7058ae08..97ec03e6dd 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,13 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Globalization; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Beatmaps; @@ -16,6 +16,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -64,7 +65,7 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.Both, Child = new ControlPointTable { - ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints + ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.AllControlPoints } } }; @@ -115,7 +116,7 @@ namespace osu.Game.Screens.Edit.Timing }); } - public IReadOnlyList ControlPoints + public IEnumerable ControlPoints { set { @@ -125,14 +126,15 @@ namespace osu.Game.Screens.Edit.Timing if (value?.Any() != true) return; - for (int i = 0; i < value.Count; i++) + var grouped = value.GroupBy(cp => cp.Time, cp => cp); + + foreach (var group in grouped) { - var cp = value[i]; - backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = cp }); + backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); } Columns = createHeaders(); - Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); } } @@ -141,41 +143,104 @@ namespace osu.Game.Screens.Edit.Timing var columns = new List { new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("offset", Anchor.Centre), - new TableColumn("BPM", Anchor.Centre), - new TableColumn("Meter", Anchor.Centre), - new TableColumn("Sample Set", Anchor.Centre), - new TableColumn("Volume", Anchor.Centre), + new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Attributes", Anchor.Centre), }; return columns.ToArray(); } - private Drawable[] createContent(int index, ControlPoint controlPoint) + private Drawable[] createContent(int index, IGrouping controlPoints) => new Drawable[] { - return new Drawable[] + new OsuSpriteText { - new OsuSpriteText + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), + Margin = new MarginPadding(10) + }, + new OsuSpriteText + { + Text = $"{controlPoints.Key:n0}ms", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), + Padding = new MarginPadding(10), + Spacing = new Vector2(10) + }, + }; + + private Drawable createAttribute(ControlPoint controlPoint) + { + if (controlPoint.AutoGenerated) + return null; + + switch (controlPoint) + { + case TimingControlPoint timing: + return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + + case DifficultyControlPoint difficulty: + + return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + + case EffectControlPoint effect: + return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + + case SampleControlPoint sample: + return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + } + + return null; + } + + private class RowAttribute : CompositeDrawable, IHasTooltip + { + private readonly string header; + private readonly string content; + + public RowAttribute(string header, string content) + { + this.header = header; + this.content = content; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.X; + + Height = 20; + + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + Masking = true; + CornerRadius = 5; + + InternalChildren = new Drawable[] { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new OsuSpriteText - { - Text = $"{controlPoint.Time}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new OsuSpriteText - { - Text = $"{(controlPoint as TimingControlPoint)?.BeatLength.ToString(CultureInfo.InvariantCulture) ?? "-"}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new OsuSpriteText - { - Text = $"{(controlPoint as TimingControlPoint)?.TimeSignature.ToString() ?? "-"}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - }; + new Box + { + Colour = colours.Yellow, + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Padding = new MarginPadding(2), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 12), + Text = header, + Colour = colours.Gray3 + }, + }; + } + + public string TooltipText => content; } protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); From ffec960b77960b855f9e8b63fc2a9b4e90814d2a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Oct 2019 17:59:54 +0900 Subject: [PATCH 047/503] Split out classes --- .../Screens/Edit/Timing/ControlPointTable.cs | 186 +++++++++++++++ osu.Game/Screens/Edit/Timing/RowAttribute.cs | 59 +++++ osu.Game/Screens/Edit/Timing/TimingScreen.cs | 219 ------------------ 3 files changed, 245 insertions(+), 219 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/ControlPointTable.cs create mode 100644 osu.Game/Screens/Edit/Timing/RowAttribute.cs diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs new file mode 100644 index 0000000000..1ff88fb5b4 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -0,0 +1,186 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Screens.Edit.Timing +{ + public class ControlPointTable : TableContainer + { + private const float horizontal_inset = 20; + private const float row_height = 25; + private const int text_size = 14; + + private readonly FillFlowContainer backgroundFlow; + + [Resolved] + private Bindable controlPoint { get; set; } + + public ControlPointTable() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Padding = new MarginPadding { Horizontal = horizontal_inset }; + RowSize = new Dimension(GridSizeMode.Absolute, row_height); + + AddInternal(backgroundFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Depth = 1f, + Padding = new MarginPadding { Horizontal = -horizontal_inset }, + Margin = new MarginPadding { Top = row_height } + }); + } + + public IEnumerable ControlPoints + { + set + { + Content = null; + backgroundFlow.Clear(); + + if (value?.Any() != true) + return; + + var grouped = value.GroupBy(cp => cp.Time, cp => cp); + + foreach (var group in grouped) + { + backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); + } + + Columns = createHeaders(); + Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + } + } + + private TableColumn[] createHeaders() + { + var columns = new List + { + new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Attributes", Anchor.Centre), + }; + + return columns.ToArray(); + } + + private Drawable[] createContent(int index, IGrouping controlPoints) => new Drawable[] + { + new OsuSpriteText + { + Text = $"#{index + 1}", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), + Margin = new MarginPadding(10) + }, + new OsuSpriteText + { + Text = $"{controlPoints.Key:n0}ms", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), + Padding = new MarginPadding(10), + Spacing = new Vector2(10) + }, + }; + + private Drawable createAttribute(ControlPoint controlPoint) + { + if (controlPoint.AutoGenerated) + return null; + + switch (controlPoint) + { + case TimingControlPoint timing: + return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + + case DifficultyControlPoint difficulty: + + return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + + case EffectControlPoint effect: + return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + + case SampleControlPoint sample: + return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + } + + return null; + } + + protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); + + private class HeaderText : OsuSpriteText + { + public HeaderText(string text) + { + Text = text.ToUpper(); + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); + } + } + + public class RowBackground : OsuClickableContainer + { + private const int fade_duration = 100; + + private readonly Box hoveredBackground; + + public RowBackground() + { + RelativeSizeAxes = Axes.X; + Height = 25; + + AlwaysPresent = true; + + CornerRadius = 3; + Masking = true; + + Children = new Drawable[] + { + hoveredBackground = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoveredBackground.Colour = colours.Blue; + } + + protected override bool OnHover(HoverEvent e) + { + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + base.OnHoverLost(e); + } + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/RowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttribute.cs new file mode 100644 index 0000000000..8716382142 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/RowAttribute.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + public class RowAttribute : CompositeDrawable, IHasTooltip + { + private readonly string header; + private readonly string content; + + public RowAttribute(string header, string content) + { + this.header = header; + this.content = content; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.X; + + Height = 20; + + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + Masking = true; + CornerRadius = 5; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = colours.Yellow, + RelativeSizeAxes = Axes.Both, + }, + new OsuSpriteText + { + Padding = new MarginPadding(2), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 12), + Text = header, + Colour = colours.Gray3 + }, + }; + } + + public string TooltipText => content; + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 97ec03e6dd..3dda57becc 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,22 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -87,216 +80,4 @@ namespace osu.Game.Screens.Edit.Timing } } } - - public class ControlPointTable : TableContainer - { - private const float horizontal_inset = 20; - private const float row_height = 25; - private const int text_size = 14; - - private readonly FillFlowContainer backgroundFlow; - - [Resolved] - private Bindable controlPoint { get; set; } - - public ControlPointTable() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Padding = new MarginPadding { Horizontal = horizontal_inset }; - RowSize = new Dimension(GridSizeMode.Absolute, row_height); - - AddInternal(backgroundFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Depth = 1f, - Padding = new MarginPadding { Horizontal = -horizontal_inset }, - Margin = new MarginPadding { Top = row_height } - }); - } - - public IEnumerable ControlPoints - { - set - { - Content = null; - backgroundFlow.Clear(); - - if (value?.Any() != true) - return; - - var grouped = value.GroupBy(cp => cp.Time, cp => cp); - - foreach (var group in grouped) - { - backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); - } - - Columns = createHeaders(); - Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); - } - } - - private TableColumn[] createHeaders() - { - var columns = new List - { - new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("Attributes", Anchor.Centre), - }; - - return columns.ToArray(); - } - - private Drawable[] createContent(int index, IGrouping controlPoints) => new Drawable[] - { - new OsuSpriteText - { - Text = $"#{index + 1}", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), - Margin = new MarginPadding(10) - }, - new OsuSpriteText - { - Text = $"{controlPoints.Key:n0}ms", - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), - Padding = new MarginPadding(10), - Spacing = new Vector2(10) - }, - }; - - private Drawable createAttribute(ControlPoint controlPoint) - { - if (controlPoint.AutoGenerated) - return null; - - switch (controlPoint) - { - case TimingControlPoint timing: - return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); - - case DifficultyControlPoint difficulty: - - return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); - - case EffectControlPoint effect: - return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); - - case SampleControlPoint sample: - return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); - } - - return null; - } - - private class RowAttribute : CompositeDrawable, IHasTooltip - { - private readonly string header; - private readonly string content; - - public RowAttribute(string header, string content) - { - this.header = header; - this.content = content; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AutoSizeAxes = Axes.X; - - Height = 20; - - Anchor = Anchor.CentreLeft; - Origin = Anchor.CentreLeft; - - Masking = true; - CornerRadius = 5; - - InternalChildren = new Drawable[] - { - new Box - { - Colour = colours.Yellow, - RelativeSizeAxes = Axes.Both, - }, - new OsuSpriteText - { - Padding = new MarginPadding(2), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.Default.With(weight: FontWeight.SemiBold, size: 12), - Text = header, - Colour = colours.Gray3 - }, - }; - } - - public string TooltipText => content; - } - - protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); - - private class HeaderText : OsuSpriteText - { - public HeaderText(string text) - { - Text = text.ToUpper(); - Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black); - } - } - - public class RowBackground : OsuClickableContainer - { - private const int fade_duration = 100; - - private readonly Box hoveredBackground; - - public RowBackground() - { - RelativeSizeAxes = Axes.X; - Height = 25; - - AlwaysPresent = true; - - CornerRadius = 3; - Masking = true; - - Children = new Drawable[] - { - hoveredBackground = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - hoveredBackground.Colour = colours.Blue; - } - - protected override bool OnHover(HoverEvent e) - { - hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); - base.OnHoverLost(e); - } - } - } } From 7dc65ec9645e71bd790f5e157bf757ebfd6748c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Oct 2019 23:32:49 +0900 Subject: [PATCH 048/503] Add missing required types --- osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index be84ae2cf9..54dcdc8da5 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Rulesets.Osu; @@ -11,6 +13,12 @@ namespace osu.Game.Tests.Visual.Editor [TestFixture] public class TestSceneTimingScreen : EditorClockTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ControlPointTable), + typeof(RowAttribute) + }; + [BackgroundDependencyLoader] private void load() { From 0fbba9a5e5c875f63a1e4afc7181aa4ee41895cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Oct 2019 23:42:13 +0900 Subject: [PATCH 049/503] Split out more classes --- .../Visual/Editor/TestSceneTimingScreen.cs | 1 + .../Edit/Timing/ControlPointSettings.cs | 26 +++++++++++++++++++ osu.Game/Screens/Edit/Timing/TimingScreen.cs | 15 ----------- 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/ControlPointSettings.cs diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index 54dcdc8da5..3e227169e0 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -16,6 +16,7 @@ namespace osu.Game.Tests.Visual.Editor public override IReadOnlyList RequiredTypes => new[] { typeof(ControlPointTable), + typeof(ControlPointSettings), typeof(RowAttribute) }; diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs new file mode 100644 index 0000000000..2feced9738 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Edit.Timing +{ + public class ControlPointSettings : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new Box + { + Colour = colours.Gray3, + RelativeSizeAxes = Axes.Both, + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 3dda57becc..9cbba6b155 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -64,20 +64,5 @@ namespace osu.Game.Screens.Edit.Timing }; } } - - public class ControlPointSettings : CompositeDrawable - { - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - RelativeSizeAxes = Axes.Both; - - InternalChild = new Box - { - Colour = colours.Gray3, - RelativeSizeAxes = Axes.Both, - }; - } - } } } From 80bf68c1081ed4dc90f1cc5c99c7810e8e34e597 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Oct 2019 00:06:38 +0900 Subject: [PATCH 050/503] Add control sections and hook up bindable control groups --- .../Edit/Timing/ControlPointSettings.cs | 130 +++++++++++++++++- .../Screens/Edit/Timing/ControlPointTable.cs | 4 +- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 3 +- 3 files changed, 131 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 2feced9738..dc4fb2a338 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -1,11 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Timing { @@ -16,11 +25,126 @@ namespace osu.Game.Screens.Edit.Timing { RelativeSizeAxes = Axes.Both; - InternalChild = new Box + InternalChildren = new Drawable[] { - Colour = colours.Gray3, - RelativeSizeAxes = Axes.Both, + new Box + { + Colour = colours.Gray3, + RelativeSizeAxes = Axes.Both, + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(30), + Children = createSections() + }, + } }; } + + private IReadOnlyList createSections() => new Drawable[] + { + new TimingSection(), + new DifficultySection(), + new SampleSection(), + new EffectSection(), + }; + + private class TimingSection : Section + { + } + + private class DifficultySection : Section + { + } + + private class SampleSection : Section + { + } + + private class EffectSection : Section + { + } + + private class Section : Container + where T : ControlPoint + { + private const float header_height = 20; + + protected override Container Content { get; } + + [Resolved] + private Bindable> selectedPoints { get; set; } + + protected Section() + { + RelativeSizeAxes = Axes.X; + AutoSizeDuration = 200; + AutoSizeEasing = Easing.OutQuint; + AutoSizeAxes = Axes.Y; + + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = header_height, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) + }, + } + }, + Content = new Container() + { + Y = header_height, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + Colour = Color4.DarkGray, + RelativeSizeAxes = Axes.X, + Height = 100, + }, + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedPoints.BindValueChanged(points => + { + var matching = points.NewValue?.OfType().Where(p => !p.AutoGenerated).FirstOrDefault(); + + if (matching != null) + { + Content.BypassAutoSizeAxes = Axes.None; + } + else + { + Content.BypassAutoSizeAxes = Axes.Y; + } + }, true); + } + } } } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 1ff88fb5b4..5032e71fe8 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Edit.Timing private readonly FillFlowContainer backgroundFlow; [Resolved] - private Bindable controlPoint { get; set; } + private Bindable> selectedPoints { get; set; } public ControlPointTable() { @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Edit.Timing foreach (var group in grouped) { - backgroundFlow.Add(new RowBackground { Action = () => controlPoint.Value = group.First() }); + backgroundFlow.Add(new RowBackground { Action = () => selectedPoints.Value = group }); } Columns = createHeaders(); diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 9cbba6b155..5da5d3f785 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -16,7 +17,7 @@ namespace osu.Game.Screens.Edit.Timing public class TimingScreen : EditorScreenWithTimeline { [Cached] - private readonly Bindable controlPoint = new Bindable(); + private Bindable> selectedPoints = new Bindable>(); protected override Drawable CreateMainContent() => new GridContainer { From 81e8b678d342c8a9f9f646974a9659790573cdea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Oct 2019 20:17:19 +0900 Subject: [PATCH 051/503] Update editor time when a new timing point is selected --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 5da5d3f785..ed045aca86 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,11 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -19,6 +21,9 @@ namespace osu.Game.Screens.Edit.Timing [Cached] private Bindable> selectedPoints = new Bindable>(); + [Resolved] + private IAdjustableClock clock { get; set; } + protected override Drawable CreateMainContent() => new GridContainer { RelativeSizeAxes = Axes.Both, @@ -37,6 +42,13 @@ namespace osu.Game.Screens.Edit.Timing } }; + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.First().Time); }); + } + public class ControlPointList : CompositeDrawable { [Resolved] From 4883844c4c390aa515fef26d4b730c8992d6fe57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Oct 2019 20:57:56 +0900 Subject: [PATCH 052/503] Add basic information display for all types of control points --- .../Edit/Timing/ControlPointSettings.cs | 136 +++++++++++++++--- 1 file changed, 114 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index dc4fb2a338..1ab22679d9 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Edit.Timing { @@ -40,7 +39,7 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Spacing = new Vector2(30), + Spacing = new Vector2(2), Children = createSections() }, } @@ -57,31 +56,123 @@ namespace osu.Game.Screens.Edit.Timing private class TimingSection : Section { + private OsuSpriteText bpm; + private OsuSpriteText timeSignature; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bpm = new OsuSpriteText(), + timeSignature = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; + timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; + }); + } } private class DifficultySection : Section { + private OsuSpriteText multiplier; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + multiplier = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); + } } private class SampleSection : Section { + private OsuSpriteText bank; + private OsuSpriteText volume; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bank = new OsuSpriteText(), + volume = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bank.Text = $"Bank: {point.NewValue?.SampleBank}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; + }); + } } private class EffectSection : Section { + private OsuSpriteText kiai; + private OsuSpriteText omitBarLine; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + kiai = new OsuSpriteText(), + omitBarLine = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; + omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; + }); + } } - private class Section : Container + private class Section : CompositeDrawable where T : ControlPoint { - private const float header_height = 20; + private OsuCheckbox checkbox; + private Container content; - protected override Container Content { get; } + protected FillFlowContainer Flow { get; private set; } + + protected Bindable ControlPoint { get; } = new Bindable(); + + private const float header_height = 20; [Resolved] private Bindable> selectedPoints { get; set; } - protected Section() + [BackgroundDependencyLoader] + private void load(OsuColour colours) { RelativeSizeAxes = Axes.X; AutoSizeDuration = 200; @@ -94,7 +185,7 @@ namespace osu.Game.Screens.Edit.Timing { new Box { - Colour = Color4.Gray, + Colour = colours.Gray1, RelativeSizeAxes = Axes.Both, }, new Container @@ -103,13 +194,13 @@ namespace osu.Game.Screens.Edit.Timing Height = header_height, Children = new Drawable[] { - new OsuSpriteText + checkbox = new OsuCheckbox { - Text = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) - }, + LabelText = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) + } } }, - Content = new Container() + content = new Container { Y = header_height, RelativeSizeAxes = Axes.X, @@ -118,9 +209,15 @@ namespace osu.Game.Screens.Edit.Timing { new Box { - Colour = Color4.DarkGray, + Colour = colours.Gray2, + RelativeSizeAxes = Axes.Both, + }, + Flow = new FillFlowContainer + { + Padding = new MarginPadding(10), RelativeSizeAxes = Axes.X, - Height = 100, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, }, } } @@ -133,17 +230,12 @@ namespace osu.Game.Screens.Edit.Timing selectedPoints.BindValueChanged(points => { - var matching = points.NewValue?.OfType().Where(p => !p.AutoGenerated).FirstOrDefault(); + ControlPoint.Value = points.NewValue?.OfType().Where(p => !p.AutoGenerated).FirstOrDefault(); - if (matching != null) - { - Content.BypassAutoSizeAxes = Axes.None; - } - else - { - Content.BypassAutoSizeAxes = Axes.Y; - } + checkbox.Current.Value = ControlPoint.Value != null; }, true); + + checkbox.Current.BindValueChanged(selected => { content.BypassAutoSizeAxes = selected.NewValue ? Axes.None : Axes.Y; }, true); } } } From 5e22eed131ca60093f816fa8a50a06a4536f8b85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Oct 2019 21:50:21 +0900 Subject: [PATCH 053/503] Add add/remove buttons --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 53 +++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index ed045aca86..b6bd9ae61d 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -13,6 +14,8 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -51,9 +54,14 @@ namespace osu.Game.Screens.Edit.Timing public class ControlPointList : CompositeDrawable { + private OsuButton deleteButton; + [Resolved] protected IBindable Beatmap { get; private set; } + [Resolved] + private Bindable> selectedPoints { get; set; } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -73,9 +81,52 @@ namespace osu.Game.Screens.Edit.Timing { ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.AllControlPoints } - } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding(10), + Spacing = new Vector2(5), + Children = new Drawable[] + { + deleteButton = new OsuButton + { + Text = "-", + Size = new Vector2(30, 30), + Action = delete, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + }, + new OsuButton + { + Text = "+", + Action = addNew, + Size = new Vector2(30, 30), + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + }, + } + }, }; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedPoints.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); + } + + private void delete() + { + } + + private void addNew() + { + } } } } From c06f142433d547abe9d96bf082df5c36e8c8400b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Oct 2019 11:22:55 +0900 Subject: [PATCH 054/503] Fix some spacing and references --- osu.Game/Screens/Edit/Timing/ControlPointSettings.cs | 2 -- osu.Game/Screens/Edit/Timing/ControlPointTable.cs | 2 +- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 1ab22679d9..0974745294 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -13,7 +13,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using osuTK; namespace osu.Game.Screens.Edit.Timing { @@ -39,7 +38,6 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Spacing = new Vector2(2), Children = createSections() }, } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 5032e71fe8..777d34e75b 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Timing var columns = new List { new TableColumn(string.Empty, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), + new TableColumn("Time", Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), new TableColumn("Attributes", Anchor.Centre), }; diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index b6bd9ae61d..bd0a75f0b0 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; From e38b7cb169767b0d637cfcb166ed919161aa3087 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Oct 2019 17:00:56 +0900 Subject: [PATCH 055/503] Replace local Equatable implementations with abstract EquivalentTo --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 12 +++++++++--- .../Beatmaps/ControlPoints/DifficultyControlPoint.cs | 8 +++----- .../Beatmaps/ControlPoints/EffectControlPoint.cs | 10 ++++------ .../Beatmaps/ControlPoints/SampleControlPoint.cs | 9 ++++----- .../Beatmaps/ControlPoints/TimingControlPoint.cs | 9 ++++----- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 8 ++++---- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index abe7e5e803..0081fab46a 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -5,7 +5,7 @@ using System; namespace osu.Game.Beatmaps.ControlPoints { - public class ControlPoint : IComparable, IEquatable + public abstract class ControlPoint : IComparable, IEquatable { /// /// The time at which the control point takes effect. @@ -19,7 +19,13 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); - public bool Equals(ControlPoint other) - => Time.Equals(other?.Time); + /// + /// Whether this control point is equivalent to another, ignoring time. + /// + /// Another control point to compare with. + /// Whether equivalent. + public abstract bool EquivalentTo(ControlPoint other); + + public bool Equals(ControlPoint other) => Time.Equals(other?.Time) && EquivalentTo(other); } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index a3e3121575..42651fd0ca 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; namespace osu.Game.Beatmaps.ControlPoints { - public class DifficultyControlPoint : ControlPoint, IEquatable + public class DifficultyControlPoint : ControlPoint { /// /// The speed multiplier at this control point. @@ -19,8 +18,7 @@ namespace osu.Game.Beatmaps.ControlPoints private double speedMultiplier = 1; - public bool Equals(DifficultyControlPoint other) - => base.Equals(other) - && SpeedMultiplier.Equals(other?.SpeedMultiplier); + public override bool EquivalentTo(ControlPoint other) => + other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(speedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 354d86dc13..928f2a51ad 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; - namespace osu.Game.Beatmaps.ControlPoints { - public class EffectControlPoint : ControlPoint, IEquatable + public class EffectControlPoint : ControlPoint { /// /// Whether this control point enables Kiai mode. @@ -17,8 +15,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public bool OmitFirstBarLine; - public bool Equals(EffectControlPoint other) - => base.Equals(other) - && KiaiMode == other?.KiaiMode && OmitFirstBarLine == other.OmitFirstBarLine; + public override bool EquivalentTo(ControlPoint other) => + other is EffectControlPoint otherTyped && + KiaiMode == otherTyped.KiaiMode && OmitFirstBarLine == otherTyped.OmitFirstBarLine; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 7bc7a9056d..35eefebca4 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,12 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints { - public class SampleControlPoint : ControlPoint, IEquatable + public class SampleControlPoint : ControlPoint { public const string DEFAULT_BANK = "normal"; @@ -45,8 +44,8 @@ namespace osu.Game.Beatmaps.ControlPoints return newSampleInfo; } - public bool Equals(SampleControlPoint other) - => base.Equals(other) - && string.Equals(SampleBank, other?.SampleBank) && SampleVolume == other?.SampleVolume; + public override bool EquivalentTo(ControlPoint other) => + other is SampleControlPoint otherTyped && + string.Equals(SampleBank, otherTyped?.SampleBank) && SampleVolume == otherTyped?.SampleVolume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index ccb8a92b3a..03b188929b 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,13 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints { - public class TimingControlPoint : ControlPoint, IEquatable + public class TimingControlPoint : ControlPoint { /// /// The time signature at this control point. @@ -27,8 +26,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double beatLength = DEFAULT_BEAT_LENGTH; - public bool Equals(TimingControlPoint other) - => base.Equals(other) - && TimeSignature == other?.TimeSignature && beatLength.Equals(other.beatLength); + public override bool EquivalentTo(ControlPoint other) => + other is TimingControlPoint otherTyped + && TimeSignature == otherTyped?.TimeSignature && beatLength.Equals(otherTyped.beatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 83d20da458..26f7209be6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -189,7 +189,7 @@ namespace osu.Game.Beatmaps.Formats Foreground = 3 } - internal class LegacySampleControlPoint : SampleControlPoint, IEquatable + internal class LegacySampleControlPoint : SampleControlPoint { public int CustomSampleBank; @@ -203,9 +203,9 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public bool Equals(LegacySampleControlPoint other) - => base.Equals(other) - && CustomSampleBank == other?.CustomSampleBank; + public override bool EquivalentTo(ControlPoint other) => + base.EquivalentTo(other) + && CustomSampleBank == ((LegacySampleControlPoint)other).CustomSampleBank; } } } From 94ffe03e6e71701e723db6196532dde41fd1c254 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Oct 2019 16:19:06 +0900 Subject: [PATCH 056/503] Group timing points --- .../TestSceneDrawableHitObjects.cs | 2 +- .../TestSceneOsuDistanceSnapGrid.cs | 13 +- .../TestSceneSlider.cs | 2 +- .../TestSceneSliderInput.cs | 6 +- .../TestSceneTaikoPlayfield.cs | 6 +- .../Audio/DrumSampleMapping.cs | 7 +- .../Editor/TestSceneDistanceSnapGrid.cs | 10 +- .../Editor/TestSceneEditorSeekSnapping.cs | 20 ++- .../TestSceneDrawableScrollingRuleset.cs | 34 ++--- .../TestSceneBeatSyncedContainer.cs | 4 +- .../Beatmaps/ControlPoints/ControlPoint.cs | 6 +- .../ControlPoints/ControlPointGroup.cs | 48 +++++++ .../ControlPoints/ControlPointInfo.cs | 130 ++++++++++++++++-- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 92 ++----------- .../Containers/BeatSyncedContainer.cs | 2 - osu.Game/Screens/Edit/EditorClock.cs | 5 +- 16 files changed, 233 insertions(+), 154 deletions(-) create mode 100644 osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 7a9b61c60c..0369b6db4e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Tests private void load() { var controlPointInfo = new ControlPointInfo(); - controlPointInfo.TimingPoints.Add(new TimingControlPoint()); + controlPointInfo.Add(0, new TimingControlPoint()); WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index 6b8daa531f..b66123e628 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -53,9 +53,8 @@ namespace osu.Game.Rulesets.Osu.Tests Clear(); editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; - editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); beatDivisor.Value = 1; }); @@ -80,8 +79,8 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep($"set beat length = {beatLength}", () => { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beatLength }); }); createGrid(); @@ -95,8 +94,8 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep($"set speed multiplier = {multiplier}", () => { - editorBeatmap.ControlPointInfo.DifficultyPoints.Clear(); - editorBeatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = multiplier }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = multiplier }); }); createGrid(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 4893ebfdd4..a955911bd5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -308,7 +308,7 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable createDrawable(Slider slider, float circleSize, double speedMultiplier) { var cpi = new ControlPointInfo(); - cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); + cpi.Add(0, new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize, SliderTickRate = 3 }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 2eb783233a..5f75cbabec 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -313,10 +313,6 @@ namespace osu.Game.Rulesets.Osu.Tests }, 25), } }, - ControlPointInfo = - { - DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } - }, BeatmapInfo = { BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, @@ -324,6 +320,8 @@ namespace osu.Game.Rulesets.Osu.Tests }, }); + Beatmap.Value.Beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }); p.OnLoadComplete += _ => diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index eaa8ca7ebb..8522a42739 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Taiko.Tests AddStep("Reset height", () => changePlayfieldSize(6)); var controlPointInfo = new ControlPointInfo(); - controlPointInfo.TimingPoints.Add(new TimingControlPoint()); + controlPointInfo.Add(0, new TimingControlPoint()); WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap { @@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; var cpi = new ControlPointInfo(); - cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); + cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); Hit hit = new Hit(); hit.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; var cpi = new ControlPointInfo(); - cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); + cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); Hit hit = new Hit(); hit.ApplyDefaults(cpi, new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index ad2596931d..aaf113f216 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -19,12 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Audio { this.controlPoints = controlPoints; - IEnumerable samplePoints; - if (controlPoints.SamplePoints.Count == 0) - // Get the default sample point - samplePoints = new[] { controlPoints.SamplePointAt(double.MinValue) }; - else - samplePoints = controlPoints.SamplePoints; + IEnumerable samplePoints = controlPoints.SamplePoints.Count == 0 ? new[] { controlPoints.SamplePointAt(double.MinValue) } : controlPoints.SamplePoints; foreach (var s in samplePoints) { diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index a9e5930478..07646fdb78 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.Editor public TestSceneDistanceSnapGrid() { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); createGrid(); } @@ -42,8 +42,8 @@ namespace osu.Game.Tests.Visual.Editor { Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beat_length }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); BeatDivisor.Value = 1; }); @@ -81,8 +81,8 @@ namespace osu.Game.Tests.Visual.Editor { AddStep($"set beat length = {beatLength}", () => { - editorBeatmap.ControlPointInfo.TimingPoints.Clear(); - editorBeatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint { BeatLength = beatLength }); + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beatLength }); }); createGrid(); diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs index b997d6aaeb..3118e0cabe 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorSeekSnapping.cs @@ -28,18 +28,7 @@ namespace osu.Game.Tests.Visual.Editor { var testBeatmap = new Beatmap { - ControlPointInfo = new ControlPointInfo - { - TimingPoints = - { - new TimingControlPoint { Time = 0, BeatLength = 200 }, - new TimingControlPoint { Time = 100, BeatLength = 400 }, - new TimingControlPoint { Time = 175, BeatLength = 800 }, - new TimingControlPoint { Time = 350, BeatLength = 200 }, - new TimingControlPoint { Time = 450, BeatLength = 100 }, - new TimingControlPoint { Time = 500, BeatLength = 307.69230769230802 } - } - }, + ControlPointInfo = new ControlPointInfo(), HitObjects = { new HitCircle { StartTime = 0 }, @@ -47,6 +36,13 @@ namespace osu.Game.Tests.Visual.Editor } }; + testBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 200 }); + testBeatmap.ControlPointInfo.Add(100, new TimingControlPoint { BeatLength = 400 }); + testBeatmap.ControlPointInfo.Add(175, new TimingControlPoint { BeatLength = 800 }); + testBeatmap.ControlPointInfo.Add(350, new TimingControlPoint { BeatLength = 200 }); + testBeatmap.ControlPointInfo.Add(450, new TimingControlPoint { BeatLength = 100 }); + testBeatmap.ControlPointInfo.Add(500, new TimingControlPoint { BeatLength = 307.69230769230802 }); + Beatmap.Value = CreateWorkingBeatmap(testBeatmap); Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index dcab964d6d..684e79b3f5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -47,7 +47,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleSingleTimingPoint() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -61,10 +62,10 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleTimingPointBeyondEndDoesNotBecomeDominant() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range / 2 }, - new TimingControlPoint { Time = 12000, BeatLength = time_range }, - new TimingControlPoint { Time = 100000, BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range / 2 }); + beatmap.ControlPointInfo.Add(12000, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(100000, new TimingControlPoint { BeatLength = time_range }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -75,9 +76,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestRelativeBeatLengthScaleFromSecondTimingPoint() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range }, - new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -97,9 +98,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestNonRelativeScale() { - var beatmap = createBeatmap( - new TimingControlPoint { BeatLength = time_range }, - new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); + beatmap.ControlPointInfo.Add(3 * time_range, new TimingControlPoint { BeatLength = time_range / 2 }); createTest(beatmap); @@ -119,7 +120,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSliderMultiplierDoesNotAffectRelativeBeatLength() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); @@ -132,7 +134,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSliderMultiplierAffectsNonRelativeBeatLength() { - var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range }); + var beatmap = createBeatmap(); + beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2; createTest(beatmap); @@ -154,14 +157,11 @@ namespace osu.Game.Tests.Visual.Gameplay /// Creates an , containing 10 hitobjects and user-provided timing points. /// The hitobjects are spaced milliseconds apart. /// - /// The timing points to add to the beatmap. /// The . - private IBeatmap createBeatmap(params TimingControlPoint[] timingControlPoints) + private IBeatmap createBeatmap() { var beatmap = new Beatmap { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } }; - beatmap.ControlPointInfo.TimingPoints.AddRange(timingControlPoints); - for (int i = 0; i < 10; i++) beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range }); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index d84ffa0d93..b6df559686 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Internal; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -10,7 +11,6 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Lists; using osu.Framework.Timing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -153,7 +153,7 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private SortedList timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; + private IReadOnlyList timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 0081fab46a..6288c1460f 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -10,13 +10,17 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time at which the control point takes effect. /// - public double Time; + public double Time => controlPointGroup?.Time ?? 0; /// /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. /// internal bool AutoGenerated; + private ControlPointGroup controlPointGroup; + + public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; + public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); /// diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs new file mode 100644 index 0000000000..c4b990675e --- /dev/null +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -0,0 +1,48 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Beatmaps.ControlPoints +{ + public class ControlPointGroup : IComparable + { + public event Action ItemAdded; + public event Action ItemRemoved; + + /// + /// The time at which the control point takes effect. + /// + public double Time { get; } + + public IReadOnlyList ControlPoints => controlPoints; + + private readonly List controlPoints = new List(); + + public ControlPointGroup(double time) + { + Time = time; + } + + public int CompareTo(ControlPointGroup other) => Time.CompareTo(other.Time); + + public void Add(ControlPoint point) + { + point.AttachGroup(this); + + foreach (var existing in controlPoints.Where(p => p.GetType() == point.GetType()).ToArray()) + Remove(existing); + + controlPoints.Add(point); + ItemAdded?.Invoke(point); + } + + public void Remove(ControlPoint point) + { + controlPoints.Remove(point); + ItemRemoved?.Invoke(point); + } + } +} diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 68eb0ec6d1..2175eccaa2 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -12,35 +12,50 @@ namespace osu.Game.Beatmaps.ControlPoints [Serializable] public class ControlPointInfo { + /// + /// Control point groups. + /// + [JsonProperty] + public IReadOnlyList Groups => groups; + + private readonly SortedList groups = new SortedList(Comparer.Default); + /// /// All timing points. /// [JsonProperty] - public SortedList TimingPoints { get; private set; } = new SortedList(Comparer.Default); + public IReadOnlyList TimingPoints => timingPoints; + + private readonly SortedList timingPoints = new SortedList(Comparer.Default); /// /// All difficulty points. /// [JsonProperty] - public SortedList DifficultyPoints { get; private set; } = new SortedList(Comparer.Default); + public IReadOnlyList DifficultyPoints => difficultyPoints; + + private readonly SortedList difficultyPoints = new SortedList(Comparer.Default); /// /// All sound points. /// [JsonProperty] - public SortedList SamplePoints { get; private set; } = new SortedList(Comparer.Default); + public IReadOnlyList SamplePoints => samplePoints; + + private readonly SortedList samplePoints = new SortedList(Comparer.Default); /// /// All effect points. /// [JsonProperty] - public SortedList EffectPoints { get; private set; } = new SortedList(Comparer.Default); + public IReadOnlyList EffectPoints => effectPoints; - public IReadOnlyList AllControlPoints => - TimingPoints - .Concat((IEnumerable)DifficultyPoints) - .Concat(SamplePoints) - .Concat(EffectPoints).ToArray(); + private readonly SortedList effectPoints = new SortedList(Comparer.Default); + + /// + /// All control points, of all types. + /// + public IEnumerable AllControlPoints => Groups.SelectMany(g => g.ControlPoints); /// /// Finds the difficulty control point that is active at . @@ -70,6 +85,28 @@ namespace osu.Game.Beatmaps.ControlPoints /// The timing control point. public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); + /// + /// Finds the closest of the same type as that is active at . + /// + /// The time to find the timing control point at. + /// A reference point to infer type. + /// The timing control point. + public ControlPoint SimilarPointAt(double time, ControlPoint referencePoint) + { + switch (referencePoint) + { + case TimingControlPoint _: return TimingPointAt(time); + + case EffectControlPoint _: return EffectPointAt(time); + + case SampleControlPoint _: return SamplePointAt(time); + + case DifficultyControlPoint _: return DifficultyPointAt(time); + } + + return null; + } + /// /// Finds the maximum BPM represented by any timing control point. /// @@ -98,7 +135,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// The time to find the control point at. /// The control point to use when is before any control points. If null, a new control point will be constructed. /// The active control point at . - private T binarySearch(SortedList list, double time, T prePoint = null) + private T binarySearch(IReadOnlyList list, double time, T prePoint = null) where T : ControlPoint, new() { if (list == null) @@ -131,5 +168,78 @@ namespace osu.Game.Beatmaps.ControlPoints // l will be the first control point with Time > time, but we want the one before it return list[l - 1]; } + + public void Add(double time, ControlPoint newPoint, bool force = false) + { + if (!force && SimilarPointAt(time, newPoint)?.EquivalentTo(newPoint) == true) + return; + + GroupAt(time, true).Add(newPoint); + } + + public ControlPointGroup GroupAt(double time, bool createIfNotExisting) + { + var existing = Groups.FirstOrDefault(g => g.Time == time); + + if (existing != null) + return existing; + + if (createIfNotExisting) + { + var newGroup = new ControlPointGroup(time); + newGroup.ItemAdded += groupItemAdded; + newGroup.ItemRemoved += groupItemRemoved; + groups.Add(newGroup); + return newGroup; + } + + return null; + } + + private void groupItemRemoved(ControlPoint obj) + { + switch (obj) + { + case TimingControlPoint typed: + timingPoints.Remove(typed); + break; + + case EffectControlPoint typed: + effectPoints.Remove(typed); + break; + + case SampleControlPoint typed: + samplePoints.Remove(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Remove(typed); + break; + } + } + + private void groupItemAdded(ControlPoint obj) + { + switch (obj) + { + case TimingControlPoint typed: + timingPoints.Add(typed); + break; + + case EffectControlPoint typed: + effectPoints.Add(typed); + break; + + case SampleControlPoint typed: + samplePoints.Add(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Add(typed); + break; + } + } + + public void Clear() => groups.Clear(); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 786b7611b5..61f70a8c27 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -369,31 +369,29 @@ namespace osu.Game.Beatmaps.Formats if (timingChange) { var controlPoint = CreateTimingControlPoint(); - controlPoint.Time = time; controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; - handleTimingControlPoint(controlPoint); + beatmap.ControlPointInfo.Add(time, controlPoint); + } + else + { + beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint + { + SpeedMultiplier = speedMultiplier, + AutoGenerated = timingChange + }); } - handleDifficultyControlPoint(new DifficultyControlPoint + beatmap.ControlPointInfo.Add(time, new EffectControlPoint { - Time = time, - SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange - }); - - handleEffectControlPoint(new EffectControlPoint - { - Time = time, KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, AutoGenerated = timingChange }); - handleSampleControlPoint(new LegacySampleControlPoint + beatmap.ControlPointInfo.Add(time, new LegacySampleControlPoint { - Time = time, SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, @@ -401,74 +399,6 @@ namespace osu.Game.Beatmaps.Formats }); } - private void handleTimingControlPoint(TimingControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.TimingPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.TimingPoints.Remove(existing); - } - - beatmap.ControlPointInfo.TimingPoints.Add(newPoint); - } - - private void handleDifficultyControlPoint(DifficultyControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); - } - - beatmap.ControlPointInfo.DifficultyPoints.Add(newPoint); - } - - private void handleEffectControlPoint(EffectControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.EffectPoints.Remove(existing); - } - - beatmap.ControlPointInfo.EffectPoints.Add(newPoint); - } - - private void handleSampleControlPoint(SampleControlPoint newPoint) - { - var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); - - if (existing.Time == newPoint.Time) - { - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - - beatmap.ControlPointInfo.SamplePoints.Remove(existing); - } - - beatmap.ControlPointInfo.SamplePoints.Add(newPoint); - } - private void handleHitObject(string line) { // If the ruleset wasn't specified, assume the osu!standard ruleset. diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 370d044ba4..2832a70518 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -105,12 +105,10 @@ namespace osu.Game.Graphics.Containers { BeatLength = default_beat_length, AutoGenerated = true, - Time = 0 }; defaultEffect = new EffectControlPoint { - Time = 0, AutoGenerated = true, KiaiMode = false, OmitFirstBarLine = false diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 24fb561f04..1cfb123f25 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -57,7 +58,7 @@ namespace osu.Game.Screens.Edit // Depending on beatSnapLength, we may snap to a beat that is beyond timingPoint's end time, but we want to instead snap to // the next timing point's start time - var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time); + var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); if (position > nextTimingPoint?.Time) position = nextTimingPoint.Time; @@ -124,7 +125,7 @@ namespace osu.Game.Screens.Edit if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First()) seekTime = timingPoint.Time; - var nextTimingPoint = ControlPointInfo.TimingPoints.Find(t => t.Time > timingPoint.Time); + var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time); if (seekTime > nextTimingPoint?.Time) seekTime = nextTimingPoint.Time; From da6769f0fcd9966a24624ec97451a16dd01fc187 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Oct 2019 17:00:23 +0900 Subject: [PATCH 057/503] Remove necessity of AutoGenerated flag --- .../Formats/LegacyBeatmapDecoderTest.cs | 10 +-- .../Beatmaps/ControlPoints/ControlPoint.cs | 7 +-- .../ControlPoints/ControlPointInfo.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 63 ++++++++++++++----- .../Containers/BeatSyncedContainer.cs | 2 - .../Edit/Timing/ControlPointSettings.cs | 2 +- .../Screens/Edit/Timing/ControlPointTable.cs | 3 - 7 files changed, 56 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index de516d3142..c50250159e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -167,9 +167,9 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - Assert.AreEqual(42, controlPoints.DifficultyPoints.Count); - Assert.AreEqual(42, controlPoints.SamplePoints.Count); - Assert.AreEqual(42, controlPoints.EffectPoints.Count); + Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(34, controlPoints.SamplePoints.Count); + Assert.AreEqual(8, controlPoints.EffectPoints.Count); var timingPoint = controlPoints.TimingPointAt(0); Assert.AreEqual(956, timingPoint.Time); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(48428); - Assert.AreEqual(48428, difficultyPoint.Time); + Assert.AreEqual(0, difficultyPoint.Time); Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(116999); @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsFalse(effectPoint.OmitFirstBarLine); effectPoint = controlPoints.EffectPointAt(119637); - Assert.AreEqual(119637, effectPoint.Time); + Assert.AreEqual(95901, effectPoint.Time); Assert.IsFalse(effectPoint.KiaiMode); Assert.IsFalse(effectPoint.OmitFirstBarLine); } diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 6288c1460f..0861e00d8d 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -12,11 +12,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// public double Time => controlPointGroup?.Time ?? 0; - /// - /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. - /// - internal bool AutoGenerated; - private ControlPointGroup controlPointGroup; public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 2175eccaa2..7e9c8844f0 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -177,7 +177,7 @@ namespace osu.Game.Beatmaps.ControlPoints GroupAt(time, true).Add(newPoint); } - public ControlPointGroup GroupAt(double time, bool createIfNotExisting) + public ControlPointGroup GroupAt(double time, bool createIfNotExisting = false) { var existing = Groups.FirstOrDefault(g => g.Time == time); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 61f70a8c27..5589aecc19 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.IO; using System.Linq; using osu.Framework.IO.File; @@ -50,6 +51,8 @@ namespace osu.Game.Beatmaps.Formats base.ParseStreamInto(stream, beatmap); + flushPendingPoints(); + // Objects may be out of order *only* if a user has manually edited an .osu file. // Unfortunately there are ranked maps in this state (example: https://osu.ppy.sh/s/594828). // OrderBy is used to guarantee that the parsing order of hitobjects with equal start times is maintained (stably-sorted) @@ -369,34 +372,64 @@ namespace osu.Game.Beatmaps.Formats if (timingChange) { var controlPoint = CreateTimingControlPoint(); + controlPoint.BeatLength = beatLength; controlPoint.TimeSignature = timeSignature; - beatmap.ControlPointInfo.Add(time, controlPoint); - } - else - { - beatmap.ControlPointInfo.Add(time, new DifficultyControlPoint - { - SpeedMultiplier = speedMultiplier, - AutoGenerated = timingChange - }); + addControlPoint(time, controlPoint, true); } - beatmap.ControlPointInfo.Add(time, new EffectControlPoint + addControlPoint(time, new DifficultyControlPoint + { + SpeedMultiplier = speedMultiplier, + }, timingChange); + + addControlPoint(time, new EffectControlPoint { KiaiMode = kiaiMode, OmitFirstBarLine = omitFirstBarSignature, - AutoGenerated = timingChange - }); + }, timingChange); - beatmap.ControlPointInfo.Add(time, new LegacySampleControlPoint + addControlPoint(time, new LegacySampleControlPoint { SampleBank = stringSampleSet, SampleVolume = sampleVolume, CustomSampleBank = customSampleBank, - AutoGenerated = timingChange - }); + }, timingChange); + + // To handle the scenario where a non-timing line shares the same time value as a subsequent timing line but + // appears earlier in the file, we buffer non-timing control points and rewrite them *after* control points from the timing line + // with the same time value (allowing them to overwrite as necessary). + // + // The expected outcome is that we prefer the non-timing line's adjustments over the timing line's adjustments when time is equal. + if (timingChange) + flushPendingPoints(); + } + + private readonly List pendingControlPoints = new List(); + private double pendingControlPointsTime; + + private void addControlPoint(double time, ControlPoint point, bool timingChange) + { + if (timingChange) + { + beatmap.ControlPointInfo.Add(time, point); + return; + } + + if (time != pendingControlPointsTime) + flushPendingPoints(); + + pendingControlPoints.Add(point); + pendingControlPointsTime = time; + } + + private void flushPendingPoints() + { + foreach (var p in pendingControlPoints) + beatmap.ControlPointInfo.Add(pendingControlPointsTime, p); + + pendingControlPoints.Clear(); } private void handleHitObject(string line) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 2832a70518..2e76ab964f 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -104,12 +104,10 @@ namespace osu.Game.Graphics.Containers defaultTiming = new TimingControlPoint { BeatLength = default_beat_length, - AutoGenerated = true, }; defaultEffect = new EffectControlPoint { - AutoGenerated = true, KiaiMode = false, OmitFirstBarLine = false }; diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 0974745294..ce72d7c191 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -228,7 +228,7 @@ namespace osu.Game.Screens.Edit.Timing selectedPoints.BindValueChanged(points => { - ControlPoint.Value = points.NewValue?.OfType().Where(p => !p.AutoGenerated).FirstOrDefault(); + ControlPoint.Value = points.NewValue?.OfType().FirstOrDefault(); checkbox.Current.Value = ControlPoint.Value != null; }, true); diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 777d34e75b..597200e54c 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -105,9 +105,6 @@ namespace osu.Game.Screens.Edit.Timing private Drawable createAttribute(ControlPoint controlPoint) { - if (controlPoint.AutoGenerated) - return null; - switch (controlPoint) { case TimingControlPoint timing: From b8efc59cdcd2be6d4ca8cbe9466221c61b70672c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Oct 2019 20:13:22 +0900 Subject: [PATCH 058/503] Update UI components to use new grouping --- .../Edit/Timing/ControlPointSettings.cs | 4 ++-- .../Screens/Edit/Timing/ControlPointTable.cs | 18 ++++++++---------- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 10 ++++------ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index ce72d7c191..470750b860 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -167,7 +167,7 @@ namespace osu.Game.Screens.Edit.Timing private const float header_height = 20; [Resolved] - private Bindable> selectedPoints { get; set; } + private Bindable selectedPoints { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -228,7 +228,7 @@ namespace osu.Game.Screens.Edit.Timing selectedPoints.BindValueChanged(points => { - ControlPoint.Value = points.NewValue?.OfType().FirstOrDefault(); + ControlPoint.Value = points.NewValue?.ControlPoints.OfType().FirstOrDefault(); checkbox.Current.Value = ControlPoint.Value != null; }, true); diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 597200e54c..aca74d4a20 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Edit.Timing private readonly FillFlowContainer backgroundFlow; [Resolved] - private Bindable> selectedPoints { get; set; } + private Bindable selectedGroup { get; set; } public ControlPointTable() { @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit.Timing }); } - public IEnumerable ControlPoints + public IEnumerable ControlGroups { set { @@ -56,15 +56,13 @@ namespace osu.Game.Screens.Edit.Timing if (value?.Any() != true) return; - var grouped = value.GroupBy(cp => cp.Time, cp => cp); - - foreach (var group in grouped) + foreach (var group in value) { - backgroundFlow.Add(new RowBackground { Action = () => selectedPoints.Value = group }); + backgroundFlow.Add(new RowBackground { Action = () => selectedGroup.Value = group }); } Columns = createHeaders(); - Content = grouped.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); + Content = value.Select((g, i) => createContent(i, g)).ToArray().ToRectangular(); } } @@ -80,7 +78,7 @@ namespace osu.Game.Screens.Edit.Timing return columns.ToArray(); } - private Drawable[] createContent(int index, IGrouping controlPoints) => new Drawable[] + private Drawable[] createContent(int index, ControlPointGroup group) => new Drawable[] { new OsuSpriteText { @@ -90,14 +88,14 @@ namespace osu.Game.Screens.Edit.Timing }, new OsuSpriteText { - Text = $"{controlPoints.Key:n0}ms", + Text = $"{group.Time:n0}ms", Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null), + ChildrenEnumerable = group.ControlPoints.Select(createAttribute).Where(c => c != null), Padding = new MarginPadding(10), Spacing = new Vector2(10) }, diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index bd0a75f0b0..a9fd038829 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -21,7 +19,7 @@ namespace osu.Game.Screens.Edit.Timing public class TimingScreen : EditorScreenWithTimeline { [Cached] - private Bindable> selectedPoints = new Bindable>(); + private Bindable selectedPoints = new Bindable(); [Resolved] private IAdjustableClock clock { get; set; } @@ -48,7 +46,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.First().Time); }); + selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); } public class ControlPointList : CompositeDrawable @@ -59,7 +57,7 @@ namespace osu.Game.Screens.Edit.Timing protected IBindable Beatmap { get; private set; } [Resolved] - private Bindable> selectedPoints { get; set; } + private Bindable selectedPoints { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -78,7 +76,7 @@ namespace osu.Game.Screens.Edit.Timing RelativeSizeAxes = Axes.Both, Child = new ControlPointTable { - ControlPoints = Beatmap.Value.Beatmap.ControlPointInfo.AllControlPoints + ControlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups } }, new FillFlowContainer From 8ccff0e9cf6e42f21a23b324bc12cc6bea4105fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 26 Oct 2019 11:20:07 +0900 Subject: [PATCH 059/503] temp --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 6 +++--- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index c50250159e..7317771bac 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -167,9 +167,9 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(6, controlPoints.DifficultyPoints.Count); Assert.AreEqual(34, controlPoints.SamplePoints.Count); - Assert.AreEqual(8, controlPoints.EffectPoints.Count); + Assert.AreEqual(9, controlPoints.EffectPoints.Count); var timingPoint = controlPoints.TimingPointAt(0); Assert.AreEqual(956, timingPoint.Time); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(48428); - Assert.AreEqual(0, difficultyPoint.Time); + Assert.AreEqual(956, difficultyPoint.Time); Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(116999); diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 24e3c3d8ca..f8c6d3aa3b 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -95,13 +95,13 @@ namespace osu.Game.Beatmaps.ControlPoints { switch (referencePoint) { - case TimingControlPoint _: return TimingPointAt(time); + case TimingControlPoint _: return binarySearch(TimingPoints, time); - case EffectControlPoint _: return EffectPointAt(time); + case EffectControlPoint _: return binarySearch(EffectPoints, time); - case SampleControlPoint _: return SamplePointAt(time); + case SampleControlPoint _: return binarySearch(SamplePoints, time); - case DifficultyControlPoint _: return DifficultyPointAt(time); + case DifficultyControlPoint _: return binarySearch(DifficultyPoints, time); } return null; From 93b003eb5adf1fdb2c31a6e6af2809e2fc9e315a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 Oct 2019 13:31:23 +0900 Subject: [PATCH 060/503] Add selected row state --- .../Screens/Edit/Timing/ControlPointTable.cs | 54 +++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index aca74d4a20..df1f6daf4e 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -15,6 +15,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Timing { @@ -58,7 +59,7 @@ namespace osu.Game.Screens.Edit.Timing foreach (var group in value) { - backgroundFlow.Add(new RowBackground { Action = () => selectedGroup.Value = group }); + backgroundFlow.Add(new RowBackground(group)); } Columns = createHeaders(); @@ -135,12 +136,17 @@ namespace osu.Game.Screens.Edit.Timing public class RowBackground : OsuClickableContainer { + private readonly ControlPointGroup controlGroup; private const int fade_duration = 100; private readonly Box hoveredBackground; - public RowBackground() + [Resolved] + private Bindable selectedGroup { get; set; } + + public RowBackground(ControlPointGroup controlGroup) { + this.controlGroup = controlGroup; RelativeSizeAxes = Axes.X; Height = 25; @@ -157,25 +163,63 @@ namespace osu.Game.Screens.Edit.Timing Alpha = 0, }, }; + + Action = () => selectedGroup.Value = controlGroup; } + private Color4 colourHover; + private Color4 colourSelected; + [BackgroundDependencyLoader] private void load(OsuColour colours) { - hoveredBackground.Colour = colours.Blue; + hoveredBackground.Colour = colourHover = colours.BlueDarker; + colourSelected = colours.YellowDarker; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + selectedGroup.BindValueChanged(group => { Selected = controlGroup == group.NewValue; }); + } + + private bool selected; + + protected bool Selected + { + get => selected; + set + { + if (value == selected) + return; + + selected = value; + updateState(); + } } protected override bool OnHover(HoverEvent e) { - hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + updateState(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + updateState(); base.OnHoverLost(e); } + + private void updateState() + { + hoveredBackground.FadeColour(selected ? colourSelected : colourHover, 450, Easing.OutQuint); + + if (selected || IsHovered) + hoveredBackground.FadeIn(fade_duration, Easing.OutQuint); + else + hoveredBackground.FadeOut(fade_duration, Easing.OutQuint); + } } } } From de69665a4652f2f0595bb612c3c53570348522df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 Oct 2019 14:17:59 +0900 Subject: [PATCH 061/503] Reduce horizontal spacing of attributes --- osu.Game/Screens/Edit/Timing/ControlPointTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index df1f6daf4e..8d5774cd09 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Edit.Timing Direction = FillDirection.Horizontal, ChildrenEnumerable = group.ControlPoints.Select(createAttribute).Where(c => c != null), Padding = new MarginPadding(10), - Spacing = new Vector2(10) + Spacing = new Vector2(2) }, }; From 0fba272e78dc1501847d8a97c8a38a69e126b695 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 Oct 2019 15:19:36 +0900 Subject: [PATCH 062/503] Add the ability to add new ControlPoint types to existing groups --- .../Visual/Editor/TestSceneTimingScreen.cs | 5 + .../ControlPoints/ControlPointGroup.cs | 6 +- .../Edit/Timing/ControlPointSettings.cs | 190 ------------------ .../Screens/Edit/Timing/ControlPointTable.cs | 64 ++++-- .../Screens/Edit/Timing/DifficultySection.cs | 37 ++++ osu.Game/Screens/Edit/Timing/EffectSection.cs | 44 ++++ osu.Game/Screens/Edit/Timing/SampleSection.cs | 44 ++++ osu.Game/Screens/Edit/Timing/Section.cs | 126 ++++++++++++ osu.Game/Screens/Edit/Timing/TimingSection.cs | 44 ++++ 9 files changed, 346 insertions(+), 214 deletions(-) create mode 100644 osu.Game/Screens/Edit/Timing/DifficultySection.cs create mode 100644 osu.Game/Screens/Edit/Timing/EffectSection.cs create mode 100644 osu.Game/Screens/Edit/Timing/SampleSection.cs create mode 100644 osu.Game/Screens/Edit/Timing/Section.cs create mode 100644 osu.Game/Screens/Edit/Timing/TimingSection.cs diff --git a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs index 3e227169e0..121853d8d0 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneTimingScreen.cs @@ -17,6 +17,11 @@ namespace osu.Game.Tests.Visual.Editor { typeof(ControlPointTable), typeof(ControlPointSettings), + typeof(Section<>), + typeof(TimingSection), + typeof(EffectSection), + typeof(SampleSection), + typeof(DifficultySection), typeof(RowAttribute) }; diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs index d57baf25be..cb73ce884e 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { @@ -17,9 +17,9 @@ namespace osu.Game.Beatmaps.ControlPoints /// public double Time { get; } - public IReadOnlyList ControlPoints => controlPoints; + public IBindableList ControlPoints => controlPoints; - private readonly List controlPoints = new List(); + private readonly BindableList controlPoints = new BindableList(); public ControlPointGroup(double time) { diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 470750b860..e1182d9fa4 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -2,17 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Timing { @@ -51,190 +46,5 @@ namespace osu.Game.Screens.Edit.Timing new SampleSection(), new EffectSection(), }; - - private class TimingSection : Section - { - private OsuSpriteText bpm; - private OsuSpriteText timeSignature; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - bpm = new OsuSpriteText(), - timeSignature = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; - timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; - }); - } - } - - private class DifficultySection : Section - { - private OsuSpriteText multiplier; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - multiplier = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); - } - } - - private class SampleSection : Section - { - private OsuSpriteText bank; - private OsuSpriteText volume; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - bank = new OsuSpriteText(), - volume = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; - }); - } - } - - private class EffectSection : Section - { - private OsuSpriteText kiai; - private OsuSpriteText omitBarLine; - - [BackgroundDependencyLoader] - private void load() - { - Flow.AddRange(new[] - { - kiai = new OsuSpriteText(), - omitBarLine = new OsuSpriteText(), - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; - omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; - }); - } - } - - private class Section : CompositeDrawable - where T : ControlPoint - { - private OsuCheckbox checkbox; - private Container content; - - protected FillFlowContainer Flow { get; private set; } - - protected Bindable ControlPoint { get; } = new Bindable(); - - private const float header_height = 20; - - [Resolved] - private Bindable selectedPoints { get; set; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - RelativeSizeAxes = Axes.X; - AutoSizeDuration = 200; - AutoSizeEasing = Easing.OutQuint; - AutoSizeAxes = Axes.Y; - - Masking = true; - - InternalChildren = new Drawable[] - { - new Box - { - Colour = colours.Gray1, - RelativeSizeAxes = Axes.Both, - }, - new Container - { - RelativeSizeAxes = Axes.X, - Height = header_height, - Children = new Drawable[] - { - checkbox = new OsuCheckbox - { - LabelText = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) - } - } - }, - content = new Container - { - Y = header_height, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new Box - { - Colour = colours.Gray2, - RelativeSizeAxes = Axes.Both, - }, - Flow = new FillFlowContainer - { - Padding = new MarginPadding(10), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - }, - } - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - selectedPoints.BindValueChanged(points => - { - ControlPoint.Value = points.NewValue?.ControlPoints.OfType().FirstOrDefault(); - - checkbox.Current.Value = ControlPoint.Value != null; - }, true); - - checkbox.Current.BindValueChanged(selected => { content.BypassAutoSizeAxes = selected.NewValue ? Axes.None : Axes.Y; }, true); - } - } } } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 8d5774cd09..9c11443199 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -92,35 +92,57 @@ namespace osu.Game.Screens.Edit.Timing Text = $"{group.Time:n0}ms", Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - ChildrenEnumerable = group.ControlPoints.Select(createAttribute).Where(c => c != null), - Padding = new MarginPadding(10), - Spacing = new Vector2(2) - }, + new ControlGroupAttributes(group), }; - private Drawable createAttribute(ControlPoint controlPoint) + private class ControlGroupAttributes : CompositeDrawable { - switch (controlPoint) + private readonly IBindableList controlPoints; + + private readonly FillFlowContainer fill; + + public ControlGroupAttributes(ControlPointGroup group) { - case TimingControlPoint timing: - return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + InternalChild = fill = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding(10), + Spacing = new Vector2(2) + }; - case DifficultyControlPoint difficulty: + controlPoints = group.ControlPoints.GetBoundCopy(); + controlPoints.ItemsAdded += _ => createChildren(); + controlPoints.ItemsRemoved += _ => createChildren(); - return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); - - case EffectControlPoint effect: - return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); - - case SampleControlPoint sample: - return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + createChildren(); } - return null; + private void createChildren() + { + fill.ChildrenEnumerable = controlPoints.Select(createAttribute).Where(c => c != null); + } + + private Drawable createAttribute(ControlPoint controlPoint) + { + switch (controlPoint) + { + case TimingControlPoint timing: + return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + + case DifficultyControlPoint difficulty: + + return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + + case EffectControlPoint effect: + return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + + case SampleControlPoint sample: + return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + } + + return null; + } } protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? string.Empty); diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs new file mode 100644 index 0000000000..150c11f5ee --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -0,0 +1,37 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class DifficultySection : Section + { + private OsuSpriteText multiplier; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + multiplier = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); + } + + protected override DifficultyControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.DifficultyPointAt(SelectedGroup.Value.Time); + + return new DifficultyControlPoint + { + SpeedMultiplier = reference.SpeedMultiplier, + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs new file mode 100644 index 0000000000..ff8817147a --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -0,0 +1,44 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class EffectSection : Section + { + private OsuSpriteText kiai; + private OsuSpriteText omitBarLine; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + kiai = new OsuSpriteText(), + omitBarLine = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; + omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; + }); + } + + protected override EffectControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(SelectedGroup.Value.Time); + + return new EffectControlPoint + { + KiaiMode = reference.KiaiMode, + OmitFirstBarLine = reference.OmitFirstBarLine + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs new file mode 100644 index 0000000000..0d6bc74057 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -0,0 +1,44 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class SampleSection : Section + { + private OsuSpriteText bank; + private OsuSpriteText volume; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bank = new OsuSpriteText(), + volume = new OsuSpriteText(), + }); + } + + protected override SampleControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.SamplePointAt(SelectedGroup.Value.Time); + + return new SampleControlPoint + { + SampleBank = reference.SampleBank, + SampleVolume = reference.SampleVolume, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bank.Text = $"Bank: {point.NewValue?.SampleBank}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; + }); + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Edit/Timing/Section.cs b/osu.Game/Screens/Edit/Timing/Section.cs new file mode 100644 index 0000000000..c6140ff497 --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/Section.cs @@ -0,0 +1,126 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Edit.Timing +{ + internal abstract class Section : CompositeDrawable + where T : ControlPoint + { + private OsuCheckbox checkbox; + private Container content; + + protected FillFlowContainer Flow { get; private set; } + + protected Bindable ControlPoint { get; } = new Bindable(); + + private const float header_height = 20; + + [Resolved] + protected IBindable Beatmap { get; private set; } + + [Resolved] + protected Bindable SelectedGroup { get; private set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + RelativeSizeAxes = Axes.X; + AutoSizeDuration = 200; + AutoSizeEasing = Easing.OutQuint; + AutoSizeAxes = Axes.Y; + + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = colours.Gray1, + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = header_height, + Children = new Drawable[] + { + checkbox = new OsuCheckbox + { + LabelText = typeof(T).Name.Replace(typeof(ControlPoint).Name, string.Empty) + } + } + }, + content = new Container + { + Y = header_height, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Box + { + Colour = colours.Gray2, + RelativeSizeAxes = Axes.Both, + }, + Flow = new FillFlowContainer + { + Padding = new MarginPadding(10), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }, + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + checkbox.Current.BindValueChanged(selected => + { + if (selected.NewValue) + { + if (SelectedGroup.Value == null) + { + checkbox.Current.Value = false; + return; + } + + if (ControlPoint.Value == null) + SelectedGroup.Value.Add(ControlPoint.Value = CreatePoint()); + } + else + { + if (ControlPoint.Value != null) + { + SelectedGroup.Value.Remove(ControlPoint.Value); + ControlPoint.Value = null; + } + } + + content.BypassAutoSizeAxes = selected.NewValue ? Axes.None : Axes.Y; + }, true); + + SelectedGroup.BindValueChanged(points => + { + ControlPoint.Value = points.NewValue?.ControlPoints.OfType().FirstOrDefault(); + checkbox.Current.Value = ControlPoint.Value != null; + }, true); + } + + protected abstract T CreatePoint(); + } +} diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs new file mode 100644 index 0000000000..dcbb6f8bbf --- /dev/null +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -0,0 +1,44 @@ +using osu.Framework.Allocation; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Edit.Timing +{ + internal class TimingSection : Section + { + private OsuSpriteText bpm; + private OsuSpriteText timeSignature; + + [BackgroundDependencyLoader] + private void load() + { + Flow.AddRange(new[] + { + bpm = new OsuSpriteText(), + timeSignature = new OsuSpriteText(), + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ControlPoint.BindValueChanged(point => + { + bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; + timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; + }); + } + + protected override TimingControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(SelectedGroup.Value.Time); + + return new TimingControlPoint + { + BeatLength = reference.BeatLength, + TimeSignature = reference.TimeSignature + }; + } + } +} From 73369ae6130680101aeaf6216307b13e9b76f564 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 Oct 2019 16:13:24 +0900 Subject: [PATCH 063/503] Add the ability to add/remove groups --- .../ControlPoints/ControlPointInfo.cs | 19 +++++++++++-- .../Screens/Edit/Timing/ControlPointTable.cs | 2 +- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 27 ++++++++++++++----- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index e165adedea..4f83e14eaf 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Framework.Lists; namespace osu.Game.Beatmaps.ControlPoints @@ -16,9 +17,9 @@ namespace osu.Game.Beatmaps.ControlPoints /// Control point groups. /// [JsonProperty] - public IReadOnlyList Groups => groups; + public IBindableList Groups => groups; - private readonly SortedList groups = new SortedList(Comparer.Default); + private readonly BindableList groups = new BindableList(); /// /// All timing points. @@ -294,5 +295,19 @@ namespace osu.Game.Beatmaps.ControlPoints samplePoints.Clear(); effectPoints.Clear(); } + + public ControlPointGroup CreateGroup(double time) + { + var newGroup = new ControlPointGroup(time); + + int i = groups.BinarySearch(newGroup); + if (i < 0) i = ~i; + + groups.Insert(i, newGroup); + + return newGroup; + } + + public void RemoveGroup(ControlPointGroup group) => groups.Remove(group); } } diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 9c11443199..729e631d87 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -203,7 +203,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedGroup.BindValueChanged(group => { Selected = controlGroup == group.NewValue; }); + selectedGroup.BindValueChanged(group => { Selected = controlGroup == group.NewValue; }, true); } private bool selected; diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index a9fd038829..2b1c8f8497 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -52,12 +52,18 @@ namespace osu.Game.Screens.Edit.Timing public class ControlPointList : CompositeDrawable { private OsuButton deleteButton; + private ControlPointTable table; + + private IBindableList controlGroups; + + [Resolved] + protected IFrameBasedClock EditorClock { get; private set; } [Resolved] protected IBindable Beatmap { get; private set; } [Resolved] - private Bindable selectedPoints { get; set; } + private Bindable selectedGroup { get; set; } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -74,10 +80,7 @@ namespace osu.Game.Screens.Edit.Timing new OsuScrollContainer { RelativeSizeAxes = Axes.Both, - Child = new ControlPointTable - { - ControlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups - } + Child = table = new ControlPointTable(), }, new FillFlowContainer { @@ -114,15 +117,27 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedPoints.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); + selectedGroup.BindValueChanged(selected => { deleteButton.Enabled.Value = selected.NewValue != null; }, true); + + controlGroups = Beatmap.Value.Beatmap.ControlPointInfo.Groups.GetBoundCopy(); + controlGroups.ItemsAdded += _ => createContent(); + controlGroups.ItemsRemoved += _ => createContent(); + createContent(); } + private void createContent() => table.ControlGroups = controlGroups; + private void delete() { + if (selectedGroup.Value == null) + return; + + Beatmap.Value.Beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value); } private void addNew() { + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(EditorClock.CurrentTime); } } } From 81b5d7b79fd668463a7d1c616a66da5a77ec4dee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 Oct 2019 16:30:05 +0900 Subject: [PATCH 064/503] Select another group after deleting selected --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 2b1c8f8497..2e9164c60f 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -57,7 +58,7 @@ namespace osu.Game.Screens.Edit.Timing private IBindableList controlGroups; [Resolved] - protected IFrameBasedClock EditorClock { get; private set; } + private IFrameBasedClock clock { get; set; } [Resolved] protected IBindable Beatmap { get; private set; } @@ -133,11 +134,13 @@ namespace osu.Game.Screens.Edit.Timing return; Beatmap.Value.Beatmap.ControlPointInfo.RemoveGroup(selectedGroup.Value); + + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.Groups.FirstOrDefault(g => g.Time >= clock.CurrentTime); } private void addNew() { - selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(EditorClock.CurrentTime); + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(clock.CurrentTime); } } } From 0179586f7811a1d71209d61cb676a0dd856cb7d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 27 Oct 2019 16:31:23 +0900 Subject: [PATCH 065/503] Disallow inserting a group if one already exists with the current time value --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 4f83e14eaf..6418ef984b 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -301,9 +301,11 @@ namespace osu.Game.Beatmaps.ControlPoints var newGroup = new ControlPointGroup(time); int i = groups.BinarySearch(newGroup); - if (i < 0) i = ~i; - groups.Insert(i, newGroup); + if (i > 0) + return groups[i]; + + groups.Insert(~i, newGroup); return newGroup; } From 29e20bc8d2796d8ac5cb3f8a53dc684ec67263d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 10:45:11 +0900 Subject: [PATCH 066/503] Add xmldoc and combine GroupAt / CreateGroup --- .../ControlPoints/ControlPointInfo.cs | 174 ++++++++---------- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 2 +- 2 files changed, 79 insertions(+), 97 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 6418ef984b..c3e2b469ae 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.ControlPoints public class ControlPointInfo { /// - /// Control point groups. + /// All control points grouped by time. /// [JsonProperty] public IBindableList Groups => groups; @@ -86,28 +86,6 @@ namespace osu.Game.Beatmaps.ControlPoints /// The timing control point. public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); - /// - /// Finds the closest of the same type as that is active at . - /// - /// The time to find the timing control point at. - /// A reference point to infer type. - /// The timing control point. - public ControlPoint SimilarPointAt(double time, ControlPoint referencePoint) - { - switch (referencePoint) - { - case TimingControlPoint _: return binarySearch(TimingPoints, time); - - case EffectControlPoint _: return binarySearch(EffectPoints, time); - - case SampleControlPoint _: return binarySearch(SamplePoints, time); - - case DifficultyControlPoint _: return binarySearch(DifficultyPoints, time); - } - - return null; - } - /// /// Finds the maximum BPM represented by any timing control point. /// @@ -129,6 +107,62 @@ namespace osu.Game.Beatmaps.ControlPoints public double BPMMode => 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + /// + /// Remove all s and return to a pristine state. + /// + public void Clear() + { + groups.Clear(); + timingPoints.Clear(); + difficultyPoints.Clear(); + samplePoints.Clear(); + effectPoints.Clear(); + } + + /// + /// Add a new . Note that the provided control point may not be added if the correct state is already present at the provided time. + /// + /// The time at which the control point should be added. + /// The control point to add. + /// Whether the control point was added. + public bool Add(double time, ControlPoint controlPoint) + { + if (checkAlreadyExisting(time, controlPoint)) + return false; + + GroupAt(time, true).Add(controlPoint); + return true; + } + + public ControlPointGroup GroupAt(double time, bool addIfNotExisting = false) + { + var newGroup = new ControlPointGroup(time); + + int i = groups.BinarySearch(newGroup); + + if (i >= 0) + return groups[i]; + + if (addIfNotExisting) + { + newGroup.ItemAdded += groupItemAdded; + newGroup.ItemRemoved += groupItemRemoved; + + groups.Insert(~i, newGroup); + return newGroup; + } + + return null; + } + + public void RemoveGroup(ControlPointGroup group) + { + group.ItemAdded -= groupItemAdded; + group.ItemRemoved -= groupItemRemoved; + + groups.Remove(group); + } + /// /// Binary searches one of the control point lists to find the active control point at . /// Includes logic for returning a specific point when no matching point is found. @@ -183,33 +217,6 @@ namespace osu.Game.Beatmaps.ControlPoints return list[l - 1]; } - public void Add(double time, ControlPoint newPoint, bool force = false) - { - if (!force && checkAlreadyExisting(time, newPoint)) - return; - - GroupAt(time, true).Add(newPoint); - } - - public ControlPointGroup GroupAt(double time, bool createIfNotExisting = false) - { - var existing = Groups.FirstOrDefault(g => g.Time == time); - - if (existing != null) - return existing; - - if (createIfNotExisting) - { - var newGroup = new ControlPointGroup(time); - newGroup.ItemAdded += groupItemAdded; - newGroup.ItemRemoved += groupItemRemoved; - groups.Add(newGroup); - return newGroup; - } - - return null; - } - /// /// Check whether should be added. /// @@ -243,31 +250,9 @@ namespace osu.Game.Beatmaps.ControlPoints return existing?.EquivalentTo(newPoint) == true; } - private void groupItemRemoved(ControlPoint obj) + private void groupItemAdded(ControlPoint controlPoint) { - switch (obj) - { - case TimingControlPoint typed: - timingPoints.Remove(typed); - break; - - case EffectControlPoint typed: - effectPoints.Remove(typed); - break; - - case SampleControlPoint typed: - samplePoints.Remove(typed); - break; - - case DifficultyControlPoint typed: - difficultyPoints.Remove(typed); - break; - } - } - - private void groupItemAdded(ControlPoint obj) - { - switch (obj) + switch (controlPoint) { case TimingControlPoint typed: timingPoints.Add(typed); @@ -287,29 +272,26 @@ namespace osu.Game.Beatmaps.ControlPoints } } - public void Clear() + private void groupItemRemoved(ControlPoint controlPoint) { - groups.Clear(); - timingPoints.Clear(); - difficultyPoints.Clear(); - samplePoints.Clear(); - effectPoints.Clear(); + switch (controlPoint) + { + case TimingControlPoint typed: + timingPoints.Remove(typed); + break; + + case EffectControlPoint typed: + effectPoints.Remove(typed); + break; + + case SampleControlPoint typed: + samplePoints.Remove(typed); + break; + + case DifficultyControlPoint typed: + difficultyPoints.Remove(typed); + break; + } } - - public ControlPointGroup CreateGroup(double time) - { - var newGroup = new ControlPointGroup(time); - - int i = groups.BinarySearch(newGroup); - - if (i > 0) - return groups[i]; - - groups.Insert(~i, newGroup); - - return newGroup; - } - - public void RemoveGroup(ControlPointGroup group) => groups.Remove(group); } } diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 2e9164c60f..6ae01e056f 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -140,7 +140,7 @@ namespace osu.Game.Screens.Edit.Timing private void addNew() { - selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.CreateGroup(clock.CurrentTime); + selectedGroup.Value = Beatmap.Value.Beatmap.ControlPointInfo.GroupAt(clock.CurrentTime, true); } } } From cd4b7c04e9a18668680016c9b45ee1d4c3f1976d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 11:34:41 +0900 Subject: [PATCH 067/503] Add test coverage --- .../NonVisual/ControlPointInfoTest.cs | 227 ++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 osu.Game.Tests/NonVisual/ControlPointInfoTest.cs diff --git a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs new file mode 100644 index 0000000000..a51b90851c --- /dev/null +++ b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs @@ -0,0 +1,227 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps.ControlPoints; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class ControlPointInfoTest + { + [Test] + public void TestAdd() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + + Assert.That(cpi.Groups.Count, Is.EqualTo(2)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(2)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(2)); + } + + [Test] + public void TestAddRedundantTiming() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); // is *not* redundant, special exception for first timing point. + cpi.Add(1000, new TimingControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantDifficulty() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new DifficultyControlPoint()); // is redundant + cpi.Add(1000, new DifficultyControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new DifficultyControlPoint { SpeedMultiplier = 2 }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantSample() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new SampleControlPoint()); // is redundant + cpi.Add(1000, new SampleControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new SampleControlPoint { SampleVolume = 50 }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.SamplePoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddRedundantEffect() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new EffectControlPoint()); // is redundant + cpi.Add(1000, new EffectControlPoint()); // is redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.TimingPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(0)); + + cpi.Add(1000, new EffectControlPoint { KiaiMode = true }); // is not redundant + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.EffectPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.AllControlPoints.Count(), Is.EqualTo(1)); + } + + [Test] + public void TestAddGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + var group2 = cpi.GroupAt(1000, true); + + Assert.That(group, Is.EqualTo(group2)); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + } + + [Test] + public void TestGroupAtLookupOnly() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(5000, true); + Assert.That(group, Is.Not.Null); + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + Assert.That(cpi.GroupAt(1000), Is.Null); + Assert.That(cpi.GroupAt(5000), Is.Not.Null); + } + + [Test] + public void TestAddRemoveGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + cpi.RemoveGroup(group); + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + } + + [Test] + public void TestAddControlPointToGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + // usually redundant, but adding to group forces it to be added + group.Add(new DifficultyControlPoint()); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + } + + [Test] + public void TestAddDuplicateControlPointToGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + group.Add(new DifficultyControlPoint()); + group.Add(new DifficultyControlPoint { SpeedMultiplier = 2 }); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(1)); + Assert.That(cpi.DifficultyPoints.First().SpeedMultiplier, Is.EqualTo(2)); + } + + [Test] + public void TestRemoveControlPointFromGroup() + { + var cpi = new ControlPointInfo(); + + var group = cpi.GroupAt(1000, true); + Assert.That(cpi.Groups.Count, Is.EqualTo(1)); + + var difficultyPoint = new DifficultyControlPoint(); + + group.Add(difficultyPoint); + group.Remove(difficultyPoint); + + Assert.That(group.ControlPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0)); + } + + [Test] + public void TestOrdering() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + cpi.Add(10000, new TimingControlPoint { BeatLength = 200 }); + cpi.Add(5000, new TimingControlPoint { BeatLength = 100 }); + cpi.Add(3000, new DifficultyControlPoint { SpeedMultiplier = 2 }); + cpi.GroupAt(7000, true).Add(new DifficultyControlPoint { SpeedMultiplier = 4 }); + cpi.GroupAt(1000).Add(new SampleControlPoint { SampleVolume = 0 }); + cpi.GroupAt(8000, true).Add(new EffectControlPoint { KiaiMode = true }); + + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(8)); + + Assert.That(cpi.Groups, Is.Ordered.Ascending.By(nameof(ControlPointGroup.Time))); + + Assert.That(cpi.AllControlPoints, Is.Ordered.Ascending.By(nameof(ControlPoint.Time))); + Assert.That(cpi.TimingPoints, Is.Ordered.Ascending.By(nameof(ControlPoint.Time))); + } + + [Test] + public void TestClear() + { + var cpi = new ControlPointInfo(); + + cpi.Add(0, new TimingControlPoint()); + cpi.Add(1000, new TimingControlPoint { BeatLength = 500 }); + cpi.Add(10000, new TimingControlPoint { BeatLength = 200 }); + cpi.Add(5000, new TimingControlPoint { BeatLength = 100 }); + cpi.Add(3000, new DifficultyControlPoint { SpeedMultiplier = 2 }); + cpi.GroupAt(7000, true).Add(new DifficultyControlPoint { SpeedMultiplier = 4 }); + cpi.GroupAt(1000).Add(new SampleControlPoint { SampleVolume = 0 }); + cpi.GroupAt(8000, true).Add(new EffectControlPoint { KiaiMode = true }); + + cpi.Clear(); + + Assert.That(cpi.Groups.Count, Is.EqualTo(0)); + Assert.That(cpi.DifficultyPoints.Count, Is.EqualTo(0)); + Assert.That(cpi.AllControlPoints.Count, Is.EqualTo(0)); + } + } +} From 43ad4a3a3c978b4305a48576ec3769f91d7f929e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 12:31:38 +0900 Subject: [PATCH 068/503] Tidy up string output --- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 5 +++++ osu.Game/Screens/Edit/Timing/DifficultySection.cs | 2 +- osu.Game/Screens/Edit/Timing/EffectSection.cs | 4 ++-- osu.Game/Screens/Edit/Timing/SampleSection.cs | 4 ++-- osu.Game/Screens/Edit/Timing/TimingSection.cs | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index f8c84c79dd..e3451892bf 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -24,6 +24,11 @@ namespace osu.Game.Beatmaps.ControlPoints set => beatLength = MathHelper.Clamp(value, 6, 60000); } + /// + /// The BPM at this control point. + /// + public double BPM => 60000 / BeatLength; + private double beatLength = DEFAULT_BEAT_LENGTH; public override bool EquivalentTo(ControlPoint other) => diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index 150c11f5ee..df61300451 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier}"; }); + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier::0.##}x"; }); } protected override DifficultyControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index ff8817147a..57bee44177 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -25,8 +25,8 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - kiai.Text = $"Kiai: {point.NewValue?.KiaiMode}"; - omitBarLine.Text = $"Skip Bar Line: {point.NewValue?.OmitFirstBarLine}"; + kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; + omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; }); } diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index 0d6bc74057..d623ad08ae 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -37,8 +37,8 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; }); } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index dcbb6f8bbf..4f2cf82a65 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - bpm.Text = $"BPM: {point.NewValue?.BeatLength}"; + bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; }); } From ee5591d7d502244c61ca8cb2ee515eccc9403086 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 12:42:17 +0900 Subject: [PATCH 069/503] Add missing license headers --- osu.Game/Screens/Edit/Timing/DifficultySection.cs | 3 +++ osu.Game/Screens/Edit/Timing/EffectSection.cs | 3 +++ osu.Game/Screens/Edit/Timing/SampleSection.cs | 3 +++ osu.Game/Screens/Edit/Timing/TimingSection.cs | 3 +++ 4 files changed, 12 insertions(+) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index df61300451..bd363c3158 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index 57bee44177..bafdfd0b0d 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index d623ad08ae..0477ad4e78 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 4f2cf82a65..8609da4c4d 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -1,3 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; From 9acdcc912924ecc83df4bddd80ff59347cdfef94 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 14:44:45 +0900 Subject: [PATCH 070/503] Make all control point attributes bindable Properties are left intact for compatibility reasons. --- .../ControlPoints/DifficultyControlPoint.cs | 19 +++++++---- .../ControlPoints/EffectControlPoint.cs | 26 +++++++++++++-- .../ControlPoints/SampleControlPoint.cs | 27 ++++++++++++++-- .../ControlPoints/TimingControlPoint.cs | 32 ++++++++++++++----- ...egacyDifficultyCalculatorBeatmapDecoder.cs | 6 +++- 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 42651fd0ca..7726eb0245 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,24 +1,31 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { public class DifficultyControlPoint : ControlPoint { + /// + /// The speed multiplier at this control point. + /// + public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) + { + MinValue = 0.1, + MaxValue = 10 + }; + /// /// The speed multiplier at this control point. /// public double SpeedMultiplier { - get => speedMultiplier; - set => speedMultiplier = MathHelper.Clamp(value, 0.1, 10); + get => SpeedMultiplierBindable.Value; + set => SpeedMultiplierBindable.Value = value; } - private double speedMultiplier = 1; - public override bool EquivalentTo(ControlPoint other) => - other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(speedMultiplier); + other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(SpeedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 928f2a51ad..369b93ff3d 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,19 +1,39 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; + namespace osu.Game.Beatmaps.ControlPoints { public class EffectControlPoint : ControlPoint { /// - /// Whether this control point enables Kiai mode. + /// Whether the first bar line of this control point is ignored. /// - public bool KiaiMode; + public readonly BindableBool OmitFirstBarLineBindable = new BindableBool(); /// /// Whether the first bar line of this control point is ignored. /// - public bool OmitFirstBarLine; + public bool OmitFirstBarLine + { + get => OmitFirstBarLineBindable.Value; + set => OmitFirstBarLineBindable.Value = value; + } + + /// + /// Whether this control point enables Kiai mode. + /// + public readonly BindableBool KiaiModeBindable = new BindableBool(); + + /// + /// Whether this control point enables Kiai mode. + /// + public bool KiaiMode + { + get => KiaiModeBindable.Value; + set => KiaiModeBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is EffectControlPoint otherTyped && diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 07f5aa6c90..37607c716e 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints @@ -12,12 +13,34 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The default sample bank at this control point. /// - public string SampleBank = DEFAULT_BANK; + public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK); + + /// + /// The speed multiplier at this control point. + /// + public string SampleBank + { + get => SampleBankBindable.Value; + set => SampleBankBindable.Value = value; + } + + /// + /// The default sample bank at this control point. + /// + public readonly BindableInt SampleVolumeBindable = new BindableInt(100) + { + MinValue = 0, + MaxValue = 100 + }; /// /// The default sample volume at this control point. /// - public int SampleVolume = 100; + public int SampleVolume + { + get => SampleVolumeBindable.Value; + set => SampleVolumeBindable.Value = value; + } /// /// Create a SampleInfo based on the sample settings in this control point. diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index f8c84c79dd..d25d08c5bd 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Bindables; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints @@ -11,23 +11,39 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time signature at this control point. /// - public TimeSignatures TimeSignature = TimeSignatures.SimpleQuadruple; + public readonly Bindable TimeSignatureBindable = new Bindable(TimeSignatures.SimpleQuadruple); + + /// + /// The time signature at this control point. + /// + public TimeSignatures TimeSignature + { + get => TimeSignatureBindable.Value; + set => TimeSignatureBindable.Value = value; + } public const double DEFAULT_BEAT_LENGTH = 1000; /// /// The beat length at this control point. /// - public virtual double BeatLength + public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { - get => beatLength; - set => beatLength = MathHelper.Clamp(value, 6, 60000); - } + MinValue = 6, + MaxValue = 60000 + }; - private double beatLength = DEFAULT_BEAT_LENGTH; + /// + /// The beat length at this control point. + /// + public double BeatLength + { + get => BeatLengthBindable.Value; + set => BeatLengthBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is TimingControlPoint otherTyped - && TimeSignature == otherTyped.TimeSignature && beatLength.Equals(otherTyped.beatLength); + && TimeSignature == otherTyped.TimeSignature && BeatLength.Equals(otherTyped.BeatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 238187bf8f..a16d391b99 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -32,7 +32,11 @@ namespace osu.Game.Beatmaps.Formats private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint { - public override double BeatLength { get; set; } = DEFAULT_BEAT_LENGTH; + public LegacyDifficultyCalculatorControlPoint() + { + BeatLengthBindable.MinValue = double.MinValue; + BeatLengthBindable.MaxValue = double.MaxValue; + } } } } From d33b31f0c5100850be2ae873ca46ab4fdb71fffd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 15:33:08 +0900 Subject: [PATCH 071/503] Expose Current bindable in LabelledComponents Adds a `LabelledDrawable` class for usages where bindables are not present. --- .../TestSceneLabelledComponent.cs | 14 +- .../UserInterface/TestSceneLabelledTextBox.cs | 3 +- osu.Game.Tournament/Screens/SetupScreen.cs | 2 +- .../UserInterfaceV2/LabelledComponent.cs | 124 ++-------------- .../UserInterfaceV2/LabelledDrawable.cs | 132 ++++++++++++++++++ .../UserInterfaceV2/LabelledSwitchButton.cs | 2 +- .../UserInterfaceV2/LabelledTextBox.cs | 2 +- 7 files changed, 151 insertions(+), 128 deletions(-) create mode 100644 osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs index 700adad9cb..8179f92ffc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledComponent.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneLabelledComponent : OsuTestScene + public class TestSceneLabelledDrawable : OsuTestScene { [TestCase(false)] [TestCase(true)] @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent component; + LabelledDrawable component; Child = new Container { @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.Centre, Width = 500, AutoSizeAxes = Axes.Y, - Child = component = padded ? (LabelledComponent)new PaddedLabelledComponent() : new NonPaddedLabelledComponent(), + Child = component = padded ? (LabelledDrawable)new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(), }; component.Label = "a sample component"; @@ -41,9 +41,9 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private class PaddedLabelledComponent : LabelledComponent + private class PaddedLabelledDrawable : LabelledDrawable { - public PaddedLabelledComponent() + public PaddedLabelledDrawable() : base(true) { } @@ -57,9 +57,9 @@ namespace osu.Game.Tests.Visual.UserInterface }; } - private class NonPaddedLabelledComponent : LabelledComponent + private class NonPaddedLabelledDrawable : LabelledDrawable { - public NonPaddedLabelledComponent() + public NonPaddedLabelledDrawable() : base(false) { } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 53a2bfabbc..8208b55952 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Tests.Visual.UserInterface @@ -28,7 +27,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("create component", () => { - LabelledComponent component; + LabelledTextBox component; Child = new Container { diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index 091a837745..a67daa2756 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -89,7 +89,7 @@ namespace osu.Game.Tournament.Screens }; } - private class ActionableInfo : LabelledComponent + private class ActionableInfo : LabelledDrawable { private OsuButton button; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index 2e659825b7..1819b36667 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -1,132 +1,24 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Containers; -using osuTK; +using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public abstract class LabelledComponent : CompositeDrawable - where T : Drawable + public abstract class LabelledComponent : LabelledDrawable, IHasCurrentValue + where T : Drawable, IHasCurrentValue { - protected const float CONTENT_PADDING_VERTICAL = 10; - protected const float CONTENT_PADDING_HORIZONTAL = 15; - protected const float CORNER_RADIUS = 15; - - /// - /// The component that is being displayed. - /// - protected readonly T Component; - - private readonly OsuTextFlowContainer labelText; - private readonly OsuTextFlowContainer descriptionText; - - /// - /// Creates a new . - /// - /// Whether the component should be padded or should be expanded to the bounds of this . protected LabelledComponent(bool padded) + : base(padded) { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - CornerRadius = CORNER_RADIUS; - Masking = true; - - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("1c2125"), - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = padded - ? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL, Vertical = CONTENT_PADDING_VERTICAL } - : new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL }, - Spacing = new Vector2(0, 12), - Children = new Drawable[] - { - new GridContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Content = new[] - { - new Drawable[] - { - labelText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Bold)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 20 } - }, - new Container - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = Component = CreateComponent().With(d => - { - d.Anchor = Anchor.CentreRight; - d.Origin = Anchor.CentreRight; - }) - } - }, - }, - RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, - ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } - }, - descriptionText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL }, - Alpha = 0, - } - } - } - }; } - [BackgroundDependencyLoader] - private void load(OsuColour osuColour) + public Bindable Current { - descriptionText.Colour = osuColour.Yellow; + get => Component.Current; + set => Component.Current = value; } - - public string Label - { - set => labelText.Text = value; - } - - public string Description - { - set - { - descriptionText.Text = value; - - if (!string.IsNullOrEmpty(value)) - descriptionText.Show(); - else - descriptionText.Hide(); - } - } - - /// - /// Creates the component that should be displayed. - /// - /// The component. - protected abstract T CreateComponent(); } } diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs new file mode 100644 index 0000000000..f44bd72aee --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs @@ -0,0 +1,132 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public abstract class LabelledDrawable : CompositeDrawable + where T : Drawable + { + protected const float CONTENT_PADDING_VERTICAL = 10; + protected const float CONTENT_PADDING_HORIZONTAL = 15; + protected const float CORNER_RADIUS = 15; + + /// + /// The component that is being displayed. + /// + protected readonly T Component; + + private readonly OsuTextFlowContainer labelText; + private readonly OsuTextFlowContainer descriptionText; + + /// + /// Creates a new . + /// + /// Whether the component should be padded or should be expanded to the bounds of this . + protected LabelledDrawable(bool padded) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + CornerRadius = CORNER_RADIUS; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("1c2125"), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = padded + ? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL, Vertical = CONTENT_PADDING_VERTICAL } + : new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL }, + Spacing = new Vector2(0, 12), + Children = new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Content = new[] + { + new Drawable[] + { + labelText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(weight: FontWeight.Bold)) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 20 } + }, + new Container + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = Component = CreateComponent().With(d => + { + d.Anchor = Anchor.CentreRight; + d.Origin = Anchor.CentreRight; + }) + } + }, + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + ColumnDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } + }, + descriptionText = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold, italics: true)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL }, + Alpha = 0, + } + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour osuColour) + { + descriptionText.Colour = osuColour.Yellow; + } + + public string Label + { + set => labelText.Text = value; + } + + public string Description + { + set + { + descriptionText.Text = value; + + if (!string.IsNullOrEmpty(value)) + descriptionText.Show(); + else + descriptionText.Hide(); + } + } + + /// + /// Creates the component that should be displayed. + /// + /// The component. + protected abstract T CreateComponent(); + } +} diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs index c973f1d13e..c374d80830 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs @@ -3,7 +3,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledSwitchButton : LabelledComponent + public class LabelledSwitchButton : LabelledComponent { public LabelledSwitchButton() : base(true) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs index 50d2a14482..2cbe095d0b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 { - public class LabelledTextBox : LabelledComponent + public class LabelledTextBox : LabelledComponent { public event TextBox.OnCommitHandler OnCommit; From 0a11cbf656aef28930ad01e1306ed907958d1832 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 16:20:33 +0900 Subject: [PATCH 072/503] Make OsuButton correctly block hover events --- osu.Game/Graphics/UserInterface/OsuButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index c1810800a0..4124d2ad58 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -59,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { hover.FadeIn(200); - return base.OnHover(e); + return true; } protected override void OnHoverLost(HoverLostEvent e) From 9c3e54909ca56882d230d4b4ebbd39d36fda96bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 16:20:54 +0900 Subject: [PATCH 073/503] Ensure tooltips of RowAttributes are up-to-date --- osu.Game/Screens/Edit/Timing/ControlPointTable.cs | 8 ++++---- osu.Game/Screens/Edit/Timing/RowAttribute.cs | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 729e631d87..96e3ab48f2 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -128,17 +128,17 @@ namespace osu.Game.Screens.Edit.Timing switch (controlPoint) { case TimingControlPoint timing: - return new RowAttribute("timing", $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); + return new RowAttribute("timing", () => $"{60000 / timing.BeatLength:n1}bpm {timing.TimeSignature}"); case DifficultyControlPoint difficulty: - return new RowAttribute("difficulty", $"{difficulty.SpeedMultiplier:n2}x"); + return new RowAttribute("difficulty", () => $"{difficulty.SpeedMultiplier:n2}x"); case EffectControlPoint effect: - return new RowAttribute("effect", $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); + return new RowAttribute("effect", () => $"{(effect.KiaiMode ? "Kiai " : "")}{(effect.OmitFirstBarLine ? "NoBarLine " : "")}"); case SampleControlPoint sample: - return new RowAttribute("sample", $"{sample.SampleBank} {sample.SampleVolume}%"); + return new RowAttribute("sample", () => $"{sample.SampleBank} {sample.SampleVolume}%"); } return null; diff --git a/osu.Game/Screens/Edit/Timing/RowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttribute.cs index 8716382142..be8f693683 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttribute.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,9 +15,9 @@ namespace osu.Game.Screens.Edit.Timing public class RowAttribute : CompositeDrawable, IHasTooltip { private readonly string header; - private readonly string content; + private readonly Func content; - public RowAttribute(string header, string content) + public RowAttribute(string header, Func content) { this.header = header; this.content = content; @@ -54,6 +55,6 @@ namespace osu.Game.Screens.Edit.Timing }; } - public string TooltipText => content; + public string TooltipText => content(); } } From f761eddec754ef130297d12b4e383e9988d55de2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 16:21:14 +0900 Subject: [PATCH 074/503] Add default bindable values --- osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs | 2 ++ osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 5 +++-- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 7726eb0245..8b21098a51 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -12,6 +12,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) { + Precision = 0.1, + Default = 1, MinValue = 0.1, MaxValue = 10 }; diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 37607c716e..42865c686c 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The default sample bank at this control point. /// - public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK); + public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK) { Default = DEFAULT_BANK }; /// /// The speed multiplier at this control point. @@ -30,7 +30,8 @@ namespace osu.Game.Beatmaps.ControlPoints public readonly BindableInt SampleVolumeBindable = new BindableInt(100) { MinValue = 0, - MaxValue = 100 + MaxValue = 100, + Default = 100 }; /// diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index fb548e60aa..51b3377394 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time signature at this control point. /// - public readonly Bindable TimeSignatureBindable = new Bindable(TimeSignatures.SimpleQuadruple); + public readonly Bindable TimeSignatureBindable = new Bindable(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple }; /// /// The time signature at this control point. @@ -29,6 +29,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { + Default = DEFAULT_BEAT_LENGTH, MinValue = 6, MaxValue = 60000 }; From 522572eacefefa13ae0f4524402984ce141932f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 16:21:31 +0900 Subject: [PATCH 075/503] Add ability to adjust all control point attributes --- .../Screens/Edit/Timing/DifficultySection.cs | 20 +++++-- osu.Game/Screens/Edit/Timing/EffectSection.cs | 17 +++--- osu.Game/Screens/Edit/Timing/SampleSection.cs | 28 ++++++--- osu.Game/Screens/Edit/Timing/TimingSection.cs | 59 ++++++++++++++++--- 4 files changed, 97 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index bd363c3158..d3e1b2a84f 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -2,21 +2,27 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class DifficultySection : Section { - private OsuSpriteText multiplier; + private SettingsSlider multiplier; [BackgroundDependencyLoader] private void load() { Flow.AddRange(new[] { - multiplier = new OsuSpriteText(), + multiplier = new SettingsSlider + { + LabelText = "Speed Multiplier", + Bindable = new DifficultyControlPoint().SpeedMultiplierBindable, + RelativeSizeAxes = Axes.X, + } }); } @@ -24,7 +30,13 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier::0.##}x"; }); + ControlPoint.BindValueChanged(point => + { + if (point.NewValue != null) + { + multiplier.Bindable = point.NewValue.SpeedMultiplierBindable; + } + }, true); } protected override DifficultyControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index bafdfd0b0d..fcd733cf00 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -3,22 +3,22 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Screens.Edit.Timing { internal class EffectSection : Section { - private OsuSpriteText kiai; - private OsuSpriteText omitBarLine; + private LabelledSwitchButton kiai; + private LabelledSwitchButton omitBarLine; [BackgroundDependencyLoader] private void load() { Flow.AddRange(new[] { - kiai = new OsuSpriteText(), - omitBarLine = new OsuSpriteText(), + kiai = new LabelledSwitchButton { Label = "Kiai Time" }, + omitBarLine = new LabelledSwitchButton { Label = "Skip Bar Line" }, }); } @@ -28,8 +28,11 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; - omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; + if (point.NewValue != null) + { + kiai.Current = point.NewValue.KiaiModeBindable; + omitBarLine.Current = point.NewValue.OmitFirstBarLineBindable; + } }); } diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index 0477ad4e78..816f90d19e 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -2,23 +2,32 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class SampleSection : Section { - private OsuSpriteText bank; - private OsuSpriteText volume; + private LabelledTextBox bank; + private SettingsSlider volume; [BackgroundDependencyLoader] private void load() { - Flow.AddRange(new[] + Flow.AddRange(new Drawable[] { - bank = new OsuSpriteText(), - volume = new OsuSpriteText(), + bank = new LabelledTextBox + { + Label = "Bank Name", + }, + volume = new SettingsSlider + { + Bindable = new SampleControlPoint().SampleVolumeBindable, + LabelText = "Volume", + } }); } @@ -39,8 +48,11 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; + if (point.NewValue != null) + { + bank.Current = point.NewValue.SampleBankBindable; + volume.Bindable = point.NewValue.SampleVolumeBindable; + } }); } } diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 8609da4c4d..9aecbe9160 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -2,23 +2,33 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Graphics.Sprites; +using osu.Game.Beatmaps.Timing; +using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Edit.Timing { internal class TimingSection : Section { - private OsuSpriteText bpm; - private OsuSpriteText timeSignature; + private SettingsSlider bpm; + private SettingsEnumDropdown timeSignature; [BackgroundDependencyLoader] private void load() { - Flow.AddRange(new[] + Flow.AddRange(new Drawable[] { - bpm = new OsuSpriteText(), - timeSignature = new OsuSpriteText(), + bpm = new BPMSlider + { + Bindable = new TimingControlPoint().BeatLengthBindable, + LabelText = "BPM", + }, + timeSignature = new SettingsEnumDropdown + { + LabelText = "Time Signature" + }, }); } @@ -28,8 +38,11 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.BindValueChanged(point => { - bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; - timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; + if (point.NewValue != null) + { + bpm.Bindable = point.NewValue.BeatLengthBindable; + timeSignature.Bindable = point.NewValue.TimeSignatureBindable; + } }); } @@ -43,5 +56,35 @@ namespace osu.Game.Screens.Edit.Timing TimeSignature = reference.TimeSignature }; } + + private class BPMSlider : SettingsSlider + { + private readonly BindableDouble beatLengthBindable = new BindableDouble(); + + private BindableDouble bpmBindable; + + public override Bindable Bindable + { + get => base.Bindable; + set + { + // incoming will be beatlength + + beatLengthBindable.UnbindBindings(); + beatLengthBindable.BindTo(value); + + base.Bindable = bpmBindable = new BindableDouble(beatLengthToBpm(beatLengthBindable.Value)) + { + MinValue = beatLengthToBpm(beatLengthBindable.MaxValue), + MaxValue = beatLengthToBpm(beatLengthBindable.MinValue), + Default = beatLengthToBpm(beatLengthBindable.Default), + }; + + bpmBindable.BindValueChanged(bpm => beatLengthBindable.Value = beatLengthToBpm(bpm.NewValue)); + } + } + + private double beatLengthToBpm(double beatLength) => 60000 / beatLength; + } } } From e287dae64b59aa1cf6f67f2485f7541b98a8cc44 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 29 Oct 2019 21:25:48 +0300 Subject: [PATCH 076/503] Fix VotePill can be activated by the comment sender --- osu.Game/Overlays/Comments/VotePill.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index e8d9013fd9..b2c8c52bf3 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -43,6 +43,7 @@ namespace osu.Game.Overlays.Comments private readonly BindableBool isVoted = new BindableBool(); private readonly BindableInt votesCount = new BindableInt(); + private bool disabled; public VotePill(Comment comment) { @@ -69,6 +70,8 @@ namespace osu.Game.Overlays.Comments votesCount.Value = comment.VotesCount; isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); votesCount.BindValueChanged(count => votesCounter.Text = $"+{count.NewValue}", true); + + api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId ? true : false, true); } private void onAction() @@ -145,16 +148,30 @@ namespace osu.Game.Overlays.Comments protected override bool OnHover(HoverEvent e) { + if (disabled) + return false; + onHoverAction(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { + if (disabled) + return; + updateDisplay(); base.OnHoverLost(e); } + protected override bool OnClick(ClickEvent e) + { + if (disabled) + return false; + + return base.OnClick(e); + } + private void updateDisplay() { if (isVoted.Value) From 30d9b21b86264bbc8cfae70f7ac65ae390ea250e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 29 Oct 2019 21:57:20 +0300 Subject: [PATCH 077/503] Condition simplification --- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index b2c8c52bf3..32fbe55fb5 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -71,7 +71,7 @@ namespace osu.Game.Overlays.Comments isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); votesCount.BindValueChanged(count => votesCounter.Text = $"+{count.NewValue}", true); - api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId ? true : false, true); + api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId, true); } private void onAction() From 092d16bb6465a2555654f991d492098a0355d7c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 29 Oct 2019 23:43:16 +0300 Subject: [PATCH 078/503] Dont use binding to set disabled value --- osu.Game/Overlays/Comments/VotePill.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 32fbe55fb5..a895ad2bcf 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -61,6 +61,8 @@ namespace osu.Game.Overlays.Comments { AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); + + disabled = api.LocalUser.Value.Id == comment.UserId; } protected override void LoadComplete() @@ -70,8 +72,6 @@ namespace osu.Game.Overlays.Comments votesCount.Value = comment.VotesCount; isVoted.BindValueChanged(voted => background.Colour = voted.NewValue ? AccentColour : OsuColour.Gray(0.05f), true); votesCount.BindValueChanged(count => votesCounter.Text = $"+{count.NewValue}", true); - - api.LocalUser.BindValueChanged(user => disabled = user.NewValue?.Id == comment.UserId, true); } private void onAction() From 1502a6c631920debf7bcdbda293326bb9be300e1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 30 Oct 2019 03:09:14 +0300 Subject: [PATCH 079/503] Cleanups --- osu.Game/Overlays/Comments/VotePill.cs | 37 +++++++++----------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index a895ad2bcf..5d0431314b 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -43,14 +43,11 @@ namespace osu.Game.Overlays.Comments private readonly BindableBool isVoted = new BindableBool(); private readonly BindableInt votesCount = new BindableInt(); - private bool disabled; public VotePill(Comment comment) { this.comment = comment; - Action = onAction; - AutoSizeAxes = Axes.X; Height = 20; LoadingAnimationSize = new Vector2(10); @@ -62,7 +59,8 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - disabled = api.LocalUser.Value.Id == comment.UserId; + if (api.LocalUser.Value.Id != comment.UserId) + Action = onAction; } protected override void LoadComplete() @@ -148,41 +146,30 @@ namespace osu.Game.Overlays.Comments protected override bool OnHover(HoverEvent e) { - if (disabled) - return false; - onHoverAction(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - if (disabled) - return; - updateDisplay(); base.OnHoverLost(e); } - protected override bool OnClick(ClickEvent e) - { - if (disabled) - return false; - - return base.OnClick(e); - } - private void updateDisplay() { - if (isVoted.Value) + if (Action != null) { - hoverLayer.FadeTo(IsHovered ? 1 : 0); - sideNumber.Hide(); - } - else - sideNumber.FadeTo(IsHovered ? 1 : 0); + if (isVoted.Value) + { + hoverLayer.FadeTo(IsHovered ? 1 : 0); + sideNumber.Hide(); + } + else + sideNumber.FadeTo(IsHovered ? 1 : 0); - borderContainer.BorderThickness = IsHovered ? 3 : 0; + borderContainer.BorderThickness = IsHovered ? 3 : 0; + } } private void onHoverAction() From 2c31492bbe57f2ae9cca0b77f6a6f7cc0e967971 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 30 Oct 2019 03:27:06 +0300 Subject: [PATCH 080/503] Fix comment can be voted if user is null --- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 5d0431314b..9a10e4a2c1 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if (api.LocalUser.Value.Id != comment.UserId) + if ((api.LocalUser.Value?.Id ?? comment.UserId) != comment.UserId) Action = onAction; } From f1a2643c401b83ee8ec952b76dacf896910990d1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 30 Oct 2019 03:45:05 +0300 Subject: [PATCH 081/503] Add test scene --- .../Visual/Online/TestSceneVotePill.cs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneVotePill.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs new file mode 100644 index 0000000000..8ddb16d8ca --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -0,0 +1,59 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Overlays.Comments; +using osu.Framework.Allocation; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneVotePill : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(VotePill) + }; + + private VotePill votePill; + + [BackgroundDependencyLoader] + private void load() + { + var userComment = new Comment + { + IsVoted = false, + UserId = API.LocalUser.Value?.Id, + VotesCount = 10, + }; + + var randomComment = new Comment + { + IsVoted = false, + UserId = 455454, + VotesCount = 2, + }; + + AddStep("Random comment", () => addVotePill(randomComment)); + AddStep("Click", () => votePill.Click()); + AddAssert("Loading", () => votePill.IsLoading == true); + AddStep("User comment", () => addVotePill(userComment)); + AddStep("Click", () => votePill.Click()); + AddAssert("Not loading", () => votePill.IsLoading == false); + } + + private void addVotePill(Comment comment) + { + Clear(); + Add(votePill = new VotePill(comment) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + } +} From 7f755fe726085b1e42afa8430f9f07429aa02545 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 30 Oct 2019 03:47:17 +0300 Subject: [PATCH 082/503] Add more tests --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 8ddb16d8ca..76bf825541 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -44,6 +44,9 @@ namespace osu.Game.Tests.Visual.Online AddStep("User comment", () => addVotePill(userComment)); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => votePill.IsLoading == false); + AddStep("Log out", API.Logout); + AddStep("Click", () => votePill.Click()); + AddAssert("Not loading", () => votePill.IsLoading == false); } private void addVotePill(Comment comment) From 8ad5ccda68e679acae583b636cd125ac9b74674e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 30 Oct 2019 04:16:14 +0300 Subject: [PATCH 083/503] Test steps rearrangement and condition fix --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 13 ++++++++----- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 76bf825541..47cb806fb8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -27,24 +27,27 @@ namespace osu.Game.Tests.Visual.Online var userComment = new Comment { IsVoted = false, - UserId = API.LocalUser.Value?.Id, + UserId = API.LocalUser.Value.Id, VotesCount = 10, }; var randomComment = new Comment { IsVoted = false, - UserId = 455454, + UserId = 4444, VotesCount = 2, }; + AddStep("User comment", () => addVotePill(userComment)); + AddStep("Click", () => votePill.Click()); + AddAssert("Not loading", () => votePill.IsLoading == false); + AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading == true); - AddStep("User comment", () => addVotePill(userComment)); - AddStep("Click", () => votePill.Click()); - AddAssert("Not loading", () => votePill.IsLoading == false); + AddStep("Log out", API.Logout); + AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => votePill.IsLoading == false); } diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 9a10e4a2c1..54eba63095 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if ((api.LocalUser.Value?.Id ?? comment.UserId) != comment.UserId) + if (api.LocalUser.Value.Id != comment.UserId && api.LocalUser.Value.Id != 1) Action = onAction; } From 759395bcb5802f76dfea0db38be65f27561da27f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 30 Oct 2019 04:31:09 +0300 Subject: [PATCH 084/503] CI fix --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 47cb806fb8..7ccb025b47 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -40,16 +40,16 @@ namespace osu.Game.Tests.Visual.Online AddStep("User comment", () => addVotePill(userComment)); AddStep("Click", () => votePill.Click()); - AddAssert("Not loading", () => votePill.IsLoading == false); + AddAssert("Not loading", () => !votePill.IsLoading); AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); - AddAssert("Loading", () => votePill.IsLoading == true); + AddAssert("Loading", () => votePill.IsLoading); AddStep("Log out", API.Logout); AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); - AddAssert("Not loading", () => votePill.IsLoading == false); + AddAssert("Not loading", () => !votePill.IsLoading); } private void addVotePill(Comment comment) From 5899bbd8a63d8a4035c180f0c507fc7b3676cda3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Oct 2019 18:44:07 +0900 Subject: [PATCH 085/503] Fix merge regressions --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 6 +++--- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index cf084e838e..2ecc516919 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -167,9 +167,9 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - Assert.AreEqual(6, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); Assert.AreEqual(34, controlPoints.SamplePoints.Count); - Assert.AreEqual(9, controlPoints.EffectPoints.Count); + Assert.AreEqual(8, controlPoints.EffectPoints.Count); var timingPoint = controlPoints.TimingPointAt(0); Assert.AreEqual(956, timingPoint.Time); @@ -191,7 +191,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(48428); - Assert.AreEqual(956, difficultyPoint.Time); + Assert.AreEqual(0, difficultyPoint.Time); Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); difficultyPoint = controlPoints.DifficultyPointAt(116999); diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index d9328d1636..51b3377394 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -34,6 +34,7 @@ namespace osu.Game.Beatmaps.ControlPoints MaxValue = 60000 }; + /// /// The beat length at this control point. /// public double BeatLength From 35be8f9dfbab66ba527631ba2b100f1c9c48f35f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 30 Oct 2019 19:33:54 +0900 Subject: [PATCH 086/503] Share framework file-exclusion function --- osu.Game/IO/Archives/ZipArchiveReader.cs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 9033e7529d..35f38ea7e8 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -1,30 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.IO; using System.Linq; +using osu.Framework.IO.Stores; using SharpCompress.Archives.Zip; -using SharpCompress.Common; namespace osu.Game.IO.Archives { public sealed class ZipArchiveReader : ArchiveReader { - /// - /// List of substrings that indicate a file should be ignored during the import process - /// (usually due to representing no useful data and being autogenerated by the OS). - /// - private static readonly string[] filename_ignore_list = - { - // Mac-specific - "__MACOSX", - ".DS_Store", - // Windows-specific - "Thumbs.db" - }; - private readonly Stream archiveStream; private readonly ZipArchive archive; @@ -58,9 +44,7 @@ namespace osu.Game.IO.Archives archiveStream.Dispose(); } - private static bool canBeIgnored(IEntry entry) => filename_ignore_list.Any(ignoredName => entry.Key.IndexOf(ignoredName, StringComparison.OrdinalIgnoreCase) >= 0); - - public override IEnumerable Filenames => archive.Entries.Where(e => !canBeIgnored(e)).Select(e => e.Key).ToArray(); + public override IEnumerable Filenames => archive.Entries.Select(e => e.Key).ExcludeSystemFileNames(); public override Stream GetUnderlyingStream() => archiveStream; } From 8fbe76b574471e3f2decbcf49bde704fd202c5eb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 21:06:55 +0800 Subject: [PATCH 087/503] Use slnf for filtering platform. --- osu.Android.sln | 126 ------ osu.Android.sln.DotSettings | 834 ----------------------------------- osu.Android.slnf | 19 + osu.Desktop.slnf | 20 + osu.iOS.sln | 187 -------- osu.iOS.sln.DotSettings | 836 ------------------------------------ osu.iOS.slnf | 18 + osu.sln | 318 +++++++++++++- 8 files changed, 371 insertions(+), 1987 deletions(-) delete mode 100644 osu.Android.sln delete mode 100644 osu.Android.sln.DotSettings create mode 100644 osu.Android.slnf create mode 100644 osu.Desktop.slnf delete mode 100644 osu.iOS.sln delete mode 100644 osu.iOS.sln.DotSettings create mode 100644 osu.iOS.slnf diff --git a/osu.Android.sln b/osu.Android.sln deleted file mode 100644 index ebf2c55cb4..0000000000 --- a/osu.Android.sln +++ /dev/null @@ -1,126 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28516.95 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Android", "osu.Android\osu.Android.csproj", "{D1D5F9A8-B40B-40E6-B02F-482D03346D3D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.Android", "osu.Game.Rulesets.Catch.Tests.Android\osu.Game.Rulesets.Catch.Tests.Android.csproj", "{C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.Android", "osu.Game.Rulesets.Mania.Tests.Android\osu.Game.Rulesets.Mania.Tests.Android.csproj", "{531F1092-DB27-445D-AA33-2A77C7187C99}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.Android", "osu.Game.Rulesets.Osu.Tests.Android\osu.Game.Rulesets.Osu.Tests.Android.csproj", "{90CAB706-39CB-4B93-9629-3218A6FF8E9B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.Android", "osu.Game.Rulesets.Taiko.Tests.Android\osu.Game.Rulesets.Taiko.Tests.Android.csproj", "{3701A0A1-8476-42C6-B5C4-D24129B4A484}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.Android", "osu.Game.Tests.Android\osu.Game.Tests.Android.csproj", "{5CC222DC-5716-4499-B897-DCBDDA4A5CF9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Build.0 = Release|Any CPU - {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Deploy.0 = Release|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Build.0 = Release|Any CPU - {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Deploy.0 = Release|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Build.0 = Debug|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.ActiveCfg = Release|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Build.0 = Release|Any CPU - {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Deploy.0 = Release|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Build.0 = Release|Any CPU - {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Deploy.0 = Release|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Build.0 = Release|Any CPU - {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Deploy.0 = Release|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Build.0 = Release|Any CPU - {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Deploy.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668} - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - Policies = $0 - $0.TextStylePolicy = $1 - $1.EolMarker = Windows - $1.inheritsSet = VisualStudio - $1.inheritsScope = text/plain - $1.scope = text/x-csharp - $0.CSharpFormattingPolicy = $2 - $2.IndentSwitchSection = True - $2.NewLinesForBracesInProperties = True - $2.NewLinesForBracesInAccessors = True - $2.NewLinesForBracesInAnonymousMethods = True - $2.NewLinesForBracesInControlBlocks = True - $2.NewLinesForBracesInAnonymousTypes = True - $2.NewLinesForBracesInObjectCollectionArrayInitializers = True - $2.NewLinesForBracesInLambdaExpressionBody = True - $2.NewLineForElse = True - $2.NewLineForCatch = True - $2.NewLineForFinally = True - $2.NewLineForMembersInObjectInit = True - $2.NewLineForMembersInAnonymousTypes = True - $2.NewLineForClausesInQuery = True - $2.SpacingAfterMethodDeclarationName = False - $2.SpaceAfterMethodCallName = False - $2.SpaceBeforeOpenSquareBracket = False - $2.inheritsSet = Mono - $2.inheritsScope = text/x-csharp - $2.scope = text/x-csharp - EndGlobalSection -EndGlobal diff --git a/osu.Android.sln.DotSettings b/osu.Android.sln.DotSettings deleted file mode 100644 index 5a97fc7518..0000000000 --- a/osu.Android.sln.DotSettings +++ /dev/null @@ -1,834 +0,0 @@ - - True - True - True - True - ExplicitlyExcluded - ExplicitlyExcluded - SOLUTION - HINT - WARNING - - True - WARNING - WARNING - HINT - HINT - HINT - HINT - WARNING - WARNING - WARNING - HINT - WARNING - HINT - SUGGESTION - HINT - HINT - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - WARNING - WARNING - HINT - WARNING - WARNING - DO_NOT_SHOW - HINT - WARNING - DO_NOT_SHOW - WARNING - HINT - HINT - HINT - ERROR - HINT - HINT - HINT - WARNING - WARNING - HINT - DO_NOT_SHOW - HINT - HINT - HINT - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - HINT - HINT - HINT - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - WARNING - - WARNING - WARNING - WARNING - ERROR - WARNING - WARNING - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - WARNING - WARNING - HINT - WARNING - HINT - HINT - HINT - HINT - HINT - HINT - HINT - - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - WARNING - WARNING - HINT - HINT - WARNING - <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> - Code Cleanup (peppy) - Required - Required - Required - Explicit - ExpressionBody - ExpressionBody - True - NEXT_LINE - True - True - True - True - True - True - True - True - NEXT_LINE - 1 - 1 - NEXT_LINE - MULTILINE - NEXT_LINE - 1 - 1 - True - NEXT_LINE - NEVER - NEVER - True - False - True - NEVER - False - False - True - False - False - True - True - False - False - CHOP_IF_LONG - True - 200 - CHOP_IF_LONG - False - False - AABB - API - BPM - GC - GL - GLSL - HID - HUD - ID - IP - IPC - LTRB - MD5 - NS - OS - RGB - RNG - SHA - SRGB - TK - SS - PP - GMT - QAT - BNG - UI - HINT - <?xml version="1.0" encoding="utf-16"?> -<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> -</Patterns> - Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. -See the LICENCE file in the repository root for full licence text. - - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - True - True - True - True - True - True - True - True - True - True - True - True - o!f – Object Initializer: Anchor&Origin - True - constant("Centre") - 0 - True - True - 2.0 - InCSharpFile - ofao - True - Anchor = Anchor.$anchor$, -Origin = Anchor.$anchor$, - True - True - o!f – InternalChildren = [] - True - True - 2.0 - InCSharpFile - ofic - True - InternalChildren = new Drawable[] -{ - $END$ -}; - True - True - o!f – new GridContainer { .. } - True - True - 2.0 - InCSharpFile - ofgc - True - new GridContainer -{ - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } -}; - True - True - o!f – new FillFlowContainer { .. } - True - True - 2.0 - InCSharpFile - offf - True - new FillFlowContainer -{ - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } -}, - True - True - o!f – new Container { .. } - True - True - 2.0 - InCSharpFile - ofcont - True - new Container -{ - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } -}, - True - True - o!f – BackgroundDependencyLoader load() - True - True - 2.0 - InCSharpFile - ofbdl - True - [BackgroundDependencyLoader] -private void load() -{ - $END$ -} - True - True - o!f – new Box { .. } - True - True - 2.0 - InCSharpFile - ofbox - True - new Box -{ - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, -}, - True - True - o!f – Children = [] - True - True - 2.0 - InCSharpFile - ofc - True - Children = new Drawable[] -{ - $END$ -}; - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True diff --git a/osu.Android.slnf b/osu.Android.slnf new file mode 100644 index 0000000000..7d90f97eb9 --- /dev/null +++ b/osu.Android.slnf @@ -0,0 +1,19 @@ +{ + "solution": { + "path": "osu.sln", + "projects": [ + "osu.Android\\osu.Android.csproj", + "osu.Game.Rulesets.Catch.Tests.Android\\osu.Game.Rulesets.Catch.Tests.Android.csproj", + "osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj", + "osu.Game.Rulesets.Mania.Tests.Android\\osu.Game.Rulesets.Mania.Tests.Android.csproj", + "osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj", + "osu.Game.Rulesets.Osu.Tests.Android\\osu.Game.Rulesets.Osu.Tests.Android.csproj", + "osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj", + "osu.Game.Rulesets.Taiko.Tests.Android\\osu.Game.Rulesets.Taiko.Tests.Android.csproj", + "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", + "osu.Game.Tests.Android\\osu.Game.Tests.Android.csproj", + "osu.Game.Tests\\osu.Game.Tests.csproj", + "osu.Game\\osu.Game.csproj" + ] + } +} \ No newline at end of file diff --git a/osu.Desktop.slnf b/osu.Desktop.slnf new file mode 100644 index 0000000000..e6b6446f72 --- /dev/null +++ b/osu.Desktop.slnf @@ -0,0 +1,20 @@ +{ + "solution": { + "path": "osu.sln", + "projects": [ + "osu.Desktop\\osu.Desktop.csproj", + "osu.Game.Rulesets.Catch.Tests\\osu.Game.Rulesets.Catch.Tests.csproj", + "osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj", + "osu.Game.Rulesets.Mania.Tests\\osu.Game.Rulesets.Mania.Tests.csproj", + "osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj", + "osu.Game.Rulesets.Osu.Tests\\osu.Game.Rulesets.Osu.Tests.csproj", + "osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj", + "osu.Game.Rulesets.Taiko.Tests\\osu.Game.Rulesets.Taiko.Tests.csproj", + "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", + "osu.Game.Tests\\osu.Game.Tests.csproj", + "osu.Game.Tournament.Tests\\osu.Game.Tournament.Tests.csproj", + "osu.Game.Tournament\\osu.Game.Tournament.csproj", + "osu.Game\\osu.Game.csproj" + ] + } +} \ No newline at end of file diff --git a/osu.iOS.sln b/osu.iOS.sln deleted file mode 100644 index 21d02d33ab..0000000000 --- a/osu.iOS.sln +++ /dev/null @@ -1,187 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2006 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.iOS", "osu.iOS\osu.iOS.csproj", "{3F082D0B-A964-43D7-BDF7-C256D76A50D0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.iOS", "osu.Game.Tests.iOS\osu.Game.Tests.iOS.csproj", "{65FF8E19-6934-469B-B690-23C6D6E56A17}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.iOS", "osu.Game.Rulesets.Taiko.Tests.iOS\osu.Game.Rulesets.Taiko.Tests.iOS.csproj", "{7E408809-66AC-49D1-AF4D-98834F9B979A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.iOS", "osu.Game.Rulesets.Osu.Tests.iOS\osu.Game.Rulesets.Osu.Tests.iOS.csproj", "{6653CA6F-DB06-4604-A3FD-762E25C2AF96}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.iOS", "osu.Game.Rulesets.Mania.Tests.iOS\osu.Game.Rulesets.Mania.Tests.iOS.csproj", "{39FD990E-B6CE-4B2A-999F-BC008CF2C64C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.iOS", "osu.Game.Rulesets.Catch.Tests.iOS\osu.Game.Rulesets.Catch.Tests.iOS.csproj", "{4004C7B7-1A62-43F1-9DF2-52450FA67E70}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - Debug|iPhoneSimulator = Debug|iPhoneSimulator - Release|iPhone = Release|iPhone - Release|iPhoneSimulator = Release|iPhoneSimulator - Debug|iPhone = Debug|iPhone - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.Build.0 = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.Build.0 = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.Build.0 = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhone.ActiveCfg = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhone.Build.0 = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhone.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.Build.0 = Debug|Any CPU - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|Any CPU.ActiveCfg = Release|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.ActiveCfg = Release|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.Build.0 = Release|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.ActiveCfg = Debug|iPhone - {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.Build.0 = Debug|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|Any CPU.ActiveCfg = Release|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.ActiveCfg = Release|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.Build.0 = Release|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.ActiveCfg = Debug|iPhone - {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.Build.0 = Debug|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|Any CPU.ActiveCfg = Release|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.ActiveCfg = Release|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.Build.0 = Release|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.ActiveCfg = Debug|iPhone - {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.Build.0 = Debug|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|Any CPU.ActiveCfg = Release|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.ActiveCfg = Release|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.Build.0 = Release|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.ActiveCfg = Debug|iPhone - {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.Build.0 = Debug|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|Any CPU.ActiveCfg = Release|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.ActiveCfg = Release|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.Build.0 = Release|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.ActiveCfg = Debug|iPhone - {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.Build.0 = Debug|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|Any CPU.ActiveCfg = Release|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.ActiveCfg = Release|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.Build.0 = Release|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.ActiveCfg = Debug|iPhone - {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.Build.0 = Debug|iPhone - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668} - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - Policies = $0 - $0.TextStylePolicy = $1 - $1.EolMarker = Windows - $1.scope = text/x-csharp - $1.FileWidth = 80 - $1.TabsToSpaces = True - $0.CSharpFormattingPolicy = $2 - $2.scope = text/x-csharp - EndGlobalSection -EndGlobal diff --git a/osu.iOS.sln.DotSettings b/osu.iOS.sln.DotSettings deleted file mode 100644 index 752b817910..0000000000 --- a/osu.iOS.sln.DotSettings +++ /dev/null @@ -1,836 +0,0 @@ - - True - True - True - True - ExplicitlyExcluded - ExplicitlyExcluded - SOLUTION - HINT - WARNING - - True - WARNING - WARNING - HINT - HINT - HINT - HINT - WARNING - WARNING - WARNING - HINT - WARNING - HINT - SUGGESTION - HINT - HINT - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - WARNING - WARNING - HINT - WARNING - WARNING - DO_NOT_SHOW - HINT - WARNING - DO_NOT_SHOW - WARNING - HINT - HINT - HINT - ERROR - HINT - HINT - HINT - WARNING - WARNING - HINT - DO_NOT_SHOW - HINT - HINT - HINT - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - HINT - HINT - HINT - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - WARNING - - WARNING - WARNING - WARNING - ERROR - WARNING - WARNING - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - WARNING - WARNING - HINT - WARNING - HINT - HINT - HINT - HINT - HINT - HINT - HINT - - HINT - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - HINT - WARNING - WARNING - HINT - HINT - WARNING - WARNING - <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> - Code Cleanup (peppy) - Required - Required - Required - Explicit - ExpressionBody - ExpressionBody - True - NEXT_LINE - True - True - True - True - True - True - True - True - NEXT_LINE - 1 - 1 - NEXT_LINE - MULTILINE - NEXT_LINE - 1 - 1 - True - NEXT_LINE - NEVER - NEVER - True - False - True - NEVER - False - False - True - False - False - True - True - False - False - CHOP_IF_LONG - True - 200 - CHOP_IF_LONG - False - False - AABB - API - BPM - GC - GL - GLSL - HID - HUD - ID - IP - IPC - LTRB - MD5 - NS - OS - RGB - RNG - SHA - SRGB - TK - SS - PP - GMT - QAT - BNG - UI - False - HINT - <?xml version="1.0" encoding="utf-16"?> -<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> -</Patterns> - Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. -See the LICENCE file in the repository root for full licence text. - - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> - <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - True - True - True - True - True - True - True - True - True - True - True - True - o!f – Object Initializer: Anchor&Origin - True - constant("Centre") - 0 - True - True - 2.0 - InCSharpFile - ofao - True - Anchor = Anchor.$anchor$, -Origin = Anchor.$anchor$, - True - True - o!f – InternalChildren = [] - True - True - 2.0 - InCSharpFile - ofic - True - InternalChildren = new Drawable[] -{ - $END$ -}; - True - True - o!f – new GridContainer { .. } - True - True - 2.0 - InCSharpFile - ofgc - True - new GridContainer -{ - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } -}; - True - True - o!f – new FillFlowContainer { .. } - True - True - 2.0 - InCSharpFile - offf - True - new FillFlowContainer -{ - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } -}, - True - True - o!f – new Container { .. } - True - True - 2.0 - InCSharpFile - ofcont - True - new Container -{ - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } -}, - True - True - o!f – BackgroundDependencyLoader load() - True - True - 2.0 - InCSharpFile - ofbdl - True - [BackgroundDependencyLoader] -private void load() -{ - $END$ -} - True - True - o!f – new Box { .. } - True - True - 2.0 - InCSharpFile - ofbox - True - new Box -{ - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, -}, - True - True - o!f – Children = [] - True - True - 2.0 - InCSharpFile - ofc - True - Children = new Drawable[] -{ - $END$ -}; - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True - True diff --git a/osu.iOS.slnf b/osu.iOS.slnf new file mode 100644 index 0000000000..33a1497a54 --- /dev/null +++ b/osu.iOS.slnf @@ -0,0 +1,18 @@ +{ + "solution": { + "path": "osu.sln", + "projects": [ + "osu.Game.Rulesets.Catch.Tests.iOS\\osu.Game.Rulesets.Catch.Tests.iOS.csproj", + "osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj", + "osu.Game.Rulesets.Mania.Tests.iOS\\osu.Game.Rulesets.Mania.Tests.iOS.csproj", + "osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj", + "osu.Game.Rulesets.Osu.Tests.iOS\\osu.Game.Rulesets.Osu.Tests.iOS.csproj", + "osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj", + "osu.Game.Rulesets.Taiko.Tests.iOS\\osu.Game.Rulesets.Taiko.Tests.iOS.csproj", + "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", + "osu.Game.Tests.iOS\\osu.Game.Tests.iOS.csproj", + "osu.Game.Tests\\osu.Game.Tests.csproj", + "osu.Game\\osu.Game.csproj" + ] + } +} \ No newline at end of file diff --git a/osu.sln b/osu.sln index 688339fab5..12ea89aaad 100644 --- a/osu.sln +++ b/osu.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2006 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29424.173 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" EndProject @@ -25,68 +25,378 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko.Tes EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament", "osu.Game.Tournament\osu.Game.Tournament.csproj", "{5672CA4D-1B37-425B-A118-A8DA26E78938}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Tournament", "osu.Game.Tournament\osu.Game.Tournament.csproj", "{5672CA4D-1B37-425B-A118-A8DA26E78938}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Tournament.Tests", "osu.Game.Tournament.Tests\osu.Game.Tournament.Tests.csproj", "{5789E78D-38F9-4072-AB7B-978F34B2C17F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.iOS", "osu.iOS\osu.iOS.csproj", "{3F082D0B-A964-43D7-BDF7-C256D76A50D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.iOS", "osu.Game.Tests.iOS\osu.Game.Tests.iOS.csproj", "{65FF8E19-6934-469B-B690-23C6D6E56A17}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.iOS", "osu.Game.Rulesets.Taiko.Tests.iOS\osu.Game.Rulesets.Taiko.Tests.iOS.csproj", "{7E408809-66AC-49D1-AF4D-98834F9B979A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.iOS", "osu.Game.Rulesets.Osu.Tests.iOS\osu.Game.Rulesets.Osu.Tests.iOS.csproj", "{6653CA6F-DB06-4604-A3FD-762E25C2AF96}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.iOS", "osu.Game.Rulesets.Mania.Tests.iOS\osu.Game.Rulesets.Mania.Tests.iOS.csproj", "{39FD990E-B6CE-4B2A-999F-BC008CF2C64C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.iOS", "osu.Game.Rulesets.Catch.Tests.iOS\osu.Game.Rulesets.Catch.Tests.iOS.csproj", "{4004C7B7-1A62-43F1-9DF2-52450FA67E70}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Android", "osu.Android\osu.Android.csproj", "{D1D5F9A8-B40B-40E6-B02F-482D03346D3D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.Android", "osu.Game.Rulesets.Catch.Tests.Android\osu.Game.Rulesets.Catch.Tests.Android.csproj", "{C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.Android", "osu.Game.Rulesets.Mania.Tests.Android\osu.Game.Rulesets.Mania.Tests.Android.csproj", "{531F1092-DB27-445D-AA33-2A77C7187C99}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.Android", "osu.Game.Rulesets.Osu.Tests.Android\osu.Game.Rulesets.Osu.Tests.Android.csproj", "{90CAB706-39CB-4B93-9629-3218A6FF8E9B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.Android", "osu.Game.Rulesets.Taiko.Tests.Android\osu.Game.Rulesets.Taiko.Tests.Android.csproj", "{3701A0A1-8476-42C6-B5C4-D24129B4A484}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.Android", "osu.Game.Tests.Android\osu.Game.Tests.Android.csproj", "{5CC222DC-5716-4499-B897-DCBDDA4A5CF9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10DF8F12-50FD-45D8-8A38-17BA764BF54D}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + osu.Android.props = osu.Android.props + osu.Game.props = osu.Game.props + osu.iOS.props = osu.iOS.props + osu.sln.DotSettings = osu.sln.DotSettings + osu.TestProject.props = osu.TestProject.props + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|iPhone = Debug|iPhone + Debug|iPhoneSimulator = Debug|iPhoneSimulator Release|Any CPU = Release|Any CPU + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.Build.0 = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhone.Build.0 = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.ActiveCfg = Release|Any CPU {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.Build.0 = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhone.ActiveCfg = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhone.Build.0 = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhone.Build.0 = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.ActiveCfg = Release|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.Build.0 = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhone.ActiveCfg = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhone.Build.0 = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhone.Build.0 = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.Build.0 = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhone.ActiveCfg = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhone.Build.0 = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhone.Build.0 = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.Build.0 = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhone.ActiveCfg = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhone.Build.0 = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhone.Build.0 = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.ActiveCfg = Release|Any CPU {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.Build.0 = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhone.ActiveCfg = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhone.Build.0 = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhone.Build.0 = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.Build.0 = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhone.ActiveCfg = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhone.Build.0 = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhone.Build.0 = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.ActiveCfg = Release|Any CPU {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|Any CPU.Build.0 = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhone.ActiveCfg = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhone.Build.0 = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5672CA4D-1B37-425B-A118-A8DA26E78938}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhone.Build.0 = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.ActiveCfg = Release|Any CPU {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|Any CPU.Build.0 = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhone.ActiveCfg = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhone.Build.0 = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5789E78D-38F9-4072-AB7B-978F34B2C17F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.ActiveCfg = Debug|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.Build.0 = Debug|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|Any CPU.ActiveCfg = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.ActiveCfg = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.Build.0 = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.ActiveCfg = Debug|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.Build.0 = Debug|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|Any CPU.ActiveCfg = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.ActiveCfg = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.Build.0 = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.ActiveCfg = Debug|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.Build.0 = Debug|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|Any CPU.ActiveCfg = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.ActiveCfg = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.Build.0 = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.ActiveCfg = Debug|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.Build.0 = Debug|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|Any CPU.ActiveCfg = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.ActiveCfg = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.Build.0 = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.ActiveCfg = Debug|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.Build.0 = Debug|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|Any CPU.ActiveCfg = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.ActiveCfg = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.Build.0 = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.ActiveCfg = Debug|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.Build.0 = Debug|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|Any CPU.ActiveCfg = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.ActiveCfg = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.Build.0 = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhone.Build.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhone.ActiveCfg = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhone.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhone.Deploy.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {D1D5F9A8-B40B-40E6-B02F-482D03346D3D}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhone.Build.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Build.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhone.ActiveCfg = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhone.Build.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhone.Deploy.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhone.Build.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Build.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|Any CPU.Deploy.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhone.ActiveCfg = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhone.Build.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhone.Deploy.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {531F1092-DB27-445D-AA33-2A77C7187C99}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhone.Build.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Build.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|Any CPU.Deploy.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhone.ActiveCfg = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhone.Build.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhone.Deploy.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {90CAB706-39CB-4B93-9629-3218A6FF8E9B}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhone.Build.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Build.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|Any CPU.Deploy.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhone.ActiveCfg = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhone.Build.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhone.Deploy.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {3701A0A1-8476-42C6-B5C4-D24129B4A484}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhone.Build.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhone.Deploy.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Build.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|Any CPU.Deploy.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhone.ActiveCfg = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhone.Build.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhone.Deploy.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {5CC222DC-5716-4499-B897-DCBDDA4A5CF9}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 93fae7ad4d257e91c53ecbd9d0bb8a106111fcd4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 21:46:30 +0800 Subject: [PATCH 088/503] Remove meanless properties. --- .../osu.Game.Rulesets.Catch.Tests.iOS.csproj | 2 -- .../osu.Game.Rulesets.Mania.Tests.iOS.csproj | 2 -- .../osu.Game.Rulesets.Osu.Tests.iOS.csproj | 2 -- .../osu.Game.Rulesets.Taiko.Tests.iOS.csproj | 2 -- osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj | 2 -- osu.Game/osu.Game.csproj | 3 --- osu.TestProject.props | 3 --- osu.iOS/osu.iOS.csproj | 2 -- 8 files changed, 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj index 7990c35e09..708779986c 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -1,6 +1,5 @@ - Debug iPhoneSimulator @@ -33,5 +32,4 @@ - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj index 58c2e2aa5a..52e558931b 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -1,6 +1,5 @@ - Debug iPhoneSimulator @@ -33,5 +32,4 @@ - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index c7787bd162..cacd035078 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -1,6 +1,5 @@ - Debug iPhoneSimulator @@ -33,5 +32,4 @@ - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj index 3e46bb89af..c20bd4fe02 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -1,6 +1,5 @@ - Debug iPhoneSimulator @@ -33,5 +32,4 @@ - \ No newline at end of file diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj index 5c0713b895..583d188295 100644 --- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -1,6 +1,5 @@ - Debug iPhoneSimulator @@ -48,5 +47,4 @@ - \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0cb09d9b14..53678b96c7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -17,9 +17,6 @@ Copyright (c) 2019 ppy Pty Ltd osu game - - - diff --git a/osu.TestProject.props b/osu.TestProject.props index a5c70f4edc..79f1cf49d1 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -3,9 +3,6 @@ osu.Game.Tests.VisualTestRunner - - - diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 19d1acf014..49d45e9031 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -1,6 +1,5 @@ - Debug iPhoneSimulator @@ -77,5 +76,4 @@ - \ No newline at end of file From 31595159beed1e0476c48ccf5b33ed3e222915ab Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 21:54:14 +0800 Subject: [PATCH 089/503] Normalize .props --- osu.Game.props => Directory.Build.props | 6 +++--- osu.Desktop/osu.Desktop.csproj | 1 - osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 1 - osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 1 - osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 1 - osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 1 - osu.Game.Tournament/osu.Game.Tournament.csproj | 1 - osu.Game/osu.Game.csproj | 1 - osu.TestProject.props | 5 ++--- 9 files changed, 5 insertions(+), 13 deletions(-) rename osu.Game.props => Directory.Build.props (78%) diff --git a/osu.Game.props b/Directory.Build.props similarity index 78% rename from osu.Game.props rename to Directory.Build.props index 1a3c0aec3e..4f7ad880b5 100644 --- a/osu.Game.props +++ b/Directory.Build.props @@ -1,13 +1,13 @@ - 7.2 + 7.3 - ..\app.manifest + $(MSBuildThisFileDirectory)app.manifest - + osu.licenseheader diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 2d1282634f..84881ce1d3 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -1,5 +1,4 @@  - netcoreapp3.0 WinExe diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 883cac67d1..53d8651476 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,5 +1,4 @@  - netstandard2.0 Library diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index a086da0565..061cced227 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,5 +1,4 @@  - netstandard2.0 Library diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index b0ca314551..afd5e1f753 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,5 +1,4 @@  - netstandard2.0 Library diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 656ebcc7c2..482f459564 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,5 +1,4 @@  - netstandard2.0 Library diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index bddaff0a80..7e1f0eb2b3 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,5 +1,4 @@  - netstandard2.0 Library diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 53678b96c7..717e3e7de8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,5 +1,4 @@  - netstandard2.0 Library diff --git a/osu.TestProject.props b/osu.TestProject.props index 79f1cf49d1..7e87bc5414 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -1,13 +1,12 @@ - osu.Game.Tests.VisualTestRunner - + - + VisualTestRunner.cs From 990227827731a203e5091844f7993a077b91bd6e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 22:28:10 +0800 Subject: [PATCH 090/503] Merge props orthogonally. --- osu.Android.props | 27 ++++-------- osu.iOS.props | 105 ++++++++++++++-------------------------------- 2 files changed, 41 insertions(+), 91 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 8b31be3f12..26a80660ca 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,13 +1,10 @@ - - Debug - AnyCPU + bin\$(Configuration) 4 2.0 false false - default Library 512 Off @@ -15,37 +12,31 @@ Xamarin.Android.Net.AndroidClientHandler v9.0 false + true + armeabi-v7a;x86;arm64-v8a + true + cjk,mideast,other,rare,west + SdkOnly + prompt - + True portable False DEBUG;TRACE - prompt false false - SdkOnly true false - cjk,mideast,other,rare,west - true - armeabi-v7a;x86;arm64-v8a - true - + false None True - prompt true false - SdkOnly False true - cjk,mideast,other,rare,west - true - armeabi-v7a;x86;arm64-v8a - true diff --git a/osu.iOS.props b/osu.iOS.props index 719aced705..8079022ca0 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -5,91 +5,50 @@ PackageReference --nolinkaway -lstdc++ -lbz2 -framework AudioToolbox -framework AVFoundation -framework CoreMedia -framework VideoToolbox -framework SystemConfiguration -framework CFNetwork -framework Accelerate + bin\$(Platform)\$(Configuration) + cjk,mideast,other,rare,west + false + $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" + NSUrlSessionHandler + + iPhone Developer + + + true + full + false + DEBUG;ENABLE_TEST_CLOUD; + true + true + + + pdbonly + true + + + x86_64 + None + + + true + SdkOnly + ARM64 + Entitlements.plist - true - full - false - bin\iPhoneSimulator\Debug - DEBUG;ENABLE_TEST_CLOUD; - prompt - 4 - iPhone Developer - true - true true 25823 - None - x86_64 - NSUrlSessionHandler false - - Default - $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" - false - cjk,mideast,other,rare,west - - - pdbonly - true - bin\iPhone\Release - - prompt - 4 - iPhone Distribution - true - true - Entitlements.plist - SdkOnly - ARM64 - NSUrlSessionHandler - - Default - $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" - false - cjk,mideast,other,rare,west - pdbonly - true - bin\iPhoneSimulator\Release - - prompt - 4 - iPhone Developer true - None - x86_64 - NSUrlSessionHandler - - Default - $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" - false - cjk,mideast,other,rare,west - true - full - false - bin\iPhone\Debug - DEBUG;ENABLE_TEST_CLOUD; - prompt - 4 - iPhone Developer true - true - true - true - Entitlements.plist 28126 - SdkOnly - ARM64 - NSUrlSessionHandler - - Default - $(DefaultMtouchExtraArgs) -gcc_flags "$(DefaultMtouchGccFlags)" - false - cjk,mideast,other,rare,west + + + true From 47e3498b7149920e3b32367289cd96424cca2806 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 22:42:25 +0800 Subject: [PATCH 091/503] Use cake as local tool and builds for slnf. --- .config/dotnet-tools.json | 12 ++++++++++++ build.ps1 | 2 +- build.sh | 2 +- build/Desktop.proj | 17 +++++++++++++++++ build/build.cake | 7 ++++--- global.json | 5 +++++ osu.sln | 1 + 7 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 .config/dotnet-tools.json create mode 100644 build/Desktop.proj create mode 100644 global.json diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000000..1b70c949eb --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "cake.tool": { + "version": "0.35.0", + "commands": [ + "dotnet-cake" + ] + } + } +} \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 2dbd10a150..4b3b1f717a 100755 --- a/build.ps1 +++ b/build.ps1 @@ -21,7 +21,7 @@ if ($DryRun) { $cakeArguments += "-dryrun" } if ($Experimental) { $cakeArguments += "-experimental" } $cakeArguments += $ScriptArgs -dotnet tool install Cake.Tool --global --version 0.35.0 +dotnet tool restore dotnet cake ./build/build.cake --bootstrap dotnet cake ./build/build.cake $cakeArguments exit $LASTEXITCODE \ No newline at end of file diff --git a/build.sh b/build.sh index ac6bd877a6..2c22f08574 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,5 @@ echo "Installing Cake.Tool..." -dotnet tool install Cake.Tool --global --version 0.35.0 +dotnet tool restore # Parse arguments. CAKE_ARGUMENTS=() diff --git a/build/Desktop.proj b/build/Desktop.proj new file mode 100644 index 0000000000..b1c6b065e8 --- /dev/null +++ b/build/Desktop.proj @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/build.cake b/build/build.cake index cfdfebee61..389ff4829d 100644 --- a/build/build.cake +++ b/build/build.cake @@ -11,7 +11,8 @@ var target = Argument("target", "Build"); var configuration = Argument("configuration", "Release"); var rootDirectory = new DirectoryPath(".."); -var solution = rootDirectory.CombineWithFilePath("osu.sln"); +var desktopBuilds = rootDirectory.CombineWithFilePath("build/Desktop.proj"); +var desktopSlnf = rootDirectory.CombineWithFilePath("osu.Desktop.slnf"); /////////////////////////////////////////////////////////////////////////////// // TASKS @@ -19,7 +20,7 @@ var solution = rootDirectory.CombineWithFilePath("osu.sln"); Task("Compile") .Does(() => { - DotNetCoreBuild(solution.FullPath, new DotNetCoreBuildSettings { + DotNetCoreBuild(desktopBuilds.FullPath, new DotNetCoreBuildSettings { Configuration = configuration, }); }); @@ -41,7 +42,7 @@ Task("InspectCode") .WithCriteria(IsRunningOnWindows()) .IsDependentOn("Compile") .Does(() => { - InspectCode(solution, new InspectCodeSettings { + InspectCode(desktopSlnf, new InspectCodeSettings { CachesHome = "inspectcode", OutputFile = "inspectcodereport.xml", }); diff --git a/global.json b/global.json new file mode 100644 index 0000000000..d8b8d14c36 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "Microsoft.Build.Traversal": "2.0.19" + } +} \ No newline at end of file diff --git a/osu.sln b/osu.sln index 12ea89aaad..1baf62da15 100644 --- a/osu.sln +++ b/osu.sln @@ -56,6 +56,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10DF8F12-50FD-45D8-8A38-17BA764BF54D}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + global.json = global.json osu.Android.props = osu.Android.props osu.Game.props = osu.Game.props osu.iOS.props = osu.iOS.props From bcf8e3a9d473856d20d7c25141da7c4754d18a1d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 22:56:33 +0800 Subject: [PATCH 092/503] Remove redundant properties from desktop projects. While OutputType=Library maybe doubtful, PlatformTarget=AnyCPU should be clearly the default. --- Directory.Build.props | 12 ++++++++++-- osu.Desktop/osu.Desktop.csproj | 3 +-- .../osu.Game.Rulesets.Catch.csproj | 1 - .../osu.Game.Rulesets.Mania.csproj | 1 - osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 1 - .../osu.Game.Rulesets.Taiko.csproj | 1 - osu.Game.Tournament/osu.Game.Tournament.csproj | 1 - osu.Game/osu.Game.csproj | 8 -------- osu.sln | 2 +- 9 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 4f7ad880b5..76f1ccc0ca 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -15,10 +15,18 @@ - ppy Pty Ltd - Copyright (c) 2019 ppy Pty Ltd NU1701 + + ppy Pty Ltd + https://github.com/ppy/osu/blob/master/LICENCE.md + https://github.com/ppy/osu + https://github.com/ppy/osu + Automated release. + ppy Pty Ltd + Copyright (c) 2019 ppy Pty Ltd + osu game + \ No newline at end of file diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 84881ce1d3..453cf6f94d 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -2,7 +2,6 @@ netcoreapp3.0 WinExe - AnyCPU true click the circles. to the beat. osu! @@ -22,13 +21,13 @@ - + diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 53d8651476..f24cf1def9 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -2,7 +2,6 @@ netstandard2.0 Library - AnyCPU true catch the fruit. to the beat. diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 061cced227..0af200d19b 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -2,7 +2,6 @@ netstandard2.0 Library - AnyCPU true smash the keys. to the beat. diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index afd5e1f753..fb3fe8808d 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -2,7 +2,6 @@ netstandard2.0 Library - AnyCPU true click the circles. to the beat. diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 482f459564..0a2b189c3a 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -2,7 +2,6 @@ netstandard2.0 Library - AnyCPU true bash the drum. to the beat. diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 7e1f0eb2b3..f5306facaf 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -2,7 +2,6 @@ netstandard2.0 Library - AnyCPU true tools for tournaments. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 717e3e7de8..fce50c43d2 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -2,19 +2,11 @@ netstandard2.0 Library - AnyCPU true osu! ppy.osu.Game - ppy Pty Ltd - https://github.com/ppy/osu/blob/master/LICENCE.md - https://github.com/ppy/osu - https://github.com/ppy/osu - Automated release. - Copyright (c) 2019 ppy Pty Ltd - osu game diff --git a/osu.sln b/osu.sln index 1baf62da15..1f4faae6b9 100644 --- a/osu.sln +++ b/osu.sln @@ -56,9 +56,9 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10DF8F12-50FD-45D8-8A38-17BA764BF54D}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + Directory.Build.props = Directory.Build.props global.json = global.json osu.Android.props = osu.Android.props - osu.Game.props = osu.Game.props osu.iOS.props = osu.iOS.props osu.sln.DotSettings = osu.sln.DotSettings osu.TestProject.props = osu.TestProject.props From 847cf8639fa87e505f47154134c0f8f7b1751cfa Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 22:58:23 +0800 Subject: [PATCH 093/503] Move to VS2019 stable for CI. --- appveyor.yml | 2 +- appveyor_deploy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f59c0b162d..f911d67c6e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{branch}-{build}' -image: Visual Studio 2019 Preview +image: Visual Studio 2019 test: off build_script: - cmd: PowerShell -Version 2.0 .\build.ps1 diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index 13635b943c..fb7825b31d 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: '{build}' -image: Visual Studio 2019 Preview +image: Visual Studio 2019 test: off skip_non_tags: true build_script: From c95052b10fc6f4707bebf3587e23ee938d10fb60 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:03:02 +0800 Subject: [PATCH 094/503] Resolve package downgrade and VS claims for iOS. --- osu.iOS.props | 12 +------ osu.iOS/osu.iOS.csproj | 80 +++++++++++++++++++++++++++++++----------- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/osu.iOS.props b/osu.iOS.props index 8079022ca0..55f1317a58 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -12,6 +12,7 @@ NSUrlSessionHandler iPhone Developer + true true @@ -68,21 +69,10 @@ - - - - - - - - - - - diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 49d45e9031..378ac231c2 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -54,26 +54,66 @@ - - - - - - - - - - - - - - - - - - - - + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + + + false + \ No newline at end of file From e57e9a3817094fb8788f1f5a29af0fb6b483e8d3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:07:22 +0800 Subject: [PATCH 095/503] Update VSCode restore instructions. Use slnf when dotnet.exe knows it. --- .vscode/tasks.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 70e620bca2..04ff7c1bea 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -100,7 +100,7 @@ "command": "dotnet", "args": [ "restore", - "osu.sln" + "build/Desktop.proj" ], "problemMatcher": [] } From 3ad0369d7b77b6890ecfc69e32aef219aff8d138 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:09:08 +0800 Subject: [PATCH 096/503] Resolve new diagnostics in C# 7.3 --- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 2 +- osu.Game/Updater/SimpleUpdateManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 3a14b6d9c2..fbf0435953 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -195,7 +195,7 @@ namespace osu.Game.Tournament.Screens.Drawings } } - writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run((Action)writeAction); + writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run(writeAction); } private void reloadTeams() diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index 4789ac94d2..f76cba7f41 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -29,7 +29,7 @@ namespace osu.Game.Updater version = game.Version; if (game.IsDeployedBuild) - Schedule(() => Task.Run(() => checkForUpdateAsync())); + Schedule(() => Task.Run(checkForUpdateAsync)); } private async void checkForUpdateAsync() From b0414c105f966f255fe25d4cbd18116b050b1ef6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:16:57 +0800 Subject: [PATCH 097/503] Copy parts of DotSettings from framework. --- osu.sln.DotSettings | 830 ++++++++++++++++++++++---------------------- 1 file changed, 421 insertions(+), 409 deletions(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index ed162eed6e..0a65fad9df 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -125,6 +125,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING ERROR @@ -201,6 +202,7 @@ HINT HINT + HINT WARNING WARNING WARNING @@ -271,10 +273,13 @@ GC GL GLSL + 2D + 3D HID HUD ID IL + IOS IP IPC JIT @@ -286,399 +291,400 @@ RGB RNG SHA + RGB SRGB TK - SS - PP - GMT - QAT - BNG + SS + PP + GMT + QAT + BNG UI False HINT <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> </Patterns> Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. See the LICENCE file in the repository root for full licence text. @@ -738,6 +744,7 @@ See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True True True @@ -773,7 +780,7 @@ Origin = Anchor.$anchor$, True InternalChildren = new Drawable[] { - $END$ + $END$ }; True True @@ -786,12 +793,12 @@ Origin = Anchor.$anchor$, True new GridContainer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } }; True True @@ -804,12 +811,12 @@ Origin = Anchor.$anchor$, True new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } }, True True @@ -822,11 +829,11 @@ Origin = Anchor.$anchor$, True new Container { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } }, True True @@ -840,7 +847,7 @@ Origin = Anchor.$anchor$, [BackgroundDependencyLoader] private void load() { - $END$ + $END$ } True True @@ -853,8 +860,8 @@ private void load() True new Box { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, }, True True @@ -867,8 +874,9 @@ private void load() True Children = new Drawable[] { - $END$ + $END$ }; + True True True True @@ -886,4 +894,8 @@ private void load() True True True - True + True + True + True + True + True From 9d4f80c2a236ecb35f1b0e02fed21494bddddb0a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:37:58 +0800 Subject: [PATCH 098/503] Add icon and use licence expression for NuGet. Unlike framework, if other components are packed, they are likely to use different icons. --- Directory.Build.props | 2 +- assets/lazer-nuget.png | Bin 0 -> 12471 bytes osu.Game/osu.Game.csproj | 7 +++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 assets/lazer-nuget.png diff --git a/Directory.Build.props b/Directory.Build.props index 76f1ccc0ca..b4baa2833e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -21,7 +21,7 @@ ppy Pty Ltd - https://github.com/ppy/osu/blob/master/LICENCE.md + MIT https://github.com/ppy/osu https://github.com/ppy/osu Automated release. diff --git a/assets/lazer-nuget.png b/assets/lazer-nuget.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a587fdc26734c1f263023d7eefa8fd644e978b GIT binary patch literal 12471 zcmV;oFi6jdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>DFic5AK~#8N?R^P! z9MzfbU%jdq?UF59-Yp#4csI83g0TS;2ulJ9i-8c52?L73WuK|*|u4&VzdG7zO`$yGORZk5DgJb+YUxU}{9jj?tE$^>zdpyB(I_=kW-NSt4 zbF`Gp<%*|LsV?4V=ih_8za^fCH%Fq;EjxB>-*nFM^FB{e3PO^nX6;X+yc+zX>-OrL&HO-;>LJs!_|W_r2Ut1}-2 zJMe4#-CwwvOb`lC3xA6?^>i!}d-cfCqi?phwLUO&_N*qZOksynz7Y7L2!J5{`|rPB zIdROm3o0rrzsn|j0h{s?u{X{1PO~DONV20XI9Wh{+*{UfoKZh=c#@k0RFyL+`;6emK7;~`*tY)^OhAD({ZnSWY&{k4a94?5tWfx!j$?xaJjuBh<7 z|IYiDOl)YlgBf2dGz~sJ7leix-H&mG{&_nkx3y4e+d)b(^CE#M>Hq6y?ZdlG3C$V|DzxdZ{i z=HZgo(`~JXzEeAD#DiRWQi4Q~_C!Pb(_QyetXz5ZFFCFIzUFfIa%#PyG1S&g`n$VH zU$>u4eqScW<8ex*@+%RTuWG*pVgZgljIHBPkGDFe7aSLO7f&Sbau$TzFjwRe1l${+ z)78;=U-_`=@AI`zxJx+E0^nNx)N?gU&pPYQKsb1rsIl{%@UPGm1a7Z4S~4C;Gl66A zn6YIKFw#o<&0v8v{>ngS=Af7XYmwJo@G0JfY!OyW<^U&@sk0MuBbG@;6CXaa`h{;? z_KnM$x%Py)gcB(M?zdllee#)$7C!0mdmC&`zCjQ~^7Pg&(${=W6t!nuEEcoXYBLgv zL>4nuzzvvPfnB>ft$-P@2|5!Z3+Rj^rb&J|=g2gi1;>qrFyuMuV~W;6(c+yk4)+a4YSX zaAXBcaIrh^Up|{$lZR)RZD$RPL=P z#mq0KgvHIH7aZh4>!Z)Cr}!Gye9qT_a5!wKabOO#Kc7|uh!LzH8Epoxg?J#JRZ)ci z?Z`T{P1O1QesY~Tj6lQoN5;1Br=rcH! z15z--a9jh{BM=CP_RKobW)Rb+k!l>8J1xRvXxTg4liX0dW0dPI` zz{9n3=gxUr^SLW+na^4ieezR^JjsMm(mP392@qKZd$~-y892wzj|*n`k83GRHwpm8 z<2+nLWw=$5*TC_eot@Ox)kQr$J#5)CLSYrZNa!zbBmL3O1TA{UJIshMT{DuyPRfL4G3R=<)ec~S z^v^0_raj(l#z0ej92A-XM%uL_8Eyr{1j6(?5L7_lafs4V2n+=g%sTYL9=Z@oK( zYX*dO1JQ^U4hDUfeeJS;*LUPq%wh~Pl&cTY}>b4&u>WX{jOqu=%-Wm{B zFc1RZ-o3f;`an2%x#ge+M)(eOQexF7+vY%1x~ORU(}+1Af0NPO11TE7?{&U39Dgf zFyCyY`UQ3YuA7z!vrjuSwClyh8cNrd#@BqZcFN-OmVVAPg%i|3e=UIL!t*cqv3S6v zGM}{pu|V?e#$M(FcD_3wpj~D_+szEfrTzT@u4~n2wQiuazZVQ8SV8c{}6sl)@j z+Q=18`DRa_aSLzdPKolMKLX%-^{MA4hs(n^TiOxU{`9tklz1yU;_r`-G(%bvRTu^m z(0o<+0M!B&8~Ejd2nv~obXtv3V*t0hyPX0)-#6C1{lQY+Dw?3h3IOiZGjHy^|Ksxe zO0%MVn0`#%LeLk_)=Utu7-FgCKmbq%OZ(B!Toz02!*QyM7%1q^ZRQIwo5ofeH3r(c ziH=5Ta>Jy5;4NIdDCsL!09@}qL#_gB#R#ChxRscMwO=$Q#m*4BN8t}m! z{N!ufj0$UjcxDso6si^AxZU_`U;*uR(m(ipxF7k{GGBqUa#~>B#QlD_m*_}@tw5D= zRRhPOB37s>ulxaT6=emA5dhb!`yOm4DGgqnrTw@(0>3vom$jI`r=nOZU={-WjRJ-Z zWN~WJ!F)WZ!W;l61=#~8s5mKo@FrV%XFY~UR87|iTwk}G3w8yB(4KS`4D_{jMLRyvn76^b@$nv3(<7MEQ4_WaC28RxI z5!Gkjg6{=eTk4L}8MEhnhqvql78?{weeJ19Do0P-6B#2&_zKPcxm_?nx$iI~H#Sjn{r*hZ+$?5A zd%`8T1^6?pM8ka(ZyuR&sEa%<*O=9-o;jVj9P_mh0dQToe8t7?5?@JH@W&laZD|qd zU$FpTotn^G0OR`W3UZyF<(v853mO83U@`qL2Qu9qBR!hPl&+YFp)_?+O$DB|ZemxU z3P2~HA5YQr$x|-ptw9k0&xnyDzbZzhRIocpZ|5krpO)8YAO#Ikiy8f~0=bwEzij23 z(Ql`H7s`XeeTK01u{5|3rlqX6E8^i0T!?uw3m`Kl@OAzRI~;MtsQ|eC@c;g!tRxhi z$2~Br48Z*NBq+7{fKgFAz{p|(LMs#_1R!oM0YICWmZlcu_pn}$`VJzIz~?I&01YH)2r?{O?Z$xY2f<;uJTj23d+ z7oNKU?-DrTty2MT*VNR^5wA3@2DzrR~WBV_XC2d+-Db?O0?@5SwSwmu5BS;mck+#lS436 zhP(J4T^f_s_8g``lJ_aJ5JG^u96_L@AxdgH2Z8{Ezzhxsy)O5;{1-ZwgWwtDJ%FK& z8ac9b*ZOTcyrqF*eKG(H{j%AK-tr>p#+p3n9HL_U$_F6$TWX1!&{~O?JTvOaJ!2Fz zr#$nti;oomLD~`|4-jFc zF-(Jl3u0}=dPO~td?b#SDE-O#lYFu&60dF*tDocr-$(Gr=aR;LpPD<2 zN(M#>8){QCmMy5=uw@f2kkh0%vH-XK-+vk9^?8S7nSUl~dhcP1bw_$1U_g?=Z~*=s z0$?_A5C9yP9$P{FzgtG$Z_Fmw)ZwI;`$=a)>RuKq6#UJRuJ_FG6ufo;l`+vgE9-Gl~3H&!zA$zLF6T1D-K#fiNF$ zcq#i?f2NEmBhSqG43iB=?bq0%xW-j;V3wjZGc~pUNbjR?&!piQp)rjLKOZ7TEs-v`E*x9EroAhM!uP&MLSmTGOR$L+U0^eHnoVPAr$E@)*`cI1B~m7dT~7eE!$yar+wTWrg61*^Dh_vO&`VFe&Yla za8FsR;lo6g)vRh8qz`pw(m^vY0f+k=4wPU-FfV@{S%84QWRzY0FP3C8kZW3$@W))- zvqw|OMblXey*VS^J^Rk)|Z4v3+30G-zf|LY(4ptJ-e|9Bl#IhZQ{; z5MHP0sNQP$es!i$EJ-Ck-+2BjFMpi~0J}K%$m|S&x7pOB@x}@xm-a(jARHx2SdKVI z$6b99LCWX~4XB z9Gs;@p8S-euWY8+hr1}bW;dl@LLtryt8< ze!HS`+La}#3>bvu_SS4IWI(!88=ILnDzzBw_uRGICIi7Gm}GGjNBJ7Lmo-r6n`ctR zkItt6XCV6cY9TT0IP=sSC>;mjx)0>1>>fazAjd=Lz&WEmb`NxsWxQefpgD*NFIDmjzm2rGXMf!cm3 zi}@fWn5hZ?3ij!G#(&F#ZDcRlF9bpYf?=3?3Bi9#71q8%{d{-4FZkq+p zU0YS1SArY~0C(O(b-9?NH6L7MmPSO}a2lgoHb`TBq1DoI%s5wRNoK^2i5p$Nm-J@# z(Yeef1c8Yo2Awbvb=gb`U$sE2_1g#NCK+a^CWV***I^|D zh`Yo@6hWK5=Lm2;2ZFhJEa1oja5LGX6S$^Tu5N=q0iGG$IP!8^SPgU-PzOzt%}40y zJ#SL{*^Q*NbdeTGW>U5sbkJEaJu^pgIF$Vl2fG%M(HG7HK-VptE7!9IIfdTd zBT}L)csZ|@4_qwZ!ceDGz{Z+_Prs;09qpmcmp4$yZ(kO9fAW>>q#=Flj9KUJ=o7~$ zo;uS^TVX0cfq-dv9ad0{Cm?ie8Iv7dUD?v4z>xr?l4;9@`GxNkH=7@+gPbO*11tdFfV(CW z&1Zp|c8{pAb{`xYB-=ZU4F%k%6sJeA_4}ynsZZ$GuU??YUp}HVR@_p<367ZceMiYv zaeQ`7no~-vSOOLYu}l`wJ(Gqa_{)InEG$5}GfMGo2PpRG9*TajQ;biIY`4&6YijhQ8K^}c}kc-aIC zNmc-+;Cnq;GKRij7P9Fc4qR(|zD3UX@auFOQo5CTaoF-M?b*zt*!raT|aPe+dn zXPSi-b!MRek{v84e17O_bI4uI{etkLVA(mo4tm)q-2=E@q=^!|?VVI7zEGA*B!s0( zbw|Zmf~UT+uPag@hSSZ<*I-RyxM9_@;(k&oeoD(YW`l1}gu-c@#W<8ig*N#hS64yl0;#9@nbSx|8fbclR-U{>dZBbH*47 zTzLjn{Nw_v`q@QP#wi|{6~1}_mEL>~`BqHH%mpwrA7+(>N4O{h2~7B4;c*3(;Saut zMC&nf4=)$#WBEuPsq~sN#qK`ZZ-Pu!0SFL;6--ZIQb-s7LI_y6(#%LLWIw8! zHR6i5i6G$W8VoEL$y5qMoYoyOA)f#M=~yD!l4WK9W{wNm<`9v0w{x!Eksb9jar6?d zn^H@@OQw_e{3)b;sa6PvDtH(b)SHe{WbH1aCIjE;^+Z9hI7hE$KRuy}JWCtIq!0I^ z@kHY*`5GB*F^}-UT41myvBNYZ%nXZfYatKf0>gqxFfl0J)K2l1Ba~?CphPoNAoT8YzB-+eDkHLIGT77i2>F)j=Vxlm!4|3aSO*He&HOo^XL_78g1WM*?v8 z$l*pYk4*(jnp>TkoC~oO^*pv#43B0-&D-UqoH5?crU9=&tfQk7ozn8qj z%E`kKee}H@l-Qd6P6L?V^W0~guY1WivNC6?n&tNyxHp%G4U7r~tbj;eA^eI029bZA*!dX*u^M0(*k&7Y%jx4|}xBt318Ba#Rh(6%vp?OY#8$c8b zGln_sUH80A>GjQ|btN(>7YKs(&4ue>^0kf_CEndd9e2Maa^@@`59X{u!-NgdmeL;Y zPVZ{xo7KoyUqxOnc+k|ddIQBiv45X2*?g3`9{NBGRr^L(k#AHrd061xta+|b2@8kM zC~Tg?0d^T7@(r&f|L9sO8CNH^lgctVDU5uwC2*IA$WvWPp2{$J@O4sdS7X6cGbPZ? z?$tB#Wir(@v!Lo}J^9KS_P2bcOr<@TI(dO(LOt7Co(qhtS=wi)5_^tDsq^=*a}Z^p zk^#60>BC?O@jM%h@lC5I&)8~_UTGEVyTLF3CiX}VCHJtujaj;Q1ibwqCHAys6E6qQM^V@sU~0Jr?UtI4KC|YgS-X)^ zCJ%93!2QO^B(AAaIkfOJ@{F#^e5;sgB4m_JIc5VN)4-Xf4Ioa#U^u z3}C1}3^RlKq(=aoO%WwCMG$O>hd_KeCtnB20-pyaiJ%Jc0NUfr4aiF;U_9Dk0ZU_e zlbNq`B(5j8pHhHx09HyW1Af)u4gh_?c)P`|wFxz(E#ov98H?F%)K^f%Lr({1)L+9} z*0WMgaN+{cK&qv+7bnaIZz6#%Y## z3zypy!KH=2E*OT!i~PNl3->uQ(>Fi!0TGyTKOpE<%m+}P^R4629GnWFHqi%ekJH>e z&HLWrEifzZ%{mbPApM)WZhwWMe3MG>0(hp3u$^Fm36xedTVza-4}C`T1^_Z0a{@5Q zuApD|Ef(m99rFR~v!a^-(^?x{nf(+ML-TBzKHI(-pPX|TjrFTQzhH{300ucFo)s`n%rdnz z0sXYHl-d~1N-mhf=KpXe4U`yGN|AuJyJo?pIX#gGMz-=2FFzGB0EdzXTMxcr=>|9; z!Alt`JRnjYvuNoG7(&wqf%$+_t72!O@j#|O%tyOURu(}&E&Gb~0%L5+%*;oJO8wM+ z^vFxhd`PV$^Hh)k+`H<*{}g6NWh(FW&KylH(?Umrcn(awov9lv=1Vvg0=Owvh;2=? zLx3($ED(^j5~`1ts-cDmZ!?(z^UneA?xwxZ@RlS04-_KE=yAAfbJJU)hT$`_+yDn7 z(N&*N^u0#03C(s&DAm+r+EzNpM;Rn=UOo$x3oZv13P84kiLC(c2^L@=kz!$#Zm_(( zJZJEyO|2ts$wVT2VAGt&4lku>*wZ{^#e!L%H|=BJ;OyJOg@`hGm}qTld&qJM7fYsi zS;LSEOubg;vD+2Z&pKf~fKRhI)nqF;wKBrrGt*H9n)!fi6EQ)~$e#mnZQ2OV?u{%- z0)cr&fR6QaKg`U}oBNwlumJq#-rqmK*#O==$ka-(MbL(Y$u|Qpq!bUQ3>7f~1OUHA zU7?U|I00P2U@#w$!UX}qn1@}_IryWRaNiF~0i`9B(kTA?YcJlI7n{wedHIC%@ELFmSF#pr-=XqCeKg36i-| zRPJZxx0jNyiUk1CzZny%smG(g5c<*xd{GRuw+6)m0BAV==(A7UE~YiBR)BrCHli%& zE8Mx@G)Gspz7S2$0?u{7Sf|W)68PF7mxb|98A-me9Q@%s0cIfZ4*6+g`Hn;6>c_GVw;L-sv1umGL*)9NuFwu$`{n5^R=Q?d0ZUSb!*et>BJUr(J zEuBo%$&tT#N*hoUqOR`lPrmxCE8gTS1ZRUT0H8+fP(D3TJQ{ zkl8TC-Lkj^nglhouw-{InLCNf~|66u# zzoVtCwV>cnq8I@Hl@k|Sclqmwn-0Ec8AWhLP;%ik$Fqe%U?u&z}PoCwi zg0&wgMgRa%CAQ|{k8Tx9lv-E;%(V|*Jj1BS4W~rT#e4~?wxE$9s1yVN5ZY7#Rnwii zCBZCZWG`nrmj`&A9IgaU0?RI$otZIx;P{+H0X#Y{E1~r}w*A}38$ZRfcxM5W0xSJ> z3fR-ovF!)$E*n#O1yd?hD*>WnR?YouDE{eQqcR&{m=hBVMqt3i36K#;rmAD^XeZLs zlhJE6SEgm6eq$jH z0nDVDG>ke^(dVmAA9r0MnZOGY&eA6Z#aaLW6pQ}z?|<`iy)&8+oiYQ2^Lr?G#Tn#= z|FVG4Fomghfe;7|^XR1Xg8x>ZHGt{TBA6k!%@zc8(oLvE3JT&1E9L_bJoFoutB@l4 z$I-oa1qXiZ?Ap!D2RQIc`CVNvz46*D%zV5`RFw7u`4iyW(BJ#uz4%p^e!Z)9SnYY1 zLcm#px2}R>A7)P&vC{l-nDbnQI$1<8qksZ{F})_=0EA8s>zaXcgvJ|?ZR7%k0H)qf zXaVfAx}F^%uq9<7@_lVqW}U)a?HM{sU~c00Dr)aIcJI6k&&I$H(gJ6u(E|Ok001r= zoqE>XyN(?=^p0g~%w*TZ8VX;((5T2jXutW!7$7E?2J_cnfPq#|8pQyTa$N~%G~mP~ z0V3Grk_+gAlYu4)SRmI~6Ul|={kz%ps}nxPR#GID+;-bNcm9fN@Ib) z9prTd_*V*q9l%_ilMm=euIri+SkyqlbEXjOJ(Bq#lo?FJR8>jWx-FY-{?-rvWx{JkROjXI)Jz%nCy0w#%2aaZGAp$9L=VnD;m<-oD*c-!Gf20<$ThxKm=ATMIR(Y%2&&g zUTV*+zrXFrYd-#n4=66>v%)~R012#0kxryjZ!BA|W&jsxR+K zW{sips}_(8%tyX&o@j%hk2ODC8R+=SqYq#G(|`H}-u3}8Ob7K3*_7%(K&`+lPp@8f z?%B(pq7d6Jt3{q5*|8+0UfxRDd%2fK@9yq)Bm{^XiXDfKMk0bqR*-qW6JYSiDMHJq zQ0U9kNyGE~Jqq(7#GLM>YeSuz8h8A7#-ce7bM1hceu=>l005RH_~GmCoHuXo8IOxE zU8-;4V0-^j@&3QQvyJpeJ~eh^1KM@;2rQpHpqYpxthC<=5Fg|UI*XY;W(SRP`S67^ zD0tQ+j`o=bP3-ge9{XS%Grukz-MRPkpHG@Q{a&uYXwZO}eu=>n0053M`0nc0zr1Mi zqDRDn#!?9IyS_OyvjwY%o<3YW=@RSss!zNOM5CDxFWaG*ctHi)w@W>R>1QEu0!(p( z&|1M=5u~zf7m<%MBHF`3jaR$O07nG#%i_ED?)k@tIaBZC8a(M6aOMMpDFA>Ff_GNG zcERGsiys!Ngh%*3B=aTk(E|>2Fs-?J)!N>PrA`4q4&UEjfN6M6U35b=VEzQs+L@P|TEvGPvw-LNGwV6LPwsy3(MPVj@Un~XULTl`4h$;uffHo` zBp`5pCSa&#=ia+(t7|S5%x=s)AIJh?1NMnn2?GKUd3~!`Q%_oi{-k~RP*hsTdAnzP zEd?%`E|#|wWBHBkl;!IIq`~7Vh0E(n#NYbGKmPCU{`QXBIXLS71D--~q6Gi|<-oPj z#t+xsc>2_-|3aNHjkd8%!0aL`U@;^JLNyCQdpE`2Z=~2;+sW^C_AsUxV1fuHCp?{Bdi^0hd z007q&!Qs>6C1?LS6bQ@`Pr!C&zR70^5U##VXbq71Xpi`8ZEE8I*k(~Tkig)R zT~3e1CwvXV#J35()9Xp|d71Ida6H1b6J!K>V>4Rc8R^;Z*8A`NuZu6g^gZ4KNr5jM zbd#^*WC;L(Yr`5Kf(tcn+V-P~Z-4j4 zJMO#fx3_U%&};HfIP-y%DF6}>0+A*B?$+BTU$b)MFRCglFBJh3VgvP=xC#s~VX-8< zGF8b$<~tIrjNpUT_*%z-W2CorQ5xx&!zEl0mE-d^E^aej$tfoLbFAXoyC^35hQJPO zTKRV~z<6kVO^9VX{@zQgU;6o1uey8#?~z)6LQTGkQ$YX#^g~*Mz~hgsTC!rFp@Mq=;}a>;nR#NVHe?%eECLqA$4o~$#^-7{ z2X#0P$AQVnSkMRjt**>z1u!1VxUg_`M|wV9yY}NdS6p(zQ;9?ZxjpjVlcx1%fMll< z&>vU>1c|{{o_+DcdGpTrQCV5pY(aQDJ80rOx)6U4#^VKwATt#UM!^qbja@|H*oP~k zIXtSy;0&0H?-zmbSPX-O#xc+)zTG>X1J?2q>gkDmytA?K&nvILZq=r(n~}%DTyUc& zpYal>ngB?^8i-a1g_6`TCApl01iGK{v19YzX$-$K_Ch=8w)@pv%nk% z`Rf(a#**<^tSJ(UeYSt!zIQmNd;jMD@wYpou_zc0NkfrLKV^J;K77#xzzp;qMGAu~ z-qE8*`|rE^o`oYu)lUcoL-nQM@C2XFSLb%Shw&MeCH@j0|KeDA|7ks~Ct~qfT+_6p z$wcx9|J@vqCt6xtTeq|wI<(`7XP#=j{r20Dw}Z)Gw$$=39MjGCA`5^S@;+c4q=k^b z@^4wFG!%AMRaSZ#E@rrvN~Ls;*psbot?~5n$AFTt=3g_jW%)wmuSEc?Any&oR>cY` zW5I0TuY%b_7{U;SFoYotVF*JQ!Vrcqg#YFs`v3fwc4`p|61D&U002ovPDHLkV1lHj BjmH20 literal 0 HcmV?d00001 diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index fce50c43d2..6e7a07e192 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -7,7 +7,14 @@ osu! ppy.osu.Game + icon.png + + + True + icon.png + + From 8d290a324291dcceccbbc587b40f483106cf0436 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Oct 2019 23:43:13 +0800 Subject: [PATCH 099/503] Resolve CS0067. --- osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs | 6 +++++- .../Visual/Gameplay/TestSceneSkinnableDrawable.cs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs index 685a51d208..46769f65fe 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -101,7 +101,11 @@ namespace osu.Game.Rulesets.Osu.Tests public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); - public event Action SourceChanged; + public event Action SourceChanged + { + add { } + remove { } + } } private class MovingCursorInputManager : ManualInputManager diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index b3d4820737..8beb107269 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -326,7 +326,11 @@ namespace osu.Game.Tests.Visual.Gameplay public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); - public event Action SourceChanged; + public event Action SourceChanged + { + add { } + remove { } + } } private class TestSkinComponent : ISkinComponent From ff3db9f3b26eb9182116d53916a030eba4946dcb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Oct 2019 02:58:58 +0800 Subject: [PATCH 100/503] Update README to require VS2019 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0460e9cbcf..1e2d539697 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh - A desktop platform with the [.NET Core SDK 3.0](https://www.microsoft.com/net/learn/get-started) or higher installed. - When running on linux, please have a system-wide ffmpeg installation available to support video decoding. - When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs. -- When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2017+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). +- When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). ## Running osu! From 473045308374118211ae5338e06d9b96a2f949c6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 31 Oct 2019 02:10:00 +0300 Subject: [PATCH 101/503] Apply suggestions --- .../Visual/Online/TestSceneVotePill.cs | 22 ++++++++++++------- osu.Game/Overlays/Comments/VotePill.cs | 20 ++++++++--------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 7ccb025b47..22e11aa464 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -8,6 +8,8 @@ using osu.Framework.Graphics; using osu.Game.Overlays.Comments; using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Users; +using osu.Framework.MathUtils; namespace osu.Game.Tests.Visual.Online { @@ -24,13 +26,6 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load() { - var userComment = new Comment - { - IsVoted = false, - UserId = API.LocalUser.Value.Id, - VotesCount = 10, - }; - var randomComment = new Comment { IsVoted = false, @@ -38,7 +33,11 @@ namespace osu.Game.Tests.Visual.Online VotesCount = 2, }; - AddStep("User comment", () => addVotePill(userComment)); + AddStep("Log in", () => API.LocalUser.Value = new User + { + Id = RNG.Next(2, 100000) + }); + AddStep("User comment", () => addVotePill(getUserComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -52,6 +51,13 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Not loading", () => !votePill.IsLoading); } + private Comment getUserComment() => new Comment + { + IsVoted = false, + UserId = API.LocalUser.Value.Id, + VotesCount = 10, + }; + private void addVotePill(Comment comment) { Clear(); diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 54eba63095..ad17264229 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -158,18 +158,18 @@ namespace osu.Game.Overlays.Comments private void updateDisplay() { - if (Action != null) - { - if (isVoted.Value) - { - hoverLayer.FadeTo(IsHovered ? 1 : 0); - sideNumber.Hide(); - } - else - sideNumber.FadeTo(IsHovered ? 1 : 0); + if (Action == null) + return; - borderContainer.BorderThickness = IsHovered ? 3 : 0; + if (isVoted.Value) + { + hoverLayer.FadeTo(IsHovered ? 1 : 0); + sideNumber.Hide(); } + else + sideNumber.FadeTo(IsHovered ? 1 : 0); + + borderContainer.BorderThickness = IsHovered ? 3 : 0; } private void onHoverAction() From 43b2cbb865f031eacb431a7d8ccb5fd4fbd04954 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 16:25:26 +0900 Subject: [PATCH 102/503] Implement slider control point deletion --- .../Components/PathControlPointVisualiser.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index bbe771d8b0..b578c75474 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -2,12 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit.Compose; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { @@ -20,6 +24,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private InputManager inputManager; + [Resolved(CanBeNull = true)] + private IPlacementHandler placementHandler { get; set; } + public PathControlPointVisualiser(Slider slider) { this.slider = slider; @@ -70,5 +77,44 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components piece.IsSelected.Value = piece.Index == index; } } + + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Delete: + var newControlPoints = new List(); + + foreach (var piece in pieces) + { + if (!piece.IsSelected.Value) + newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); + } + + // Ensure that there are any points to be deleted + if (newControlPoints.Count == slider.Path.ControlPoints.Length) + return false; + + // If there are 0 remaining control points, treat the slider as being deleted + if (newControlPoints.Count == 0) + { + placementHandler?.Delete(slider); + return true; + } + + // Make control points relative + Vector2 first = newControlPoints[0]; + for (int i = 0; i < newControlPoints.Count; i++) + newControlPoints[i] = newControlPoints[i] - first; + + // The slider's position defines the position of the first control point, and all further control points are relative to that point + slider.Position = slider.Position + first; + ControlPointsChanged?.Invoke(newControlPoints.ToArray()); + + return true; + } + + return false; + } } } From 83abb845b648def4b42b2cebace3f5ace3c78e01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 17:50:06 +0900 Subject: [PATCH 103/503] Fix code quality --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 66911d9615..efd4aae23e 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -74,7 +74,13 @@ namespace osu.Game.Graphics.Containers { RelativeSizeAxes = Axes.Both, TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => game.HandleLink(url, linkType, linkArgument)), + Action = () => + { + if (action != null) + action(); + else + game.HandleLink(url, linkType, linkArgument); + }, }); return drawables; From 78194cfa6e193c53cef9a4417a8cbbbe7d7283f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:54:06 +0900 Subject: [PATCH 104/503] Implement slider control point deletions --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index b578c75474..17eb236ae0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components case Key.Delete: var newControlPoints = new List(); - foreach (var piece in pieces) + foreach (var piece in Pieces) { if (!piece.IsSelected.Value) newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); From 18f374eec653612784227dfcbe7d6aaf914e5c5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 31 Oct 2019 17:58:33 +0900 Subject: [PATCH 105/503] Deselect deleted control points --- .../Sliders/Components/PathControlPointVisualiser.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 17eb236ae0..a6ee928c90 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -109,6 +109,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components // The slider's position defines the position of the first control point, and all further control points are relative to that point slider.Position = slider.Position + first; + + // Since pieces are re-used, they will not point to the deleted control points while remaining selected + foreach (var piece in Pieces) + piece.IsSelected.Value = false; + ControlPointsChanged?.Invoke(newControlPoints.ToArray()); return true; From 11447023eb21ad6f251a95d1310d16bf7852c003 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 18:34:41 +0900 Subject: [PATCH 106/503] Improve splitting out of link handling --- .../Graphics/Containers/LinkFlowContainer.cs | 29 +++++++++--------- osu.Game/Online/Chat/MessageFormatter.cs | 19 ++++++------ osu.Game/OsuGame.cs | 30 +++++++------------ osu.Game/Overlays/Changelog/ChangelogBuild.cs | 4 +-- .../Screens/Multi/Components/BeatmapTitle.cs | 2 +- osu.iOS/AppDelegate.cs | 2 +- 6 files changed, 40 insertions(+), 46 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index efd4aae23e..b5ffd1c6ad 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -44,46 +44,47 @@ namespace osu.Game.Graphics.Containers foreach (var link in links) { AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); - AddLink(text.Substring(link.Index, link.Length), link.Url, link.Action, link.Argument); + AddLink(text.Substring(link.Index, link.Length), link.Action, link.Argument ?? link.Url); previousLinkEnd = link.Index + link.Length; } AddText(text.Substring(previousLinkEnd)); } - public IEnumerable AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); + public void AddLink(string text, string url, Action creationParameters = null) => + createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), text); - public IEnumerable AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, tooltipText: tooltipText, action: action); + public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.Custom, null), tooltipText, action); - public IEnumerable AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) + public void AddLink(string text, LinkAction action, string argument, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(action, argument), null); + + public void AddLink(IEnumerable text, LinkAction action = LinkAction.External, string linkArgument = null, string tooltipText = null) { foreach (var t in text) AddArbitraryDrawable(t); - return createLink(text, null, url, linkType, linkArgument, tooltipText); + createLink(text, new LinkDetails(action, linkArgument), tooltipText); } - public IEnumerable AddUserLink(User user, Action creationParameters = null) - => createLink(AddText(user.Username, creationParameters), user.Username, null, LinkAction.OpenUserProfile, user.Id.ToString(), "View profile"); + public void AddUserLink(User user, Action creationParameters = null) + => createLink(AddText(user.Username, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user.Id.ToString()), "View Profile"); - private IEnumerable createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) + private void createLink(IEnumerable drawables, LinkDetails link, string tooltipText, Action action = null) { AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) { RelativeSizeAxes = Axes.Both, - TooltipText = tooltipText ?? (url != text ? url : string.Empty), + TooltipText = tooltipText, Action = () => { if (action != null) action(); else - game.HandleLink(url, linkType, linkArgument); + game.HandleLink(link); }, }); - - return drawables; } // We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used. diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 31a324d0ea..717de18c14 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -255,17 +255,17 @@ namespace osu.Game.Online.Chat OriginalText = Text = text; } } + } - public class LinkDetails + public class LinkDetails + { + public LinkAction Action; + public string Argument; + + public LinkDetails(LinkAction action, string argument) { - public LinkAction Action; - public string Argument; - - public LinkDetails(LinkAction action, string argument) - { - Action = action; - Argument = argument; - } + Action = action; + Argument = argument; } } @@ -279,6 +279,7 @@ namespace osu.Game.Online.Chat JoinMultiplayerMatch, Spectate, OpenUserProfile, + Custom } public class Link : IComparable diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index c028896cff..b55cc41454 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -43,7 +43,6 @@ using osu.Game.Scoring; using osu.Game.Screens.Select; using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; -using static osu.Game.Online.Chat.MessageFormatter; namespace osu.Game { @@ -216,7 +215,9 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleLink(string url, LinkAction linkType, string linkArgument) + public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + + public void HandleLink(LinkDetails link) { Action showNotImplementedError = () => notifications?.Post(new SimpleNotification { @@ -224,27 +225,27 @@ namespace osu.Game Icon = FontAwesome.Solid.LifeRing, }); - switch (linkType) + switch (link.Action) { case LinkAction.OpenBeatmap: // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) + if (link.Argument != null && int.TryParse(link.Argument.Contains('?') ? link.Argument.Split('?')[0] : link.Argument, out int beatmapId)) ShowBeatmap(beatmapId); break; case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) + if (int.TryParse(link.Argument, out int setId)) ShowBeatmapSet(setId); break; case LinkAction.OpenChannel: try { - channelManager.OpenChannel(linkArgument); + channelManager.OpenChannel(link.Argument); } catch (ChannelNotFoundException) { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); + Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); } break; @@ -256,28 +257,19 @@ namespace osu.Game break; case LinkAction.External: - OpenUrlExternally(url); + OpenUrlExternally(link.Argument); break; case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) + if (long.TryParse(link.Argument, out long userId)) ShowUser(userId); break; default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); + throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action."); } } - public void HandleUrl(string url) - { - Logger.Log($"Request to handle url: {url}"); - - LinkDetails linkDetails = GetLinkDetails(url); - - Schedule(() => HandleLink(url, linkDetails.Action, linkDetails.Argument)); - } - public void OpenUrlExternally(string url) { if (url.StartsWith("/")) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index bce1be5941..d8488b21ab 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Changelog t.Font = fontLarge; t.Colour = entryColour; }); - title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, + title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, creationParameters: t => { t.Font = fontLarge; @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = entryColour; }); else if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t => { t.Font = fontMedium; t.Colour = entryColour; diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index e096fb33da..f79cac7649 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Multi.Components Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)), Font = OsuFont.GetFont(size: TextSize), } - }, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); + }, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); } } } diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 07e0245195..164a182ebe 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -21,7 +21,7 @@ namespace osu.iOS if (url.IsFileUrl) Task.Run(() => game.Import(url.Path)); else - Task.Run(() => game.HandleUrl(url.AbsoluteString)); + Task.Run(() => game.HandleLink(url.AbsoluteString)); return true; } } From f13dc93a4d867352797046d7a5b46a9c941eaf06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 18:49:13 +0900 Subject: [PATCH 107/503] Fix external link tooltip regression --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index b5ffd1c6ad..61391b7102 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Graphics.Containers } public void AddLink(string text, string url, Action creationParameters = null) => - createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), text); + createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), url); public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) => createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.Custom, null), tooltipText, action); From e3ca64bb8c6dad982b579d126fbaefa402629c04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2019 19:18:54 +0900 Subject: [PATCH 108/503] Remove iOS "import from stable" for now --- osu.Game/Database/ArchiveModelManager.cs | 2 +- osu.iOS/Info.plist | 8 +++----- osu.iOS/OsuGameIOS.cs | 2 -- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 3c1e07b765..9fed8e03ac 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -67,7 +67,7 @@ namespace osu.Game.Database public virtual string[] HandledExtensions => new[] { ".zip" }; - public virtual bool SupportsImportFromStable => (RuntimeInfo.IsDesktop || RuntimeInfo.OS == RuntimeInfo.Platform.iOS); + public virtual bool SupportsImportFromStable => RuntimeInfo.IsDesktop; protected readonly FileStore Files; diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist index 67f71b64b6..5ceccdf99f 100644 --- a/osu.iOS/Info.plist +++ b/osu.iOS/Info.plist @@ -34,9 +34,9 @@ UIStatusBarHidden NSCameraUsageDescription - We don't really use the camera. - NSMicrophoneUsageDescription - We don't really use the microphone. + We don't really use the camera. + NSMicrophoneUsageDescription + We don't really use the microphone. UISupportedInterfaceOrientations UIInterfaceOrientationPortrait @@ -111,8 +111,6 @@ - UIFileSharingEnabled - CFBundleURLTypes diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index ac66357fc9..6cf18df9a6 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -3,14 +3,12 @@ using System; using Foundation; -using osu.Framework.Platform; using osu.Game; namespace osu.iOS { public class OsuGameIOS : OsuGame { - public override Storage GetStorageForStableInstall() => Storage; public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); } } From 944380906324d53936b67b04b30e9a01097bdb42 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 11:22:32 +0900 Subject: [PATCH 109/503] Protect against requests to show overlays before the target overlay is ready --- osu.Game/OsuGame.cs | 77 ++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b55cc41454..fb9a7f7965 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -215,16 +215,20 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + /// + /// Handle an arbitrary URL. Displays via in-game overlays where possible. + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The URL to load. + public void HandleLink(string url) => Schedule(() => HandleLink(MessageFormatter.GetLinkDetails(url))); + /// + /// Handle a specific . + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The link to load. public void HandleLink(LinkDetails link) { - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); - switch (link.Action) { case LinkAction.OpenBeatmap: @@ -239,21 +243,17 @@ namespace osu.Game break; case LinkAction.OpenChannel: - try - { - channelManager.OpenChannel(link.Argument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); - } - + ShowChannel(link.Argument); break; case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - showNotImplementedError.Invoke(); + waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + })); break; case LinkAction.External: @@ -270,31 +270,47 @@ namespace osu.Game } } - public void OpenUrlExternally(string url) + public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ => { if (url.StartsWith("/")) url = $"{API.Endpoint}{url}"; externalLinkOpener.OpenUrlExternally(url); - } + }); + + /// + /// Open a specific channel in chat. + /// + /// The channel to display. + public void ShowChannel(string channel) => waitForReady(() => channelManager, _ => + { + try + { + channelManager.OpenChannel(channel); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{channel}\" does not exist"); + } + }); /// /// Show a beatmap set as an overlay. /// /// The set to display. - public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); + public void ShowBeatmapSet(int setId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmapSet(setId)); /// /// Show a user's profile as an overlay. /// /// The user to display. - public void ShowUser(long userId) => userProfile.ShowUser(userId); + public void ShowUser(long userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId)); /// /// Show a beatmap's set as an overlay, displaying the given beatmap. /// /// The beatmap to show. - public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); + public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId)); /// /// Present a beatmap at song select immediately. @@ -452,6 +468,23 @@ namespace osu.Game performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName)); } + /// + /// Wait for the game (and target component) to become loaded and then run an action. + /// + /// A function to retrieve a (potentially not-yet-constructed) target instance. + /// The action to perform on the instance when load is confirmed. + /// The type of the target instance. + private void waitForReady(Func retrieveInstance, Action action) + where T : Drawable + { + var instance = retrieveInstance(); + + if (ScreenStack == null || ScreenStack.CurrentScreen is StartupScreen || instance?.IsLoaded != true) + Schedule(() => waitForReady(retrieveInstance, action)); + else + action(instance); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 898520935ec5c26994ac209ccd8229eb362b880e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 11:40:51 +0900 Subject: [PATCH 110/503] Move link handling code to OsuGame This allows for future calls from arguments / associations --- .../Graphics/Containers/LinkFlowContainer.cs | 92 +++++-------------- osu.Game/Online/Chat/MessageFormatter.cs | 25 ++--- osu.Game/OsuGame.cs | 55 +++++++++++ osu.Game/Overlays/Changelog/ChangelogBuild.cs | 4 +- .../Screens/Multi/Components/BeatmapTitle.cs | 2 +- 5 files changed, 92 insertions(+), 86 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 15068d81c0..61391b7102 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -8,9 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Framework.Logging; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; using osu.Game.Users; namespace osu.Game.Graphics.Containers @@ -23,21 +20,12 @@ namespace osu.Game.Graphics.Containers } private OsuGame game; - private ChannelManager channelManager; - private Action showNotImplementedError; [BackgroundDependencyLoader(true)] - private void load(OsuGame game, NotificationOverlay notifications, ChannelManager channelManager) + private void load(OsuGame game) { // will be null in tests this.game = game; - this.channelManager = channelManager; - - showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); } public void AddLinks(string text, List links) @@ -56,85 +44,47 @@ namespace osu.Game.Graphics.Containers foreach (var link in links) { AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); - AddLink(text.Substring(link.Index, link.Length), link.Url, link.Action, link.Argument); + AddLink(text.Substring(link.Index, link.Length), link.Action, link.Argument ?? link.Url); previousLinkEnd = link.Index + link.Length; } AddText(text.Substring(previousLinkEnd)); } - public IEnumerable AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); + public void AddLink(string text, string url, Action creationParameters = null) => + createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.External, url), url); - public IEnumerable AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) - => createLink(AddText(text, creationParameters), text, tooltipText: tooltipText, action: action); + public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(LinkAction.Custom, null), tooltipText, action); - public IEnumerable AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) + public void AddLink(string text, LinkAction action, string argument, string tooltipText = null, Action creationParameters = null) + => createLink(AddText(text, creationParameters), new LinkDetails(action, argument), null); + + public void AddLink(IEnumerable text, LinkAction action = LinkAction.External, string linkArgument = null, string tooltipText = null) { foreach (var t in text) AddArbitraryDrawable(t); - return createLink(text, null, url, linkType, linkArgument, tooltipText); + createLink(text, new LinkDetails(action, linkArgument), tooltipText); } - public IEnumerable AddUserLink(User user, Action creationParameters = null) - => createLink(AddText(user.Username, creationParameters), user.Username, null, LinkAction.OpenUserProfile, user.Id.ToString(), "View profile"); + public void AddUserLink(User user, Action creationParameters = null) + => createLink(AddText(user.Username, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user.Id.ToString()), "View Profile"); - private IEnumerable createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) + private void createLink(IEnumerable drawables, LinkDetails link, string tooltipText, Action action = null) { AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) { RelativeSizeAxes = Axes.Both, - TooltipText = tooltipText ?? (url != text ? url : string.Empty), - Action = action ?? (() => + TooltipText = tooltipText, + Action = () => { - switch (linkType) - { - case LinkAction.OpenBeatmap: - // TODO: proper query params handling - if (linkArgument != null && int.TryParse(linkArgument.Contains('?') ? linkArgument.Split('?')[0] : linkArgument, out int beatmapId)) - game?.ShowBeatmap(beatmapId); - break; - - case LinkAction.OpenBeatmapSet: - if (int.TryParse(linkArgument, out int setId)) - game?.ShowBeatmapSet(setId); - break; - - case LinkAction.OpenChannel: - try - { - channelManager?.OpenChannel(linkArgument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{linkArgument}\" does not exist"); - } - - break; - - case LinkAction.OpenEditorTimestamp: - case LinkAction.JoinMultiplayerMatch: - case LinkAction.Spectate: - showNotImplementedError?.Invoke(); - break; - - case LinkAction.External: - game?.OpenUrlExternally(url); - break; - - case LinkAction.OpenUserProfile: - if (long.TryParse(linkArgument, out long userId)) - game?.ShowUser(userId); - break; - - default: - throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); - } - }), + if (action != null) + action(); + else + game.HandleLink(link); + }, }); - - return drawables; } // We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used. diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 3ffff281f8..717de18c14 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -81,7 +81,7 @@ namespace osu.Game.Online.Chat //since we just changed the line display text, offset any already processed links. result.Links.ForEach(l => l.Index -= l.Index > index ? m.Length - displayText.Length : 0); - var details = getLinkDetails(linkText); + var details = GetLinkDetails(linkText); result.Links.Add(new Link(linkText, index, displayText.Length, linkActionOverride ?? details.Action, details.Argument)); //adjust the offset for processing the current matches group. @@ -98,7 +98,7 @@ namespace osu.Game.Online.Chat var linkText = m.Groups["link"].Value; var indexLength = linkText.Length; - var details = getLinkDetails(linkText); + var details = GetLinkDetails(linkText); var link = new Link(linkText, index, indexLength, details.Action, details.Argument); // sometimes an already-processed formatted link can reduce to a simple URL, too @@ -109,7 +109,7 @@ namespace osu.Game.Online.Chat } } - private static LinkDetails getLinkDetails(string url) + public static LinkDetails GetLinkDetails(string url) { var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); args[0] = args[0].TrimEnd(':'); @@ -255,17 +255,17 @@ namespace osu.Game.Online.Chat OriginalText = Text = text; } } + } - public class LinkDetails + public class LinkDetails + { + public LinkAction Action; + public string Argument; + + public LinkDetails(LinkAction action, string argument) { - public LinkAction Action; - public string Argument; - - public LinkDetails(LinkAction action, string argument) - { - Action = action; - Argument = argument; - } + Action = action; + Argument = argument; } } @@ -279,6 +279,7 @@ namespace osu.Game.Online.Chat JoinMultiplayerMatch, Spectate, OpenUserProfile, + Custom } public class Link : IComparable diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4dcc181bea..b55cc41454 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -215,6 +215,61 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; + public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + + public void HandleLink(LinkDetails link) + { + Action showNotImplementedError = () => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + }); + + switch (link.Action) + { + case LinkAction.OpenBeatmap: + // TODO: proper query params handling + if (link.Argument != null && int.TryParse(link.Argument.Contains('?') ? link.Argument.Split('?')[0] : link.Argument, out int beatmapId)) + ShowBeatmap(beatmapId); + break; + + case LinkAction.OpenBeatmapSet: + if (int.TryParse(link.Argument, out int setId)) + ShowBeatmapSet(setId); + break; + + case LinkAction.OpenChannel: + try + { + channelManager.OpenChannel(link.Argument); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); + } + + break; + + case LinkAction.OpenEditorTimestamp: + case LinkAction.JoinMultiplayerMatch: + case LinkAction.Spectate: + showNotImplementedError.Invoke(); + break; + + case LinkAction.External: + OpenUrlExternally(link.Argument); + break; + + case LinkAction.OpenUserProfile: + if (long.TryParse(link.Argument, out long userId)) + ShowUser(userId); + break; + + default: + throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action."); + } + } + public void OpenUrlExternally(string url) { if (url.StartsWith("/")) diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index bce1be5941..d8488b21ab 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Changelog t.Font = fontLarge; t.Colour = entryColour; }); - title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External, + title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, creationParameters: t => { t.Font = fontLarge; @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = entryColour; }); else if (entry.GithubUser.GithubUrl != null) - title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => + title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t => { t.Font = fontMedium; t.Colour = entryColour; diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index e096fb33da..f79cac7649 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Multi.Components Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)), Font = OsuFont.GetFont(size: TextSize), } - }, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); + }, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); } } } From f038c579f01b89327c57f0ff307c0917957c9667 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 11:22:32 +0900 Subject: [PATCH 111/503] Protect against requests to show overlays before the target overlay is ready --- osu.Game/OsuGame.cs | 77 ++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b55cc41454..fb9a7f7965 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -215,16 +215,20 @@ namespace osu.Game private ExternalLinkOpener externalLinkOpener; - public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); + /// + /// Handle an arbitrary URL. Displays via in-game overlays where possible. + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The URL to load. + public void HandleLink(string url) => Schedule(() => HandleLink(MessageFormatter.GetLinkDetails(url))); + /// + /// Handle a specific . + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The link to load. public void HandleLink(LinkDetails link) { - Action showNotImplementedError = () => notifications?.Post(new SimpleNotification - { - Text = @"This link type is not yet supported!", - Icon = FontAwesome.Solid.LifeRing, - }); - switch (link.Action) { case LinkAction.OpenBeatmap: @@ -239,21 +243,17 @@ namespace osu.Game break; case LinkAction.OpenChannel: - try - { - channelManager.OpenChannel(link.Argument); - } - catch (ChannelNotFoundException) - { - Logger.Log($"The requested channel \"{link.Argument}\" does not exist"); - } - + ShowChannel(link.Argument); break; case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - showNotImplementedError.Invoke(); + waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.Solid.LifeRing, + })); break; case LinkAction.External: @@ -270,31 +270,47 @@ namespace osu.Game } } - public void OpenUrlExternally(string url) + public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ => { if (url.StartsWith("/")) url = $"{API.Endpoint}{url}"; externalLinkOpener.OpenUrlExternally(url); - } + }); + + /// + /// Open a specific channel in chat. + /// + /// The channel to display. + public void ShowChannel(string channel) => waitForReady(() => channelManager, _ => + { + try + { + channelManager.OpenChannel(channel); + } + catch (ChannelNotFoundException) + { + Logger.Log($"The requested channel \"{channel}\" does not exist"); + } + }); /// /// Show a beatmap set as an overlay. /// /// The set to display. - public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); + public void ShowBeatmapSet(int setId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmapSet(setId)); /// /// Show a user's profile as an overlay. /// /// The user to display. - public void ShowUser(long userId) => userProfile.ShowUser(userId); + public void ShowUser(long userId) => waitForReady(() => userProfile, _ => userProfile.ShowUser(userId)); /// /// Show a beatmap's set as an overlay, displaying the given beatmap. /// /// The beatmap to show. - public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); + public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId)); /// /// Present a beatmap at song select immediately. @@ -452,6 +468,23 @@ namespace osu.Game performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName)); } + /// + /// Wait for the game (and target component) to become loaded and then run an action. + /// + /// A function to retrieve a (potentially not-yet-constructed) target instance. + /// The action to perform on the instance when load is confirmed. + /// The type of the target instance. + private void waitForReady(Func retrieveInstance, Action action) + where T : Drawable + { + var instance = retrieveInstance(); + + if (ScreenStack == null || ScreenStack.CurrentScreen is StartupScreen || instance?.IsLoaded != true) + Schedule(() => waitForReady(retrieveInstance, action)); + else + action(instance); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From ddd58ea3da88aedcb7123cd7921f656f4b5c9498 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 1 Nov 2019 19:40:45 +0900 Subject: [PATCH 112/503] Use LongRunningLoad on network load components --- osu.Game/Audio/PreviewTrack.cs | 1 + osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs | 1 + osu.Game/Users/Drawables/DrawableAvatar.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 22ce7d4711..ff667249a7 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -9,6 +9,7 @@ using osu.Framework.Threading; namespace osu.Game.Audio { + [LongRunningLoad] public abstract class PreviewTrack : Component { /// diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index d0db7765c2..5245bc319d 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Textures; namespace osu.Game.Beatmaps.Drawables { + [LongRunningLoad] public class BeatmapSetCover : Sprite { private readonly BeatmapSetInfo set; diff --git a/osu.Game/Users/Drawables/DrawableAvatar.cs b/osu.Game/Users/Drawables/DrawableAvatar.cs index ee3cf6331b..ee9af15863 100644 --- a/osu.Game/Users/Drawables/DrawableAvatar.cs +++ b/osu.Game/Users/Drawables/DrawableAvatar.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Users.Drawables { + [LongRunningLoad] public class DrawableAvatar : Container { /// From fe3583b6eec4575a9bde01ef3454452071bdd161 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 3 Nov 2019 13:16:54 +0900 Subject: [PATCH 113/503] Move schedule call --- osu.Game/OsuGame.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fb9a7f7965..1f823e6eba 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -220,14 +220,14 @@ namespace osu.Game /// This can be called from a non-thread-safe non-game-loaded state. /// /// The URL to load. - public void HandleLink(string url) => Schedule(() => HandleLink(MessageFormatter.GetLinkDetails(url))); + public void HandleLink(string url) => HandleLink(MessageFormatter.GetLinkDetails(url)); /// /// Handle a specific . /// This can be called from a non-thread-safe non-game-loaded state. /// /// The link to load. - public void HandleLink(LinkDetails link) + public void HandleLink(LinkDetails link) => Schedule(() => { switch (link.Action) { @@ -268,7 +268,7 @@ namespace osu.Game default: throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action."); } - } + }); public void OpenUrlExternally(string url) => waitForReady(() => externalLinkOpener, _ => { From bcf8a6d514d6c44df4f3bcd4fca97a51464c7297 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 3 Nov 2019 19:59:37 +0900 Subject: [PATCH 114/503] Fix slider creation regressing with path selection changes --- .../Sliders/Components/PathControlPointPiece.cs | 13 +++++++++---- .../Components/PathControlPointVisualiser.cs | 14 ++++++++++---- .../Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 +- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index e2ea6a12d7..cfcd266c7f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -128,19 +128,24 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnMouseDown(MouseDownEvent e) { isClicked = true; - return true; + return false; } protected override bool OnMouseUp(MouseUpEvent e) { isClicked = false; - return true; + return false; } protected override bool OnClick(ClickEvent e) { - RequestSelection?.Invoke(Index); - return true; + if (RequestSelection != null) + { + RequestSelection.Invoke(Index); + return true; + } + + return false; } protected override bool OnDragStart(DragStartEvent e) => true; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index b70c11427a..c0fc5ccb0a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -17,12 +17,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components internal readonly Container Pieces; private readonly Slider slider; + private readonly bool allowSelection; private InputManager inputManager; - public PathControlPointVisualiser(Slider slider) + public PathControlPointVisualiser(Slider slider, bool allowSelection) { this.slider = slider; + this.allowSelection = allowSelection; RelativeSizeAxes = Axes.Both; @@ -42,11 +44,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components while (slider.Path.ControlPoints.Length > Pieces.Count) { - Pieces.Add(new PathControlPointPiece(slider, Pieces.Count) + var piece = new PathControlPointPiece(slider, Pieces.Count) { ControlPointsChanged = c => ControlPointsChanged?.Invoke(c), - RequestSelection = selectPiece - }); + }; + + if (allowSelection) + piece.RequestSelection = selectPiece; + + Pieces.Add(piece); } while (slider.Path.ControlPoints.Length < Pieces.Count) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 6f5309c2c2..9c0afada29 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders bodyPiece = new SliderBodyPiece(), headCirclePiece = new HitCirclePiece(), tailCirclePiece = new HitCirclePiece(), - new PathControlPointVisualiser(HitObject) { ControlPointsChanged = _ => updateSlider() }, + new PathControlPointVisualiser(HitObject, false) { ControlPointsChanged = _ => updateSlider() }, }; setState(PlacementState.Initial); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index f612ba9dfc..25362820a3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece = new SliderBodyPiece(), HeadBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.Start), TailBlueprint = CreateCircleSelectionBlueprint(slider, SliderPosition.End), - ControlPointVisualiser = new PathControlPointVisualiser(sliderObject) { ControlPointsChanged = onNewControlPoints }, + ControlPointVisualiser = new PathControlPointVisualiser(sliderObject, true) { ControlPointsChanged = onNewControlPoints }, }; } From fe23b9a262d90ad9926d754e9d6bc4df5dd3ca42 Mon Sep 17 00:00:00 2001 From: Joehu Date: Sun, 3 Nov 2019 07:32:47 -0800 Subject: [PATCH 115/503] Fix mod section overflowing mod select overlay at higher ui scale --- osu.Game/Overlays/Mods/ModSection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index dedd397fa5..35a94eb43f 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -158,7 +158,8 @@ namespace osu.Game.Overlays.Mods }, ButtonsContainer = new FillFlowContainer { - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Spacing = new Vector2(50f, 0f), From 66253a0bd4142166cb7164bb0d9aca4712b9b6e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 02:21:50 +0900 Subject: [PATCH 116/503] Handle selection on mouse down instead of click This is how other elements work, and feels better with drag preselection --- .../Components/PathControlPointPiece.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index cfcd266c7f..0353ba241c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -29,8 +29,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private readonly Container marker; private readonly Drawable markerRing; - private bool isClicked; - [Resolved] private OsuColour colours { get; set; } @@ -101,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components markerRing.Alpha = IsSelected.Value ? 1 : 0; Color4 colour = isSegmentSeparator ? colours.Red : colours.Yellow; - if (IsHovered || isClicked || IsSelected.Value) + if (IsHovered || IsSelected.Value) colour = Color4.White; marker.Colour = colour; } @@ -126,18 +124,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => marker.ReceivePositionalInputAt(screenSpacePos); protected override bool OnMouseDown(MouseDownEvent e) - { - isClicked = true; - return false; - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - isClicked = false; - return false; - } - - protected override bool OnClick(ClickEvent e) { if (RequestSelection != null) { @@ -148,6 +134,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } + protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null; + + protected override bool OnClick(ClickEvent e) => RequestSelection != null; + protected override bool OnDragStart(DragStartEvent e) => true; protected override bool OnDrag(DragEvent e) From 64d900b38770da44090c9124fb4ba1e83c39033c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 11:33:37 +0900 Subject: [PATCH 117/503] Disable input for non-selected blueprints --- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 0701513933..2923411ce1 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -82,6 +82,9 @@ namespace osu.Game.Rulesets.Edit } } + // When not selected, input is only required for the blueprint itself to receive IsHovering + protected override bool ShouldBeConsideredForInput(Drawable child) => State == SelectionState.Selected; + /// /// Selects this , causing it to become visible. /// From c8beb5296f512d8c932c248eeea651675902c8d1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 13:26:44 +0900 Subject: [PATCH 118/503] Use PlatformAction.Delete instead of Delete key --- .../Components/PathControlPointVisualiser.cs | 11 +++++++---- .../Edit/Compose/Components/SelectionHandler.cs | 17 +++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 1118cae344..f2a392feee 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; @@ -15,7 +16,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointVisualiser : CompositeDrawable + public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler { public Action ControlPointsChanged; @@ -84,11 +85,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } } - protected override bool OnKeyDown(KeyDownEvent e) + public bool OnPressed(PlatformAction action) { - switch (e.Key) + switch (action.ActionMethod) { - case Key.Delete: + case PlatformActionMethod.Delete: var newControlPoints = new List(); foreach (var piece in Pieces) @@ -127,5 +128,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } + + public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index d7821eff07..664b9e3a8c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -8,6 +8,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; @@ -22,7 +24,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A component which outlines s and handles movement of selections. /// - public class SelectionHandler : CompositeDrawable + public class SelectionHandler : CompositeDrawable, IKeyBindingHandler { public const float BORDER_RADIUS = 2; @@ -72,22 +74,21 @@ namespace osu.Game.Screens.Edit.Compose.Components { } - protected override bool OnKeyDown(KeyDownEvent e) + public bool OnPressed(PlatformAction action) { - if (e.Repeat) - return base.OnKeyDown(e); - - switch (e.Key) + switch (action.ActionMethod) { - case Key.Delete: + case PlatformActionMethod.Delete: foreach (var h in selectedBlueprints.ToList()) placementHandler.Delete(h.DrawableObject.HitObject); return true; } - return base.OnKeyDown(e); + return false; } + public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + #endregion #region Selection Handling From 7c20a589f2dac47c55bcad3b032d9e04fc99fc6d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 13:56:21 +0900 Subject: [PATCH 119/503] Remove unused usings --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 1 - osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index f2a392feee..6962736157 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -12,7 +12,6 @@ using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; -using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 664b9e3a8c..1722476e53 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -10,14 +10,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; -using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { From fe374eabe04b3c51efa732c88a71ea6802b322ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 15:47:01 +0900 Subject: [PATCH 120/503] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 8b31be3f12..78c7583923 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0cb09d9b14..42b930b1af 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 719aced705..dfc9c2d60a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 44d079167676370c41e2a9677b8a8d2f4dce3341 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 16:26:31 +0900 Subject: [PATCH 121/503] Update button usage --- osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs | 2 +- osu.Game/Graphics/UserInterface/OsuButton.cs | 2 +- osu.Game/Overlays/Settings/SidebarButton.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index a8c2362910..b6b2b2f92d 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.Editor } } - private class StartStopButton : Button + private class StartStopButton : BasicButton { private IAdjustableClock adjustableClock; private bool started; diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 4124d2ad58..319c3dd0b4 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public class OsuButton : Button + public class OsuButton : BasicButton { private Box hover; diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index a94f76e7af..cdb4dc463a 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -17,7 +17,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SidebarButton : Button + public class SidebarButton : BasicButton { private readonly SpriteIcon drawableIcon; private readonly SpriteText headerText; From 0db34a47f8314f1d46c48f44e04e31d8a80a9077 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 17:28:42 +0900 Subject: [PATCH 122/503] Fix selecting underneath selected blueprints --- .../Compose/Components/BlueprintContainer.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index a145dea6af..7a3a303ff3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -254,15 +254,31 @@ namespace osu.Game.Screens.Edit.Compose.Components { Debug.Assert(!clickSelectionBegan); - foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) + bool hoveringSelected = false; + + // Make sure any already-selected blueprints aren't being hovered over + foreach (SelectionBlueprint selected in selectionHandler.SelectedBlueprints) { - if (blueprint.IsHovered) + if (selected.IsHovered) { - selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); - clickSelectionBegan = true; + hoveringSelected = true; break; } } + + // Attempt a new selection at the mouse position + if (!hoveringSelected) + { + foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) + { + if (blueprint.IsHovered) + { + selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); + clickSelectionBegan = true; + break; + } + } + } } /// From d77882c21bcc9ebb4379fd7e6ad6d04a1f2ea451 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 17:31:52 +0900 Subject: [PATCH 123/503] Fix slider selection input handled outside path --- .../Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index d28cf7b492..78f4c4d992 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -43,5 +43,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components Size = body.Size; OriginPosition = body.PathOffset; } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => body.ReceivePositionalInputAt(screenSpacePos); } } From 861268eb1ded856d1ebf6fb21115af38e7baec49 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 14:52:33 +0900 Subject: [PATCH 124/503] Add basic structure for new follow point renderer --- .../TestSceneFollowPoints.cs | 315 ++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs new file mode 100644 index 0000000000..c33c94c9c8 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -0,0 +1,315 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using JetBrains.Annotations; +using NUnit.Framework; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneFollowPoints : OsuTestScene + { + private Container hitObjectContainer; + private FollowPointRenderer followPointRenderer; + + [SetUp] + public void Setup() => Schedule(() => + { + Children = new Drawable[] + { + hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, + followPointRenderer = new FollowPointRenderer { RelativeSizeAxes = Axes.Both } + }; + }); + + [Test] + public void TestAddSingleHitObject() + { + addObject(new HitCircle { Position = new Vector2(100, 100) }); + } + + [Test] + public void TestRemoveSingleHitObject() + { + } + + [Test] + public void TestAddMultipleHitObjects() + { + } + + [Test] + public void TestRemoveEndObject() + { + } + + [Test] + public void TestRemoveStartObject() + { + } + + [Test] + public void TestRemoveMiddleObject() + { + } + + private void addObject(HitCircle hitCircle, Action func = null) + { + AddStep("add hitobject", () => + { + hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + var drawableCircle = new DrawableHitCircle(hitCircle); + + hitObjectContainer.Add(drawableCircle); + followPointRenderer.AddFollowPoints(drawableCircle); + + func?.Invoke(drawableCircle); + }); + } + + private void removeObject(Func func) + { + AddStep("remove hitobject", () => + { + var drawableObject = func?.Invoke(); + + hitObjectContainer.Remove(drawableObject); + followPointRenderer.RemoveFollowPoints(drawableObject); + }); + } + + private class FollowPointRenderer : CompositeDrawable + { + /// + /// Adds the s around a . + /// This includes s leading into , and s exiting . + /// + /// The to add s for. + public void AddFollowPoints(DrawableHitObject hitObject) + { + var startGroup = new FollowPointGroup(hitObject); + AddInternal(startGroup); + + // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups + int startIndex = IndexOfInternal(startGroup); + + if (startIndex < InternalChildren.Count - 1) + { + // h1 -> -> -> h2 + // hitObject nextGroup + + var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; + startGroup.End = nextGroup.Start; + } + + if (startIndex > 0) + { + // h1 -> -> -> h2 + // prevGroup hitObject + + var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + previousGroup.End = startGroup.Start; + } + } + + /// + /// Removes the s around a . + /// This includes s leading into , and s exiting . + /// + /// The to remove s for. + public void RemoveFollowPoints(DrawableHitObject hitObject) + { + var groups = findGroups(hitObject); + + // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject + RemoveInternal(groups.start); + + if (groups.end != null) + { + // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) + groups.end.End = groups.start.End; + } + } + + /// + /// Finds the s with as the start and end s. + /// + /// The to find the relevant of. + /// A tuple containing the end group (the where is the end of), + /// and the start group (the where is the start of). + private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableHitObject hitObject) + { + // endGroup startGroup + // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 + // hitObject + + FollowPointGroup startGroup = null; // The group which the hitobject is the start in + FollowPointGroup endGroup = null; // The group which the hitobject is the end in + + int startIndex = 0; + + for (; startIndex < InternalChildren.Count; startIndex++) + { + var group = (FollowPointGroup)InternalChildren[startIndex]; + + if (group.Start == hitObject) + { + startGroup = group; + break; + } + } + + if (startIndex > 0) + endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + + return (startGroup, endGroup); + } + + protected override int Compare(Drawable x, Drawable y) + { + var groupX = (FollowPointGroup)x; + var groupY = (FollowPointGroup)y; + + return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); + } + } + + private class FollowPointGroup : CompositeDrawable + { + private const int spacing = 32; + private const double preempt = 800; + + public FollowPointGroup(DrawableHitObject start) + { + Start = start; + } + + /// + /// The which s will exit from. + /// + [NotNull] + public DrawableHitObject Start { get; } + + private DrawableHitObject end; + + /// + /// The which s will enter. + /// + [CanBeNull] + public DrawableHitObject End + { + get => end; + set + { + end = value; + refreshFollowPoints(); + } + } + + private void refreshFollowPoints() + { + ClearInternal(); + + if (End == null) + return; + + OsuHitObject osuStart = (OsuHitObject)Start.HitObject; + OsuHitObject osuEnd = (OsuHitObject)End.HitObject; + + if (osuEnd.NewCombo) + return; + + if (osuStart is Spinner || osuEnd is Spinner) + return; + + Vector2 startPosition = osuStart.EndPosition; + Vector2 endPosition = osuEnd.Position; + double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; + double endTime = osuEnd.StartTime; + + Vector2 distanceVector = endPosition - startPosition; + int distance = (int)distanceVector.Length; + float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); + double duration = endTime - startTime; + + for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) + { + float fraction = (float)d / distance; + Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; + Vector2 pointEndPosition = startPosition + fraction * distanceVector; + double fadeOutTime = startTime + fraction * duration; + double fadeInTime = fadeOutTime - preempt; + + FollowPoint fp; + + AddInternal(fp = new FollowPoint + { + Position = pointStartPosition, + Rotation = rotation, + Alpha = 0, + Scale = new Vector2(1.5f * osuEnd.Scale), + }); + + using (fp.BeginAbsoluteSequence(fadeInTime)) + { + fp.FadeIn(osuEnd.TimeFadeIn); + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); + fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); + } + + fp.Expire(true); + } + } + } + + private class FollowPoint : CompositeDrawable + { + private const float width = 8; + + public override bool RemoveWhenNotAlive => false; + + public FollowPoint() + { + Origin = Anchor.Centre; + + InternalChild = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container + { + Masking = true, + AutoSizeAxes = Axes.Both, + CornerRadius = width / 2, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Color4.White.Opacity(0.2f), + Radius = 4, + }, + Child = new Box + { + Size = new Vector2(width), + Blending = BlendingParameters.Additive, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Alpha = 0.5f, + } + }, confineMode: ConfineMode.NoScaling); + } + } + } +} From 7e60bc724097d12c180a6ed5ff521257dc332f5e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:12:32 +0900 Subject: [PATCH 125/503] Fix groups having 0 size --- osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index c33c94c9c8..ca7be9bb64 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -198,6 +198,7 @@ namespace osu.Game.Rulesets.Osu.Tests public FollowPointGroup(DrawableHitObject start) { Start = start; + RelativeSizeAxes = Axes.Both; } /// From c1850b2353c1e85b0153c301f0b82d980ab87211 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:12:42 +0900 Subject: [PATCH 126/503] Add some basic tests --- .../TestSceneFollowPoints.cs | 100 ++++++++++++++++-- 1 file changed, 90 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index ca7be9bb64..66aea68a3c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; @@ -40,54 +42,132 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestAddSingleHitObject() { - addObject(new HitCircle { Position = new Vector2(100, 100) }); + addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }); } [Test] public void TestRemoveSingleHitObject() { + DrawableHitObject obj = null; + + addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); + removeObject(() => obj); } [Test] public void TestAddMultipleHitObjects() { + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }); } [Test] public void TestRemoveEndObject() { + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); + + removeObject(() => objects.Last()); } [Test] public void TestRemoveStartObject() { + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); + + removeObject(() => objects.First()); } [Test] public void TestRemoveMiddleObject() { + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); + + removeObject(() => objects[2]); } - private void addObject(HitCircle hitCircle, Action func = null) + [Test] + public void TestMoveHitObject() { - AddStep("add hitobject", () => + var objects = new List(); + + AddStep("reset", () => objects.Clear()); + + addObjects(() => new[] { - hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }, o => objects.Add(o)); - var drawableCircle = new DrawableHitCircle(hitCircle); + AddStep("move hitobject", () => ((OsuHitObject)objects[2].HitObject).Position = new Vector2(300, 100)); + } - hitObjectContainer.Add(drawableCircle); - followPointRenderer.AddFollowPoints(drawableCircle); + private void addObjects(Func ctorFunc, Action storeFunc = null) + { + AddStep("add hitobjects", () => + { + var circles = ctorFunc(); - func?.Invoke(drawableCircle); + for (int i = 0; i < circles.Length; i++) + { + circles[i].StartTime = Time.Current + 1000 + 500 * (i + 1); + circles[i].ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + var drawableCircle = new DrawableHitCircle(circles[i]); + hitObjectContainer.Add(drawableCircle); + followPointRenderer.AddFollowPoints(drawableCircle); + + storeFunc?.Invoke(drawableCircle); + } }); } - private void removeObject(Func func) + private void removeObject(Func getFunc) { AddStep("remove hitobject", () => { - var drawableObject = func?.Invoke(); + var drawableObject = getFunc?.Invoke(); hitObjectContainer.Remove(drawableObject); followPointRenderer.RemoveFollowPoints(drawableObject); From f861d8099c1344c60f67db77ea955ad47c33013e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:13:50 +0900 Subject: [PATCH 127/503] Remove unnecessary class --- .../TestSceneFollowPoints.cs | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 66aea68a3c..ed1d8f5184 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -6,21 +6,17 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using NUnit.Framework; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Skinning; +using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Tests.Visual; using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { @@ -359,38 +355,5 @@ namespace osu.Game.Rulesets.Osu.Tests } } } - - private class FollowPoint : CompositeDrawable - { - private const float width = 8; - - public override bool RemoveWhenNotAlive => false; - - public FollowPoint() - { - Origin = Anchor.Centre; - - InternalChild = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container - { - Masking = true, - AutoSizeAxes = Axes.Both, - CornerRadius = width / 2, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = Color4.White.Opacity(0.2f), - Radius = 4, - }, - Child = new Box - { - Size = new Vector2(width), - Blending = BlendingParameters.Additive, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Alpha = 0.5f, - } - }, confineMode: ConfineMode.NoScaling); - } - } } } From 513ad96adf09130dcc613d9b15d934e257118909 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:15:13 +0900 Subject: [PATCH 128/503] Cleanup property --- .../TestSceneFollowPoints.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index ed1d8f5184..43d6cc9ab9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -268,21 +268,22 @@ namespace osu.Game.Rulesets.Osu.Tests private class FollowPointGroup : CompositeDrawable { + // Todo: These shouldn't be constants private const int spacing = 32; private const double preempt = 800; + /// + /// The which s will exit from. + /// + [NotNull] + public readonly DrawableHitObject Start; + public FollowPointGroup(DrawableHitObject start) { Start = start; RelativeSizeAxes = Axes.Both; } - /// - /// The which s will exit from. - /// - [NotNull] - public DrawableHitObject Start { get; } - private DrawableHitObject end; /// From c0badf1dce9d5a2463f40ce698b431c25ed23852 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:17:51 +0900 Subject: [PATCH 129/503] Type to DrawableOsuHitObject --- .../TestSceneFollowPoints.cs | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 43d6cc9ab9..bb3e6a5044 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -22,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Tests { public class TestSceneFollowPoints : OsuTestScene { - private Container hitObjectContainer; + private Container hitObjectContainer; private FollowPointRenderer followPointRenderer; [SetUp] @@ -30,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Tests { Children = new Drawable[] { - hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, + hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, followPointRenderer = new FollowPointRenderer { RelativeSizeAxes = Axes.Both } }; }); @@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveSingleHitObject() { - DrawableHitObject obj = null; + DrawableOsuHitObject obj = null; addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); removeObject(() => obj); @@ -66,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveEndObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -85,7 +84,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveStartObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -104,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestRemoveMiddleObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -123,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestMoveHitObject() { - var objects = new List(); + var objects = new List(); AddStep("reset", () => objects.Clear()); @@ -136,10 +135,10 @@ namespace osu.Game.Rulesets.Osu.Tests new HitCircle { Position = new Vector2(500, 500) }, }, o => objects.Add(o)); - AddStep("move hitobject", () => ((OsuHitObject)objects[2].HitObject).Position = new Vector2(300, 100)); + AddStep("move hitobject", () => objects[2].HitObject.Position = new Vector2(300, 100)); } - private void addObjects(Func ctorFunc, Action storeFunc = null) + private void addObjects(Func ctorFunc, Action storeFunc = null) { AddStep("add hitobjects", () => { @@ -159,7 +158,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); } - private void removeObject(Func getFunc) + private void removeObject(Func getFunc) { AddStep("remove hitobject", () => { @@ -173,11 +172,11 @@ namespace osu.Game.Rulesets.Osu.Tests private class FollowPointRenderer : CompositeDrawable { /// - /// Adds the s around a . + /// Adds the s around a . /// This includes s leading into , and s exiting . /// - /// The to add s for. - public void AddFollowPoints(DrawableHitObject hitObject) + /// The to add s for. + public void AddFollowPoints(DrawableOsuHitObject hitObject) { var startGroup = new FollowPointGroup(hitObject); AddInternal(startGroup); @@ -205,11 +204,11 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Removes the s around a . + /// Removes the s around a . /// This includes s leading into , and s exiting . /// - /// The to remove s for. - public void RemoveFollowPoints(DrawableHitObject hitObject) + /// The to remove s for. + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) { var groups = findGroups(hitObject); @@ -224,12 +223,12 @@ namespace osu.Game.Rulesets.Osu.Tests } /// - /// Finds the s with as the start and end s. + /// Finds the s with as the start and end s. /// - /// The to find the relevant of. + /// The to find the relevant of. /// A tuple containing the end group (the where is the end of), /// and the start group (the where is the start of). - private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableHitObject hitObject) + private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) { // endGroup startGroup // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 @@ -273,24 +272,24 @@ namespace osu.Game.Rulesets.Osu.Tests private const double preempt = 800; /// - /// The which s will exit from. + /// The which s will exit from. /// [NotNull] - public readonly DrawableHitObject Start; + public readonly DrawableOsuHitObject Start; - public FollowPointGroup(DrawableHitObject start) + public FollowPointGroup(DrawableOsuHitObject start) { Start = start; RelativeSizeAxes = Axes.Both; } - private DrawableHitObject end; + private DrawableOsuHitObject end; /// - /// The which s will enter. + /// The which s will enter. /// [CanBeNull] - public DrawableHitObject End + public DrawableOsuHitObject End { get => end; set @@ -307,8 +306,8 @@ namespace osu.Game.Rulesets.Osu.Tests if (End == null) return; - OsuHitObject osuStart = (OsuHitObject)Start.HitObject; - OsuHitObject osuEnd = (OsuHitObject)End.HitObject; + OsuHitObject osuStart = Start.HitObject; + OsuHitObject osuEnd = End.HitObject; if (osuEnd.NewCombo) return; From e0ba35db755e97abdd33a07db109dbb3ecfff3a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:22:37 +0900 Subject: [PATCH 130/503] Implement binding to hitobjects + refreshing --- .../TestSceneFollowPoints.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index bb3e6a5044..b914a8b29d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -283,6 +283,12 @@ namespace osu.Game.Rulesets.Osu.Tests RelativeSizeAxes = Axes.Both; } + protected override void LoadComplete() + { + base.LoadComplete(); + bindHitObject(Start); + } + private DrawableOsuHitObject end; /// @@ -295,10 +301,19 @@ namespace osu.Game.Rulesets.Osu.Tests set { end = value; + + bindHitObject(end); refreshFollowPoints(); } } + private void bindHitObject(DrawableOsuHitObject drawableObject) + { + drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; + } + private void refreshFollowPoints() { ClearInternal(); From 02a7f92d18375176eee9827e17aa126b708f8106 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:34:13 +0900 Subject: [PATCH 131/503] Allow constructing arbitrary hitobject types --- .../TestSceneFollowPoints.cs | 62 ++++++++++++------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index b914a8b29d..68f37e5d1d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -35,24 +35,24 @@ namespace osu.Game.Rulesets.Osu.Tests }); [Test] - public void TestAddSingleHitObject() + public void TestAddSingleHitCircle() { - addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }); + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); } [Test] - public void TestRemoveSingleHitObject() + public void TestRemoveSingleHitCircle() { DrawableOsuHitObject obj = null; - addObjects(() => new[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); removeObject(() => obj); } [Test] - public void TestAddMultipleHitObjects() + public void TestAddMultipleHitCircles() { - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -63,13 +63,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveEndObject() + public void TestRemoveEndHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -82,13 +82,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveStartObject() + public void TestRemoveStartHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -101,13 +101,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveMiddleObject() + public void TestRemoveMiddleHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -120,13 +120,13 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestMoveHitObject() + public void TestMoveHitCircle() { var objects = new List(); AddStep("reset", () => objects.Clear()); - addObjects(() => new[] + addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) }, new HitCircle { Position = new Vector2(200, 200) }, @@ -138,22 +138,38 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("move hitobject", () => objects[2].HitObject.Position = new Vector2(300, 100)); } - private void addObjects(Func ctorFunc, Action storeFunc = null) + private void addObjects(Func ctorFunc, Action storeFunc = null) { AddStep("add hitobjects", () => { - var circles = ctorFunc(); + var objects = ctorFunc(); - for (int i = 0; i < circles.Length; i++) + for (int i = 0; i < objects.Length; i++) { - circles[i].StartTime = Time.Current + 1000 + 500 * (i + 1); - circles[i].ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + objects[i].StartTime = Time.Current + 1000 + 500 * (i + 1); + objects[i].ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - var drawableCircle = new DrawableHitCircle(circles[i]); - hitObjectContainer.Add(drawableCircle); - followPointRenderer.AddFollowPoints(drawableCircle); + DrawableOsuHitObject drawableObject = null; - storeFunc?.Invoke(drawableCircle); + switch (objects[i]) + { + case HitCircle circle: + drawableObject = new DrawableHitCircle(circle); + break; + + case Slider slider: + drawableObject = new DrawableSlider(slider); + break; + + case Spinner spinner: + drawableObject = new DrawableSpinner(spinner); + break; + } + + hitObjectContainer.Add(drawableObject); + followPointRenderer.AddFollowPoints(drawableObject); + + storeFunc?.Invoke(drawableObject); } }); } From bfe7309964b772d1b5a33aa6ee89be9b5359023f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:34:17 +0900 Subject: [PATCH 132/503] Fix nullref --- osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 68f37e5d1d..9587c721c6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -318,7 +318,9 @@ namespace osu.Game.Rulesets.Osu.Tests { end = value; - bindHitObject(end); + if (end != null) + bindHitObject(end); + refreshFollowPoints(); } } From ddfcda9e029e5385ca8969a58e9aac33d70fc75c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:34:24 +0900 Subject: [PATCH 133/503] Remove abstract ConnectionRenderer class --- .../Connections/ConnectionRenderer.cs | 21 ------------------- .../Connections/FollowPointRenderer.cs | 5 +++-- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- 3 files changed, 4 insertions(+), 24 deletions(-) delete mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs deleted file mode 100644 index 9106f4c7bd..0000000000 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects; -using System.Collections.Generic; - -namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections -{ - /// - /// Connects hit objects visually, for example with follow points. - /// - public abstract class ConnectionRenderer : LifetimeManagementContainer - where T : HitObject - { - /// - /// Hit objects to create connections for - /// - public abstract IEnumerable HitObjects { get; set; } - } -} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index a269b87c75..863ce869aa 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -5,11 +5,12 @@ using System; using System.Collections.Generic; using osuTK; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { - public class FollowPointRenderer : ConnectionRenderer + public class FollowPointRenderer : CompositeDrawable { private int pointDistance = 32; @@ -47,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private IEnumerable hitObjects; - public override IEnumerable HitObjects + public IEnumerable HitObjects { get => hitObjects; set diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 69e53d6eea..cbb29ce387 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.UI { private readonly ApproachCircleProxyContainer approachCircles; private readonly JudgementContainer judgementLayer; - private readonly ConnectionRenderer connectionLayer; + private readonly FollowPointRenderer connectionLayer; public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); From 712253ff50ec387a324cc1a0e10bb3bb948d372c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 15:39:23 +0900 Subject: [PATCH 134/503] Replace follow point renderer with new implementation --- .../TestSceneFollowPoints.cs | 206 ------------------ .../Drawables/Connections/FollowPointGroup.cs | 120 ++++++++++ .../Connections/FollowPointRenderer.cs | 168 +++++++------- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 16 +- 4 files changed, 206 insertions(+), 304 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 9587c721c6..3c447e5009 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -4,13 +4,11 @@ using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; @@ -184,209 +182,5 @@ namespace osu.Game.Rulesets.Osu.Tests followPointRenderer.RemoveFollowPoints(drawableObject); }); } - - private class FollowPointRenderer : CompositeDrawable - { - /// - /// Adds the s around a . - /// This includes s leading into , and s exiting . - /// - /// The to add s for. - public void AddFollowPoints(DrawableOsuHitObject hitObject) - { - var startGroup = new FollowPointGroup(hitObject); - AddInternal(startGroup); - - // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups - int startIndex = IndexOfInternal(startGroup); - - if (startIndex < InternalChildren.Count - 1) - { - // h1 -> -> -> h2 - // hitObject nextGroup - - var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; - startGroup.End = nextGroup.Start; - } - - if (startIndex > 0) - { - // h1 -> -> -> h2 - // prevGroup hitObject - - var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - previousGroup.End = startGroup.Start; - } - } - - /// - /// Removes the s around a . - /// This includes s leading into , and s exiting . - /// - /// The to remove s for. - public void RemoveFollowPoints(DrawableOsuHitObject hitObject) - { - var groups = findGroups(hitObject); - - // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject - RemoveInternal(groups.start); - - if (groups.end != null) - { - // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) - groups.end.End = groups.start.End; - } - } - - /// - /// Finds the s with as the start and end s. - /// - /// The to find the relevant of. - /// A tuple containing the end group (the where is the end of), - /// and the start group (the where is the start of). - private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) - { - // endGroup startGroup - // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 - // hitObject - - FollowPointGroup startGroup = null; // The group which the hitobject is the start in - FollowPointGroup endGroup = null; // The group which the hitobject is the end in - - int startIndex = 0; - - for (; startIndex < InternalChildren.Count; startIndex++) - { - var group = (FollowPointGroup)InternalChildren[startIndex]; - - if (group.Start == hitObject) - { - startGroup = group; - break; - } - } - - if (startIndex > 0) - endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - - return (startGroup, endGroup); - } - - protected override int Compare(Drawable x, Drawable y) - { - var groupX = (FollowPointGroup)x; - var groupY = (FollowPointGroup)y; - - return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); - } - } - - private class FollowPointGroup : CompositeDrawable - { - // Todo: These shouldn't be constants - private const int spacing = 32; - private const double preempt = 800; - - /// - /// The which s will exit from. - /// - [NotNull] - public readonly DrawableOsuHitObject Start; - - public FollowPointGroup(DrawableOsuHitObject start) - { - Start = start; - RelativeSizeAxes = Axes.Both; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - bindHitObject(Start); - } - - private DrawableOsuHitObject end; - - /// - /// The which s will enter. - /// - [CanBeNull] - public DrawableOsuHitObject End - { - get => end; - set - { - end = value; - - if (end != null) - bindHitObject(end); - - refreshFollowPoints(); - } - } - - private void bindHitObject(DrawableOsuHitObject drawableObject) - { - drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; - } - - private void refreshFollowPoints() - { - ClearInternal(); - - if (End == null) - return; - - OsuHitObject osuStart = Start.HitObject; - OsuHitObject osuEnd = End.HitObject; - - if (osuEnd.NewCombo) - return; - - if (osuStart is Spinner || osuEnd is Spinner) - return; - - Vector2 startPosition = osuStart.EndPosition; - Vector2 endPosition = osuEnd.Position; - double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; - double endTime = osuEnd.StartTime; - - Vector2 distanceVector = endPosition - startPosition; - int distance = (int)distanceVector.Length; - float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); - double duration = endTime - startTime; - - for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) - { - float fraction = (float)d / distance; - Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; - Vector2 pointEndPosition = startPosition + fraction * distanceVector; - double fadeOutTime = startTime + fraction * duration; - double fadeInTime = fadeOutTime - preempt; - - FollowPoint fp; - - AddInternal(fp = new FollowPoint - { - Position = pointStartPosition, - Rotation = rotation, - Alpha = 0, - Scale = new Vector2(1.5f * osuEnd.Scale), - }); - - using (fp.BeginAbsoluteSequence(fadeInTime)) - { - fp.FadeIn(osuEnd.TimeFadeIn); - fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); - fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); - } - - fp.Expire(true); - } - } - } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs new file mode 100644 index 0000000000..06aadcc342 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -0,0 +1,120 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using JetBrains.Annotations; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Types; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections +{ + public class FollowPointGroup : CompositeDrawable + { + // Todo: These shouldn't be constants + private const int spacing = 32; + private const double preempt = 800; + + /// + /// The which s will exit from. + /// + [NotNull] + public readonly DrawableOsuHitObject Start; + + public FollowPointGroup(DrawableOsuHitObject start) + { + Start = start; + RelativeSizeAxes = Axes.Both; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + bindHitObject(Start); + } + + private DrawableOsuHitObject end; + + /// + /// The which s will enter. + /// + [CanBeNull] + public DrawableOsuHitObject End + { + get => end; + set + { + end = value; + + if (end != null) + bindHitObject(end); + + refreshFollowPoints(); + } + } + + private void bindHitObject(DrawableOsuHitObject drawableObject) + { + drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); + drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; + } + + private void refreshFollowPoints() + { + ClearInternal(); + + if (End == null) + return; + + OsuHitObject osuStart = Start.HitObject; + OsuHitObject osuEnd = End.HitObject; + + if (osuEnd.NewCombo) + return; + + if (osuStart is Spinner || osuEnd is Spinner) + return; + + Vector2 startPosition = osuStart.EndPosition; + Vector2 endPosition = osuEnd.Position; + double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; + double endTime = osuEnd.StartTime; + + Vector2 distanceVector = endPosition - startPosition; + int distance = (int)distanceVector.Length; + float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); + double duration = endTime - startTime; + + for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) + { + float fraction = (float)d / distance; + Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; + Vector2 pointEndPosition = startPosition + fraction * distanceVector; + double fadeOutTime = startTime + fraction * duration; + double fadeInTime = fadeOutTime - preempt; + + FollowPoint fp; + + AddInternal(fp = new FollowPoint + { + Position = pointStartPosition, + Rotation = rotation, + Alpha = 0, + Scale = new Vector2(1.5f * osuEnd.Scale), + }); + + using (fp.BeginAbsoluteSequence(fadeInTime)) + { + fp.FadeIn(osuEnd.TimeFadeIn); + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); + fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); + } + + fp.Expire(true); + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 863ce869aa..47c35746f0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -1,122 +1,104 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; -using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPointRenderer : CompositeDrawable { - private int pointDistance = 32; + /// + /// Adds the s around a . + /// This includes s leading into , and s exiting . + /// + /// The to add s for. + public void AddFollowPoints(DrawableOsuHitObject hitObject) + { + var startGroup = new FollowPointGroup(hitObject); + AddInternal(startGroup); + + // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups + int startIndex = IndexOfInternal(startGroup); + + if (startIndex < InternalChildren.Count - 1) + { + // h1 -> -> -> h2 + // hitObject nextGroup + + var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; + startGroup.End = nextGroup.Start; + } + + if (startIndex > 0) + { + // h1 -> -> -> h2 + // prevGroup hitObject + + var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + previousGroup.End = startGroup.Start; + } + } /// - /// Determines how much space there is between points. + /// Removes the s around a . + /// This includes s leading into , and s exiting . /// - public int PointDistance + /// The to remove s for. + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) { - get => pointDistance; - set - { - if (pointDistance == value) return; + var groups = findGroups(hitObject); - pointDistance = value; - update(); + // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject + RemoveInternal(groups.start); + + if (groups.end != null) + { + // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) + groups.end.End = groups.start.End; } } - private int preEmpt = 800; - /// - /// Follow points to the next hitobject start appearing for this many milliseconds before an hitobject's end time. + /// Finds the s with as the start and end s. /// - public int PreEmpt + /// The to find the relevant of. + /// A tuple containing the end group (the where is the end of), + /// and the start group (the where is the start of). + private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) { - get => preEmpt; - set + // endGroup startGroup + // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 + // hitObject + + FollowPointGroup startGroup = null; // The group which the hitobject is the start in + FollowPointGroup endGroup = null; // The group which the hitobject is the end in + + int startIndex = 0; + + for (; startIndex < InternalChildren.Count; startIndex++) { - if (preEmpt == value) return; + var group = (FollowPointGroup)InternalChildren[startIndex]; - preEmpt = value; - update(); - } - } - - private IEnumerable hitObjects; - - public IEnumerable HitObjects - { - get => hitObjects; - set - { - hitObjects = value; - update(); - } - } - - public override bool RemoveCompletedTransforms => false; - - private void update() - { - ClearInternal(); - - if (hitObjects == null) - return; - - OsuHitObject prevHitObject = null; - - foreach (var currHitObject in hitObjects) - { - if (prevHitObject != null && !currHitObject.NewCombo && !(prevHitObject is Spinner) && !(currHitObject is Spinner)) + if (group.Start == hitObject) { - Vector2 startPosition = prevHitObject.EndPosition; - Vector2 endPosition = currHitObject.Position; - double startTime = (prevHitObject as IHasEndTime)?.EndTime ?? prevHitObject.StartTime; - double endTime = currHitObject.StartTime; - - Vector2 distanceVector = endPosition - startPosition; - int distance = (int)distanceVector.Length; - float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); - double duration = endTime - startTime; - - for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance) - { - float fraction = (float)d / distance; - Vector2 pointStartPosition = startPosition + (fraction - 0.1f) * distanceVector; - Vector2 pointEndPosition = startPosition + fraction * distanceVector; - double fadeOutTime = startTime + fraction * duration; - double fadeInTime = fadeOutTime - PreEmpt; - - FollowPoint fp; - - AddInternal(fp = new FollowPoint - { - Position = pointStartPosition, - Rotation = rotation, - Alpha = 0, - Scale = new Vector2(1.5f * currHitObject.Scale), - }); - - using (fp.BeginAbsoluteSequence(fadeInTime)) - { - fp.FadeIn(currHitObject.TimeFadeIn); - fp.ScaleTo(currHitObject.Scale, currHitObject.TimeFadeIn, Easing.Out); - - fp.MoveTo(pointEndPosition, currHitObject.TimeFadeIn, Easing.Out); - - fp.Delay(fadeOutTime - fadeInTime).FadeOut(currHitObject.TimeFadeIn); - } - - fp.Expire(true); - } + startGroup = group; + break; } - - prevHitObject = currHitObject; } + + if (startIndex > 0) + endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; + + return (startGroup, endGroup); + } + + protected override int Compare(Drawable x, Drawable y) + { + var groupX = (FollowPointGroup)x; + var groupY = (FollowPointGroup)y; + + return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index cbb29ce387..6d1ea4bbfc 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Rulesets.UI; -using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Skinning; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.UI { private readonly ApproachCircleProxyContainer approachCircles; private readonly JudgementContainer judgementLayer; - private readonly FollowPointRenderer connectionLayer; + private readonly FollowPointRenderer followPoints; public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); @@ -30,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.UI { InternalChildren = new Drawable[] { - connectionLayer = new FollowPointRenderer + followPoints = new FollowPointRenderer { RelativeSizeAxes = Axes.Both, Depth = 2, @@ -64,11 +63,18 @@ namespace osu.Game.Rulesets.Osu.UI }; base.Add(h); + + followPoints.AddFollowPoints((DrawableOsuHitObject)h); } - public override void PostProcess() + public override bool Remove(DrawableHitObject h) { - connectionLayer.HitObjects = HitObjectContainer.Objects.Select(d => d.HitObject).OfType(); + bool result = base.Remove(h); + + if (result) + followPoints.RemoveFollowPoints((DrawableOsuHitObject)h); + + return result; } private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) From a19e26f8aa6c8d1bbb5bf80c499704cb14f6f729 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 19:21:39 +0900 Subject: [PATCH 135/503] Improve performance of refreshes --- .../Drawables/Connections/FollowPointGroup.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 06aadcc342..750e9559fc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections protected override void LoadComplete() { base.LoadComplete(); - bindHitObject(Start); + bindEvents(Start); } private DrawableOsuHitObject end; @@ -48,20 +48,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections end = value; if (end != null) - bindHitObject(end); + bindEvents(end); - refreshFollowPoints(); + refresh(); } } - private void bindHitObject(DrawableOsuHitObject drawableObject) + private void bindEvents(DrawableOsuHitObject drawableObject) { - drawableObject.HitObject.StartTimeBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.PositionBindable.BindValueChanged(_ => refreshFollowPoints()); - drawableObject.HitObject.DefaultsApplied += refreshFollowPoints; + drawableObject.HitObject.PositionBindable.BindValueChanged(_ => scheduleRefresh()); + drawableObject.HitObject.DefaultsApplied += scheduleRefresh; } - private void refreshFollowPoints() + private void scheduleRefresh() => Scheduler.AddOnce(refresh); + + private void refresh() { ClearInternal(); From 3b6064336b63f6bd00f7bdee699cb6dae2903279 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 19:22:07 +0900 Subject: [PATCH 136/503] Implement group re-ordering based on start time --- .../Drawables/Connections/FollowPointGroup.cs | 12 +- .../Connections/FollowPointRenderer.cs | 115 ++++++++---------- 2 files changed, 65 insertions(+), 62 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 750e9559fc..79d69acd67 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -3,6 +3,7 @@ using System; using JetBrains.Annotations; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Types; @@ -16,16 +17,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private const int spacing = 32; private const double preempt = 800; + public readonly Bindable StartTime = new Bindable(); + /// /// The which s will exit from. /// [NotNull] public readonly DrawableOsuHitObject Start; - public FollowPointGroup(DrawableOsuHitObject start) + /// + /// Creates a new . + /// + /// The which s will exit from. + public FollowPointGroup([NotNull] DrawableOsuHitObject start) { Start = start; + RelativeSizeAxes = Axes.Both; + + StartTime.BindTo(Start.HitObject.StartTimeBindable); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 47c35746f0..892442f0a7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,97 +11,87 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPointRenderer : CompositeDrawable { + private readonly List groups = new List(); + /// /// Adds the s around a . /// This includes s leading into , and s exiting . /// /// The to add s for. public void AddFollowPoints(DrawableOsuHitObject hitObject) - { - var startGroup = new FollowPointGroup(hitObject); - AddInternal(startGroup); - - // Groups are sorted by their start time when added, so the index can be used to post-process other surrounding groups - int startIndex = IndexOfInternal(startGroup); - - if (startIndex < InternalChildren.Count - 1) - { - // h1 -> -> -> h2 - // hitObject nextGroup - - var nextGroup = (FollowPointGroup)InternalChildren[startIndex + 1]; - startGroup.End = nextGroup.Start; - } - - if (startIndex > 0) - { - // h1 -> -> -> h2 - // prevGroup hitObject - - var previousGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - previousGroup.End = startGroup.Start; - } - } + => addGroup(new FollowPointGroup(hitObject).With(g => g.StartTime.BindValueChanged(_ => onStartTimeChanged(g)))); /// /// Removes the s around a . /// This includes s leading into , and s exiting . /// /// The to remove s for. - public void RemoveFollowPoints(DrawableOsuHitObject hitObject) + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) => removeGroup(groups.Single(g => g.Start == hitObject)); + + /// + /// Adds a to this . + /// + /// The to add. + /// The index of in . + private int addGroup(FollowPointGroup group) { - var groups = findGroups(hitObject); + AddInternal(group); - // Regardless of the position of the hitobject in the beatmap, there will always be a group leading from the hitobject - RemoveInternal(groups.start); + // Groups are sorted by their start time when added such that the index can be used to post-process other surrounding groups + int index = groups.AddInPlace(group, Comparer.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value))); - if (groups.end != null) + if (index < groups.Count - 1) { - // When there were two groups referencing the same hitobject, merge them by updating the end group to point to the new end (the start group was already removed) - groups.end.End = groups.start.End; + // Update the group's end point to the next hitobject + // h1 -> -> -> h2 + // hitObject nextGroup + + FollowPointGroup nextGroup = groups[index + 1]; + group.End = nextGroup.Start; } + + if (index > 0) + { + // Previous group's end point to the current group's start point + // h1 -> -> -> h2 + // prevGroup hitObject + + FollowPointGroup previousGroup = groups[index - 1]; + previousGroup.End = group.Start; + } + + return index; } /// - /// Finds the s with as the start and end s. + /// Removes a from this . /// - /// The to find the relevant of. - /// A tuple containing the end group (the where is the end of), - /// and the start group (the where is the start of). - private (FollowPointGroup start, FollowPointGroup end) findGroups(DrawableOsuHitObject hitObject) + /// The to remove. + /// Whether was removed. + private bool removeGroup(FollowPointGroup group) { - // endGroup startGroup - // h1 -> -> -> -> -> h2 -> -> -> -> -> h3 - // hitObject + RemoveInternal(group); - FollowPointGroup startGroup = null; // The group which the hitobject is the start in - FollowPointGroup endGroup = null; // The group which the hitobject is the end in + int index = groups.IndexOf(group); - int startIndex = 0; - - for (; startIndex < InternalChildren.Count; startIndex++) + if (index > 0) { - var group = (FollowPointGroup)InternalChildren[startIndex]; - - if (group.Start == hitObject) - { - startGroup = group; - break; - } + // Update the previous group's end point to the next group's start point + // h1 -> -> -> h2 -> -> -> h3 + // prevGroup group nextGroup + // The current group's end point is used since there may not be a next group + FollowPointGroup previousGroup = groups[index - 1]; + previousGroup.End = group.End; } - if (startIndex > 0) - endGroup = (FollowPointGroup)InternalChildren[startIndex - 1]; - - return (startGroup, endGroup); + return groups.Remove(group); } - protected override int Compare(Drawable x, Drawable y) + private void onStartTimeChanged(FollowPointGroup group) { - var groupX = (FollowPointGroup)x; - var groupY = (FollowPointGroup)y; - - return groupX.Start.HitObject.StartTime.CompareTo(groupY.Start.HitObject.StartTime); + // Naive but can be improved if performance becomes problematic + removeGroup(group); + addGroup(group); } } } From 1ef2b81041dfd9225ffb7e792b8c55bfa76d6ff1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 1 Nov 2019 22:08:50 +0900 Subject: [PATCH 137/503] Fix follow point lifetime not being updated correctly --- .../Drawables/Connections/FollowPointGroup.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 79d69acd67..47196f4893 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -118,13 +118,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { - fp.FadeIn(osuEnd.TimeFadeIn); - fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); - fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); - } + // See: Expire calls are separated due to https://github.com/ppy/osu-framework/issues/2941 - fp.Expire(true); + fp.FadeIn(osuEnd.TimeFadeIn).Expire(true); + + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out) + .MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out) + .Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn) + .Expire(); + } } } } From f77de7d88013f30bd3567b4af2f7d223029b50e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 18:25:38 +0900 Subject: [PATCH 138/503] Simplify implementation --- .../Compose/Components/BlueprintContainer.cs | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 7a3a303ff3..02dd60eac1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -254,31 +254,19 @@ namespace osu.Game.Screens.Edit.Compose.Components { Debug.Assert(!clickSelectionBegan); - bool hoveringSelected = false; + // If a select blueprint is already hovered, disallow changes in selection. + if (selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) + return; - // Make sure any already-selected blueprints aren't being hovered over - foreach (SelectionBlueprint selected in selectionHandler.SelectedBlueprints) + foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) { - if (selected.IsHovered) + if (blueprint.IsHovered) { - hoveringSelected = true; + selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); + clickSelectionBegan = true; break; } } - - // Attempt a new selection at the mouse position - if (!hoveringSelected) - { - foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) - { - if (blueprint.IsHovered) - { - selectionHandler.HandleSelectionRequested(blueprint, e.CurrentState); - clickSelectionBegan = true; - break; - } - } - } } /// From f4b93ec9438f49d852bb7172ad3a6b8c368fd5d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 5 Nov 2019 18:29:08 +0900 Subject: [PATCH 139/503] Add exception when holding control --- .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 02dd60eac1..288c712bde 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -255,7 +255,9 @@ namespace osu.Game.Screens.Edit.Compose.Components Debug.Assert(!clickSelectionBegan); // If a select blueprint is already hovered, disallow changes in selection. - if (selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) + // Exception is made when holding control, as deselection should still be allowed. + if (!e.CurrentState.Keyboard.ControlPressed && + selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) return; foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) From 6c58faf30cab3f8f36d2b8d77621f0bca2529f1a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 19:31:48 +0900 Subject: [PATCH 140/503] Fix group ends potentially not being updated correctly --- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 892442f0a7..e29cf6e128 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -49,6 +49,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections FollowPointGroup nextGroup = groups[index + 1]; group.End = nextGroup.Start; } + else + group.End = null; if (index > 0) { From f2118b0eba6fa022023ef453b11b9ed61dcf2580 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 19:31:58 +0900 Subject: [PATCH 141/503] Add automated test cases --- .../TestSceneFollowPoints.cs | 178 +++++++++++------- .../Connections/FollowPointRenderer.cs | 2 + 2 files changed, 113 insertions(+), 67 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 3c447e5009..aac0119dc7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -27,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Tests { Children = new Drawable[] { - hitObjectContainer = new Container { RelativeSizeAxes = Axes.Both }, + hitObjectContainer = new TestHitObjectContainer { RelativeSizeAxes = Axes.Both }, followPointRenderer = new FollowPointRenderer { RelativeSizeAxes = Axes.Both } }; }); @@ -35,108 +33,97 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestAddSingleHitCircle() { - addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); + addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); + + assertGroups(); } [Test] public void TestRemoveSingleHitCircle() { - DrawableOsuHitObject obj = null; + addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); - addObjects(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }, o => obj = o); - removeObject(() => obj); + removeObjectStep(() => getObject(0)); + + assertGroups(); } [Test] public void TestAddMultipleHitCircles() { - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }); + addMultipleObjectsStep(); + + assertGroups(); } [Test] public void TestRemoveEndHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + removeObjectStep(() => getObject(4)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - removeObject(() => objects.Last()); + assertGroups(); } [Test] public void TestRemoveStartHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + removeObjectStep(() => getObject(0)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - removeObject(() => objects.First()); + assertGroups(); } [Test] public void TestRemoveMiddleHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + removeObjectStep(() => getObject(2)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - removeObject(() => objects[2]); + assertGroups(); } [Test] public void TestMoveHitCircle() { - var objects = new List(); + addMultipleObjectsStep(); - AddStep("reset", () => objects.Clear()); + AddStep("move hitobject", () => getObject(2).HitObject.Position = new Vector2(300, 100)); - addObjects(() => new OsuHitObject[] - { - new HitCircle { Position = new Vector2(100, 100) }, - new HitCircle { Position = new Vector2(200, 200) }, - new HitCircle { Position = new Vector2(300, 300) }, - new HitCircle { Position = new Vector2(400, 400) }, - new HitCircle { Position = new Vector2(500, 500) }, - }, o => objects.Add(o)); - - AddStep("move hitobject", () => objects[2].HitObject.Position = new Vector2(300, 100)); + assertGroups(); } - private void addObjects(Func ctorFunc, Action storeFunc = null) + [TestCase(0, 0)] // Start -> Start + [TestCase(0, 2)] // Start -> Middle + [TestCase(0, 5)] // Start -> End + [TestCase(2, 0)] // Middle -> Start + [TestCase(1, 3)] // Middle -> Middle (forwards) + [TestCase(3, 1)] // Middle -> Middle (backwards) + [TestCase(4, 0)] // End -> Start + [TestCase(4, 2)] // End -> Middle + [TestCase(4, 4)] // End -> End + public void TestReorderHitObjects(int startIndex, int endIndex) + { + addMultipleObjectsStep(); + + reorderObjectStep(startIndex, endIndex); + + assertGroups(); + } + + private void addMultipleObjectsStep() => addObjectsStep(() => new OsuHitObject[] + { + new HitCircle { Position = new Vector2(100, 100) }, + new HitCircle { Position = new Vector2(200, 200) }, + new HitCircle { Position = new Vector2(300, 300) }, + new HitCircle { Position = new Vector2(400, 400) }, + new HitCircle { Position = new Vector2(500, 500) }, + }); + + private void addObjectsStep(Func ctorFunc) { AddStep("add hitobjects", () => { @@ -166,13 +153,11 @@ namespace osu.Game.Rulesets.Osu.Tests hitObjectContainer.Add(drawableObject); followPointRenderer.AddFollowPoints(drawableObject); - - storeFunc?.Invoke(drawableObject); } }); } - private void removeObject(Func getFunc) + private void removeObjectStep(Func getFunc) { AddStep("remove hitobject", () => { @@ -182,5 +167,64 @@ namespace osu.Game.Rulesets.Osu.Tests followPointRenderer.RemoveFollowPoints(drawableObject); }); } + + private void reorderObjectStep(int startIndex, int endIndex) + { + AddStep($"move object {startIndex} to {endIndex}", () => + { + DrawableOsuHitObject toReorder = getObject(startIndex); + + double targetTime; + if (endIndex < hitObjectContainer.Count) + targetTime = getObject(endIndex).HitObject.StartTime - 1; + else + targetTime = getObject(hitObjectContainer.Count - 1).HitObject.StartTime + 1; + + hitObjectContainer.Remove(toReorder); + toReorder.HitObject.StartTime = targetTime; + hitObjectContainer.Add(toReorder); + }); + } + + private void assertGroups() + { + AddAssert("has correct group count", () => followPointRenderer.Groups.Count == hitObjectContainer.Count); + AddAssert("group endpoints are correct", () => + { + for (int i = 0; i < hitObjectContainer.Count; i++) + { + DrawableOsuHitObject expectedStart = getObject(i); + DrawableOsuHitObject expectedEnd = i < hitObjectContainer.Count - 1 ? getObject(i + 1) : null; + + if (getGroup(i).Start != expectedStart) + throw new AssertionException($"Object {i} expected to be the start of group {i}."); + + if (getGroup(i).End != expectedEnd) + throw new AssertionException($"Object {(expectedEnd == null ? "null" : i.ToString())} expected to be the end of group {i}."); + } + + return true; + }); + } + + private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index]; + + private FollowPointGroup getGroup(int index) => followPointRenderer.Groups[index]; + + private class TestHitObjectContainer : Container + { + protected override int Compare(Drawable x, Drawable y) + { + var osuX = (DrawableOsuHitObject)x; + var osuY = (DrawableOsuHitObject)y; + + int compare = osuX.HitObject.StartTime.CompareTo(osuY.HitObject.StartTime); + + if (compare == 0) + return base.Compare(x, y); + + return compare; + } + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index e29cf6e128..e5e8efae8e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPointRenderer : CompositeDrawable { + internal IReadOnlyList Groups => groups; + private readonly List groups = new List(); /// From d0286037696594660cc0641d94e68ca616ba9bdf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 22:50:01 +0900 Subject: [PATCH 142/503] Rename tests --- .../TestSceneFollowPoints.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index aac0119dc7..79a1bb579f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests }); [Test] - public void TestAddSingleHitCircle() + public void TestAddObject() { addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveSingleHitCircle() + public void TestRemoveObject() { addObjectsStep(() => new OsuHitObject[] { new HitCircle { Position = new Vector2(100, 100) } }); @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestAddMultipleHitCircles() + public void TestAddMultipleObjects() { addMultipleObjectsStep(); @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveEndHitCircle() + public void TestRemoveEndObject() { addMultipleObjectsStep(); @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveStartHitCircle() + public void TestRemoveStartObject() { addMultipleObjectsStep(); @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestRemoveMiddleHitCircle() + public void TestRemoveMiddleObject() { addMultipleObjectsStep(); @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.Tests } [Test] - public void TestMoveHitCircle() + public void TestMoveObject() { addMultipleObjectsStep(); @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.Tests [TestCase(4, 0)] // End -> Start [TestCase(4, 2)] // End -> Middle [TestCase(4, 4)] // End -> End - public void TestReorderHitObjects(int startIndex, int endIndex) + public void TestReorderObjects(int startIndex, int endIndex) { addMultipleObjectsStep(); From 68a81e0eb0f813fc3710ea09aa273d75ac2b8671 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 22:50:21 +0900 Subject: [PATCH 143/503] Fix follow point transforms not working after rewind --- .../Objects/Drawables/Connections/FollowPoint.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 89ffddf4cb..7ba044b462 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections public override bool RemoveWhenNotAlive => false; + public override bool RemoveCompletedTransforms => false; + public FollowPoint() { Origin = Anchor.Centre; From d762ec959c9240594a46ba2228095fea4b7e10ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 22:50:38 +0900 Subject: [PATCH 144/503] Schedule group refresh when loaded --- .../Objects/Drawables/Connections/FollowPointGroup.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 47196f4893..c77ecd355f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -60,7 +60,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections if (end != null) bindEvents(end); - refresh(); + if (IsLoaded) + scheduleRefresh(); + else + refresh(); } } From 0a2af2b0fe067b3caece643b1acbdc29b427a823 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 23:02:39 +0900 Subject: [PATCH 145/503] Apply transform override at a higher level --- .../Objects/Drawables/Connections/FollowPoint.cs | 2 -- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 7ba044b462..89ffddf4cb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -18,8 +18,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections public override bool RemoveWhenNotAlive => false; - public override bool RemoveCompletedTransforms => false; - public FollowPoint() { Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index e5e8efae8e..aa9ec8d96d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -15,6 +15,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private readonly List groups = new List(); + public override bool RemoveCompletedTransforms => false; + /// /// Adds the s around a . /// This includes s leading into , and s exiting . From aff275ea21784999ca29e37a695da2df430332a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 23:03:05 +0900 Subject: [PATCH 146/503] Revert "Fix follow point lifetime not being updated correctly" This reverts commit 1ef2b81041dfd9225ffb7e792b8c55bfa76d6ff1. --- .../Drawables/Connections/FollowPointGroup.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index c77ecd355f..9d651373ff 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -121,15 +121,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { - // See: Expire calls are separated due to https://github.com/ppy/osu-framework/issues/2941 - - fp.FadeIn(osuEnd.TimeFadeIn).Expire(true); - - fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out) - .MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out) - .Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn) - .Expire(); + fp.FadeIn(osuEnd.TimeFadeIn); + fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); + fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); } + + fp.Expire(true); } } } From 68ca5cb26a6b1f0d56ba258c0edb29afb808c646 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 5 Nov 2019 23:20:46 +0900 Subject: [PATCH 147/503] Adjust comments --- .../Drawables/Connections/FollowPoint.cs | 3 +++ .../Drawables/Connections/FollowPointGroup.cs | 6 ++++++ .../Connections/FollowPointRenderer.cs | 19 ++++++++++++++----- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 89ffddf4cb..db34ae1d87 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -12,6 +12,9 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { + /// + /// A single follow point positioned between two adjacent s. + /// public class FollowPoint : Container { private const float width = 8; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs index 9d651373ff..168d2b8532 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs @@ -11,12 +11,18 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { + /// + /// Visualises the s between two s. + /// public class FollowPointGroup : CompositeDrawable { // Todo: These shouldn't be constants private const int spacing = 32; private const double preempt = 800; + /// + /// The start time of . + /// public readonly Bindable StartTime = new Bindable(); /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index aa9ec8d96d..afd86e004d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -9,8 +9,14 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { + /// + /// Visualises groups of s. + /// public class FollowPointRenderer : CompositeDrawable { + /// + /// All the s contained by this . + /// internal IReadOnlyList Groups => groups; private readonly List groups = new List(); @@ -46,21 +52,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections if (index < groups.Count - 1) { - // Update the group's end point to the next hitobject + // Update the group's end point to the next group's start point // h1 -> -> -> h2 - // hitObject nextGroup + // group nextGroup FollowPointGroup nextGroup = groups[index + 1]; group.End = nextGroup.Start; } else + { + // The end point may be non-null during re-ordering group.End = null; + } if (index > 0) { - // Previous group's end point to the current group's start point + // Update the previous group's end point to the current group's start point // h1 -> -> -> h2 - // prevGroup hitObject + // prevGroup group FollowPointGroup previousGroup = groups[index - 1]; previousGroup.End = group.Start; @@ -95,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private void onStartTimeChanged(FollowPointGroup group) { - // Naive but can be improved if performance becomes problematic + // Naive but can be improved if performance becomes an issue removeGroup(group); addGroup(group); } From 1f40641d05cc9a1da02d00eaf4ba14a30c367299 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 10:32:09 +0900 Subject: [PATCH 148/503] Add failing test --- osu.Game.Tests/Visual/Gameplay/TestScenePause.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 64022b2410..6e8975f11b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -237,6 +237,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player not exited", () => Player.IsCurrentScreen()); AddStep("exit", () => Player.Exit()); confirmExited(); + confirmNoTrackAdjustments(); } private void confirmPaused() @@ -258,6 +259,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player exited", () => !Player.IsCurrentScreen()); } + private void confirmNoTrackAdjustments() + { + AddAssert("track has no adjustments", () => Beatmap.Value.Track.AggregateFrequency.Value == 1); + } + private void restart() => AddStep("restart", () => Player.Restart()); private void pause() => AddStep("pause", () => Player.Pause()); private void resume() => AddStep("resume", () => Player.Resume()); From cd1dd0f8981d2ed7c5c03b67d401ebc1ec0b4a62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 10:38:04 +0900 Subject: [PATCH 149/503] Fix adjustments not being removed correctly on retry from pause --- osu.Game/Screens/Play/GameplayClockContainer.cs | 16 ++++++++++------ osu.Game/Screens/Play/Player.cs | 2 -- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index f2efbe6073..2f2028ff53 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -162,16 +162,12 @@ namespace osu.Game.Screens.Play if (sourceClock != beatmap.Track) return; + removeSourceClockAdjustments(); + sourceClock = new TrackVirtual(beatmap.Track.Length); adjustableClock.ChangeSource(sourceClock); } - public void ResetLocalAdjustments() - { - // In the case of replays, we may have changed the playback rate. - UserPlaybackRate.Value = 1; - } - protected override void Update() { if (!IsPaused.Value) @@ -198,6 +194,14 @@ namespace osu.Game.Screens.Play protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); + + removeSourceClockAdjustments(); + sourceClock = null; + } + + private void removeSourceClockAdjustments() + { + sourceClock.ResetSpeedAdjustments(); (sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust); } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a3c39d9cc1..a9b0649fab 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -536,8 +536,6 @@ namespace osu.Game.Screens.Play return true; } - GameplayClockContainer.ResetLocalAdjustments(); - // GameplayClockContainer performs seeks / start / stop operations on the beatmap's track. // as we are no longer the current screen, we cannot guarantee the track is still usable. GameplayClockContainer.StopUsingBeatmapClock(); From 892ef017ef3b85ba184e35202a3eb14f59a51c09 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2019 03:05:03 +0000 Subject: [PATCH 150/503] Bump ppy.osu.Framework.iOS from 2019.1029.0 to 2019.1106.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.1029.0 to 2019.1106.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.1029.0...2019.1106.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 719aced705..d257948831 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 1d83f51a804f9a0972455433666f42219ed057c9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2019 03:05:05 +0000 Subject: [PATCH 151/503] Bump ppy.osu.Framework.Android from 2019.1029.0 to 2019.1106.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.1029.0 to 2019.1106.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.1029.0...2019.1106.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 8b31be3f12..d1860acbf9 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + From 8cf349c1eefa1996a1d5f9446181150bcf574ae8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 12:10:53 +0900 Subject: [PATCH 152/503] Update once more --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 42b930b1af..dbe6559c40 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + From f20bfe7a554849d6d1fc762741e0fd4f084a4e07 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:16:48 +0900 Subject: [PATCH 153/503] Fix extra semicolon --- osu.Game/Screens/Edit/Timing/DifficultySection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index bd363c3158..cd33425ee5 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier::0.##}x"; }); + ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier:0.##}x"; }); } protected override DifficultyControlPoint CreatePoint() From 9dd7f997d2c01836a43ad9630261e095e14a8c36 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:17:18 +0900 Subject: [PATCH 154/503] Reoder SampleSection to match others --- osu.Game/Screens/Edit/Timing/SampleSection.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index 0477ad4e78..e665db0a4d 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -22,17 +22,6 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override SampleControlPoint CreatePoint() - { - var reference = Beatmap.Value.Beatmap.ControlPointInfo.SamplePointAt(SelectedGroup.Value.Time); - - return new SampleControlPoint - { - SampleBank = reference.SampleBank, - SampleVolume = reference.SampleVolume, - }; - } - protected override void LoadComplete() { base.LoadComplete(); @@ -43,5 +32,16 @@ namespace osu.Game.Screens.Edit.Timing volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; }); } + + protected override SampleControlPoint CreatePoint() + { + var reference = Beatmap.Value.Beatmap.ControlPointInfo.SamplePointAt(SelectedGroup.Value.Time); + + return new SampleControlPoint + { + SampleBank = reference.SampleBank, + SampleVolume = reference.SampleVolume, + }; + } } } From 7cd4cb8a935c797fd0d977198b99f7515bc225e8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:32:12 +0900 Subject: [PATCH 155/503] Rename selectedPoints to selectedGroup --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 6ae01e056f..9317448262 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Edit.Timing public class TimingScreen : EditorScreenWithTimeline { [Cached] - private Bindable selectedPoints = new Bindable(); + private Bindable selectedGroup = new Bindable(); [Resolved] private IAdjustableClock clock { get; set; } @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedPoints.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); + selectedGroup.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); } public class ControlPointList : CompositeDrawable From 322a1f0a860eff545c166426e026f14da48437f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 12:45:35 +0900 Subject: [PATCH 156/503] Fix potential nullref --- osu.Game/Screens/Edit/Timing/TimingScreen.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index 9317448262..d9da3ff92d 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -47,7 +47,11 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedGroup.BindValueChanged(selected => { clock.Seek(selected.NewValue.Time); }); + selectedGroup.BindValueChanged(selected => + { + if (selected.NewValue != null) + clock.Seek(selected.NewValue.Time); + }); } public class ControlPointList : CompositeDrawable From 4ce3450cfc6a003c3ff220d6f57cd566d49613f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 14:08:52 +0900 Subject: [PATCH 157/503] Move button implementation to OsuButton --- .../Editor/TestSceneEditorComposeTimeline.cs | 4 +- osu.Game/Graphics/UserInterface/OsuButton.cs | 106 ++++++++++++++---- osu.Game/Overlays/Settings/SidebarButton.cs | 28 +---- osu.Game/Overlays/SettingsPanel.cs | 4 +- 4 files changed, 87 insertions(+), 55 deletions(-) diff --git a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs index b6b2b2f92d..6e5b3b93e9 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneEditorComposeTimeline.cs @@ -10,9 +10,9 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; using osuTK.Graphics; @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.Editor } } - private class StartStopButton : BasicButton + private class StartStopButton : OsuButton { private IAdjustableClock adjustableClock; private bool started; diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 319c3dd0b4..2750e61f0d 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; @@ -17,55 +19,106 @@ namespace osu.Game.Graphics.UserInterface /// /// A button with added default sound effects. /// - public class OsuButton : BasicButton + public class OsuButton : Button { - private Box hover; + public string Text + { + get => SpriteText?.Text; + set + { + if (SpriteText != null) + SpriteText.Text = value; + } + } + + private Color4? backgroundColour; + + public Color4 BackgroundColour + { + set + { + backgroundColour = value; + Background.FadeColour(value); + } + } + + protected override Container Content { get; } + + protected Box Hover; + protected Box Background; + protected SpriteText SpriteText; public OsuButton() { Height = 40; - Content.Masking = true; - Content.CornerRadius = 5; + AddInternal(Content = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + CornerRadius = 5, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + Background = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + }, + Hover = new Box + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = Color4.White.Opacity(.1f), + Blending = BlendingParameters.Additive, + Depth = float.MinValue + }, + SpriteText = CreateText(), + new HoverClickSounds(HoverSampleSet.Loud), + } + }); + + Enabled.BindValueChanged(enabledChanged, true); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - BackgroundColour = colours.BlueDark; - - AddRange(new Drawable[] - { - hover = new Box - { - RelativeSizeAxes = Axes.Both, - Blending = BlendingParameters.Additive, - Colour = Color4.White.Opacity(0.1f), - Alpha = 0, - Depth = -1 - }, - new HoverClickSounds(HoverSampleSet.Loud), - }); + if (backgroundColour == null) + BackgroundColour = colours.BlueDark; Enabled.ValueChanged += enabledChanged; Enabled.TriggerChange(); } - private void enabledChanged(ValueChangedEvent e) + protected override bool OnClick(ClickEvent e) { - this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + if (Enabled.Value) + { + Debug.Assert(backgroundColour != null); + Background.FlashColour(backgroundColour.Value, 200); + } + + return base.OnClick(e); } protected override bool OnHover(HoverEvent e) { - hover.FadeIn(200); - return true; + if (Enabled.Value) + Hover.FadeIn(200, Easing.OutQuint); + + return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - hover.FadeOut(200); base.OnHoverLost(e); + + Hover.FadeOut(300); } protected override bool OnMouseDown(MouseDownEvent e) @@ -80,12 +133,17 @@ namespace osu.Game.Graphics.UserInterface return base.OnMouseUp(e); } - protected override SpriteText CreateText() => new OsuSpriteText + protected virtual SpriteText CreateText() => new OsuSpriteText { Depth = -1, Origin = Anchor.Centre, Anchor = Anchor.Centre, Font = OsuFont.GetFont(weight: FontWeight.Bold) }; + + private void enabledChanged(ValueChangedEvent e) + { + this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + } } } diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index cdb4dc463a..5930c89d29 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; @@ -9,21 +8,18 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SidebarButton : BasicButton + public class SidebarButton : OsuButton { private readonly SpriteIcon drawableIcon; private readonly SpriteText headerText; private readonly Box selectionIndicator; private readonly Container text; - public new Action Action; private SettingsSection section; @@ -62,9 +58,6 @@ namespace osu.Game.Overlays.Settings public SidebarButton() { - BackgroundColour = OsuColour.Gray(60); - Background.Alpha = 0; - Height = Sidebar.DEFAULT_WIDTH; RelativeSizeAxes = Axes.X; @@ -99,7 +92,6 @@ namespace osu.Game.Overlays.Settings Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, }, - new HoverClickSounds(HoverSampleSet.Loud), }); } @@ -108,23 +100,5 @@ namespace osu.Game.Overlays.Settings { selectionIndicator.Colour = colours.Yellow; } - - protected override bool OnClick(ClickEvent e) - { - Action?.Invoke(section); - return base.OnClick(e); - } - - protected override bool OnHover(HoverEvent e) - { - Background.FadeTo(0.4f, 200); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - Background.FadeTo(0, 200); - base.OnHoverLost(e); - } } } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index d028664fe0..2948231c4b 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -123,9 +123,9 @@ namespace osu.Game.Overlays var button = new SidebarButton { Section = section, - Action = s => + Action = () => { - SectionsContainer.ScrollTo(s); + SectionsContainer.ScrollTo(section); Sidebar.State = ExpandedState.Contracted; }, }; From ebfb5d050d740e9df7ecd1d14d6ce716d57039c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 14:36:43 +0900 Subject: [PATCH 158/503] Move section update code to abstract method to avoid incorrect BindValue usage --- osu.Game/Screens/Edit/Timing/DifficultySection.cs | 7 +++---- osu.Game/Screens/Edit/Timing/EffectSection.cs | 12 ++++-------- osu.Game/Screens/Edit/Timing/SampleSection.cs | 12 ++++-------- osu.Game/Screens/Edit/Timing/Section.cs | 4 ++++ osu.Game/Screens/Edit/Timing/TimingSection.cs | 12 ++++-------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/Edit/Timing/DifficultySection.cs b/osu.Game/Screens/Edit/Timing/DifficultySection.cs index cd33425ee5..05e45014eb 100644 --- a/osu.Game/Screens/Edit/Timing/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Timing/DifficultySection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -20,11 +21,9 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => { multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier:0.##}x"; }); + multiplier.Text = $"Multiplier: {point.NewValue?.SpeedMultiplier:0.##}x"; } protected override DifficultyControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index bafdfd0b0d..2b37ffaaaf 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -22,15 +23,10 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; - omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; - }); + kiai.Text = $"Kiai: {(point.NewValue?.KiaiMode == true ? "on" : "off")}"; + omitBarLine.Text = $"Skip Bar Line: {(point.NewValue?.OmitFirstBarLine == true ? "on" : "off")}"; } protected override EffectControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/SampleSection.cs b/osu.Game/Screens/Edit/Timing/SampleSection.cs index e665db0a4d..1bedb1ff42 100644 --- a/osu.Game/Screens/Edit/Timing/SampleSection.cs +++ b/osu.Game/Screens/Edit/Timing/SampleSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -22,15 +23,10 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bank.Text = $"Bank: {point.NewValue?.SampleBank}"; - volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; - }); + bank.Text = $"Bank: {point.NewValue?.SampleBank}"; + volume.Text = $"Volume: {point.NewValue?.SampleVolume}%"; } protected override SampleControlPoint CreatePoint() diff --git a/osu.Game/Screens/Edit/Timing/Section.cs b/osu.Game/Screens/Edit/Timing/Section.cs index c6140ff497..ccf1582486 100644 --- a/osu.Game/Screens/Edit/Timing/Section.cs +++ b/osu.Game/Screens/Edit/Timing/Section.cs @@ -119,8 +119,12 @@ namespace osu.Game.Screens.Edit.Timing ControlPoint.Value = points.NewValue?.ControlPoints.OfType().FirstOrDefault(); checkbox.Current.Value = ControlPoint.Value != null; }, true); + + ControlPoint.BindValueChanged(OnControlPointChanged, true); } + protected abstract void OnControlPointChanged(ValueChangedEvent point); + protected abstract T CreatePoint(); } } diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 8609da4c4d..15007ffdb3 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Sprites; @@ -22,15 +23,10 @@ namespace osu.Game.Screens.Edit.Timing }); } - protected override void LoadComplete() + protected override void OnControlPointChanged(ValueChangedEvent point) { - base.LoadComplete(); - - ControlPoint.BindValueChanged(point => - { - bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; - timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; - }); + bpm.Text = $"BPM: {point.NewValue?.BPM:0.##}"; + timeSignature.Text = $"Signature: {point.NewValue?.TimeSignature}"; } protected override TimingControlPoint CreatePoint() From 5e416bd18d5dc77b458cc1d1d59db2372d1b6ec8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 14:47:31 +0900 Subject: [PATCH 159/503] Fix tournament client crashing if beatmap added with an ID of zero --- osu.Game.Tournament/TournamentGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index dbfa70704b..21552882ef 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -215,7 +215,7 @@ namespace osu.Game.Tournament foreach (var r in ladder.Rounds) foreach (var b in r.Beatmaps) - if (b.BeatmapInfo == null) + if (b.BeatmapInfo == null && b.ID > 0) { var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); req.Perform(API); From 0b09fb293e0ad9bea8657a84e19dd135c1eb566d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 15:09:08 +0900 Subject: [PATCH 160/503] Fix background being coloured --- osu.Game/Overlays/Settings/SidebarButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index 5930c89d29..68836bc6b3 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -61,6 +61,8 @@ namespace osu.Game.Overlays.Settings Height = Sidebar.DEFAULT_WIDTH; RelativeSizeAxes = Axes.X; + BackgroundColour = Color4.Black; + AddRange(new Drawable[] { text = new Container From 020b08b4500c811702380b2c3286427a36d2e3b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 14:55:05 +0900 Subject: [PATCH 161/503] Initial implementation of limited distance snap --- .../TestSceneOsuDistanceSnapGrid.cs | 2 +- .../Edit/OsuDistanceSnapGrid.cs | 4 +-- .../Edit/OsuHitObjectComposer.cs | 33 ++++++++++++------- .../Editor/TestSceneDistanceSnapGrid.cs | 2 +- .../Components/CircularDistanceSnapGrid.cs | 12 ++++--- .../Compose/Components/DistanceSnapGrid.cs | 21 +++++++++++- 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index a9a6097182..aba1d8fa1d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -153,7 +153,7 @@ namespace osu.Game.Rulesets.Osu.Tests public new float DistanceSpacing => base.DistanceSpacing; public TestOsuDistanceSnapGrid(OsuHitObject hitObject) - : base(hitObject) + : base(hitObject, null) { } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index 79cd51a7f4..9b00204d51 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -8,8 +8,8 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuDistanceSnapGrid : CircularDistanceSnapGrid { - public OsuDistanceSnapGrid(OsuHitObject hitObject) - : base(hitObject, hitObject.StackedEndPosition) + public OsuDistanceSnapGrid(OsuHitObject hitObject, OsuHitObject nextHitObject) + : base(hitObject, nextHitObject, hitObject.StackedEndPosition) { Masking = true; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index fcf2772219..a021f70598 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; @@ -60,25 +61,33 @@ namespace osu.Game.Rulesets.Osu.Edit var objects = selectedHitObjects.ToList(); if (objects.Count == 0) + return createGrid(h => h.StartTime <= EditorClock.CurrentTime); + + double minTime = objects.Min(h => h.StartTime); + return createGrid(h => h.StartTime < minTime); + } + + private OsuDistanceSnapGrid createGrid(Func hitObjectSelector) + { + int lastIndex = -1; + + for (int i = 0; i < EditorBeatmap.HitObjects.Count; i++) { - var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime <= EditorClock.CurrentTime); + HitObject hitObject = EditorBeatmap.HitObjects[i]; - if (lastObject == null) - return null; + if (!hitObjectSelector(hitObject)) + break; - return new OsuDistanceSnapGrid(lastObject); + lastIndex = i; } - else - { - double minTime = objects.Min(h => h.StartTime); - var lastObject = EditorBeatmap.HitObjects.LastOrDefault(h => h.StartTime < minTime); + if (lastIndex == -1) + return null; - if (lastObject == null) - return null; + OsuHitObject lastObject = EditorBeatmap.HitObjects[lastIndex]; + OsuHitObject nextObject = lastIndex == EditorBeatmap.HitObjects.Count - 1 ? null : EditorBeatmap.HitObjects[lastIndex + 1]; - return new OsuDistanceSnapGrid(lastObject); - } + return new OsuDistanceSnapGrid(lastObject, nextObject); } } } diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index b8c31d5dbb..0681dff528 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -62,7 +62,7 @@ namespace osu.Game.Tests.Visual.Editor public new float DistanceSpacing => base.DistanceSpacing; public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) - : base(hitObject, centrePosition) + : base(hitObject, null, centrePosition) { } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index f45115e1e4..0f2bae6305 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -12,8 +12,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { public abstract class CircularDistanceSnapGrid : DistanceSnapGrid { - protected CircularDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) - : base(hitObject, centrePosition) + protected CircularDistanceSnapGrid(HitObject hitObject, HitObject nextHitObject, Vector2 centrePosition) + : base(hitObject, nextHitObject, centrePosition) { } @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X); float dy = Math.Max(centrePosition.Y, DrawHeight - centrePosition.Y); float maxDistance = new Vector2(dx, dy).Length; - int requiredCircles = (int)(maxDistance / DistanceSpacing); + int requiredCircles = Math.Min(MaxIntervals, (int)(maxDistance / DistanceSpacing)); for (int i = 0; i < requiredCircles; i++) { @@ -65,15 +65,17 @@ namespace osu.Game.Screens.Edit.Compose.Components public override (Vector2 position, double time) GetSnappedPosition(Vector2 position) { - Vector2 direction = position - CentrePosition; + if (MaxIntervals == 0) + return (CentrePosition, StartTime); + Vector2 direction = position - CentrePosition; if (direction == Vector2.Zero) direction = new Vector2(0.001f, 0.001f); float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = Math.Max(1, (int)Math.Round(distance / radius)); + int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 193474093f..475b6e7274 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; @@ -29,6 +30,11 @@ namespace osu.Game.Screens.Edit.Compose.Components /// protected double StartTime { get; private set; } + /// + /// The maximum number of distance snapping intervals allowed. + /// + protected int MaxIntervals { get; private set; } + /// /// The position which the grid is centred on. /// The first beat snapping tick is located at + in the desired direction. @@ -49,12 +55,15 @@ namespace osu.Game.Screens.Edit.Compose.Components private readonly Cached gridCache = new Cached(); private readonly HitObject hitObject; + private readonly HitObject nextHitObject; - protected DistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) + protected DistanceSnapGrid(HitObject hitObject, [CanBeNull] HitObject nextHitObject, Vector2 centrePosition) { this.hitObject = hitObject; + this.nextHitObject = nextHitObject; CentrePosition = centrePosition; + RelativeSizeAxes = Axes.Both; } @@ -74,6 +83,16 @@ namespace osu.Game.Screens.Edit.Compose.Components private void updateSpacing() { DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(StartTime); + + if (nextHitObject == null) + MaxIntervals = int.MaxValue; + else + { + // +1 is added since a snapped hitobject may have its start time slightly less than the snapped time due to floating point errors + double maxDuration = nextHitObject.StartTime - StartTime + 1; + MaxIntervals = (int)(maxDuration / SnapProvider.DistanceToDuration(StartTime, DistanceSpacing)); + } + gridCache.Invalidate(); } From c1a6cb1defaa7fc0008f1de0db821d3faf253fdb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 15:58:47 +0900 Subject: [PATCH 162/503] Fix audio preview muting game audio indefinitely when beatmap panel is off-screen --- osu.Game/Audio/PreviewTrack.cs | 5 ++++- osu.Game/Audio/PreviewTrackManager.cs | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 22ce7d4711..937ad7e45a 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -13,11 +13,13 @@ namespace osu.Game.Audio { /// /// Invoked when this has stopped playing. + /// Not invoked in a thread-safe context. /// public event Action Stopped; /// /// Invoked when this has started playing. + /// Not invoked in a thread-safe context. /// public event Action Started; @@ -29,7 +31,7 @@ namespace osu.Game.Audio { track = GetTrack(); if (track != null) - track.Completed += () => Schedule(Stop); + track.Completed += Stop; } /// @@ -93,6 +95,7 @@ namespace osu.Game.Audio hasStarted = false; track.Stop(); + Stopped?.Invoke(); } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index e12c46ef16..fad2b5a5e8 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -46,18 +46,18 @@ namespace osu.Game.Audio { var track = CreatePreviewTrack(beatmapSetInfo, trackStore); - track.Started += () => + track.Started += () => Schedule(() => { current?.Stop(); current = track; audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); - }; + }); - track.Stopped += () => + track.Stopped += () => Schedule(() => { current = null; audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); - }; + }); return track; } From 2588534eda26d2a00f6cf070f0d150a9ee556eb1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 16:04:20 +0900 Subject: [PATCH 163/503] Skin entire selection, add xmldocs --- .../Edit/OsuHitObjectComposer.cs | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index a021f70598..812afaaa24 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -64,30 +64,37 @@ namespace osu.Game.Rulesets.Osu.Edit return createGrid(h => h.StartTime <= EditorClock.CurrentTime); double minTime = objects.Min(h => h.StartTime); - return createGrid(h => h.StartTime < minTime); + return createGrid(h => h.StartTime < minTime, objects.Count + 1); } - private OsuDistanceSnapGrid createGrid(Func hitObjectSelector) + /// + /// Creates a grid from the last matching a predicate to a target . + /// + /// A predicate that matches s where the grid can start from. + /// Only the last matching the predicate is used. + /// An offset from the selected via at which the grid should stop. + /// The from a selected to a target . + private OsuDistanceSnapGrid createGrid(Func sourceSelector, int targetOffset = 1) { - int lastIndex = -1; + if (targetOffset < 1) throw new ArgumentOutOfRangeException(nameof(targetOffset)); + + int sourceIndex = -1; for (int i = 0; i < EditorBeatmap.HitObjects.Count; i++) { - HitObject hitObject = EditorBeatmap.HitObjects[i]; - - if (!hitObjectSelector(hitObject)) + if (!sourceSelector(EditorBeatmap.HitObjects[i])) break; - lastIndex = i; + sourceIndex = i; } - if (lastIndex == -1) + if (sourceIndex == -1) return null; - OsuHitObject lastObject = EditorBeatmap.HitObjects[lastIndex]; - OsuHitObject nextObject = lastIndex == EditorBeatmap.HitObjects.Count - 1 ? null : EditorBeatmap.HitObjects[lastIndex + 1]; + OsuHitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; + OsuHitObject targetObject = sourceIndex + targetOffset < EditorBeatmap.HitObjects.Count ? EditorBeatmap.HitObjects[sourceIndex + targetOffset] : null; - return new OsuDistanceSnapGrid(lastObject, nextObject); + return new OsuDistanceSnapGrid(sourceObject, targetObject); } } } From d985d048574ef01800fd3973d65583e273d4c45a Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Wed, 6 Nov 2019 14:07:05 +0700 Subject: [PATCH 164/503] Add background colour to music player ProgressBar --- osu.Game/Overlays/NowPlayingOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 6b79f2af07..8c7e717a82 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -174,6 +174,7 @@ namespace osu.Game.Overlays Anchor = Anchor.BottomCentre, Height = progress_height, FillColour = colours.Yellow, + BackgroundColour = colours.YellowDarker.Opacity(0.5f), OnSeek = musicController.SeekTo } }, From 02c21a1379e24a7ec2bb4c2b47c2c6efbcd0a103 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Wed, 6 Nov 2019 14:11:47 +0700 Subject: [PATCH 165/503] Make progress bar hoverable --- osu.Game/Overlays/NowPlayingOverlay.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 8c7e717a82..4f73cbfacd 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -168,11 +168,11 @@ namespace osu.Game.Overlays }, } }, - progressBar = new ProgressBar + progressBar = new HoverableProgressBar { Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, - Height = progress_height, + Height = progress_height / 2, FillColour = colours.Yellow, BackgroundColour = colours.YellowDarker.Opacity(0.5f), OnSeek = musicController.SeekTo @@ -402,5 +402,20 @@ namespace osu.Game.Overlays return base.OnDragEnd(e); } } + + private class HoverableProgressBar : ProgressBar + { + protected override bool OnHover(HoverEvent e) + { + this.ResizeHeightTo(progress_height, 500, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + this.ResizeHeightTo(progress_height / 2, 500, Easing.OutQuint); + base.OnHoverLost(e); + } + } } } From b83ceab1c1b2ba594efa02d166f364a32142e4ac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 16:20:13 +0900 Subject: [PATCH 166/503] Add tests --- .../TestSceneOsuDistanceSnapGrid.cs | 47 ++++++++++++++----- .../Editor/TestSceneDistanceSnapGrid.cs | 39 +++++++++++---- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs index aba1d8fa1d..eff4d919b0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuDistanceSnapGrid.cs @@ -42,11 +42,19 @@ namespace osu.Game.Rulesets.Osu.Tests [Cached(typeof(IDistanceSnapProvider))] private readonly SnapProvider snapProvider = new SnapProvider(); - private readonly TestOsuDistanceSnapGrid grid; + private TestOsuDistanceSnapGrid grid; public TestSceneOsuDistanceSnapGrid() { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + } + + [SetUp] + public void Setup() => Schedule(() => + { + editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; + editorBeatmap.ControlPointInfo.Clear(); + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); Children = new Drawable[] { @@ -58,14 +66,6 @@ namespace osu.Game.Rulesets.Osu.Tests grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }), new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position } }; - } - - [SetUp] - public void Setup() => Schedule(() => - { - editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1; - editorBeatmap.ControlPointInfo.Clear(); - editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); }); [TestCase(1)] @@ -102,6 +102,27 @@ namespace osu.Game.Rulesets.Osu.Tests assertSnappedDistance((float)beat_length * 2); } + [Test] + public void TestLimitedDistance() + { + AddStep("create limited grid", () => + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + grid = new TestOsuDistanceSnapGrid(new HitCircle { Position = grid_position }, new HitCircle { StartTime = 200 }), + new SnappingCursorContainer { GetSnapPosition = v => grid.GetSnappedPosition(grid.ToLocalSpace(v)).position } + }; + }); + + AddStep("move mouse outside grid", () => InputManager.MoveMouseTo(grid.ToScreenSpace(grid_position + new Vector2((float)beat_length, 0) * 3f))); + assertSnappedDistance((float)beat_length * 2); + } + private void assertSnappedDistance(float expectedDistance) => AddAssert($"snap distance = {expectedDistance}", () => { Vector2 snappedPosition = grid.GetSnappedPosition(grid.ToLocalSpace(InputManager.CurrentState.Mouse.Position)).position; @@ -152,8 +173,8 @@ namespace osu.Game.Rulesets.Osu.Tests { public new float DistanceSpacing => base.DistanceSpacing; - public TestOsuDistanceSnapGrid(OsuHitObject hitObject) - : base(hitObject, null) + public TestOsuDistanceSnapGrid(OsuHitObject hitObject, OsuHitObject nextHitObject = null) + : base(hitObject, nextHitObject) { } } @@ -164,9 +185,9 @@ namespace osu.Game.Rulesets.Osu.Tests public float GetBeatSnapDistanceAt(double referenceTime) => (float)beat_length; - public float DurationToDistance(double referenceTime, double duration) => 0; + public float DurationToDistance(double referenceTime, double duration) => (float)duration; - public double DistanceToDuration(double referenceTime, float distance) => 0; + public double DistanceToDuration(double referenceTime, float distance) => distance; public double GetSnappedDurationFromDistance(double referenceTime, float distance) => 0; diff --git a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs index 0681dff528..e4c987923c 100644 --- a/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editor/TestSceneDistanceSnapGrid.cs @@ -32,7 +32,11 @@ namespace osu.Game.Tests.Visual.Editor { editorBeatmap = new EditorBeatmap(new OsuBeatmap()); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); + } + [SetUp] + public void Setup() => Schedule(() => + { Children = new Drawable[] { new Box @@ -42,7 +46,7 @@ namespace osu.Game.Tests.Visual.Editor }, new TestDistanceSnapGrid(new HitObject(), grid_position) }; - } + }); [TestCase(1)] [TestCase(2)] @@ -57,12 +61,29 @@ namespace osu.Game.Tests.Visual.Editor AddStep($"set beat divisor = {divisor}", () => BeatDivisor.Value = divisor); } + [Test] + public void TestLimitedDistance() + { + AddStep("create limited grid", () => + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.SlateGray + }, + new TestDistanceSnapGrid(new HitObject(), grid_position, new HitObject { StartTime = 100 }) + }; + }); + } + private class TestDistanceSnapGrid : DistanceSnapGrid { public new float DistanceSpacing => base.DistanceSpacing; - public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition) - : base(hitObject, null, centrePosition) + public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition, HitObject nextHitObject = null) + : base(hitObject, nextHitObject, centrePosition) { } @@ -77,7 +98,7 @@ namespace osu.Game.Tests.Visual.Editor int beatIndex = 0; - for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth; s += DistanceSpacing, beatIndex++) + for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -90,7 +111,7 @@ namespace osu.Game.Tests.Visual.Editor beatIndex = 0; - for (float s = centrePosition.X - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) + for (float s = centrePosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -103,7 +124,7 @@ namespace osu.Game.Tests.Visual.Editor beatIndex = 0; - for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight; s += DistanceSpacing, beatIndex++) + for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -116,7 +137,7 @@ namespace osu.Game.Tests.Visual.Editor beatIndex = 0; - for (float s = centrePosition.Y - DistanceSpacing; s >= 0; s -= DistanceSpacing, beatIndex++) + for (float s = centrePosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++) { AddInternal(new Circle { @@ -138,9 +159,9 @@ namespace osu.Game.Tests.Visual.Editor public float GetBeatSnapDistanceAt(double referenceTime) => 10; - public float DurationToDistance(double referenceTime, double duration) => 0; + public float DurationToDistance(double referenceTime, double duration) => (float)duration; - public double DistanceToDuration(double referenceTime, float distance) => 0; + public double DistanceToDuration(double referenceTime, float distance) => distance; public double GetSnappedDurationFromDistance(double referenceTime, float distance) => 0; From ee544e174a3971716fcd9a6ea0f284c2cb213da3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 16:33:42 +0900 Subject: [PATCH 167/503] Group -> Connection --- .../TestSceneFollowPoints.cs | 4 +- ...PointGroup.cs => FollowPointConnection.cs} | 6 +- .../Connections/FollowPointRenderer.cs | 76 +++++++++---------- 3 files changed, 43 insertions(+), 43 deletions(-) rename osu.Game.Rulesets.Osu/Objects/Drawables/Connections/{FollowPointGroup.cs => FollowPointConnection.cs} (95%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index 79a1bb579f..94ca2d4cd1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void assertGroups() { - AddAssert("has correct group count", () => followPointRenderer.Groups.Count == hitObjectContainer.Count); + AddAssert("has correct group count", () => followPointRenderer.Connections.Count == hitObjectContainer.Count); AddAssert("group endpoints are correct", () => { for (int i = 0; i < hitObjectContainer.Count; i++) @@ -209,7 +209,7 @@ namespace osu.Game.Rulesets.Osu.Tests private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index]; - private FollowPointGroup getGroup(int index) => followPointRenderer.Groups[index]; + private FollowPointConnection getGroup(int index) => followPointRenderer.Connections[index]; private class TestHitObjectContainer : Container { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs similarity index 95% rename from osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 168d2b8532..1e032eb977 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointGroup.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// Visualises the s between two s. /// - public class FollowPointGroup : CompositeDrawable + public class FollowPointConnection : CompositeDrawable { // Todo: These shouldn't be constants private const int spacing = 32; @@ -32,10 +32,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections public readonly DrawableOsuHitObject Start; /// - /// Creates a new . + /// Creates a new . /// /// The which s will exit from. - public FollowPointGroup([NotNull] DrawableOsuHitObject start) + public FollowPointConnection([NotNull] DrawableOsuHitObject start) { Start = start; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index afd86e004d..00ef0ba0d0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -10,16 +10,16 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { /// - /// Visualises groups of s. + /// Visualises connections between s. /// public class FollowPointRenderer : CompositeDrawable { /// - /// All the s contained by this . + /// All the s contained by this . /// - internal IReadOnlyList Groups => groups; + internal IReadOnlyList Connections => connections; - private readonly List groups = new List(); + private readonly List connections = new List(); public override bool RemoveCompletedTransforms => false; @@ -29,84 +29,84 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// The to add s for. public void AddFollowPoints(DrawableOsuHitObject hitObject) - => addGroup(new FollowPointGroup(hitObject).With(g => g.StartTime.BindValueChanged(_ => onStartTimeChanged(g)))); + => addConnection(new FollowPointConnection(hitObject).With(g => g.StartTime.BindValueChanged(_ => onStartTimeChanged(g)))); /// /// Removes the s around a . /// This includes s leading into , and s exiting . /// /// The to remove s for. - public void RemoveFollowPoints(DrawableOsuHitObject hitObject) => removeGroup(groups.Single(g => g.Start == hitObject)); + public void RemoveFollowPoints(DrawableOsuHitObject hitObject) => removeGroup(connections.Single(g => g.Start == hitObject)); /// - /// Adds a to this . + /// Adds a to this . /// - /// The to add. - /// The index of in . - private int addGroup(FollowPointGroup group) + /// The to add. + /// The index of in . + private int addConnection(FollowPointConnection connection) { - AddInternal(group); + AddInternal(connection); - // Groups are sorted by their start time when added such that the index can be used to post-process other surrounding groups - int index = groups.AddInPlace(group, Comparer.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value))); + // Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections + int index = connections.AddInPlace(connection, Comparer.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value))); - if (index < groups.Count - 1) + if (index < connections.Count - 1) { - // Update the group's end point to the next group's start point + // Update the connection's end point to the next connection's start point // h1 -> -> -> h2 - // group nextGroup + // connection nextGroup - FollowPointGroup nextGroup = groups[index + 1]; - group.End = nextGroup.Start; + FollowPointConnection nextConnection = connections[index + 1]; + connection.End = nextConnection.Start; } else { // The end point may be non-null during re-ordering - group.End = null; + connection.End = null; } if (index > 0) { - // Update the previous group's end point to the current group's start point + // Update the previous connection's end point to the current connection's start point // h1 -> -> -> h2 - // prevGroup group + // prevGroup connection - FollowPointGroup previousGroup = groups[index - 1]; - previousGroup.End = group.Start; + FollowPointConnection previousConnection = connections[index - 1]; + previousConnection.End = connection.Start; } return index; } /// - /// Removes a from this . + /// Removes a from this . /// - /// The to remove. - /// Whether was removed. - private bool removeGroup(FollowPointGroup group) + /// The to remove. + /// Whether was removed. + private bool removeGroup(FollowPointConnection connection) { - RemoveInternal(group); + RemoveInternal(connection); - int index = groups.IndexOf(group); + int index = connections.IndexOf(connection); if (index > 0) { - // Update the previous group's end point to the next group's start point + // Update the previous connection's end point to the next connection's start point // h1 -> -> -> h2 -> -> -> h3 - // prevGroup group nextGroup - // The current group's end point is used since there may not be a next group - FollowPointGroup previousGroup = groups[index - 1]; - previousGroup.End = group.End; + // prevGroup connection nextGroup + // The current connection's end point is used since there may not be a next connection + FollowPointConnection previousConnection = connections[index - 1]; + previousConnection.End = connection.End; } - return groups.Remove(group); + return connections.Remove(connection); } - private void onStartTimeChanged(FollowPointGroup group) + private void onStartTimeChanged(FollowPointConnection connection) { // Naive but can be improved if performance becomes an issue - removeGroup(group); - addGroup(group); + removeGroup(connection); + addConnection(connection); } } } From 7b5b3ff15c21d378d607b2e4cccafe2a8f366bc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 16:36:12 +0900 Subject: [PATCH 168/503] Remove unused returns --- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 00ef0ba0d0..be192080f9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// The to add. /// The index of in . - private int addConnection(FollowPointConnection connection) + private void addConnection(FollowPointConnection connection) { AddInternal(connection); @@ -74,8 +74,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections FollowPointConnection previousConnection = connections[index - 1]; previousConnection.End = connection.Start; } - - return index; } /// @@ -83,7 +81,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// The to remove. /// Whether was removed. - private bool removeGroup(FollowPointConnection connection) + private void removeGroup(FollowPointConnection connection) { RemoveInternal(connection); @@ -99,7 +97,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections previousConnection.End = connection.End; } - return connections.Remove(connection); + connections.Remove(connection); } private void onStartTimeChanged(FollowPointConnection connection) From 2c1bfd62efaba5e37651de1ea97911674c1c5539 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 17:27:41 +0900 Subject: [PATCH 169/503] Disallow selections to be moved outside of the playfield --- .../Edit/ManiaSelectionHandler.cs | 4 +-- .../Edit/OsuSelectionHandler.cs | 25 +++++++++++++++++-- .../Compose/Components/BlueprintContainer.cs | 3 ++- .../Compose/Components/SelectionHandler.cs | 5 ++-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 732231b0d9..9cdf045b5b 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Edit editorClock = clock; } - public override void HandleMovement(MoveSelectionEvent moveEvent) + public override bool HandleMovement(MoveSelectionEvent moveEvent) { var maniaBlueprint = (ManiaSelectionBlueprint)moveEvent.Blueprint; int lastColumn = maniaBlueprint.DrawableObject.HitObject.Column; @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Edit performDragMovement(moveEvent); performColumnMovement(lastColumn, moveEvent); - base.HandleMovement(moveEvent); + return true; } /// diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 472267eb66..9418565907 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -4,13 +4,34 @@ using System.Linq; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit { public class OsuSelectionHandler : SelectionHandler { - public override void HandleMovement(MoveSelectionEvent moveEvent) + public override bool HandleMovement(MoveSelectionEvent moveEvent) { + Vector2 minPosition = new Vector2(float.MaxValue, float.MaxValue); + Vector2 maxPosition = new Vector2(float.MinValue, float.MinValue); + + // Go through all hitobjects to make sure they would remain in the bounds of the editor after movement, before any movement is attempted + foreach (var h in SelectedHitObjects.OfType()) + { + if (h is Spinner) + { + // Spinners don't support position adjustments + continue; + } + + // Stacking is not considered + minPosition = Vector2.ComponentMin(minPosition, Vector2.ComponentMin(h.EndPosition + moveEvent.InstantDelta, h.Position + moveEvent.InstantDelta)); + maxPosition = Vector2.ComponentMax(maxPosition, Vector2.ComponentMax(h.EndPosition + moveEvent.InstantDelta, h.Position + moveEvent.InstantDelta)); + } + + if (minPosition.X < 0 || minPosition.Y < 0 || maxPosition.X > DrawWidth || maxPosition.Y > DrawHeight) + return false; + foreach (var h in SelectedHitObjects.OfType()) { if (h is Spinner) @@ -22,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Edit h.Position += moveEvent.InstantDelta; } - base.HandleMovement(moveEvent); + return true; } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 288c712bde..c4d8176c7a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -367,7 +367,8 @@ namespace osu.Game.Screens.Edit.Compose.Components (Vector2 snappedPosition, double snappedTime) = composer.GetSnappedPosition(ToLocalSpace(movePosition), draggedObject.StartTime); // Move the hitobjects - selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition))); + if (!selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, startPosition, ToScreenSpace(snappedPosition)))) + return true; // Apply the start time at the newly snapped-to position double offset = snappedTime - draggedObject.StartTime; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 1722476e53..44bf22cfe1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -68,9 +68,8 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Handles the selected s being moved. /// /// The move event. - public virtual void HandleMovement(MoveSelectionEvent moveEvent) - { - } + /// Whether any s were moved. + public virtual bool HandleMovement(MoveSelectionEvent moveEvent) => false; public bool OnPressed(PlatformAction action) { From ee4839b7e7e3f44b4be35b536a5abcacf96aa8cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 18:09:36 +0900 Subject: [PATCH 170/503] Reduce delay on parallax --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index f65a0a469a..a5ebac5b1f 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -71,7 +71,7 @@ namespace osu.Game.Graphics.Containers double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); - content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 1000, Easing.OutQuint); + content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 100, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } From aaa06396f0e8699a3737dbb34293acb9a9784c0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 18:11:56 +0900 Subject: [PATCH 171/503] Reduce editor parallax --- osu.Game/Screens/Edit/Editor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..e97c89c2dc 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -36,6 +36,8 @@ namespace osu.Game.Screens.Edit { protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); + public override float BackgroundParallaxAmount => 0.1f; + public override bool AllowBackButton => false; public override bool HideOverlaysOnEnter => true; From 3680e7c7047853f936075675855a2410b93b3721 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Nov 2019 18:15:57 +0900 Subject: [PATCH 172/503] Seek editor when hit objects are double clicked --- .../Edit/Compose/Components/BlueprintContainer.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 288c712bde..1ce7863d60 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Framework.Input.Events; +using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; @@ -30,6 +31,9 @@ namespace osu.Game.Screens.Edit.Compose.Components private SelectionHandler selectionHandler; private InputManager inputManager; + [Resolved] + private IAdjustableClock adjustableClock { get; set; } + [Resolved] private HitObjectComposer composer { get; set; } @@ -106,6 +110,17 @@ namespace osu.Game.Screens.Edit.Compose.Components return true; } + protected override bool OnDoubleClick(DoubleClickEvent e) + { + SelectionBlueprint clickedBlueprint = selectionHandler.SelectedBlueprints.FirstOrDefault(b => b.IsHovered); + + if (clickedBlueprint == null) + return false; + + adjustableClock?.Seek(clickedBlueprint.DrawableObject.HitObject.StartTime); + return true; + } + protected override bool OnMouseUp(MouseUpEvent e) { // Special case for when a drag happened instead of a click From 4330507da8862d9d6cb8118bba95ac375bbd5972 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 12:46:25 +0300 Subject: [PATCH 173/503] Use api.IsLoggedIn --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 12 +++++++++--- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 22e11aa464..c113bf0a04 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using osu.Framework.MathUtils; +using osu.Game.Online.API; namespace osu.Game.Tests.Visual.Online { @@ -21,6 +22,11 @@ namespace osu.Game.Tests.Visual.Online typeof(VotePill) }; + protected override bool UseOnlineAPI => true; + + [Resolved] + private IAPIProvider api { get; set; } + private VotePill votePill; [BackgroundDependencyLoader] @@ -33,7 +39,7 @@ namespace osu.Game.Tests.Visual.Online VotesCount = 2, }; - AddStep("Log in", () => API.LocalUser.Value = new User + AddStep("Log in", () => api.LocalUser.Value = new User { Id = RNG.Next(2, 100000) }); @@ -45,7 +51,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading); - AddStep("Log out", API.Logout); + AddStep("Log out", api.Logout); AddStep("Random comment", () => addVotePill(randomComment)); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -54,7 +60,7 @@ namespace osu.Game.Tests.Visual.Online private Comment getUserComment() => new Comment { IsVoted = false, - UserId = API.LocalUser.Value.Id, + UserId = api.LocalUser.Value.Id, VotesCount = 10, }; diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index ad17264229..a5a19f5111 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if (api.LocalUser.Value.Id != comment.UserId && api.LocalUser.Value.Id != 1) + if (api.LocalUser.Value.Id != comment.UserId && api.IsLoggedIn) Action = onAction; } From 5589329e16aec04e473f41310ffb307bd08e0f51 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 12:54:04 +0300 Subject: [PATCH 174/503] Split tests --- .../Visual/Online/TestSceneVotePill.cs | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index c113bf0a04..c93fbabb41 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -29,16 +29,9 @@ namespace osu.Game.Tests.Visual.Online private VotePill votePill; - [BackgroundDependencyLoader] - private void load() + [Test] + public void TestUserCommentPill() { - var randomComment = new Comment - { - IsVoted = false, - UserId = 4444, - VotesCount = 2, - }; - AddStep("Log in", () => api.LocalUser.Value = new User { Id = RNG.Next(2, 100000) @@ -46,13 +39,25 @@ namespace osu.Game.Tests.Visual.Online AddStep("User comment", () => addVotePill(getUserComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); + } - AddStep("Random comment", () => addVotePill(randomComment)); + [Test] + public void TestRandomCommentPill() + { + AddStep("Log in", () => api.LocalUser.Value = new User + { + Id = RNG.Next(2, 100000) + }); + AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading); + } + [Test] + public void TestOfflineRandomCommentPill() + { AddStep("Log out", api.Logout); - AddStep("Random comment", () => addVotePill(randomComment)); + AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); } @@ -64,6 +69,13 @@ namespace osu.Game.Tests.Visual.Online VotesCount = 10, }; + private Comment getRandomComment() => new Comment + { + IsVoted = false, + UserId = 4444, + VotesCount = 2, + }; + private void addVotePill(Comment comment) { Clear(); From 31f2d6a842e380077b4866e948b8b50dfce864e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Nov 2019 19:06:24 +0900 Subject: [PATCH 175/503] Fix regressed test --- .../Components/TestScenePreviewTrackManager.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index df6740421b..f3f6444149 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -34,6 +34,7 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; AddStep("get track", () => track = getOwnedTrack()); + AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start", () => track.Start()); AddAssert("started", () => track.IsRunning); AddStep("stop", () => track.Stop()); @@ -52,6 +53,8 @@ namespace osu.Game.Tests.Visual.Components track2 = getOwnedTrack(); }); + AddUntilStep("wait loaded", () => track1.IsLoaded && track2.IsLoaded); + AddStep("start track 1", () => track1.Start()); AddStep("start track 2", () => track2.Start()); AddAssert("track 1 stopped", () => !track1.IsRunning); @@ -64,6 +67,7 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; AddStep("get track", () => track = getOwnedTrack()); + AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start", () => track.Start()); AddStep("stop by owner", () => trackManager.StopAnyPlaying(this)); AddAssert("stopped", () => !track.IsRunning); @@ -76,6 +80,7 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); + AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start", () => track.Start()); AddStep("attempt stop", () => trackManager.StopAnyPlaying(this)); AddAssert("not stopped", () => track.IsRunning); @@ -89,16 +94,24 @@ namespace osu.Game.Tests.Visual.Components { var track = getTrack(); - Add(track); + LoadComponentAsync(track, Add); return track; } private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner { + private readonly PreviewTrack track; + public TestTrackOwner(PreviewTrack track) { - AddInternal(track); + this.track = track; + } + + [BackgroundDependencyLoader] + private void load() + { + LoadComponentAsync(track, AddInternal); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 6ecea0e4c1e3ce8a42a5880baf7c6a7730d85844 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 18:15:49 +0300 Subject: [PATCH 176/503] Fix DummyAPIAccess being potentially incorrect --- osu.Game/Online/API/DummyAPIAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 6c04c77dc0..28132765d3 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online.API public Bindable Activity { get; } = new Bindable(); - public bool IsLoggedIn => true; + public bool IsLoggedIn => State == APIState.Online; public string ProvidedUsername => LocalUser.Value.Username; From 8395df596b8cc14000aa3548d0b96f81c727fab2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 18:24:30 +0300 Subject: [PATCH 177/503] Don't use online API for tests --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index c93fbabb41..5bdafdfec4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -6,11 +6,9 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Overlays.Comments; -using osu.Framework.Allocation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; using osu.Framework.MathUtils; -using osu.Game.Online.API; namespace osu.Game.Tests.Visual.Online { @@ -22,17 +20,12 @@ namespace osu.Game.Tests.Visual.Online typeof(VotePill) }; - protected override bool UseOnlineAPI => true; - - [Resolved] - private IAPIProvider api { get; set; } - private VotePill votePill; [Test] public void TestUserCommentPill() { - AddStep("Log in", () => api.LocalUser.Value = new User + AddStep("Log in", () => API.LocalUser.Value = new User { Id = RNG.Next(2, 100000) }); @@ -44,7 +37,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestRandomCommentPill() { - AddStep("Log in", () => api.LocalUser.Value = new User + AddStep("Log in", () => API.LocalUser.Value = new User { Id = RNG.Next(2, 100000) }); @@ -56,7 +49,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestOfflineRandomCommentPill() { - AddStep("Log out", api.Logout); + AddStep("Log out", API.Logout); AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -65,7 +58,7 @@ namespace osu.Game.Tests.Visual.Online private Comment getUserComment() => new Comment { IsVoted = false, - UserId = api.LocalUser.Value.Id, + UserId = API.LocalUser.Value.Id, VotesCount = 10, }; From 59aa9b59d62a5c830e12454aae1bb5d0f1e15cde Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 6 Nov 2019 18:32:09 +0300 Subject: [PATCH 178/503] Move login to it's own function --- osu.Game.Tests/Visual/Online/TestSceneVotePill.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index 5bdafdfec4..8197cf72de 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -7,8 +7,6 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Overlays.Comments; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Users; -using osu.Framework.MathUtils; namespace osu.Game.Tests.Visual.Online { @@ -25,10 +23,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestUserCommentPill() { - AddStep("Log in", () => API.LocalUser.Value = new User - { - Id = RNG.Next(2, 100000) - }); + AddStep("Log in", logIn); AddStep("User comment", () => addVotePill(getUserComment())); AddStep("Click", () => votePill.Click()); AddAssert("Not loading", () => !votePill.IsLoading); @@ -37,10 +32,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestRandomCommentPill() { - AddStep("Log in", () => API.LocalUser.Value = new User - { - Id = RNG.Next(2, 100000) - }); + AddStep("Log in", logIn); AddStep("Random comment", () => addVotePill(getRandomComment())); AddStep("Click", () => votePill.Click()); AddAssert("Loading", () => votePill.IsLoading); @@ -55,6 +47,8 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Not loading", () => !votePill.IsLoading); } + private void logIn() => API.Login("localUser", "password"); + private Comment getUserComment() => new Comment { IsVoted = false, From 55230a36dd089d49513f074ddcfc8b3070db056e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 19:58:07 +0300 Subject: [PATCH 179/503] Set correct legacy version --- osu.Game/Skinning/LegacySkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 051d10747b..f9bf78b8ad 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -5,7 +5,7 @@ namespace osu.Game.Skinning { public class LegacySkinConfiguration : DefaultSkinConfiguration { - public const decimal LATEST_VERSION = 2.5m; + public const decimal LATEST_VERSION = 2.7m; /// /// Legacy version of this skin. From 502dcc566978b9bc2420d102e76ecbf51260b875 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:23:22 +0300 Subject: [PATCH 180/503] Fix incorrect skin version case --- osu.Game/Skinning/LegacySkinDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index ea087353a0..7dcb7ea3ac 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -34,7 +34,7 @@ namespace osu.Game.Skinning return; case @"Version": - if (pair.Value == "latest" || pair.Value == "User") + if (pair.Value == "latest") skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; else if (decimal.TryParse(pair.Value, out var version)) skin.LegacyVersion = version; From 947602f70afcc6b58d473f0f36ceb28bddfe41b7 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:24:19 +0300 Subject: [PATCH 181/503] Specify why legacy version is nullable --- osu.Game/Skinning/LegacySkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index f9bf78b8ad..33c29cd47c 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -8,7 +8,7 @@ namespace osu.Game.Skinning public const decimal LATEST_VERSION = 2.7m; /// - /// Legacy version of this skin. + /// Legacy version of this skin. Null if no version was set to allow fallback to a parent skin version. /// public decimal? LegacyVersion { get; internal set; } } From ba14345107fc46fc1e00656d58a96e89a69d2abd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:27:55 +0300 Subject: [PATCH 182/503] Specify culture and number style --- osu.Game/Skinning/LegacySkinDecoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 7dcb7ea3ac..88ba7b23b7 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Globalization; using osu.Game.Beatmaps.Formats; namespace osu.Game.Skinning @@ -36,7 +37,7 @@ namespace osu.Game.Skinning case @"Version": if (pair.Value == "latest") skin.LegacyVersion = LegacySkinConfiguration.LATEST_VERSION; - else if (decimal.TryParse(pair.Value, out var version)) + else if (decimal.TryParse(pair.Value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var version)) skin.LegacyVersion = version; return; From 69d9a0ae1a0813db3f722df54abdf1fdb53c819d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:30:26 +0300 Subject: [PATCH 183/503] Use null check and pattern matching --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index f6a366b21d..c76a61084d 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -77,8 +77,8 @@ namespace osu.Game.Skinning switch (legacy) { case LegacySkinConfigurations.Version: - if (Configuration.LegacyVersion.HasValue) - return SkinUtils.As(new Bindable(Configuration.LegacyVersion.Value)); + if (Configuration.LegacyVersion != null) + return SkinUtils.As(new Bindable((decimal)Configuration.LegacyVersion)); break; } From 198a1750c3db0e2b6a2467478333a08d8a65e6db Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 6 Nov 2019 20:46:02 +0300 Subject: [PATCH 184/503] Use `is` pattern matching --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index c76a61084d..1730effc29 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -77,8 +77,8 @@ namespace osu.Game.Skinning switch (legacy) { case LegacySkinConfigurations.Version: - if (Configuration.LegacyVersion != null) - return SkinUtils.As(new Bindable((decimal)Configuration.LegacyVersion)); + if (Configuration.LegacyVersion is decimal version) + return SkinUtils.As(new Bindable(version)); break; } From d400e4a5f6a576b83a355bd34ef405d774382811 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 7 Nov 2019 09:30:50 +0900 Subject: [PATCH 185/503] Add shared constant for parallax amount --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index a5ebac5b1f..86f922e4b8 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -69,9 +69,11 @@ namespace osu.Game.Graphics.Containers { Vector2 offset = (input.CurrentState.Mouse == null ? Vector2.Zero : ToLocalSpace(input.CurrentState.Mouse.Position) - DrawSize / 2) * ParallaxAmount; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000); + const float parallax_duration = 100; - content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, 100, Easing.OutQuint); + double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + + content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } From 8141509a71cd88cd02eb12f7c84f1832e2cb3a95 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 12:59:05 +0900 Subject: [PATCH 186/503] Split hold note blueprints into separate file --- .../HoldNoteNoteSelectionBlueprint.cs | 29 +++++++++++++++++++ .../Blueprints/HoldNoteSelectionBlueprint.cs | 22 -------------- 2 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs new file mode 100644 index 0000000000..3bbfcae10c --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Mania.Objects.Drawables; + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints +{ + public class HoldNoteNoteSelectionBlueprint : NoteSelectionBlueprint + { + public HoldNoteNoteSelectionBlueprint(DrawableNote note) + : base(note) + { + Select(); + } + + protected override void Update() + { + base.Update(); + + Anchor = DrawableObject.Anchor; + Origin = DrawableObject.Origin; + + Position = DrawableObject.DrawPosition; + } + + // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. + public override bool HandlePositionalInput => false; + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index 3a9eb1f043..a0a3a9d0f7 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -64,27 +64,5 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints } public override Quad SelectionQuad => ScreenSpaceDrawQuad; - - private class HoldNoteNoteSelectionBlueprint : NoteSelectionBlueprint - { - public HoldNoteNoteSelectionBlueprint(DrawableNote note) - : base(note) - { - Select(); - } - - protected override void Update() - { - base.Update(); - - Anchor = DrawableObject.Anchor; - Origin = DrawableObject.Origin; - - Position = DrawableObject.DrawPosition; - } - - // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. - public override bool HandlePositionalInput => false; - } } } From 8d42e45fd3aa9b6d6dec99d1373d340096f8982e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 13:23:00 +0900 Subject: [PATCH 187/503] Make holdnote notes update lazily --- .../HoldNoteNoteSelectionBlueprint.cs | 24 ++++++++++++++----- .../Edit/Blueprints/HoldNotePosition.cs | 11 +++++++++ .../Blueprints/HoldNoteSelectionBlueprint.cs | 4 ++-- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs index 3bbfcae10c..5aaf4c09fd 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs @@ -1,15 +1,24 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class HoldNoteNoteSelectionBlueprint : NoteSelectionBlueprint + public class HoldNoteNoteSelectionBlueprint : ManiaSelectionBlueprint { - public HoldNoteNoteSelectionBlueprint(DrawableNote note) - : base(note) + protected new DrawableHoldNote DrawableObject => (DrawableHoldNote)base.DrawableObject; + + private readonly HoldNotePosition position; + + public HoldNoteNoteSelectionBlueprint(DrawableHoldNote holdNote, HoldNotePosition position) + : base(holdNote) { + this.position = position; + InternalChild = new EditNotePiece { RelativeSizeAxes = Axes.X }; + Select(); } @@ -17,10 +26,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Anchor = DrawableObject.Anchor; - Origin = DrawableObject.Origin; + DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail; - Position = DrawableObject.DrawPosition; + Anchor = note.Anchor; + Origin = note.Origin; + + Size = note.DrawSize; + Position = note.DrawPosition; } // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs new file mode 100644 index 0000000000..219dad566d --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePosition.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints +{ + public enum HoldNotePosition + { + Start, + End + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index a0a3a9d0f7..244cfa0b69 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints InternalChildren = new Drawable[] { - new HoldNoteNoteSelectionBlueprint(DrawableObject.Head), - new HoldNoteNoteSelectionBlueprint(DrawableObject.Tail), + new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.Start), + new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.End), new BodyPiece { AccentColour = Color4.Transparent, From 1f9f03dc66aaff484ae279b78cc0c3562c9e4348 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 13:31:06 +0900 Subject: [PATCH 188/503] Add temporary fix for null references --- .../Blueprints/HoldNoteNoteSelectionBlueprint.cs | 14 +++++++++----- .../Blueprints/HoldNoteSelectionBlueprint.cs | 16 ++++++++++------ .../Edit/Blueprints/NoteSelectionBlueprint.cs | 4 +++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs index 5aaf4c09fd..acce41db6f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteNoteSelectionBlueprint.cs @@ -26,13 +26,17 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail; + // Todo: This shouldn't exist, mania should not reference the drawable hitobject directly. + if (DrawableObject.IsLoaded) + { + DrawableNote note = position == HoldNotePosition.Start ? DrawableObject.Head : DrawableObject.Tail; - Anchor = note.Anchor; - Origin = note.Origin; + Anchor = note.Anchor; + Origin = note.Origin; - Size = note.DrawSize; - Position = note.DrawPosition; + Size = note.DrawSize; + Position = note.DrawPosition; + } } // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index 244cfa0b69..56c0b671a0 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -54,13 +54,17 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Size = DrawableObject.DrawSize + new Vector2(0, DrawableObject.Tail.DrawHeight); + // Todo: This shouldn't exist, mania should not reference the drawable hitobject directly. + if (DrawableObject.IsLoaded) + { + Size = DrawableObject.DrawSize + new Vector2(0, DrawableObject.Tail.DrawHeight); - // This is a side-effect of not matching the hitobject's anchors/origins, which is kinda hard to do - // When scrolling upwards our origin is already at the top of the head note (which is the intended location), - // but when scrolling downwards our origin is at the _bottom_ of the tail note (where we need to be at the _top_ of the tail note) - if (direction.Value == ScrollingDirection.Down) - Y -= DrawableObject.Tail.DrawHeight; + // This is a side-effect of not matching the hitobject's anchors/origins, which is kinda hard to do + // When scrolling upwards our origin is already at the top of the head note (which is the intended location), + // but when scrolling downwards our origin is at the _bottom_ of the tail note (where we need to be at the _top_ of the tail note) + if (direction.Value == ScrollingDirection.Down) + Y -= DrawableObject.Tail.DrawHeight; + } } public override Quad SelectionQuad => ScreenSpaceDrawQuad; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs index b83c4aa9aa..2bff33c4cf 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs @@ -19,7 +19,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - Size = DrawableObject.DrawSize; + // Todo: This shouldn't exist, mania should not reference the drawable hitobject directly. + if (DrawableObject.IsLoaded) + Size = DrawableObject.DrawSize; } } } From b1da81571f77132b4267c92b217d5c7ca5c4916e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 14:00:12 +0900 Subject: [PATCH 189/503] Implement slider head control point snapping --- .../Sliders/Components/PathControlPointPiece.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 0353ba241c..155e814596 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osuTK; using osuTK.Graphics; @@ -29,6 +30,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components private readonly Container marker; private readonly Drawable markerRing; + [Resolved(CanBeNull = true)] + private IDistanceSnapProvider snapProvider { get; set; } + [Resolved] private OsuColour colours { get; set; } @@ -146,12 +150,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components if (Index == 0) { - // Special handling for the head - only the position of the slider changes - slider.Position += e.Delta; + // Special handling for the head control point - the position of the slider changes which means the snapped position and time have to be taken into account + (Vector2 snappedPosition, double snappedTime) = snapProvider?.GetSnappedPosition(e.MousePosition, slider.StartTime) ?? (e.MousePosition, slider.StartTime); + Vector2 movementDelta = snappedPosition - slider.Position; + + slider.Position += movementDelta; + slider.StartTime = snappedTime; // Since control points are relative to the position of the slider, they all need to be offset backwards by the delta for (int i = 1; i < newControlPoints.Length; i++) - newControlPoints[i] -= e.Delta; + newControlPoints[i] -= movementDelta; } else newControlPoints[Index] += e.Delta; From f3ddc4c00b60c3e08b68de08f6409ea967df58ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 14:08:02 +0900 Subject: [PATCH 190/503] Advance editor clock after a snapped placement --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1c942e52ce..805fc2b46f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -40,6 +40,9 @@ namespace osu.Game.Rulesets.Edit [Resolved] protected IFrameBasedClock EditorClock { get; private set; } + [Resolved] + private IAdjustableClock adjustableClock { get; set; } + [Resolved] private BindableBeatDivisor beatDivisor { get; set; } @@ -256,6 +259,9 @@ namespace osu.Game.Rulesets.Edit public void EndPlacement(HitObject hitObject) { EditorBeatmap.Add(hitObject); + + adjustableClock.Seek(hitObject.StartTime); + showGridFor(Enumerable.Empty()); } From f2084df0bb25c9336237f47de7c6d6e4434cb18d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2019 06:19:49 +0000 Subject: [PATCH 191/503] Bump Microsoft.NET.Test.Sdk from 16.3.0 to 16.4.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.3.0 to 16.4.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v16.3...v16.4.0) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 4b629902cb..1dbe9b39ee 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 30511d672d..8fc4dbfe72 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 3aea9e0387..fddf176fd0 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 717e795112..b5bd384e05 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index aa29fc802c..c5998c9cfc 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,7 +3,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 371ffcdf9e..d58a724c27 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -5,7 +5,7 @@ - + From 20d6eceecff465a37d8c6f9a602ec3fe48ad40bb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 16:03:35 +0900 Subject: [PATCH 192/503] Move DrawableOsuMenuItem out of OsuMenu --- .../UserInterface/DrawableOsuMenuItem.cs | 133 ++++++++++++++++++ osu.Game/Graphics/UserInterface/OsuMenu.cs | 123 ---------------- 2 files changed, 133 insertions(+), 123 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs new file mode 100644 index 0000000000..efa0b3d69c --- /dev/null +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -0,0 +1,133 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; +using osuTK.Graphics; + +namespace osu.Game.Graphics.UserInterface +{ + public class DrawableOsuMenuItem : Menu.DrawableMenuItem + { + private const int margin_horizontal = 17; + private const int text_size = 17; + private const int transition_length = 80; + public const int MARGIN_VERTICAL = 4; + + private SampleChannel sampleClick; + private SampleChannel sampleHover; + + private TextContainer text; + + public DrawableOsuMenuItem(MenuItem item) + : base(item) + { + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleHover = audio.Samples.Get(@"UI/generic-hover"); + sampleClick = audio.Samples.Get(@"UI/generic-select"); + + BackgroundColour = Color4.Transparent; + BackgroundColourHover = OsuColour.FromHex(@"172023"); + + updateTextColour(); + } + + private void updateTextColour() + { + switch ((Item as OsuMenuItem)?.Type) + { + default: + case MenuItemType.Standard: + text.Colour = Color4.White; + break; + + case MenuItemType.Destructive: + text.Colour = Color4.Red; + break; + + case MenuItemType.Highlighted: + text.Colour = OsuColour.FromHex(@"ffcc22"); + break; + } + } + + protected override bool OnHover(HoverEvent e) + { + sampleHover.Play(); + text.BoldText.FadeIn(transition_length, Easing.OutQuint); + text.NormalText.FadeOut(transition_length, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + text.BoldText.FadeOut(transition_length, Easing.OutQuint); + text.NormalText.FadeIn(transition_length, Easing.OutQuint); + base.OnHoverLost(e); + } + + protected override bool OnClick(ClickEvent e) + { + sampleClick.Play(); + return base.OnClick(e); + } + + protected sealed override Drawable CreateContent() => text = CreateTextContainer(); + protected virtual TextContainer CreateTextContainer() => new TextContainer(); + + protected class TextContainer : Container, IHasText + { + public string Text + { + get => NormalText.Text; + set + { + NormalText.Text = value; + BoldText.Text = value; + } + } + + public readonly SpriteText NormalText; + public readonly SpriteText BoldText; + + public TextContainer() + { + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + NormalText = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: text_size), + Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + }, + BoldText = new OsuSpriteText + { + AlwaysPresent = true, + Alpha = 0, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), + Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + } + }; + } + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index c4c6950eb1..be642e6afb 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,18 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osuTK; namespace osu.Game.Graphics.UserInterface @@ -53,122 +47,5 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Direction == Direction.Horizontal ? Anchor.BottomLeft : Anchor.TopRight }; - - protected class DrawableOsuMenuItem : DrawableMenuItem - { - private const int margin_horizontal = 17; - private const int text_size = 17; - private const int transition_length = 80; - public const int MARGIN_VERTICAL = 4; - - private SampleChannel sampleClick; - private SampleChannel sampleHover; - - private TextContainer text; - - public DrawableOsuMenuItem(MenuItem item) - : base(item) - { - } - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - sampleHover = audio.Samples.Get(@"UI/generic-hover"); - sampleClick = audio.Samples.Get(@"UI/generic-select"); - - BackgroundColour = Color4.Transparent; - BackgroundColourHover = OsuColour.FromHex(@"172023"); - - updateTextColour(); - } - - private void updateTextColour() - { - switch ((Item as OsuMenuItem)?.Type) - { - default: - case MenuItemType.Standard: - text.Colour = Color4.White; - break; - - case MenuItemType.Destructive: - text.Colour = Color4.Red; - break; - - case MenuItemType.Highlighted: - text.Colour = OsuColour.FromHex(@"ffcc22"); - break; - } - } - - protected override bool OnHover(HoverEvent e) - { - sampleHover.Play(); - text.BoldText.FadeIn(transition_length, Easing.OutQuint); - text.NormalText.FadeOut(transition_length, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - text.BoldText.FadeOut(transition_length, Easing.OutQuint); - text.NormalText.FadeIn(transition_length, Easing.OutQuint); - base.OnHoverLost(e); - } - - protected override bool OnClick(ClickEvent e) - { - sampleClick.Play(); - return base.OnClick(e); - } - - protected sealed override Drawable CreateContent() => text = CreateTextContainer(); - protected virtual TextContainer CreateTextContainer() => new TextContainer(); - - protected class TextContainer : Container, IHasText - { - public string Text - { - get => NormalText.Text; - set - { - NormalText.Text = value; - BoldText.Text = value; - } - } - - public readonly SpriteText NormalText; - public readonly SpriteText BoldText; - - public TextContainer() - { - Anchor = Anchor.CentreLeft; - Origin = Anchor.CentreLeft; - - AutoSizeAxes = Axes.Both; - - Children = new Drawable[] - { - NormalText = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: text_size), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, - }, - BoldText = new OsuSpriteText - { - AlwaysPresent = true, - Alpha = 0, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, - } - }; - } - } - } } } From 29672c48e126bb39829426f4174be8207e0f0bc6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 16:04:13 +0900 Subject: [PATCH 193/503] Make simple OsuMenuItem ctor invoke the complex one --- osu.Game/Graphics/UserInterface/OsuMenuItem.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs index b7aa666302..0fe41937ce 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs @@ -11,9 +11,8 @@ namespace osu.Game.Graphics.UserInterface public readonly MenuItemType Type; public OsuMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : base(text) + : this(text, type, null) { - Type = type; } public OsuMenuItem(string text, MenuItemType type, Action action) From c3a3b4091bfd92841521822191b1caea5f6730fb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 22:26:35 +0900 Subject: [PATCH 194/503] Add basic implementation of a toggleable menu item --- .../UserInterface/TestSceneToggleMenuItem.cs | 33 ++++++++++ .../UserInterface/DrawableOsuMenuItem.cs | 8 +-- .../UserInterface/DrawableToggleMenuItem.cs | 60 +++++++++++++++++++ osu.Game/Graphics/UserInterface/OsuMenu.cs | 11 +++- .../Graphics/UserInterface/ToggleMenuItem.cs | 25 ++++++++ 5 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs create mode 100644 osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs create mode 100644 osu.Game/Graphics/UserInterface/ToggleMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs new file mode 100644 index 0000000000..97257b5226 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneToggleMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ToggleMenuItem), + typeof(DrawableToggleMenuItem) + }; + + public TestSceneToggleMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ToggleMenuItem("Toggle"), + } + }); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs index efa0b3d69c..591ed3df83 100644 --- a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -16,10 +16,10 @@ namespace osu.Game.Graphics.UserInterface { public class DrawableOsuMenuItem : Menu.DrawableMenuItem { - private const int margin_horizontal = 17; + public const int MARGIN_HORIZONTAL = 17; + public const int MARGIN_VERTICAL = 4; private const int text_size = 17; private const int transition_length = 80; - public const int MARGIN_VERTICAL = 4; private SampleChannel sampleClick; private SampleChannel sampleHover; @@ -115,7 +115,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: text_size), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL }, }, BoldText = new OsuSpriteText { @@ -124,7 +124,7 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), - Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, + Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL }, } }; } diff --git a/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs new file mode 100644 index 0000000000..cf0f154486 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs @@ -0,0 +1,60 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public class DrawableToggleMenuItem : DrawableOsuMenuItem + { + protected new ToggleMenuItem Item => (ToggleMenuItem)base.Item; + + public DrawableToggleMenuItem(ToggleMenuItem item) + : base(item) + { + } + + protected override TextContainer CreateTextContainer() => new ToggleTextContainer + { + State = { BindTarget = Item.State } + }; + + private class ToggleTextContainer : TextContainer + { + public readonly Bindable State = new Bindable(); + + private readonly SpriteIcon checkmark; + + public ToggleTextContainer() + { + Add(checkmark = new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.Check, + Size = new Vector2(10), + Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL }, + AlwaysPresent = true, + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + State.BindValueChanged(state => checkmark.Alpha = state.NewValue ? 1 : 0, true); + } + + protected override void Update() + { + base.Update(); + + // Todo: This is bad. This can maybe be done better with a refactor of DrawableOsuMenuItem. + checkmark.X = BoldText.DrawWidth + 10; + } + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index be642e6afb..da32a2c861 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -39,7 +39,16 @@ namespace osu.Game.Graphics.UserInterface } } - protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item) => new DrawableOsuMenuItem(item); + protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item) + { + switch (item) + { + case ToggleMenuItem toggle: + return new DrawableToggleMenuItem(toggle); + } + + return new DrawableOsuMenuItem(item); + } protected override ScrollContainer CreateScrollContainer(Direction direction) => new OsuScrollContainer(direction); diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs new file mode 100644 index 0000000000..7b2bb32f47 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Bindables; + +namespace osu.Game.Graphics.UserInterface +{ + public class ToggleMenuItem : OsuMenuItem + { + public readonly BindableBool State = new BindableBool(); + + public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : this(text, type, null) + { + } + + public ToggleMenuItem(string text, MenuItemType type, Action action) + : base(text, type) + { + Action.Value = () => State.Toggle(); + State.BindValueChanged(state => action?.Invoke(state.NewValue)); + } + } +} From 5235d2b3191948818b2e744083b3683a51ab9975 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 7 Nov 2019 14:38:06 -0800 Subject: [PATCH 195/503] Fix home button not closing login and now playing overlays --- osu.Game/OsuGame.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f823e6eba..3980390611 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -601,14 +601,14 @@ namespace osu.Game loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - loadComponentSingleFile(new LoginOverlay + var login = loadComponentSingleFile(new LoginOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - loadComponentSingleFile(new NowPlayingOverlay + var nowPlaying = loadComponentSingleFile(new NowPlayingOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -671,6 +671,8 @@ namespace osu.Game }; } + overlays.AddRange(new OverlayContainer[] { login, nowPlaying }); + OverlayActivationMode.ValueChanged += mode => { if (mode.NewValue != OverlayActivation.All) CloseAllOverlays(); From 4fe69dbc896d77fd1efea4c469254fdbb3563fe0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 11:13:53 +0900 Subject: [PATCH 196/503] Fix context menu sub-menu display --- osu.Game/Graphics/UserInterface/OsuContextMenu.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index cea8427296..4b629080e1 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterface { @@ -35,5 +36,7 @@ namespace osu.Game.Graphics.UserInterface protected override void AnimateOpen() => this.FadeIn(fade_duration, Easing.OutQuint); protected override void AnimateClose() => this.FadeOut(fade_duration, Easing.OutQuint); + + protected override Menu CreateSubMenu() => new OsuContextMenu(); } } From ce08d664a52fef8633accc8f11b53ecb7d758906 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 11:15:03 +0900 Subject: [PATCH 197/503] Abstract statefulness of new menu item type --- .../TestSceneStatefulMenuItem.cs | 90 +++++++++++++++++++ .../UserInterface/TestSceneToggleMenuItem.cs | 33 ------- ...enuItem.cs => DrawableStatefulMenuItem.cs} | 44 +++++---- osu.Game/Graphics/UserInterface/OsuMenu.cs | 4 +- .../UserInterface/StatefulMenuItem.cs | 56 ++++++++++++ .../Graphics/UserInterface/ToggleMenuItem.cs | 11 ++- 6 files changed, 181 insertions(+), 57 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs rename osu.Game/Graphics/UserInterface/{DrawableToggleMenuItem.cs => DrawableStatefulMenuItem.cs} (51%) create mode 100644 osu.Game/Graphics/UserInterface/StatefulMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs new file mode 100644 index 0000000000..fbb35ba09f --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -0,0 +1,90 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneStatefulMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ToggleMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + public TestSceneStatefulMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new TestMenuItem("First", MenuItemType.Standard, getNextState), + new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } }, + new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } }, + } + }); + } + + private TestStates getNextState(TestStates state) + { + switch (state) + { + case TestStates.State1: + return TestStates.State2; + + case TestStates.State2: + return TestStates.State3; + + case TestStates.State3: + return TestStates.State1; + } + + return TestStates.State1; + } + + private class TestMenuItem : StatefulMenuItem + { + public TestMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : base(text, type) + { + } + + public TestMenuItem(string text, MenuItemType type, Func changeStateFunc) + : base(text, type, changeStateFunc) + { + } + + public override IconUsage? GetIconForState(TestStates state) + { + switch (state) + { + case TestStates.State1: + return FontAwesome.Solid.DiceOne; + + case TestStates.State2: + return FontAwesome.Solid.DiceTwo; + + case TestStates.State3: + return FontAwesome.Solid.DiceThree; + } + + return null; + } + } + + private enum TestStates + { + State1, + State2, + State3 + } + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs deleted file mode 100644 index 97257b5226..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneToggleMenuItem : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(OsuMenu), - typeof(ToggleMenuItem), - typeof(DrawableToggleMenuItem) - }; - - public TestSceneToggleMenuItem() - { - Add(new OsuMenu(Direction.Vertical, true) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] - { - new ToggleMenuItem("Toggle"), - } - }); - } - } -} diff --git a/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs similarity index 51% rename from osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs rename to osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs index cf0f154486..3dc99f2dbe 100644 --- a/osu.Game/Graphics/UserInterface/DrawableToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs @@ -8,33 +8,33 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class DrawableToggleMenuItem : DrawableOsuMenuItem + public class DrawableStatefulMenuItem : DrawableOsuMenuItem { - protected new ToggleMenuItem Item => (ToggleMenuItem)base.Item; + protected new StatefulMenuItem Item => (StatefulMenuItem)base.Item; - public DrawableToggleMenuItem(ToggleMenuItem item) + public DrawableStatefulMenuItem(StatefulMenuItem item) : base(item) { } - protected override TextContainer CreateTextContainer() => new ToggleTextContainer - { - State = { BindTarget = Item.State } - }; + protected override TextContainer CreateTextContainer() => new ToggleTextContainer(Item); private class ToggleTextContainer : TextContainer { - public readonly Bindable State = new Bindable(); + private readonly StatefulMenuItem menuItem; + private readonly Bindable state; + private readonly SpriteIcon stateIcon; - private readonly SpriteIcon checkmark; - - public ToggleTextContainer() + public ToggleTextContainer(StatefulMenuItem menuItem) { - Add(checkmark = new SpriteIcon + this.menuItem = menuItem; + + state = menuItem.State.GetBoundCopy(); + + Add(stateIcon = new SpriteIcon { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Icon = FontAwesome.Solid.Check, Size = new Vector2(10), Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL }, AlwaysPresent = true, @@ -44,8 +44,7 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { base.LoadComplete(); - - State.BindValueChanged(state => checkmark.Alpha = state.NewValue ? 1 : 0, true); + state.BindValueChanged(updateState, true); } protected override void Update() @@ -53,7 +52,20 @@ namespace osu.Game.Graphics.UserInterface base.Update(); // Todo: This is bad. This can maybe be done better with a refactor of DrawableOsuMenuItem. - checkmark.X = BoldText.DrawWidth + 10; + stateIcon.X = BoldText.DrawWidth + 10; + } + + private void updateState(ValueChangedEvent state) + { + var icon = menuItem.GetIconForState(state.NewValue); + + if (icon == null) + stateIcon.Alpha = 0; + else + { + stateIcon.Alpha = 1; + stateIcon.Icon = icon.Value; + } } } } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index da32a2c861..e7bf4f66ee 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -43,8 +43,8 @@ namespace osu.Game.Graphics.UserInterface { switch (item) { - case ToggleMenuItem toggle: - return new DrawableToggleMenuItem(toggle); + case StatefulMenuItem stateful: + return new DrawableStatefulMenuItem(stateful); } return new DrawableOsuMenuItem(item); diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs new file mode 100644 index 0000000000..ede2c9df48 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics.UserInterface +{ + public abstract class StatefulMenuItem : OsuMenuItem + { + public readonly Bindable State = new Bindable(); + + protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : this(text, type, null) + { + } + + protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) + : base(text, type) + { + Action.Value = () => State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value; + } + + public abstract IconUsage? GetIconForState(object state); + } + + public abstract class StatefulMenuItem : StatefulMenuItem + where T : struct + { + public new readonly Bindable State = new Bindable(); + + protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : this(text, type, null) + { + } + + protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) + : base(text, type, o => changeStateFunc?.Invoke((T)o) ?? o) + { + base.State.BindValueChanged(state => + { + if (state.NewValue == null) + base.State.Value = default(T); + + State.Value = (T)base.State.Value; + }, true); + + State.BindValueChanged(state => base.State.Value = state.NewValue); + } + + public sealed override IconUsage? GetIconForState(object state) => GetIconForState((T)state); + + public abstract IconUsage? GetIconForState(T state); + } +} diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index 7b2bb32f47..a0ed745c5a 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -2,24 +2,23 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Bindables; +using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public class ToggleMenuItem : OsuMenuItem + public class ToggleMenuItem : StatefulMenuItem { - public readonly BindableBool State = new BindableBool(); - public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } public ToggleMenuItem(string text, MenuItemType type, Action action) - : base(text, type) + : base(text, type, value => !value) { - Action.Value = () => State.Toggle(); State.BindValueChanged(state => action?.Invoke(state.NewValue)); } + + public override IconUsage? GetIconForState(bool state) => state ? (IconUsage?)FontAwesome.Solid.Check : null; } } From 30f877c4ab7751066bd6a0ca2dc45178de355b69 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 12:47:42 +0900 Subject: [PATCH 198/503] Implement a three-state menu item --- .../TestSceneThreeStateMenuItem.cs | 35 ++++++++++++ .../UserInterface/ThreeStateMenuItem.cs | 53 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs create mode 100644 osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs new file mode 100644 index 0000000000..caa07e7b60 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneThreeStateMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ThreeStateMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + public TestSceneThreeStateMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ThreeStateMenuItem("First"), + new ThreeStateMenuItem("Second") { State = { Value = ThreeStates.Indeterminate } }, + new ThreeStateMenuItem("Third") { State = { Value = ThreeStates.Enabled } }, + } + }); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs new file mode 100644 index 0000000000..107bfe208b --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics.UserInterface +{ + public class ThreeStateMenuItem : StatefulMenuItem + { + public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) + : base(text, type, getNextState) + { + } + + public override IconUsage? GetIconForState(ThreeStates state) + { + switch (state) + { + case ThreeStates.Indeterminate: + return FontAwesome.Regular.Circle; + + case ThreeStates.Enabled: + return FontAwesome.Solid.Check; + } + + return null; + } + + private static ThreeStates getNextState(ThreeStates state) + { + switch (state) + { + case ThreeStates.Disabled: + return ThreeStates.Enabled; + + case ThreeStates.Indeterminate: + return ThreeStates.Enabled; + + case ThreeStates.Enabled: + return ThreeStates.Disabled; + } + + return ThreeStates.Disabled; + } + } + + public enum ThreeStates + { + Disabled, + Indeterminate, + Enabled + } +} From 0a15a13fabd66d5676dfd12e1117772a31ae605a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 12:55:22 +0900 Subject: [PATCH 199/503] Reorder parameters --- .../TestSceneStatefulMenuItem.cs | 4 ++-- .../UserInterface/StatefulMenuItem.cs | 20 +++++++++++-------- .../UserInterface/ThreeStateMenuItem.cs | 8 +++++++- .../Graphics/UserInterface/ToggleMenuItem.cs | 3 +-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index fbb35ba09f..00678a6ab4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -53,12 +53,12 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestMenuItem : StatefulMenuItem { public TestMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : base(text, type) + : this(text, type, null) { } public TestMenuItem(string text, MenuItemType type, Func changeStateFunc) - : base(text, type, changeStateFunc) + : base(text, changeStateFunc, type) { } diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs index ede2c9df48..b5f9a3d635 100644 --- a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs @@ -11,15 +11,19 @@ namespace osu.Game.Graphics.UserInterface { public readonly Bindable State = new Bindable(); - protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : this(text, type, null) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) + : this(text, changeStateFunc, type, null) { } - protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, type) { - Action.Value = () => State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value; + Action.Value = () => + { + State.Value = changeStateFunc?.Invoke(State.Value) ?? State.Value; + action?.Invoke(State.Value); + }; } public abstract IconUsage? GetIconForState(object state); @@ -30,13 +34,13 @@ namespace osu.Game.Graphics.UserInterface { public new readonly Bindable State = new Bindable(); - protected StatefulMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : this(text, type, null) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) + : this(text, changeStateFunc, type, null) { } - protected StatefulMenuItem(string text, MenuItemType type, Func changeStateFunc) - : base(text, type, o => changeStateFunc?.Invoke((T)o) ?? o) + protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + : base(text, o => changeStateFunc?.Invoke((T)o) ?? o, type, o => action?.Invoke((T)o)) { base.State.BindValueChanged(state => { diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index 107bfe208b..d41a95daa1 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface @@ -8,7 +9,12 @@ namespace osu.Game.Graphics.UserInterface public class ThreeStateMenuItem : StatefulMenuItem { public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : base(text, type, getNextState) + : this(text, type, null) + { + } + + public ThreeStateMenuItem(string text, MenuItemType type, Action action) + : base(text, getNextState, type, action) { } diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index a0ed745c5a..f5a442b317 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -14,9 +14,8 @@ namespace osu.Game.Graphics.UserInterface } public ToggleMenuItem(string text, MenuItemType type, Action action) - : base(text, type, value => !value) + : base(text, value => !value, type, action) { - State.BindValueChanged(state => action?.Invoke(state.NewValue)); } public override IconUsage? GetIconForState(bool state) => state ? (IconUsage?)FontAwesome.Solid.Check : null; From 011bf095166d88d560087bbf83d07567309c585f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:14:23 +0900 Subject: [PATCH 200/503] Add xmldocs and cleanup --- .../TestSceneStatefulMenuItem.cs | 5 ++- .../UserInterface/StatefulMenuItem.cs | 45 +++++++++++++++++++ .../UserInterface/ThreeStateMenuItem.cs | 45 +++++++++++++++++-- .../Graphics/UserInterface/ToggleMenuItem.cs | 14 ++++++ 4 files changed, 104 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 00678a6ab4..d010abc862 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -74,9 +74,10 @@ namespace osu.Game.Tests.Visual.UserInterface case TestStates.State3: return FontAwesome.Solid.DiceThree; - } - return null; + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); + } } } diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs index b5f9a3d635..0d7b36e51b 100644 --- a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs @@ -7,15 +7,34 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { + /// + /// An which contains and displays a state. + /// public abstract class StatefulMenuItem : OsuMenuItem { + /// + /// The current state that should be displayed. + /// public readonly Bindable State = new Bindable(); + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, type) { @@ -26,19 +45,40 @@ namespace osu.Game.Graphics.UserInterface }; } + /// + /// Retrieves the icon to be displayed for a state. + /// + /// The state to retrieve the relevant icon for. + /// The icon to be displayed for . public abstract IconUsage? GetIconForState(object state); } public abstract class StatefulMenuItem : StatefulMenuItem where T : struct { + /// + /// The current state that should be displayed. + /// public new readonly Bindable State = new Bindable(); + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type = MenuItemType.Standard) : this(text, changeStateFunc, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. protected StatefulMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, o => changeStateFunc?.Invoke((T)o) ?? o, type, o => action?.Invoke((T)o)) { @@ -55,6 +95,11 @@ namespace osu.Game.Graphics.UserInterface public sealed override IconUsage? GetIconForState(object state) => GetIconForState((T)state); + /// + /// Retrieves the icon to be displayed for a state. + /// + /// The state to retrieve the relevant icon for. + /// The icon to be displayed for . public abstract IconUsage? GetIconForState(T state); } } diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index d41a95daa1..e33c68bebd 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -6,15 +6,41 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { + /// + /// An with three possible states. + /// public class ThreeStateMenuItem : StatefulMenuItem { + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. public ThreeStateMenuItem(string text, MenuItemType type, Action action) - : base(text, getNextState, type, action) + : this(text, getNextState, type, action) + { + } + + /// + /// Creates a new . + /// + /// The text to display. + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. + protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + : base(text, changeStateFunc, type, action) { } @@ -44,16 +70,29 @@ namespace osu.Game.Graphics.UserInterface case ThreeStates.Enabled: return ThreeStates.Disabled; - } - return ThreeStates.Disabled; + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); + } } } public enum ThreeStates { + /// + /// The current state is disabled. + /// Disabled, + + /// + /// The current state is a combination of and . + /// The state becomes if the is pressed. + /// Indeterminate, + + /// + /// The current state is enabled. + /// Enabled } } diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index f5a442b317..f9ff9859dd 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -6,13 +6,27 @@ using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { + /// + /// An which displays an enabled or disabled state. + /// public class ToggleMenuItem : StatefulMenuItem { + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. public ToggleMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } + /// + /// Creates a new . + /// + /// The text to display. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. public ToggleMenuItem(string text, MenuItemType type, Action action) : base(text, value => !value, type, action) { From a2c265c1478f1b33937d8da76343eabd688046ad Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:16:09 +0900 Subject: [PATCH 201/503] Separate ThreeStates into its own file --- .../UserInterface/ThreeStateMenuItem.cs | 19 ------------- .../Graphics/UserInterface/ThreeStates.cs | 27 +++++++++++++++++++ 2 files changed, 27 insertions(+), 19 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/ThreeStates.cs diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index e33c68bebd..ebb6436196 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -76,23 +76,4 @@ namespace osu.Game.Graphics.UserInterface } } } - - public enum ThreeStates - { - /// - /// The current state is disabled. - /// - Disabled, - - /// - /// The current state is a combination of and . - /// The state becomes if the is pressed. - /// - Indeterminate, - - /// - /// The current state is enabled. - /// - Enabled - } } diff --git a/osu.Game/Graphics/UserInterface/ThreeStates.cs b/osu.Game/Graphics/UserInterface/ThreeStates.cs new file mode 100644 index 0000000000..f099250937 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ThreeStates.cs @@ -0,0 +1,27 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// An on/off state with an extra indeterminate state. + /// + public enum ThreeStates + { + /// + /// The current state is disabled. + /// + Disabled, + + /// + /// The current state is a combination of and . + /// The state becomes if the is pressed. + /// + Indeterminate, + + /// + /// The current state is enabled. + /// + Enabled + } +} From e574aa0e94ee16366a7c4086f2eb80042edb494f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:33:15 +0900 Subject: [PATCH 202/503] Add toggle menu item test --- .../UserInterface/TestSceneToggleMenuItem.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs new file mode 100644 index 0000000000..2abda56a28 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneToggleMenuItem : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ToggleMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + public TestSceneToggleMenuItem() + { + Add(new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ToggleMenuItem("First"), + new ToggleMenuItem("Second") { State = { Value = true } } + } + }); + } + } +} From 92d8526370e8cdc166460b30c58e0d47c4cc2654 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:34:27 +0900 Subject: [PATCH 203/503] Adjust test namespaces --- .../{ => MenuItems}/TestSceneStatefulMenuItem.cs | 4 ++-- .../{ => MenuItems}/TestSceneThreeStateMenuItem.cs | 2 +- .../UserInterface/{ => MenuItems}/TestSceneToggleMenuItem.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{ => MenuItems}/TestSceneStatefulMenuItem.cs (96%) rename osu.Game.Tests/Visual/UserInterface/{ => MenuItems}/TestSceneThreeStateMenuItem.cs (95%) rename osu.Game.Tests/Visual/UserInterface/{ => MenuItems}/TestSceneToggleMenuItem.cs (94%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs similarity index 96% rename from osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs index d010abc862..95e9aea97f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs @@ -7,14 +7,14 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface +namespace osu.Game.Tests.Visual.UserInterface.MenuItems { public class TestSceneStatefulMenuItem : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(OsuMenu), - typeof(ToggleMenuItem), + typeof(StatefulMenuItem), typeof(DrawableStatefulMenuItem) }; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs similarity index 95% rename from osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs index caa07e7b60..e035e43630 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface +namespace osu.Game.Tests.Visual.UserInterface.MenuItems { public class TestSceneThreeStateMenuItem : OsuTestScene { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs similarity index 94% rename from osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs index 2abda56a28..92875740cf 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface +namespace osu.Game.Tests.Visual.UserInterface.MenuItems { public class TestSceneToggleMenuItem : OsuTestScene { From abb3a6ca5bf610f50ff8519a4847bf1b650a2c67 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Nov 2019 22:51:49 +0900 Subject: [PATCH 204/503] Initial right click context menu implementation --- .../Compose/Components/BlueprintContainer.cs | 22 +++ .../Compose/Components/SelectionHandler.cs | 67 +++++++- osu.Game/Screens/Edit/Editor.cs | 143 +++++++++--------- 3 files changed, 162 insertions(+), 70 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 8fa022f129..af0ac22a70 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; +using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { @@ -95,12 +96,18 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseDown(MouseDownEvent e) { + if (e.Button == MouseButton.Right) + return false; + beginClickSelection(e); return true; } protected override bool OnClick(ClickEvent e) { + if (e.Button == MouseButton.Right) + return false; + // Deselection should only occur if no selected blueprints are hovered // A special case for when a blueprint was selected via this click is added since OnClick() may occur outside the hitobject and should not trigger deselection if (endClickSelection() || selectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) @@ -112,6 +119,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDoubleClick(DoubleClickEvent e) { + if (e.Button == MouseButton.Right) + return false; + SelectionBlueprint clickedBlueprint = selectionHandler.SelectedBlueprints.FirstOrDefault(b => b.IsHovered); if (clickedBlueprint == null) @@ -123,6 +133,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseUp(MouseUpEvent e) { + if (e.Button == MouseButton.Right) + return false; + // Special case for when a drag happened instead of a click Schedule(() => endClickSelection()); return true; @@ -141,6 +154,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDragStart(DragStartEvent e) { + if (e.Button == MouseButton.Right) + return false; + if (!beginSelectionMovement()) { dragBox.UpdateDrag(e); @@ -152,6 +168,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDrag(DragEvent e) { + if (e.Button == MouseButton.Right) + return false; + if (!moveCurrentSelection(e)) dragBox.UpdateDrag(e); @@ -160,6 +179,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnDragEnd(DragEndEvent e) { + if (e.Button == MouseButton.Right) + return false; + if (!finishSelectionMovement()) { dragBox.FadeOut(250, Easing.OutQuint); diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 44bf22cfe1..779cd86318 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -7,11 +7,16 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Framework.Input.States; +using osu.Game.Audio; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -22,7 +27,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A component which outlines s and handles movement of selections. /// - public class SelectionHandler : CompositeDrawable, IKeyBindingHandler + public class SelectionHandler : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { public const float BORDER_RADIUS = 2; @@ -142,6 +147,8 @@ namespace osu.Game.Screens.Edit.Compose.Components #endregion + #region Outline Display + /// /// Updates whether this is visible. /// @@ -176,5 +183,63 @@ namespace osu.Game.Screens.Edit.Compose.Components outline.Size = bottomRight - topLeft; outline.Position = topLeft; } + + #endregion + + #region Context Menu + + public virtual MenuItem[] ContextMenuItems + { + get + { + if (!SelectedBlueprints.Any()) + return Array.Empty(); + + return new MenuItem[] + { + new OsuMenuItem("hit sound") + { + Items = new[] + { + createHitSampleMenuItem(HitSampleInfo.HIT_WHISTLE), + createHitSampleMenuItem(HitSampleInfo.HIT_CLAP), + createHitSampleMenuItem(HitSampleInfo.HIT_FINISH) + } + } + }; + } + } + + private MenuItem createHitSampleMenuItem(string sampleName) + { + return new ToggleMenuItem(sampleName, MenuItemType.Standard, setHitSampleState) + { + State = { Value = getHitSampleState() } + }; + + void setHitSampleState(bool enabled) + { + if (enabled) + { + foreach (var h in SelectedHitObjects) + { + // Make sure there isn't already an existing sample + if (h.Samples.Any(s => s.Name == sampleName)) + continue; + + h.Samples.Add(new HitSampleInfo { Name = sampleName }); + } + } + else + { + foreach (var h in SelectedHitObjects) + h.Samples.RemoveAll(s => s.Name == sampleName); + } + } + + bool getHitSampleState() => SelectedHitObjects.All(h => h.Samples.Any(s => s.Name == sampleName)); + } + + #endregion } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..1ae3fd71ab 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -24,6 +24,7 @@ using osuTK.Input; using System.Collections.Generic; using osu.Framework; using osu.Framework.Input.Bindings; +using osu.Game.Graphics.Cursor; using osu.Game.Input.Bindings; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Setup; @@ -85,87 +86,91 @@ namespace osu.Game.Screens.Edit fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)); - InternalChildren = new[] + InternalChild = new OsuContextMenuContainer { - new Container + RelativeSizeAxes = Axes.Both, + Children = new[] { - Name = "Screen container", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 40, Bottom = 60 }, - Child = screenContainer = new Container + new Container { + Name = "Screen container", RelativeSizeAxes = Axes.Both, - Masking = true - } - }, - new Container - { - Name = "Top bar", - RelativeSizeAxes = Axes.X, - Height = 40, - Child = menuBar = new EditorMenuBar - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Both, - Items = new[] - { - new MenuItem("File") - { - Items = fileMenuItems - } - } - } - }, - new Container - { - Name = "Bottom bar", - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = 60, - Children = new Drawable[] - { - bottomBackground = new Box { RelativeSizeAxes = Axes.Both }, - new Container + Padding = new MarginPadding { Top = 40, Bottom = 60 }, + Child = screenContainer = new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Vertical = 5, Horizontal = 10 }, - Child = new GridContainer + Masking = true + } + }, + new Container + { + Name = "Top bar", + RelativeSizeAxes = Axes.X, + Height = 40, + Child = menuBar = new EditorMenuBar + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + Items = new[] + { + new MenuItem("File") + { + Items = fileMenuItems + } + } + } + }, + new Container + { + Name = "Bottom bar", + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = 60, + Children = new Drawable[] + { + bottomBackground = new Box { RelativeSizeAxes = Axes.Both }, + new Container { RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + Padding = new MarginPadding { Vertical = 5, Horizontal = 10 }, + Child = new GridContainer { - new Dimension(GridSizeMode.Absolute, 220), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 220) - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 10 }, - Child = new TimeInfoContainer { RelativeSizeAxes = Axes.Both }, - }, - new SummaryTimeline - { - RelativeSizeAxes = Axes.Both, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 10 }, - Child = new PlaybackControl { RelativeSizeAxes = Axes.Both }, - } + new Dimension(GridSizeMode.Absolute, 220), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 220) }, - } - }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 10 }, + Child = new TimeInfoContainer { RelativeSizeAxes = Axes.Both }, + }, + new SummaryTimeline + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 10 }, + Child = new PlaybackControl { RelativeSizeAxes = Axes.Both }, + } + }, + } + }, + } } - } - }, + }, + } }; menuBar.Mode.ValueChanged += onModeChanged; From 573d11503e27e7a99202a94ee08b2912e65bcb1f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 11:13:24 +0900 Subject: [PATCH 205/503] Remove unused using --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 779cd86318..43dbeb35f7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Audio; using osu.Game.Graphics; From 046f0b0fe5947f57ae312ee80c88e6e3d42b2529 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:40:47 +0900 Subject: [PATCH 206/503] Allow right-clicks to trigger selection --- .../Edit/Compose/Components/BlueprintContainer.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index af0ac22a70..e7877f962e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -96,11 +96,8 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button == MouseButton.Right) - return false; - beginClickSelection(e); - return true; + return e.Button == MouseButton.Left; } protected override bool OnClick(ClickEvent e) @@ -133,12 +130,9 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnMouseUp(MouseUpEvent e) { - if (e.Button == MouseButton.Right) - return false; - // Special case for when a drag happened instead of a click Schedule(() => endClickSelection()); - return true; + return e.Button == MouseButton.Left; } protected override bool OnMouseMove(MouseMoveEvent e) From 864b8db638b6b3a70eb3f6189d2a9761127b3e1d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 13:52:36 +0900 Subject: [PATCH 207/503] Use three states for the hitsound menu items --- .../Compose/Components/SelectionHandler.cs | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 43dbeb35f7..dc147a92cd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -196,47 +196,61 @@ namespace osu.Game.Screens.Edit.Compose.Components return new MenuItem[] { - new OsuMenuItem("hit sound") + new OsuMenuItem("Sound") { Items = new[] { - createHitSampleMenuItem(HitSampleInfo.HIT_WHISTLE), - createHitSampleMenuItem(HitSampleInfo.HIT_CLAP), - createHitSampleMenuItem(HitSampleInfo.HIT_FINISH) + createHitSampleMenuItem("Whistle", HitSampleInfo.HIT_WHISTLE), + createHitSampleMenuItem("Clap", HitSampleInfo.HIT_CLAP), + createHitSampleMenuItem("Finish", HitSampleInfo.HIT_FINISH) } } }; } } - private MenuItem createHitSampleMenuItem(string sampleName) + private MenuItem createHitSampleMenuItem(string name, string sampleName) { - return new ToggleMenuItem(sampleName, MenuItemType.Standard, setHitSampleState) + return new ThreeStateMenuItem(name, MenuItemType.Standard, setHitSampleState) { State = { Value = getHitSampleState() } }; - void setHitSampleState(bool enabled) + void setHitSampleState(ThreeStates state) { - if (enabled) + switch (state) { - foreach (var h in SelectedHitObjects) - { - // Make sure there isn't already an existing sample - if (h.Samples.Any(s => s.Name == sampleName)) - continue; + case ThreeStates.Disabled: + foreach (var h in SelectedHitObjects) + h.Samples.RemoveAll(s => s.Name == sampleName); + break; - h.Samples.Add(new HitSampleInfo { Name = sampleName }); - } - } - else - { - foreach (var h in SelectedHitObjects) - h.Samples.RemoveAll(s => s.Name == sampleName); + case ThreeStates.Enabled: + foreach (var h in SelectedHitObjects) + { + // Make sure there isn't already an existing sample + if (h.Samples.Any(s => s.Name == sampleName)) + continue; + + h.Samples.Add(new HitSampleInfo { Name = sampleName }); + } + + break; } } - bool getHitSampleState() => SelectedHitObjects.All(h => h.Samples.Any(s => s.Name == sampleName)); + ThreeStates getHitSampleState() + { + int countExisting = SelectedHitObjects.Count(h => h.Samples.Any(s => s.Name == sampleName)); + + if (countExisting == 0) + return ThreeStates.Disabled; + + if (countExisting < SelectedHitObjects.Count()) + return ThreeStates.Indeterminate; + + return ThreeStates.Enabled; + } } #endregion From 6fc1be64c2c4adbb7335288d765c77e3343a5e73 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 14:04:57 +0900 Subject: [PATCH 208/503] Make hitobject samples a bindable list --- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 2 +- .../Beatmaps/ManiaBeatmapConverter.cs | 2 +- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs | 6 +++--- osu.Game.Rulesets.Osu/Objects/Slider.cs | 6 +++--- .../Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- osu.Game/Rulesets/Objects/HitObject.cs | 12 ++++++++---- .../Objects/Legacy/Catch/ConvertHitObjectParser.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 4 ++-- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../Objects/Legacy/Mania/ConvertHitObjectParser.cs | 2 +- .../Objects/Legacy/Osu/ConvertHitObjectParser.cs | 2 +- .../Objects/Legacy/Taiko/ConvertHitObjectParser.cs | 2 +- osu.Game/Rulesets/Objects/Types/IHasRepeats.cs | 2 +- .../Edit/Compose/Components/SelectionHandler.cs | 3 ++- 15 files changed, 30 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 0952e8981a..80a3af0aa0 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Catch.Objects public double Distance => Path.Distance; - public List> NodeSamples { get; set; } = new List>(); + public List> NodeSamples { get; set; } = new List>(); public double? LegacyLastTickOffset { get; set; } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index e10602312e..6c5bb304bf 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -255,7 +255,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// /// The time to retrieve the sample info list from. /// - private List sampleInfoListAt(double time) + private IList sampleInfoListAt(double time) { var curveData = HitObject as IHasCurve; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index ea418eedb4..6297a68e08 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -472,7 +472,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// /// The time to retrieve the sample info list from. /// - private List sampleInfoListAt(double time) + private IList sampleInfoListAt(double time) { var curveData = HitObject as IHasCurve; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index a955911bd5..46a2a36ac7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable createCatmull(int repeats = 0) { - var repeatSamples = new List>(); + var repeatSamples = new List>(); for (int i = 0; i < repeats; i++) repeatSamples.Add(new List()); @@ -297,9 +297,9 @@ namespace osu.Game.Rulesets.Osu.Tests return createDrawable(slider, 3, 1); } - private List> createEmptySamples(int repeats) + private List> createEmptySamples(int repeats) { - var repeatSamples = new List>(); + var repeatSamples = new List>(); for (int i = 0; i < repeats; i++) repeatSamples.Add(new List()); return repeatSamples; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index f60b7e67b2..c41026d954 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Osu.Objects /// internal float LazyTravelDistance; - public List> NodeSamples { get; set; } = new List>(); + public List> NodeSamples { get; set; } = new List>(); private int repeatCount; @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Osu.Objects foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { - var firstSample = Samples.Find(s => s.Name == HitSampleInfo.HIT_NORMAL) + var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) var sampleList = new List(); @@ -203,7 +203,7 @@ namespace osu.Game.Rulesets.Osu.Objects TailCircle.Position = EndPosition; } - private List getNodeSamples(int nodeIndex) => + private IList getNodeSamples(int nodeIndex) => nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; public override Judgement CreateJudgement() => new OsuJudgement(); diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index f0cf8d9c7d..180e0d8309 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps var curveData = obj as IHasCurve; // Old osu! used hit sounding to determine various hit type information - List samples = obj.Samples; + IList samples = obj.Samples; bool strong = samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); @@ -117,13 +117,13 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { - List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); + List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); int i = 0; for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) { - List currentSamples = allSamples[i]; + IList currentSamples = allSamples[i]; bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 6211fe50e6..ee0705ec5a 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Objects set => StartTimeBindable.Value = value; } - private List samples; + public readonly BindableList SamplesBindable = new BindableList(); /// /// The samples to be played when this hit object is hit. @@ -54,10 +54,14 @@ namespace osu.Game.Rulesets.Objects /// and can be treated as the default samples for the hit object. /// /// - public List Samples + public IList Samples { - get => samples ?? (samples = new List()); - set => samples = value; + get => SamplesBindable; + set + { + SamplesBindable.Clear(); + SamplesBindable.AddRange(value); + } } [JsonIgnore] diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 71e321f205..545cfe07f8 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index e990938291..bbf46a0c8f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -181,7 +181,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } // Generate the final per-node samples - var nodeSamples = new List>(nodes); + var nodeSamples = new List>(nodes); for (int i = 0; i < nodes; i++) nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); @@ -279,7 +279,7 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider. /// The hit object. protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples); + List> nodeSamples); /// /// Creates a legacy Spinner-type hit object. diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index ff6b9be8b5..8d523022d6 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public double Distance => Path.Distance; - public List> NodeSamples { get; set; } + public List> NodeSamples { get; set; } public int RepeatCount { get; set; } public double EndTime => StartTime + this.SpanCount() * Distance / Velocity; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 94aba95e90..8012b4230f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 65102f1e89..99872e630d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index eb598f1368..9dc0c01932 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, - List> nodeSamples) + List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 697adeda98..b22752e902 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Objects.Types /// n-1: The last repeat.
/// n: The last node. ///
- List> NodeSamples { get; } + List> NodeSamples { get; } } public static class HasRepeatsExtensions diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index dc147a92cd..5f0bfb6d70 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -222,7 +222,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { case ThreeStates.Disabled: foreach (var h in SelectedHitObjects) - h.Samples.RemoveAll(s => s.Name == sampleName); + h.SamplesBindable.RemoveAll(s => s.Name == sampleName); + break; case ThreeStates.Enabled: From 53e6186b6d4421bdb4abb9feca0674ea827603fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 14:59:47 +0900 Subject: [PATCH 209/503] Fix drawable hitobject samples not updating --- .../Objects/Drawables/DrawableHitObject.cs | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1d9b66f88d..592cddeff6 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -78,6 +78,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public JudgementResult Result { get; private set; } + private BindableList samplesBindable; private Bindable startTimeBindable; private Bindable comboIndexBindable; @@ -108,20 +109,7 @@ namespace osu.Game.Rulesets.Objects.Drawables throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } - var samples = GetSamples().ToArray(); - - if (samples.Length > 0) - { - if (HitObject.SampleControlPoint == null) - throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." - + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); - - samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); - foreach (var s in samples) - s.Namespace = SampleNamespace; - - AddInternal(Samples = new SkinnableSound(samples)); - } + loadSamples(); } protected override void LoadComplete() @@ -139,10 +127,34 @@ namespace osu.Game.Rulesets.Objects.Drawables comboIndexBindable.BindValueChanged(_ => updateAccentColour(), true); } + samplesBindable = HitObject.SamplesBindable.GetBoundCopy(); + samplesBindable.ItemsAdded += _ => scheduleLoadSamples(); + samplesBindable.ItemsRemoved += _ => scheduleLoadSamples(); + updateState(ArmedState.Idle, true); onDefaultsApplied(); } + private void scheduleLoadSamples() => Scheduler.AddOnce(loadSamples); + + private void loadSamples() + { + var samples = GetSamples().ToArray(); + + if (samples.Length <= 0) + return; + + if (HitObject.SampleControlPoint == null) + throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + + samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); + foreach (var s in samples) + s.Namespace = SampleNamespace; + + AddInternal(Samples = new SkinnableSound(samples)); + } + private void onDefaultsApplied() => apply(HitObject); private void apply(HitObject hitObject) From df31acb2940ca5333e019e0340c2fdd67ff5f9e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 15:39:07 +0900 Subject: [PATCH 210/503] Fix slider nested hitobject samples not getting updated --- .../TestSceneSlider.cs | 75 +++++++++++++++---- osu.Game.Rulesets.Osu/Objects/Slider.cs | 47 ++++++++---- 2 files changed, 93 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 46a2a36ac7..5c656bf594 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -126,6 +126,67 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("body positioned correctly", () => slider.Position == slider.HitObject.StackedPosition); } + [Test] + public void TestChangeSamplesWithNoNodeSamples() + { + DrawableSlider slider = null; + + AddStep("create slider", () => + { + slider = (DrawableSlider)createSlider(repeats: 1); + Add(slider); + }); + + AddStep("change samples", () => slider.HitObject.Samples = new[] + { + new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP }, + new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, + }); + + AddAssert("head samples updated", () => assertSamples(((Slider)slider.HitObject).HeadCircle)); + AddAssert("tick samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertTickSamples)); + AddAssert("repeat samples updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); + AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); + + bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + + bool assertSamples(HitObject hitObject) + { + return hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP) + && hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_WHISTLE); + } + } + + [Test] + public void TestChangeSamplesWithNodeSamples() + { + DrawableSlider slider = null; + + AddStep("create slider", () => + { + slider = (DrawableSlider)createSlider(repeats: 1); + + for (int i = 0; i < 2; i++) + ((Slider)slider.HitObject).NodeSamples.Add(new List { new HitSampleInfo { Name = HitSampleInfo.HIT_FINISH } }); + + Add(slider); + }); + + AddStep("change samples", () => slider.HitObject.Samples = new[] + { + new HitSampleInfo { Name = HitSampleInfo.HIT_CLAP }, + new HitSampleInfo { Name = HitSampleInfo.HIT_WHISTLE }, + }); + + AddAssert("head samples not updated", () => assertSamples(((Slider)slider.HitObject).HeadCircle)); + AddAssert("tick samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertTickSamples)); + AddAssert("repeat samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); + AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); + + bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + bool assertSamples(HitObject hitObject) => hitObject.Samples.All(s => s.Name != HitSampleInfo.HIT_CLAP && s.Name != HitSampleInfo.HIT_WHISTLE); + } + private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); private Drawable testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); @@ -143,7 +204,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(52, -34) }, 700), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats), StackHeight = 10 }; @@ -174,7 +234,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(distance, 0), }, distance), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats), StackHeight = stackHeight }; @@ -194,7 +253,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(400, 0) }, 600), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -218,7 +276,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(430, 0) }), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -241,7 +298,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(430, 0) }), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -265,7 +321,6 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(0, -200) }), RepeatCount = repeats, - NodeSamples = createEmptySamples(repeats) }; return createDrawable(slider, 2, 3); @@ -297,14 +352,6 @@ namespace osu.Game.Rulesets.Osu.Tests return createDrawable(slider, 3, 1); } - private List> createEmptySamples(int repeats) - { - var repeatSamples = new List>(); - for (int i = 0; i < repeats; i++) - repeatSamples.Add(new List()); - return repeatSamples; - } - private Drawable createDrawable(Slider slider, float circleSize, double speedMultiplier) { var cpi = new ControlPointInfo(); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index c41026d954..f3399af2de 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -108,6 +108,12 @@ namespace osu.Game.Rulesets.Osu.Objects public HitCircle HeadCircle; public SliderTailCircle TailCircle; + public Slider() + { + SamplesBindable.ItemsAdded += _ => updateNestedSamples(); + SamplesBindable.ItemsRemoved += _ => updateNestedSamples(); + } + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -128,18 +134,6 @@ namespace osu.Game.Rulesets.Osu.Objects foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { - var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) - ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) - var sampleList = new List(); - - if (firstSample != null) - sampleList.Add(new HitSampleInfo - { - Bank = firstSample.Bank, - Volume = firstSample.Volume, - Name = @"slidertick", - }); - switch (e.Type) { case SliderEventType.Tick: @@ -151,7 +145,6 @@ namespace osu.Game.Rulesets.Osu.Objects Position = Position + Path.PositionAt(e.PathProgress), StackHeight = StackHeight, Scale = Scale, - Samples = sampleList }); break; @@ -161,7 +154,6 @@ namespace osu.Game.Rulesets.Osu.Objects StartTime = e.Time, Position = Position, StackHeight = StackHeight, - Samples = getNodeSamples(0), SampleControlPoint = SampleControlPoint, }); break; @@ -187,11 +179,12 @@ namespace osu.Game.Rulesets.Osu.Objects Position = Position + Path.PositionAt(e.PathProgress), StackHeight = StackHeight, Scale = Scale, - Samples = getNodeSamples(e.SpanIndex + 1) }); break; } } + + updateNestedSamples(); } private void updateNestedPositions() @@ -203,6 +196,30 @@ namespace osu.Game.Rulesets.Osu.Objects TailCircle.Position = EndPosition; } + private void updateNestedSamples() + { + var firstSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) + ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) + var sampleList = new List(); + + if (firstSample != null) + sampleList.Add(new HitSampleInfo + { + Bank = firstSample.Bank, + Volume = firstSample.Volume, + Name = @"slidertick", + }); + + foreach (var tick in NestedHitObjects.OfType()) + tick.Samples = sampleList; + + foreach (var repeat in NestedHitObjects.OfType()) + repeat.Samples = getNodeSamples(repeat.RepeatIndex + 1); + + if (HeadCircle != null) + HeadCircle.Samples = getNodeSamples(0); + } + private IList getNodeSamples(int nodeIndex) => nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; From 5fe764b2db98b30113fdc9f2fc7690df8db97ed8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 16:19:34 +0900 Subject: [PATCH 211/503] Fix tournament videos stuttering when changing scenes --- .../Components/TourneyVideo.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index 4f4660f645..f28a2773b6 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; +using osu.Framework.Timing; using osu.Game.Graphics; namespace osu.Game.Tournament.Components @@ -15,6 +16,9 @@ namespace osu.Game.Tournament.Components { private readonly VideoSprite video; + private ManualClock manualClock; + private IFrameBasedClock sourceClock; + public TourneyVideo(Stream stream) { if (stream == null) @@ -41,5 +45,22 @@ namespace osu.Game.Tournament.Components video.Loop = value; } } + + protected override void LoadComplete() + { + base.LoadComplete(); + + sourceClock = Clock; + Clock = new FramedClock(manualClock = new ManualClock()); + } + + protected override void Update() + { + base.Update(); + + // we want to avoid seeking as much as possible, because we care about performance, not sync. + // to avoid seeking completely, we only increment out local clock when in an updating state. + manualClock.CurrentTime += sourceClock.ElapsedFrameTime; + } } } From a9b4106075614da8a60eae0afa3f30b85f7bf53d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 16:19:43 +0900 Subject: [PATCH 212/503] Remove unnecessary (for now) scheduling --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 592cddeff6..9c72a1a220 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -128,15 +128,13 @@ namespace osu.Game.Rulesets.Objects.Drawables } samplesBindable = HitObject.SamplesBindable.GetBoundCopy(); - samplesBindable.ItemsAdded += _ => scheduleLoadSamples(); - samplesBindable.ItemsRemoved += _ => scheduleLoadSamples(); + samplesBindable.ItemsAdded += _ => loadSamples(); + samplesBindable.ItemsRemoved += _ => loadSamples(); updateState(ArmedState.Idle, true); onDefaultsApplied(); } - private void scheduleLoadSamples() => Scheduler.AddOnce(loadSamples); - private void loadSamples() { var samples = GetSamples().ToArray(); From b4cb4c124366097b79239f267033eed6e7c3dffb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 16:19:55 +0900 Subject: [PATCH 213/503] Remove previous samples on change --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 9c72a1a220..818571bb23 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Objects.Drawables // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first protected virtual string SampleNamespace => null; - protected SkinnableSound Samples; + protected SkinnableSound Samples { get; private set; } protected virtual IEnumerable GetSamples() => HitObject.Samples; @@ -137,6 +137,12 @@ namespace osu.Game.Rulesets.Objects.Drawables private void loadSamples() { + if (Samples != null) + { + RemoveInternal(Samples); + Samples = null; + } + var samples = GetSamples().ToArray(); if (samples.Length <= 0) From df08a95734e8184847a55210f2da9eed9a6c30f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 16:46:58 +0900 Subject: [PATCH 214/503] Separate addition/removal into separate methods --- .../Compose/Components/SelectionHandler.cs | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 5f0bfb6d70..7b61640c89 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -185,6 +185,36 @@ namespace osu.Game.Screens.Edit.Compose.Components #endregion + #region Sample Changes + + /// + /// Adds a hit sample to all selected s. + /// + /// The name of the hit sample. + public void AddHitSample(string sampleName) + { + foreach (var h in SelectedHitObjects) + { + // Make sure there isn't already an existing sample + if (h.Samples.Any(s => s.Name == sampleName)) + continue; + + h.Samples.Add(new HitSampleInfo { Name = sampleName }); + } + } + + /// + /// Removes a hit sample from all selected s. + /// + /// The name of the hit sample. + public void RemoveHitSample(string sampleName) + { + foreach (var h in SelectedHitObjects) + h.SamplesBindable.RemoveAll(s => s.Name == sampleName); + } + + #endregion + #region Context Menu public virtual MenuItem[] ContextMenuItems @@ -221,21 +251,11 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (state) { case ThreeStates.Disabled: - foreach (var h in SelectedHitObjects) - h.SamplesBindable.RemoveAll(s => s.Name == sampleName); - + RemoveHitSample(sampleName); break; case ThreeStates.Enabled: - foreach (var h in SelectedHitObjects) - { - // Make sure there isn't already an existing sample - if (h.Samples.Any(s => s.Name == sampleName)) - continue; - - h.Samples.Add(new HitSampleInfo { Name = sampleName }); - } - + AddHitSample(sampleName); break; } } From 8bcbc93501626e11d230532647f3dfff374121aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:00:47 +0900 Subject: [PATCH 215/503] Fix tournament buttons playing sound effects --- .../Screens/Drawings/DrawingsScreen.cs | 9 +++---- .../Screens/Editors/TeamEditorScreen.cs | 3 +-- .../Screens/Editors/TournamentEditorScreen.cs | 3 +-- .../Screens/Gameplay/GameplayScreen.cs | 4 +-- .../Screens/MapPool/MapPoolScreen.cs | 10 ++++---- osu.Game.Tournament/TournamentGameBase.cs | 3 +-- osu.Game.Tournament/TournamentSceneManager.cs | 25 +++++++++---------- osu.Game.Tournament/TourneyButton.cs | 15 +++++++++++ osu.Game/Graphics/UserInterface/OsuButton.cs | 6 +++-- 9 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 osu.Game.Tournament/TourneyButton.cs diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 3a14b6d9c2..e8906466f3 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -15,7 +15,6 @@ using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Drawings.Components; @@ -128,21 +127,21 @@ namespace osu.Game.Tournament.Screens.Drawings // Control panel container new ControlPanel { - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Begin random", Action = teamsContainer.StartScrolling, }, - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Stop random", Action = teamsContainer.StopScrolling, }, - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, @@ -150,7 +149,7 @@ namespace osu.Game.Tournament.Screens.Drawings Action = reloadTeams }, new ControlPanel.Spacer(), - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index a4479f3cfd..e1f6d16623 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Settings; @@ -32,7 +31,7 @@ namespace osu.Game.Tournament.Screens.Editors [BackgroundDependencyLoader] private void load() { - ControlPanel.Add(new OsuButton + ControlPanel.Add(new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Add all countries", diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index 50d3207345..32cf6bbcc8 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osuTK; @@ -56,7 +55,7 @@ namespace osu.Game.Tournament.Screens.Editors { Children = new Drawable[] { - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Add new", diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index b9a74bfe16..6a3095d42d 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -103,13 +103,13 @@ namespace osu.Game.Tournament.Screens.Gameplay { Children = new Drawable[] { - warmupButton = new OsuButton + warmupButton = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Toggle warmup", Action = () => warmup.Toggle() }, - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Toggle chat", diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index ec55bb5b54..7a5fc2cd06 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -60,32 +60,32 @@ namespace osu.Game.Tournament.Screens.MapPool { Text = "Current Mode" }, - buttonRedBan = new OsuButton + buttonRedBan = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Red Ban", Action = () => setMode(TeamColour.Red, ChoiceType.Ban) }, - buttonBlueBan = new OsuButton + buttonBlueBan = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Blue Ban", Action = () => setMode(TeamColour.Blue, ChoiceType.Ban) }, - buttonRedPick = new OsuButton + buttonRedPick = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Red Pick", Action = () => setMode(TeamColour.Red, ChoiceType.Pick) }, - buttonBluePick = new OsuButton + buttonBluePick = new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Blue Pick", Action = () => setMode(TeamColour.Blue, ChoiceType.Pick) }, new ControlPanel.Spacer(), - new OsuButton + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Reset", diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 21552882ef..3b7718c61d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -18,7 +18,6 @@ using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -76,7 +75,7 @@ namespace osu.Game.Tournament AddRange(new[] { - new OsuButton + new TourneyButton { Text = "Save Changes", Width = 140, diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 02ee1c8603..7164141dea 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; -using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens; @@ -107,23 +106,23 @@ namespace osu.Game.Tournament Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) }, new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) }, + new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) }, } }, }, diff --git a/osu.Game.Tournament/TourneyButton.cs b/osu.Game.Tournament/TourneyButton.cs new file mode 100644 index 0000000000..12872d3197 --- /dev/null +++ b/osu.Game.Tournament/TourneyButton.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tournament +{ + public class TourneyButton : OsuButton + { + public TourneyButton() + : base(null) + { + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 2750e61f0d..c6a9aa1c97 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -48,7 +48,7 @@ namespace osu.Game.Graphics.UserInterface protected Box Background; protected SpriteText SpriteText; - public OsuButton() + public OsuButton(HoverSampleSet? hoverSounds = HoverSampleSet.Loud) { Height = 40; @@ -78,10 +78,12 @@ namespace osu.Game.Graphics.UserInterface Depth = float.MinValue }, SpriteText = CreateText(), - new HoverClickSounds(HoverSampleSet.Loud), } }); + if (hoverSounds.HasValue) + AddInternal(new HoverClickSounds(hoverSounds.Value)); + Enabled.BindValueChanged(enabledChanged, true); } From 380859e06e11137716ec7b2748214a58a213b0b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:13:45 +0900 Subject: [PATCH 216/503] Set clock on video directly; ignore long frames --- .../Components/TourneyVideo.cs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index f28a2773b6..8582b1634c 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -16,8 +16,7 @@ namespace osu.Game.Tournament.Components { private readonly VideoSprite video; - private ManualClock manualClock; - private IFrameBasedClock sourceClock; + private readonly ManualClock manualClock; public TourneyVideo(Stream stream) { @@ -34,6 +33,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, + Clock = new FramedClock(manualClock = new ManualClock()) }; } @@ -46,21 +46,16 @@ namespace osu.Game.Tournament.Components } } - protected override void LoadComplete() - { - base.LoadComplete(); - - sourceClock = Clock; - Clock = new FramedClock(manualClock = new ManualClock()); - } - protected override void Update() { base.Update(); - // we want to avoid seeking as much as possible, because we care about performance, not sync. - // to avoid seeking completely, we only increment out local clock when in an updating state. - manualClock.CurrentTime += sourceClock.ElapsedFrameTime; + if (manualClock != null && Clock.ElapsedFrameTime < 100) + { + // we want to avoid seeking as much as possible, because we care about performance, not sync. + // to avoid seeking completely, we only increment out local clock when in an updating state. + manualClock.CurrentTime += Clock.ElapsedFrameTime; + } } } } From 651a1e2ae10fb5001aa0a7e7fa466fd0e429ca3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:20:20 +0900 Subject: [PATCH 217/503] Highlight selected tournament screen's button --- osu.Game.Tournament/TournamentSceneManager.cs | 85 +++++++++++++++---- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 7164141dea..69248b6692 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; +using osu.Game.Graphics; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens; @@ -35,6 +36,7 @@ namespace osu.Game.Tournament private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay(); private Container chatContainer; + private FillFlowContainer buttons; public TournamentSceneManager() { @@ -100,29 +102,32 @@ namespace osu.Game.Tournament Colour = Color4.Black, RelativeSizeAxes = Axes.Both, }, - new FillFlowContainer + buttons = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, + Spacing = new Vector2(2), + Padding = new MarginPadding(2), Children = new Drawable[] { - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Setup", Action = () => SetScreen(typeof(SetupScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) }, - new Container { RelativeSizeAxes = Axes.X, Height = 50 }, - new TourneyButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) }, + new ScreenButton(typeof(SetupScreen)) { Text = "Setup", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(TeamEditorScreen)) { Text = "Team Editor", RequestSelection = SetScreen }, + new ScreenButton(typeof(RoundEditorScreen)) { Text = "Rounds Editor", RequestSelection = SetScreen }, + new ScreenButton(typeof(LadderEditorScreen)) { Text = "Bracket Editor", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(ScheduleScreen)) { Text = "Schedule", RequestSelection = SetScreen }, + new ScreenButton(typeof(LadderScreen)) { Text = "Bracket", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(TeamIntroScreen)) { Text = "TeamIntro", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(MapPoolScreen)) { Text = "MapPool", RequestSelection = SetScreen }, + new ScreenButton(typeof(GameplayScreen)) { Text = "Gameplay", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(TeamWinScreen)) { Text = "Win", RequestSelection = SetScreen }, + new Separator(), + new ScreenButton(typeof(DrawingsScreen)) { Text = "Drawings", RequestSelection = SetScreen }, + new ScreenButton(typeof(ShowcaseScreen)) { Text = "Showcase", RequestSelection = SetScreen }, } }, }, @@ -162,6 +167,50 @@ namespace osu.Game.Tournament chatContainer.FadeOut(100); break; } + + foreach (var s in buttons.OfType()) + s.IsSelected = screenType == s.Type; + } + + private class Separator : CompositeDrawable + { + public Separator() + { + RelativeSizeAxes = Axes.X; + Height = 20; + } + } + + private class ScreenButton : TourneyButton + { + public readonly Type Type; + + public ScreenButton(Type type) + { + Type = type; + BackgroundColour = OsuColour.Gray(0.2f); + Action = () => RequestSelection(type); + + RelativeSizeAxes = Axes.X; + } + + private bool isSelected; + + public Action RequestSelection; + + public bool IsSelected + { + get => isSelected; + set + { + if (value == isSelected) + return; + + isSelected = value; + BackgroundColour = isSelected ? Color4.SkyBlue : OsuColour.Gray(0.2f); + SpriteText.Colour = isSelected ? Color4.Black : Color4.White; + } + } } } } From eb9fff96bacec5ca553e0565336d11b9e341bd33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:12:47 +0900 Subject: [PATCH 218/503] Read default beat divisor from beatmap --- osu.Game/Screens/Edit/Editor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..97f01fd9f3 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -64,7 +64,10 @@ namespace osu.Game.Screens.Edit { this.host = host; - // TODO: should probably be done at a DrawableRuleset level to share logic with Player. + beatDivisor.Value = Beatmap.Value.BeatmapInfo.BeatDivisor; + beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue); + + // Todo: should probably be done at a DrawableRuleset level to share logic with Player. var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); From 998e1dfe47aa0b1a2e05a63508194d0a831e208b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:23:47 +0900 Subject: [PATCH 219/503] Fix non-1/1 initial beat divisor control display --- .../Edit/Compose/Components/BeatDivisorControl.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 4d89e43ee5..9e4691e4dd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -218,12 +218,17 @@ namespace osu.Game.Screens.Edit.Compose.Components } AddInternal(marker = new Marker()); + } - CurrentNumber.ValueChanged += div => + protected override void LoadComplete() + { + base.LoadComplete(); + + CurrentNumber.BindValueChanged(div => { marker.MoveToX(getMappedPosition(div.NewValue), 100, Easing.OutQuint); marker.Flash(); - }; + }, true); } protected override void UpdateValue(float value) From 36cc79f04f94c1c077fe8575a97e9b012f973d84 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:24:02 +0900 Subject: [PATCH 220/503] Softly handle invalid beat divisors instead of throwing --- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index a724f354e7..ce95d81f54 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -29,7 +29,10 @@ namespace osu.Game.Screens.Edit set { if (!VALID_DIVISORS.Contains(value)) - throw new ArgumentOutOfRangeException($"Provided divisor is not in {nameof(VALID_DIVISORS)}"); + { + // If it doesn't match, value will be 0, but will be clamped to the valid range via DefaultMinValue + value = Array.FindLast(VALID_DIVISORS, d => d < value); + } base.Value = value; } From e90492831462e68adf09fa71203eb19e775d9f8e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 17:42:19 +0900 Subject: [PATCH 221/503] Seek to first hitobject when entering editor --- osu.Game/Screens/Edit/Editor.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 35408e4003..f932517387 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -69,6 +69,14 @@ namespace osu.Game.Screens.Edit clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); + if (Beatmap.Value.Beatmap.HitObjects.Count > 0) + { + double targetTime = Beatmap.Value.Beatmap.HitObjects[0].StartTime; + double beatLength = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(targetTime).BeatLength; + + clock.Seek(Math.Max(0, targetTime - beatLength)); + } + dependencies.CacheAs(clock); dependencies.CacheAs(clock); dependencies.Cache(beatDivisor); From 7b8ed1ac9ad0567189d327670e37b3b4dd7ad26c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:26:24 +0900 Subject: [PATCH 222/503] Improve tournament screen transitions --- .../Screens/TournamentScreen.cs | 12 ++--- osu.Game.Tournament/TournamentSceneManager.cs | 54 +++++++++++++------ 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index 9d58ca2240..0b5b3e728b 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -10,6 +10,8 @@ namespace osu.Game.Tournament.Screens { public abstract class TournamentScreen : CompositeDrawable { + public const double FADE_DELAY = 200; + [Resolved] protected LadderInfo LadderInfo { get; private set; } @@ -18,14 +20,8 @@ namespace osu.Game.Tournament.Screens RelativeSizeAxes = Axes.Both; } - public override void Hide() - { - this.FadeOut(200); - } + public override void Hide() => this.FadeOut(FADE_DELAY); - public override void Show() - { - this.FadeIn(200); - } + public override void Show() => this.FadeIn(FADE_DELAY); } } diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 02ee1c8603..d66f980202 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Platform; +using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; @@ -130,37 +131,58 @@ namespace osu.Game.Tournament }, }; + foreach (var drawable in screens) + drawable.Hide(); + SetScreen(typeof(SetupScreen)); } + private float depth; + + private Drawable currentScreen; + private ScheduledDelegate scheduledHide; + public void SetScreen(Type screenType) { - var screen = screens.FirstOrDefault(s => s.GetType() == screenType); - if (screen == null) return; + var target = screens.FirstOrDefault(s => s.GetType() == screenType); - foreach (var s in screens.Children) + if (target == null || currentScreen == target) return; + + if (scheduledHide?.Completed == false) { - if (s == screen) - { - s.Show(); - if (s is IProvideVideo) - video.FadeOut(200); - else - video.Show(); - } - else - s.Hide(); + scheduledHide.RunTask(); + scheduledHide.Cancel(); // see https://github.com/ppy/osu-framework/issues/2967 + scheduledHide = null; } - switch (screen) + var lastScreen = currentScreen; + currentScreen = target; + + if (currentScreen is IProvideVideo) + { + video.FadeOut(200); + + // delay the hide to avoid a double-fade transition. + scheduledHide = Scheduler.AddDelayed(() => lastScreen?.Hide(), TournamentScreen.FADE_DELAY); + } + else + { + lastScreen?.Hide(); + video.Show(); + } + + screens.ChangeChildDepth(currentScreen, depth--); + currentScreen.Show(); + + switch (currentScreen) { case GameplayScreen _: case MapPoolScreen _: - chatContainer.FadeIn(100); + chatContainer.FadeIn(TournamentScreen.FADE_DELAY); break; default: - chatContainer.FadeOut(100); + chatContainer.FadeOut(TournamentScreen.FADE_DELAY); break; } } From 12b855d68feffd9b2053284de58d0c20c7bcdb36 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 17:56:11 +0900 Subject: [PATCH 223/503] Make drawing screen transition properly --- osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 3a14b6d9c2..f78124a66a 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -24,7 +24,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Drawings { - public class DrawingsScreen : CompositeDrawable + public class DrawingsScreen : TournamentScreen { private const string results_filename = "drawings_results.txt"; From a849bc074654a65d25500f14ade4cff330683ce0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 18:51:01 +0900 Subject: [PATCH 224/503] Move implementation into resetTrack for safety --- osu.Game/Screens/Edit/Editor.cs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index f932517387..ca3b4fdce5 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -69,14 +69,6 @@ namespace osu.Game.Screens.Edit clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); - if (Beatmap.Value.Beatmap.HitObjects.Count > 0) - { - double targetTime = Beatmap.Value.Beatmap.HitObjects[0].StartTime; - double beatLength = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(targetTime).BeatLength; - - clock.Seek(Math.Max(0, targetTime - beatLength)); - } - dependencies.CacheAs(clock); dependencies.CacheAs(clock); dependencies.Cache(beatDivisor); @@ -249,7 +241,8 @@ namespace osu.Game.Screens.Edit base.OnEntering(last); Background.FadeColour(Color4.DarkGray, 500); - resetTrack(); + + resetTrack(true); } public override bool OnExiting(IScreen next) @@ -260,10 +253,24 @@ namespace osu.Game.Screens.Edit return base.OnExiting(next); } - private void resetTrack() + private void resetTrack(bool seekToStart = false) { Beatmap.Value.Track?.ResetSpeedAdjustments(); Beatmap.Value.Track?.Stop(); + + if (seekToStart) + { + double targetTime = 0; + + if (Beatmap.Value.Beatmap.HitObjects.Count > 0) + { + // seek to one beat length before the first hitobject + targetTime = Beatmap.Value.Beatmap.HitObjects[0].StartTime; + targetTime -= Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(targetTime).BeatLength; + } + + clock.Seek(Math.Max(0, targetTime)); + } } private void exportBeatmap() => host.OpenFileExternally(Beatmap.Value.Save()); From 8ef9ccc39edf317f14a79b5bcb5a6fcc2ca091ea Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 8 Nov 2019 13:19:06 +0300 Subject: [PATCH 225/503] Schedule new track assignment after stopping current track --- osu.Game/Audio/PreviewTrackManager.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index fad2b5a5e8..08a69fa265 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -46,12 +46,18 @@ namespace osu.Game.Audio { var track = CreatePreviewTrack(beatmapSetInfo, trackStore); - track.Started += () => Schedule(() => + track.Started += () => { + // Stopping track should not be within the below schedule since its stop event schedules a null assign to current. + // Due to that, assigning the new track to current must be scheduled after the null assign to avoid current track loss. current?.Stop(); - current = track; - audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); - }); + + Schedule(() => + { + current = track; + audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); + }); + }; track.Stopped += () => Schedule(() => { From 901a8d597b81617c7032e9a16cbd57c5b0181511 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 8 Nov 2019 13:20:02 +0300 Subject: [PATCH 226/503] Add test steps ensuring correct behaviour --- .../Visual/Components/TestScenePreviewTrackManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index f3f6444149..7d46958496 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -59,6 +59,9 @@ namespace osu.Game.Tests.Visual.Components AddStep("start track 2", () => track2.Start()); AddAssert("track 1 stopped", () => !track1.IsRunning); AddAssert("track 2 started", () => track2.IsRunning); + AddStep("start track 1", () => track1.Start()); + AddAssert("track 2 stopped", () => !track2.IsRunning); + AddAssert("track 1 started", () => track1.IsRunning); } [Test] From c280f1ab0826ae9b1fe3768ca9b8450d5d98d42f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 19:35:55 +0900 Subject: [PATCH 227/503] Fix incorrect DI usage in some tournament screen tests --- .../Screens/TestSceneTeamIntroScreen.cs | 5 ++--- osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index 3d340e393c..e36b594ff2 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamIntro; @@ -13,7 +12,7 @@ namespace osu.Game.Tournament.Tests.Screens public class TestSceneTeamIntroScreen : LadderTestScene { [Cached] - private readonly Bindable currentMatch = new Bindable(); + private readonly LadderInfo ladder = new LadderInfo(); [BackgroundDependencyLoader] private void load() @@ -22,7 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); - currentMatch.Value = match; + ladder.CurrentMatch.Value = match; Add(new TeamIntroScreen { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index 6f5e17a36e..5cb35a506f 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -3,7 +3,6 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.TeamWin; @@ -13,7 +12,7 @@ namespace osu.Game.Tournament.Tests.Screens public class TestSceneTeamWinScreen : LadderTestScene { [Cached] - private readonly Bindable currentMatch = new Bindable(); + private readonly LadderInfo ladder = new LadderInfo(); [BackgroundDependencyLoader] private void load() @@ -22,7 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA"); match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN"); match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); - currentMatch.Value = match; + ladder.CurrentMatch.Value = match; Add(new TeamWinScreen { From 97ea07db0e6ec5406f8b73cdc05618b8aad35793 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 8 Nov 2019 19:44:47 +0900 Subject: [PATCH 228/503] Add delete option to the right-click menu --- .../Edit/Compose/Components/SelectionHandler.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 7b61640c89..9b7082dec5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -80,8 +80,7 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (action.ActionMethod) { case PlatformActionMethod.Delete: - foreach (var h in selectedBlueprints.ToList()) - placementHandler.Delete(h.DrawableObject.HitObject); + deleteSelected(); return true; } @@ -144,6 +143,12 @@ namespace osu.Game.Screens.Edit.Compose.Components UpdateVisibility(); } + private void deleteSelected() + { + foreach (var h in selectedBlueprints.ToList()) + placementHandler.Delete(h.DrawableObject.HitObject); + } + #endregion #region Outline Display @@ -234,7 +239,8 @@ namespace osu.Game.Screens.Edit.Compose.Components createHitSampleMenuItem("Clap", HitSampleInfo.HIT_CLAP), createHitSampleMenuItem("Finish", HitSampleInfo.HIT_FINISH) } - } + }, + new OsuMenuItem("Delete", MenuItemType.Destructive, deleteSelected), }; } } From 9ed8b3a125ec5b549d4d67e96775dd5d7b7897e6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Nov 2019 21:15:24 +0800 Subject: [PATCH 229/503] Use original dotsettings, with word IOS added to dictionary. --- osu.sln.DotSettings | 829 ++++++++++++++++++++++---------------------- 1 file changed, 409 insertions(+), 420 deletions(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 0a65fad9df..eb9e3ffafb 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -125,7 +125,6 @@ WARNING WARNING WARNING - WARNING WARNING WARNING ERROR @@ -202,7 +201,6 @@ HINT HINT - HINT WARNING WARNING WARNING @@ -273,8 +271,6 @@ GC GL GLSL - 2D - 3D HID HUD ID @@ -291,400 +287,399 @@ RGB RNG SHA - RGB SRGB TK - SS - PP - GMT - QAT - BNG + SS + PP + GMT + QAT + BNG UI False HINT <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> </Patterns> Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. See the LICENCE file in the repository root for full licence text. @@ -744,7 +739,6 @@ See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> - True True True @@ -780,7 +774,7 @@ Origin = Anchor.$anchor$, True InternalChildren = new Drawable[] { - $END$ + $END$ }; True True @@ -793,12 +787,12 @@ Origin = Anchor.$anchor$, True new GridContainer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } }; True True @@ -811,12 +805,12 @@ Origin = Anchor.$anchor$, True new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } }, True True @@ -829,11 +823,11 @@ Origin = Anchor.$anchor$, True new Container { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } }, True True @@ -847,7 +841,7 @@ Origin = Anchor.$anchor$, [BackgroundDependencyLoader] private void load() { - $END$ + $END$ } True True @@ -860,8 +854,8 @@ private void load() True new Box { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, }, True True @@ -874,9 +868,8 @@ private void load() True Children = new Drawable[] { - $END$ + $END$ }; - True True True True @@ -894,8 +887,4 @@ private void load() True True True - True - True - True - True - True + True From a0f58ba9c47da15216ee769b9483d01c40d38f42 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Nov 2019 21:17:59 +0800 Subject: [PATCH 230/503] Add missing project to iOS filter. --- osu.iOS.slnf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.iOS.slnf b/osu.iOS.slnf index 33a1497a54..48b1a095a1 100644 --- a/osu.iOS.slnf +++ b/osu.iOS.slnf @@ -12,7 +12,8 @@ "osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj", "osu.Game.Tests.iOS\\osu.Game.Tests.iOS.csproj", "osu.Game.Tests\\osu.Game.Tests.csproj", - "osu.Game\\osu.Game.csproj" + "osu.Game\\osu.Game.csproj", + "osu.iOS\\osu.iOS.csproj" ] } } \ No newline at end of file From ff225c3691312bbb9d79bbc733c5ed760d5c9b25 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 8 Nov 2019 06:04:18 -0800 Subject: [PATCH 231/503] Remove toolbarElements --- osu.Game/OsuGame.cs | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3980390611..145b7de9f2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -102,8 +102,6 @@ namespace osu.Game private readonly List overlays = new List(); - private readonly List toolbarElements = new List(); - private readonly List visibleBlockingOverlays = new List(); public OsuGame(string[] args = null) @@ -134,17 +132,13 @@ namespace osu.Game /// /// Close all game-wide overlays. /// - /// Whether the toolbar (and accompanying controls) should also be hidden. - public void CloseAllOverlays(bool hideToolbarElements = true) + /// Whether the toolbar should also be hidden. + public void CloseAllOverlays(bool hideToolbar = true) { foreach (var overlay in overlays) overlay.Hide(); - if (hideToolbarElements) - { - foreach (var overlay in toolbarElements) - overlay.Hide(); - } + if (hideToolbar) Toolbar.Hide(); } private DependencyContainer dependencies; @@ -570,11 +564,7 @@ namespace osu.Game CloseAllOverlays(false); menuScreen?.MakeCurrent(); }, - }, d => - { - topMostOverlayContent.Add(d); - toolbarElements.Add(d); - }); + }, topMostOverlayContent.Add); loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add, true); @@ -613,11 +603,7 @@ namespace osu.Game GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, d => - { - rightFloatingOverlayContent.Add(d); - toolbarElements.Add(d); - }, true); + }, rightFloatingOverlayContent.Add, true); loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); From 2dd514012aa945d5f1d077b77c3cd0e6e9dc45e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Nov 2019 23:28:22 +0900 Subject: [PATCH 232/503] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index d1860acbf9..7bfc27109f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,6 +62,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index dbe6559c40..a646fc01d1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 4010ef1d74..e3a49ea1b3 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From b675024161746b0f77d89a974f7ac905196e98d1 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 8 Nov 2019 20:28:24 -0800 Subject: [PATCH 233/503] Remove horizontal padding on toolbar ruleset selector --- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 2c79f5bc0e..8f2dbce6f7 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -18,8 +18,6 @@ namespace osu.Game.Overlays.Toolbar { public class ToolbarRulesetSelector : RulesetSelector { - private const float padding = 10; - protected Drawable ModeButtonLine { get; private set; } public ToolbarRulesetSelector() @@ -39,7 +37,7 @@ namespace osu.Game.Overlays.Toolbar }, ModeButtonLine = new Container { - Size = new Vector2(padding * 2 + ToolbarButton.WIDTH, 3), + Size = new Vector2(ToolbarButton.WIDTH, 3), Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, Masking = true, @@ -91,7 +89,6 @@ namespace osu.Game.Overlays.Toolbar RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Direction = FillDirection.Horizontal, - Padding = new MarginPadding { Left = padding, Right = padding }, }; protected override bool OnKeyDown(KeyDownEvent e) From 5c476416080276e01a7000b1644ea35170693672 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 9 Nov 2019 16:23:22 +0900 Subject: [PATCH 234/503] Reorder conditional --- osu.Game/Overlays/Comments/VotePill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index a5a19f5111..ab35a477aa 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Comments AccentColour = borderContainer.BorderColour = sideNumber.Colour = colours.GreenLight; hoverLayer.Colour = Color4.Black.Opacity(0.5f); - if (api.LocalUser.Value.Id != comment.UserId && api.IsLoggedIn) + if (api.IsLoggedIn && api.LocalUser.Value.Id != comment.UserId) Action = onAction; } From 20ed6c4d520444955e7fa690a9e06b6d1391ef9e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:07:51 +0300 Subject: [PATCH 235/503] Use track check solution for this --- osu.Game/Audio/PreviewTrackManager.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 08a69fa265..f104dc8f9f 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -46,21 +46,20 @@ namespace osu.Game.Audio { var track = CreatePreviewTrack(beatmapSetInfo, trackStore); - track.Started += () => + track.Started += () => Schedule(() => { - // Stopping track should not be within the below schedule since its stop event schedules a null assign to current. - // Due to that, assigning the new track to current must be scheduled after the null assign to avoid current track loss. - current?.Stop(); + var last = current; + current = track; + last?.Stop(); - Schedule(() => - { - current = track; - audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); - }); - }; + audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); + }); track.Stopped += () => Schedule(() => { + if (current != track) + return; + current = null; audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); }); From 9d61d73cedf9088af374f18f1018f7e32f64b3cd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:09:04 +0300 Subject: [PATCH 236/503] Change Track and TrackManagerPreviewTrack accessibilities --- osu.Game/Audio/PreviewTrack.cs | 25 +++++++++++++------------ osu.Game/Audio/PreviewTrackManager.cs | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 1234554e79..b39d2bc8f8 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -24,36 +24,37 @@ namespace osu.Game.Audio /// public event Action Started; - private Track track; + protected Track Track; + private bool hasStarted; [BackgroundDependencyLoader] private void load() { - track = GetTrack(); - if (track != null) - track.Completed += Stop; + Track = GetTrack(); + if (Track != null) + Track.Completed += Stop; } /// /// Length of the track. /// - public double Length => track?.Length ?? 0; + public double Length => Track?.Length ?? 0; /// /// The current track time. /// - public double CurrentTime => track?.CurrentTime ?? 0; + public double CurrentTime => Track?.CurrentTime ?? 0; /// /// Whether the track is loaded. /// - public bool TrackLoaded => track?.IsLoaded ?? false; + public bool TrackLoaded => Track?.IsLoaded ?? false; /// /// Whether the track is playing. /// - public bool IsRunning => track?.IsRunning ?? false; + public bool IsRunning => Track?.IsRunning ?? false; private ScheduledDelegate startDelegate; @@ -63,7 +64,7 @@ namespace osu.Game.Audio /// Whether the track is started or already playing. public bool Start() { - if (track == null) + if (Track == null) return false; startDelegate = Schedule(() => @@ -73,7 +74,7 @@ namespace osu.Game.Audio hasStarted = true; - track.Restart(); + Track.Restart(); Started?.Invoke(); }); @@ -87,7 +88,7 @@ namespace osu.Game.Audio { startDelegate?.Cancel(); - if (track == null) + if (Track == null) return; if (!hasStarted) @@ -95,7 +96,7 @@ namespace osu.Game.Audio hasStarted = false; - track.Stop(); + Track.Stop(); Stopped?.Invoke(); } diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index f104dc8f9f..1c1b4c3059 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -90,7 +90,7 @@ namespace osu.Game.Audio /// protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); - protected class TrackManagerPreviewTrack : PreviewTrack + public class TrackManagerPreviewTrack : PreviewTrack { public IPreviewTrackOwner Owner { get; private set; } From 9a00898c0d3dae94f922782fc3eebc871959d04b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:21:46 +0300 Subject: [PATCH 237/503] Add test for non-present preview tracks To avoid reverting what #6738 solved --- .../TestScenePreviewTrackManager.cs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 7d46958496..3a9fce90cd 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; using osu.Game.Audio; using osu.Game.Beatmaps; +using static osu.Game.Tests.Visual.Components.TestScenePreviewTrackManager.TestPreviewTrackManager; namespace osu.Game.Tests.Visual.Components { @@ -91,9 +92,25 @@ namespace osu.Game.Tests.Visual.Components AddAssert("stopped", () => !track.IsRunning); } - private PreviewTrack getTrack() => trackManager.Get(null); + [Test] + public void TestNonPresentTrack() + { + TestPreviewTrack track = null; - private PreviewTrack getOwnedTrack() + AddStep("get non-present track", () => + { + Add(new TestTrackOwner(track = getTrack())); + track.Alpha = 0; + }); + AddUntilStep("wait loaded", () => track.IsLoaded); + AddStep("start", () => track.Start()); + AddStep("seek to end", () => track.Track.Seek(track.Track.Length)); + AddAssert("track stopped", () => !track.IsRunning); + } + + private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); + + private TestPreviewTrack getOwnedTrack() { var track = getTrack(); @@ -125,14 +142,16 @@ namespace osu.Game.Tests.Visual.Components } } - private class TestPreviewTrackManager : PreviewTrackManager + public class TestPreviewTrackManager : PreviewTrackManager { protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); - protected class TestPreviewTrack : TrackManagerPreviewTrack + public class TestPreviewTrack : TrackManagerPreviewTrack { private readonly ITrackStore trackManager; + public new Track Track => base.Track; + public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager) : base(beatmapSetInfo, trackManager) { From 8f4916ad2d7fee51b0c28acad32a89fdf6c8f3ec Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 10 Nov 2019 23:53:31 +0300 Subject: [PATCH 238/503] Add inline comment --- osu.Game/Audio/PreviewTrackManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 1c1b4c3059..8f723194e3 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -48,6 +48,7 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { + // Assign the new track to current before stopping last track to avoid assigning null to current. var last = current; current = track; last?.Stop(); From 93954c8da0996307f277473bf4ac894d97d06395 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 10 Nov 2019 23:58:07 +0300 Subject: [PATCH 239/503] Use BindableList for selected mods --- .../Online/TestSceneLeaderboardModSelector.cs | 31 +++++++++++++------ .../BeatmapSet/LeaderboardModSelector.cs | 20 +++++------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 3a64ac79f6..799528220b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Bindables; using osu.Game.Rulesets; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Tests.Visual.Online { @@ -26,10 +27,10 @@ namespace osu.Game.Tests.Visual.Online public TestSceneLeaderboardModSelector() { LeaderboardModSelector modSelector; - FillFlowContainer selectedMods; + FillFlowContainer selectedMods; Bindable ruleset = new Bindable(); - Add(selectedMods = new FillFlowContainer + Add(selectedMods = new FillFlowContainer { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, @@ -42,16 +43,28 @@ namespace osu.Game.Tests.Visual.Online Ruleset = { BindTarget = ruleset } }); - modSelector.SelectedMods.BindValueChanged(mods => + modSelector.SelectedMods.ItemsAdded += mods => { - selectedMods.Clear(); + mods.ForEach(mod => selectedMods.Add(new SpriteText + { + Text = mod.Acronym, + })); + }; - foreach (var mod in mods.NewValue) - selectedMods.Add(new SpriteText + modSelector.SelectedMods.ItemsRemoved += mods => + { + mods.ForEach(mod => + { + foreach (var selected in selectedMods) { - Text = mod.Acronym, - }); - }); + if (selected.Text == mod.Acronym) + { + selectedMods.Remove(selected); + break; + } + } + }); + }; AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 4b6fd5bfc2..75c24cb710 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; using osu.Framework.Bindables; -using System.Collections.Generic; using osu.Game.Rulesets; using osuTK; using osu.Game.Rulesets.UI; @@ -21,7 +20,7 @@ namespace osu.Game.Overlays.BeatmapSet { public class LeaderboardModSelector : CompositeDrawable { - public readonly Bindable> SelectedMods = new Bindable>(); + public readonly BindableList SelectedMods = new BindableList(); public readonly Bindable Ruleset = new Bindable(); private readonly FillFlowContainer modsContainer; @@ -47,8 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet private void onRulesetChanged(ValueChangedEvent ruleset) { - SelectedMods.Value = new List(); - + SelectedMods.Clear(); modsContainer.Clear(); if (ruleset.NewValue == null) @@ -67,22 +65,18 @@ namespace osu.Game.Overlays.BeatmapSet private void selectionChanged(Mod mod, bool selected) { - var mods = SelectedMods.Value.ToList(); - if (selected) - mods.Add(mod); + SelectedMods.Add(mod); else - mods.Remove(mod); + SelectedMods.Remove(mod); - SelectedMods.Value = mods; - - if (!mods.Any() && !IsHovered) + if (!SelectedMods.Any() && !IsHovered) highlightAll(); } protected override bool OnHover(HoverEvent e) { - if (!SelectedMods.Value.Any()) + if (!SelectedMods.Any()) modsContainer.ForEach(button => { if (!button.IsHovered) @@ -96,7 +90,7 @@ namespace osu.Game.Overlays.BeatmapSet { base.OnHoverLost(e); - if (!SelectedMods.Value.Any()) + if (!SelectedMods.Any()) highlightAll(); } From 5e70e1e53f6c3be0cf4eb0348095cb78e712682f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 11:31:42 +0900 Subject: [PATCH 240/503] Update .gitignore --- .gitignore | 100 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index e60058ab35..e6b5db5904 100644 --- a/.gitignore +++ b/.gitignore @@ -10,14 +10,8 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs -### Cake ### -tools/** -build/tools/** - -fastlane/report.xml - # Build results -bin/[Dd]ebug/ +[Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ @@ -104,7 +98,6 @@ $tf/ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -inspectcode # JustCode is a .NET coding add-in .JustCode @@ -254,20 +247,87 @@ paket-files/ # FAKE - F# Make .fake/ -# JetBrains Rider -.idea/.idea.osu/.idea/*.xml -.idea/.idea.osu/.idea/codeStyles/*.xml -.idea/.idea.osu/.idea/dataSources/*.xml -.idea/.idea.osu/.idea/dictionaries/*.xml -.idea/.idea.osu/*.iml -*.sln.iml - -# CodeRush -.cr/ - # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc -Staging/ +# Cake # +/tools/** +/build/tools/** +/build/temp/** + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +.idea/modules.xml +.idea/*.iml +.idea/modules +*.iml +*.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# fastlane +fastlane/report.xml + +# inspectcode inspectcodereport.xml +inspectcode From 93f1c3c1520c95ecd7494e36bbdbc9fd4f50bbc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 11:31:55 +0900 Subject: [PATCH 241/503] Update rider configurations --- .idea/.gitignore | 0 .idea/.idea.osu.Desktop/.idea/.name | 1 + .../.idea/codeStyles/codeStyleConfig.xml | 5 +++++ .idea/.idea.osu.Desktop/.idea/dataSources.xml | 14 ++++++++++++++ .idea/.idea.osu.Desktop/.idea/encodings.xml | 4 ++++ .idea/.idea.osu.Desktop/.idea/indexLayout.xml | 8 ++++++++ .idea/.idea.osu.Desktop/.idea/misc.xml | 6 ++++++ .idea/.idea.osu.Desktop/.idea/modules.xml | 8 ++++++++ .../.idea/projectSettingsUpdater.xml | 6 ++++++ .../runConfigurations/CatchRuleset__Tests_.xml | 0 .../runConfigurations/ManiaRuleset__Tests_.xml | 0 .../runConfigurations/OsuRuleset__Tests_.xml | 0 .../runConfigurations/TaikoRuleset__Tests_.xml | 0 .../.idea/runConfigurations/Tournament.xml | 0 .../runConfigurations/Tournament__Tests_.xml | 0 .../.idea/runConfigurations/osu_.xml | 0 .../.idea/runConfigurations/osu___Tests_.xml | 0 .idea/.idea.osu.Desktop/.idea/vcs.xml | 16 ++++++++++++++++ .idea/.idea.osu/.idea/indexLayout.xml | 8 ++++++++ .idea/.idea.osu/.idea/modules.xml | 8 ++++++++ .idea/.idea.osu/.idea/projectSettingsUpdater.xml | 6 ++++++ .idea/.idea.osu/.idea/vcs.xml | 6 ++++++ 22 files changed, 96 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/.idea.osu.Desktop/.idea/.name create mode 100644 .idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/dataSources.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/encodings.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/indexLayout.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/misc.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/modules.xml create mode 100644 .idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/CatchRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/ManiaRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/OsuRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/TaikoRuleset__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/Tournament.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/Tournament__Tests_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/osu_.xml (100%) rename .idea/{.idea.osu => .idea.osu.Desktop}/.idea/runConfigurations/osu___Tests_.xml (100%) create mode 100644 .idea/.idea.osu.Desktop/.idea/vcs.xml create mode 100644 .idea/.idea.osu/.idea/indexLayout.xml create mode 100644 .idea/.idea.osu/.idea/modules.xml create mode 100644 .idea/.idea.osu/.idea/projectSettingsUpdater.xml create mode 100644 .idea/.idea.osu/.idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.idea/.idea.osu.Desktop/.idea/.name b/.idea/.idea.osu.Desktop/.idea/.name new file mode 100644 index 0000000000..12bf4aebba --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/.name @@ -0,0 +1 @@ +osu.Desktop \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml b/.idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000..a55e7a179b --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/dataSources.xml b/.idea/.idea.osu.Desktop/.idea/dataSources.xml new file mode 100644 index 0000000000..10f8c1c84d --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/dataSources.xml @@ -0,0 +1,14 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:$USER_HOME$/.local/share/osu/client.db + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/encodings.xml b/.idea/.idea.osu.Desktop/.idea/encodings.xml new file mode 100644 index 0000000000..15a15b218a --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/indexLayout.xml b/.idea/.idea.osu.Desktop/.idea/indexLayout.xml new file mode 100644 index 0000000000..27ba142e96 --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/misc.xml b/.idea/.idea.osu.Desktop/.idea/misc.xml new file mode 100644 index 0000000000..1d8c84d0af --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/modules.xml b/.idea/.idea.osu.Desktop/.idea/modules.xml new file mode 100644 index 0000000000..fe63f5faf3 --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml b/.idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000000..7515e76054 --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/CatchRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/CatchRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/ManiaRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/ManiaRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/ManiaRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/ManiaRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/OsuRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/OsuRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/OsuRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/OsuRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/TaikoRuleset__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/TaikoRuleset__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/TaikoRuleset__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/TaikoRuleset__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/Tournament.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/Tournament.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/Tournament__Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament__Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/Tournament__Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/Tournament__Tests_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/osu_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/osu_.xml diff --git a/.idea/.idea.osu/.idea/runConfigurations/osu___Tests_.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu___Tests_.xml similarity index 100% rename from .idea/.idea.osu/.idea/runConfigurations/osu___Tests_.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/osu___Tests_.xml diff --git a/.idea/.idea.osu.Desktop/.idea/vcs.xml b/.idea/.idea.osu.Desktop/.idea/vcs.xml new file mode 100644 index 0000000000..3de04b744c --- /dev/null +++ b/.idea/.idea.osu.Desktop/.idea/vcs.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/indexLayout.xml b/.idea/.idea.osu/.idea/indexLayout.xml new file mode 100644 index 0000000000..27ba142e96 --- /dev/null +++ b/.idea/.idea.osu/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/modules.xml b/.idea/.idea.osu/.idea/modules.xml new file mode 100644 index 0000000000..0360fdbc5e --- /dev/null +++ b/.idea/.idea.osu/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/projectSettingsUpdater.xml b/.idea/.idea.osu/.idea/projectSettingsUpdater.xml new file mode 100644 index 0000000000..7515e76054 --- /dev/null +++ b/.idea/.idea.osu/.idea/projectSettingsUpdater.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.osu/.idea/vcs.xml b/.idea/.idea.osu/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/.idea.osu/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 990a82cd06593da8d7a4b6e30b24b26dc98d00ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 11:32:06 +0900 Subject: [PATCH 242/503] Update readme --- README.md | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1e2d539697..67eb3254e1 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ git pull Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this provided [below](#contributing). -> Visual Studio Code users must run the `Restore` task before any build attempt. +- Visual Studio / Rider users should load the project via one of the platform-specific .slnf files, rather than the main .sln. This will allow access to template run configurations. +- Visual Studio Code users must run the `Restore` task before any build attempt. You can also build and run osu! from the command-line with a single command: @@ -69,18 +70,6 @@ If you are not interested in debugging osu!, you can add `-c Release` to gain pe If the build fails, try to restore nuget packages with `dotnet restore`. -#### A note for Linux users - -On Linux, the environment variable `LD_LIBRARY_PATH` must point to the build directory, located at `osu.Desktop/bin/Debug/$NETCORE_VERSION`. - -`$NETCORE_VERSION` is the version of the targeted .NET Core SDK. You can check it by running `grep TargetFramework osu.Desktop/osu.Desktop.csproj | sed -r 's/.*>(.*)<\/.*/\1/'`. - -For example, you can run osu! with the following command: - -```shell -LD_LIBRARY_PATH="$(pwd)/osu.Desktop/bin/Debug/netcoreapp3.0" dotnet run --project osu.Desktop -``` - ### Testing with resource/framework modifications Sometimes it may be necessary to cross-test changes in [osu-resources](https://github.com/ppy/osu-resources) or [osu-framework](https://github.com/ppy/osu-framework). This can be achieved by running some commands as documented on the [osu-resources](https://github.com/ppy/osu-resources/wiki/Testing-local-resources-checkout-with-other-projects) and [osu-framework](https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects) wiki pages. From e924a5d51e0596ab003d07c38ee3417bacb431a4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Nov 2019 13:04:38 +0900 Subject: [PATCH 243/503] Disable ruleset input in the editor --- osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs index af565f8896..4710465536 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRulesetWrapper.cs @@ -64,6 +64,10 @@ namespace osu.Game.Rulesets.Edit drawableRuleset.Playfield.PostProcess(); } + public override bool PropagatePositionalInputSubTree => false; + + public override bool PropagateNonPositionalInputSubTree => false; + public PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => drawableRuleset.CreatePlayfieldAdjustmentContainer(); protected override void Dispose(bool isDisposing) From 3b13ad480af5afa7f0fe15c300a5e02bcf0fb4d7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Nov 2019 13:06:41 +0900 Subject: [PATCH 244/503] Increase fade-out time of hitobjects in the editor --- .../Edit/DrawableOsuEditRuleset.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index cc08d356f9..e262fa3c60 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -2,8 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; using osuTK; @@ -17,6 +21,25 @@ namespace osu.Game.Rulesets.Osu.Edit { } + public override DrawableHitObject CreateDrawableRepresentation(OsuHitObject h) + => base.CreateDrawableRepresentation(h)?.With(d => d.ApplyCustomUpdateState += updateState); + + private void updateState(DrawableHitObject hitObject, ArmedState state) + { + switch (state) + { + case ArmedState.Miss: + // Get the existing fade out transform + var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha)); + if (existing == null) + return; + + using (hitObject.BeginAbsoluteSequence(existing.StartTime)) + hitObject.FadeOut(500).Expire(); + break; + } + } + protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor(); public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new OsuPlayfieldAdjustmentContainer { Size = Vector2.One }; From f3dc38e3427f9c52364bcc11a8ea36d065b0934c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Nov 2019 13:41:10 +0900 Subject: [PATCH 245/503] Add Ctrl+A to select all (esc to deselect all) --- .../Compose/Components/BlueprintContainer.cs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 8fa022f129..7528ac8aa6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; @@ -17,10 +18,11 @@ using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK; +using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { - public class BlueprintContainer : CompositeDrawable + public class BlueprintContainer : CompositeDrawable, IKeyBindingHandler { public event Action> SelectionChanged; @@ -169,6 +171,37 @@ namespace osu.Game.Screens.Edit.Compose.Components return true; } + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Escape: + if (!selectionHandler.SelectedBlueprints.Any()) + return false; + + deselectAll(); + return true; + } + + return false; + } + + protected override bool OnKeyUp(KeyUpEvent e) => false; + + public bool OnPressed(PlatformAction action) + { + switch (action.ActionType) + { + case PlatformActionType.SelectAll: + selectAll(); + return true; + } + + return false; + } + + public bool OnReleased(PlatformAction action) => false; + protected override void Update() { base.Update(); @@ -314,6 +347,15 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + /// + /// Selects all s. + /// + private void selectAll() + { + selectionBlueprints.ToList().ForEach(m => m.Select()); + selectionHandler.UpdateVisibility(); + } + /// /// Deselects all selected s. /// From dc88bd3d611a1a5c31c3768eb637725b6a6bf02d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 13:49:12 +0900 Subject: [PATCH 246/503] Add local preserving container to OsuTestScene to ensure correct test dimensions --- osu.Game/Tests/Visual/OsuTestScene.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 96b39b303e..daa1a56221 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -10,12 +10,16 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Database; +using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -93,6 +97,10 @@ namespace osu.Game.Tests.Visual return Dependencies; } + protected override Container Content => content ?? base.Content; + + private readonly Container content; + protected OsuTestScene() { localStorage = new Lazy(() => new NativeStorage($"{GetType().Name}-{Guid.NewGuid()}")); @@ -104,6 +112,8 @@ namespace osu.Game.Tests.Visual usage.Migrate(); return factory; }); + + base.Content.Add(content = new DrawSizePreservingFillContainer()); } [Resolved] From 8ac708ada5f44773ed593f02f5badd144d9a93f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 13:58:35 +0900 Subject: [PATCH 247/503] Move scaling container to OsuGame so OsuGameBase doesn't apply UI scale --- osu.Game/OsuGame.cs | 2 ++ osu.Game/OsuGameBase.cs | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f823e6eba..c375ccda81 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -393,6 +393,8 @@ namespace osu.Game protected virtual Loader CreateLoader() => new Loader(); + protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything); + #region Beatmap progression private void beatmapChanged(ValueChangedEvent beatmap) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 194a439b06..947df75783 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -26,7 +26,6 @@ using osu.Framework.Input; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Database; -using osu.Game.Graphics.Containers; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; @@ -228,7 +227,7 @@ namespace osu.Game Child = content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both } }; - base.Content.Add(new ScalingContainer(ScalingMode.Everything) { Child = MenuCursorContainer }); + base.Content.Add(CreateScalingContainer().WithChild(MenuCursorContainer)); KeyBindingStore.Register(globalBinding); dependencies.Cache(globalBinding); @@ -238,6 +237,8 @@ namespace osu.Game Add(previewTrackManager); } + protected virtual Container CreateScalingContainer() => new DrawSizePreservingFillContainer(); + protected override void LoadComplete() { base.LoadComplete(); From 13fd95d513da835f427e59095b606ced479ff29b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 14:03:29 +0900 Subject: [PATCH 248/503] Remove misplaced usings --- osu.Game/Tests/Visual/OsuTestScene.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index daa1a56221..345fff90aa 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -17,9 +17,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; -using osu.Game.Configuration; using osu.Game.Database; -using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; From fced262c41859aa3fc01f3ffcb3eeded6610245e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 17:03:40 +0900 Subject: [PATCH 249/503] Add labelled dropdown component --- .../UserInterfaceV2/LabelledDropdown.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs new file mode 100644 index 0000000000..7e50fa7bc6 --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public class LabelledDropdown : LabelledComponent, T> + { + public LabelledDropdown() + : base(true) + { + } + + public IEnumerable Items + { + get => Component.Items; + set => Component.Items = value; + } + + protected override OsuDropdown CreateComponent() => new OsuDropdown + { + RelativeSizeAxes = Axes.X, + Width = 0.5f, + }; + } +} From 702a1c496bd6e2a146dd5a7b2a82d42752f90e42 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 17:03:50 +0900 Subject: [PATCH 250/503] Add ruleset selection to tournament client --- osu.Game.Tournament/Models/LadderInfo.cs | 3 +++ osu.Game.Tournament/Screens/SetupScreen.cs | 13 ++++++++++++- osu.Game.Tournament/TournamentGameBase.cs | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 547c4eab08..5db0b01547 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Bindables; +using osu.Game.Rulesets; namespace osu.Game.Tournament.Models { @@ -14,6 +15,8 @@ namespace osu.Game.Tournament.Models [Serializable] public class LadderInfo { + public Bindable Ruleset = new Bindable(); + public BindableList Matches = new BindableList(); public BindableList Rounds = new BindableList(); public BindableList Teams = new BindableList(); diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index a67daa2756..b511d572da 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; using osu.Game.Overlays; +using osu.Game.Rulesets; using osu.Game.Tournament.IPC; using osuTK; using osuTK.Graphics; @@ -28,6 +29,9 @@ namespace osu.Game.Tournament.Screens [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private RulesetStore rulesets { get; set; } + [BackgroundDependencyLoader] private void load() { @@ -85,7 +89,14 @@ namespace osu.Game.Tournament.Screens Value = api?.LocalUser.Value.Username, Failing = api?.IsLoggedIn != true, Description = "In order to access the API and display metadata, a login is required." - } + }, + new LabelledDropdown + { + Label = "Ruleset", + Description = "Decides what stats are displayed and which ranks are retrieved for players", + Items = rulesets.AvailableRulesets, + Current = LadderInfo.Ruleset, + }, }; } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 3b7718c61d..59edd18341 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -126,6 +126,8 @@ namespace osu.Game.Tournament ladder = new LadderInfo(); } + Ruleset.BindTo(ladder.Ruleset); + dependencies.Cache(ladder); bool addedInfo = false; From 5d96e6d90a30b85d27866d70ce9ff5f693247e0f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 17:39:48 +0900 Subject: [PATCH 251/503] Populate users centrally, using the correct ruleset --- .../Screens/Editors/TeamEditorScreen.cs | 26 +++------------ osu.Game.Tournament/TournamentGameBase.cs | 32 ++++++++++++++++--- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index e1f6d16623..11c2732d62 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; @@ -24,7 +23,7 @@ namespace osu.Game.Tournament.Screens.Editors public class TeamEditorScreen : TournamentEditorScreen { [Resolved] - private Framework.Game game { get; set; } + private TournamentGameBase game { get; set; } protected override BindableList Storage => LadderInfo.Teams; @@ -198,6 +197,9 @@ namespace osu.Game.Tournament.Screens.Editors [Resolved] protected IAPIProvider API { get; private set; } + [Resolved] + private TournamentGameBase game { get; set; } + private readonly Bindable userId = new Bindable(); private readonly Container drawableContainer; @@ -280,25 +282,7 @@ namespace osu.Game.Tournament.Screens.Editors return; } - var req = new GetUserRequest(user.Id); - - req.Success += res => - { - // TODO: this should be done in a better way. - user.Username = res.Username; - user.Country = res.Country; - user.Cover = res.Cover; - - updatePanel(); - }; - - req.Failure += _ => - { - user.Id = 1; - updatePanel(); - }; - - API.Queue(req); + game.PopulateUser(user, updatePanel, updatePanel); }, true); } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 59edd18341..b0ca099a86 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Drawing; using System.IO; using System.Linq; @@ -21,11 +22,13 @@ using osu.Game.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; +using osu.Game.Users; using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Tournament { + [Cached(typeof(TournamentGameBase))] public abstract class TournamentGameBase : OsuGameBase { private const string bracket_filename = "bracket.json"; @@ -197,10 +200,7 @@ namespace osu.Game.Tournament foreach (var p in t.Players) if (string.IsNullOrEmpty(p.Username)) { - var req = new GetUserRequest(p.Id); - req.Perform(API); - p.Username = req.Result.Username; - + PopulateUser(p); addedInfo = true; } @@ -228,6 +228,30 @@ namespace osu.Game.Tournament return addedInfo; } + public void PopulateUser(User user, Action success = null, Action failure = null) + { + var req = new GetUserRequest(user.Id, Ruleset.Value); + + req.Success += res => + { + user.Username = res.Username; + user.Statistics = res.Statistics; + user.Username = res.Username; + user.Country = res.Country; + user.Cover = res.Cover; + + success?.Invoke(); + }; + + req.Failure += _ => + { + user.Id = 1; + failure?.Invoke(); + }; + + API.Queue(req); + } + protected override void LoadComplete() { MenuCursorContainer.Cursor.AlwaysPresent = true; // required for tooltip display From 6d3d7c5d95823d9915e197116e7f327dad54592b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 11 Nov 2019 11:57:14 +0300 Subject: [PATCH 252/503] Remove unnecessary use of local --- osu.Game/Audio/PreviewTrackManager.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 8f723194e3..72b33c4073 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -48,11 +48,8 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { - // Assign the new track to current before stopping last track to avoid assigning null to current. - var last = current; + current?.Stop(); current = track; - last?.Stop(); - audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); }); From a345fd8a86ef706aed8f004ccd1d380e5ee15495 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2019 09:26:56 +0000 Subject: [PATCH 253/503] Bump Newtonsoft.Json from 12.0.2 to 12.0.3 Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 12.0.2 to 12.0.3. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/12.0.2...12.0.3) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 42f746c286..baa1c14071 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -19,7 +19,7 @@ - + From ce4843be22ff62e95362da8a2f24530c1fb9b91c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 18:42:32 +0900 Subject: [PATCH 254/503] Move tests to parent namespace for now --- .../UserInterface/{MenuItems => }/TestSceneStatefulMenuItem.cs | 2 +- .../{MenuItems => }/TestSceneThreeStateMenuItem.cs | 2 +- .../UserInterface/{MenuItems => }/TestSceneToggleMenuItem.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{MenuItems => }/TestSceneStatefulMenuItem.cs (98%) rename osu.Game.Tests/Visual/UserInterface/{MenuItems => }/TestSceneThreeStateMenuItem.cs (95%) rename osu.Game.Tests/Visual/UserInterface/{MenuItems => }/TestSceneToggleMenuItem.cs (94%) diff --git a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs similarity index 98% rename from osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 95e9aea97f..fd30da39e6 100644 --- a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface.MenuItems +namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneStatefulMenuItem : OsuTestScene { diff --git a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs similarity index 95% rename from osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs index e035e43630..caa07e7b60 100644 --- a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneThreeStateMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface.MenuItems +namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneThreeStateMenuItem : OsuTestScene { diff --git a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs similarity index 94% rename from osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs index 92875740cf..2abda56a28 100644 --- a/osu.Game.Tests/Visual/UserInterface/MenuItems/TestSceneToggleMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual.UserInterface.MenuItems +namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneToggleMenuItem : OsuTestScene { From bed62e0d2f2b62d19a76bfb051c04263900706c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 18:56:18 +0900 Subject: [PATCH 255/503] Rename ThreeState -> TernaryState and add basic tests --- .../UserInterface/TestSceneTernaryMenuItem.cs | 65 +++++++++++++++++++ .../TestSceneThreeStateMenuItem.cs | 35 ---------- .../{ThreeStates.cs => TernaryState.cs} | 14 ++-- .../UserInterface/ThreeStateMenuItem.cs | 28 ++++---- 4 files changed, 86 insertions(+), 56 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs rename osu.Game/Graphics/UserInterface/{ThreeStates.cs => TernaryState.cs} (56%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs new file mode 100644 index 0000000000..fdb8c330c5 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneTernaryMenuItem : ManualInputManagerTestScene + { + private readonly OsuMenu menu; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OsuMenu), + typeof(ThreeStateMenuItem), + typeof(DrawableStatefulMenuItem) + }; + + private readonly Bindable state = new Bindable(TernaryState.Indeterminate); + + public TestSceneTernaryMenuItem() + { + Add(menu = new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ThreeStateMenuItem("First"), + new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, + new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, + } + }); + + checkState(TernaryState.Indeterminate); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + } + + private void click() => + AddStep("click", () => + { + InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre); + InputManager.Click(MouseButton.Left); + }); + + private void checkState(TernaryState expected) + => AddAssert($"state is {expected}", () => state.Value == expected); + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs deleted file mode 100644 index caa07e7b60..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneThreeStateMenuItem.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneThreeStateMenuItem : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(OsuMenu), - typeof(ThreeStateMenuItem), - typeof(DrawableStatefulMenuItem) - }; - - public TestSceneThreeStateMenuItem() - { - Add(new OsuMenu(Direction.Vertical, true) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] - { - new ThreeStateMenuItem("First"), - new ThreeStateMenuItem("Second") { State = { Value = ThreeStates.Indeterminate } }, - new ThreeStateMenuItem("Third") { State = { Value = ThreeStates.Enabled } }, - } - }); - } - } -} diff --git a/osu.Game/Graphics/UserInterface/ThreeStates.cs b/osu.Game/Graphics/UserInterface/TernaryState.cs similarity index 56% rename from osu.Game/Graphics/UserInterface/ThreeStates.cs rename to osu.Game/Graphics/UserInterface/TernaryState.cs index f099250937..784122e35c 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStates.cs +++ b/osu.Game/Graphics/UserInterface/TernaryState.cs @@ -6,22 +6,22 @@ namespace osu.Game.Graphics.UserInterface /// /// An on/off state with an extra indeterminate state. /// - public enum ThreeStates + public enum TernaryState { /// - /// The current state is disabled. + /// The current state is false. /// - Disabled, + False, /// - /// The current state is a combination of and . - /// The state becomes if the is pressed. + /// The current state is a combination of and . + /// The state becomes if the is pressed. /// Indeterminate, /// - /// The current state is enabled. + /// The current state is true. /// - Enabled + True } } diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs index ebb6436196..c5b9edf3c4 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs @@ -9,7 +9,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An with three possible states. /// - public class ThreeStateMenuItem : StatefulMenuItem + public class ThreeStateMenuItem : StatefulMenuItem { /// /// Creates a new . @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.UserInterface /// The text to display. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. - public ThreeStateMenuItem(string text, MenuItemType type, Action action) + public ThreeStateMenuItem(string text, MenuItemType type, Action action) : this(text, getNextState, type, action) { } @@ -39,37 +39,37 @@ namespace osu.Game.Graphics.UserInterface /// A function that mutates a state to another state after this is pressed. /// The type of action which this performs. /// A delegate to be invoked when this is pressed. - protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, changeStateFunc, type, action) { } - public override IconUsage? GetIconForState(ThreeStates state) + public override IconUsage? GetIconForState(TernaryState state) { switch (state) { - case ThreeStates.Indeterminate: - return FontAwesome.Regular.Circle; + case TernaryState.Indeterminate: + return FontAwesome.Solid.DotCircle; - case ThreeStates.Enabled: + case TernaryState.True: return FontAwesome.Solid.Check; } return null; } - private static ThreeStates getNextState(ThreeStates state) + private static TernaryState getNextState(TernaryState state) { switch (state) { - case ThreeStates.Disabled: - return ThreeStates.Enabled; + case TernaryState.False: + return TernaryState.True; - case ThreeStates.Indeterminate: - return ThreeStates.Enabled; + case TernaryState.Indeterminate: + return TernaryState.True; - case ThreeStates.Enabled: - return ThreeStates.Disabled; + case TernaryState.True: + return TernaryState.False; default: throw new ArgumentOutOfRangeException(nameof(state), state, null); From 82cc6aa0c5b2b251a229808b0a6494ba684a7cbb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 19:00:14 +0900 Subject: [PATCH 256/503] Remove unused constructor --- .../Visual/UserInterface/TestSceneStatefulMenuItem.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index fd30da39e6..bd7f73c6d8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -52,11 +52,6 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestMenuItem : StatefulMenuItem { - public TestMenuItem(string text, MenuItemType type = MenuItemType.Standard) - : this(text, type, null) - { - } - public TestMenuItem(string text, MenuItemType type, Func changeStateFunc) : base(text, changeStateFunc, type) { From 54da8e4035cd3b033eee59839e5c7428a297d25d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Nov 2019 19:09:38 +0900 Subject: [PATCH 257/503] Combine similar tests --- .../TestSceneStatefulMenuItem.cs | 81 ++++++++++++++++--- .../UserInterface/TestSceneTernaryMenuItem.cs | 65 --------------- 2 files changed, 70 insertions(+), 76 deletions(-) delete mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index bd7f73c6d8..1eff30d15e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -3,33 +3,92 @@ using System; using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public class TestSceneStatefulMenuItem : OsuTestScene + public class TestSceneStatefulMenuItem : ManualInputManagerTestScene { public override IReadOnlyList RequiredTypes => new[] { typeof(OsuMenu), typeof(StatefulMenuItem), - typeof(DrawableStatefulMenuItem) + typeof(ThreeStateMenuItem), + typeof(DrawableStatefulMenuItem), }; - public TestSceneStatefulMenuItem() + [Test] + public void TestTernaryMenuItem() { - Add(new OsuMenu(Direction.Vertical, true) + OsuMenu menu = null; + + Bindable state = new Bindable(TernaryState.Indeterminate); + + AddStep("create menu", () => { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] + state.Value = TernaryState.Indeterminate; + + Child = menu = new OsuMenu(Direction.Vertical, true) { - new TestMenuItem("First", MenuItemType.Standard, getNextState), - new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } }, - new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } }, - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new ThreeStateMenuItem("First"), + new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, + new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, + } + }; + }); + + checkState(TernaryState.Indeterminate); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + + click(); + checkState(TernaryState.True); + + click(); + checkState(TernaryState.False); + + AddStep("change state via bindable", () => state.Value = TernaryState.True); + + void click() => + AddStep("click", () => + { + InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre); + InputManager.Click(MouseButton.Left); + }); + + void checkState(TernaryState expected) + => AddAssert($"state is {expected}", () => state.Value == expected); + } + + [Test] + public void TestCustomState() + { + AddStep("create menu", () => + { + Child = new OsuMenu(Direction.Vertical, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Items = new[] + { + new TestMenuItem("First", MenuItemType.Standard, getNextState), + new TestMenuItem("Second", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State2 } }, + new TestMenuItem("Third", MenuItemType.Standard, getNextState) { State = { Value = TestStates.State3 } }, + } + }; }); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs deleted file mode 100644 index fdb8c330c5..0000000000 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTernaryMenuItem.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; -using osuTK.Input; - -namespace osu.Game.Tests.Visual.UserInterface -{ - public class TestSceneTernaryMenuItem : ManualInputManagerTestScene - { - private readonly OsuMenu menu; - - public override IReadOnlyList RequiredTypes => new[] - { - typeof(OsuMenu), - typeof(ThreeStateMenuItem), - typeof(DrawableStatefulMenuItem) - }; - - private readonly Bindable state = new Bindable(TernaryState.Indeterminate); - - public TestSceneTernaryMenuItem() - { - Add(menu = new OsuMenu(Direction.Vertical, true) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Items = new[] - { - new ThreeStateMenuItem("First"), - new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, - new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, - } - }); - - checkState(TernaryState.Indeterminate); - - click(); - checkState(TernaryState.True); - - click(); - checkState(TernaryState.False); - - click(); - checkState(TernaryState.True); - - click(); - checkState(TernaryState.False); - } - - private void click() => - AddStep("click", () => - { - InputManager.MoveMouseTo(menu.ScreenSpaceDrawQuad.Centre); - InputManager.Click(MouseButton.Left); - }); - - private void checkState(TernaryState expected) - => AddAssert($"state is {expected}", () => state.Value == expected); - } -} From 9c1a9c29e45bac8624e2374192d6c2b60b4cc3f3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 18:40:28 +0800 Subject: [PATCH 258/503] Remove redundant package references in iOS props. --- osu.iOS.props | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.iOS.props b/osu.iOS.props index d2d7d490e9..0184e45c15 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,12 +73,6 @@ - - - - - - From 3d1c31f2ae57d010e1845d4a77dcd4b4b395ab74 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 19:45:52 +0800 Subject: [PATCH 259/503] Copy configs from framework repo. --- .editorconfig | 167 ++++++++- osu.sln.DotSettings | 846 +++++++++++++++++++++++--------------------- 2 files changed, 594 insertions(+), 419 deletions(-) diff --git a/.editorconfig b/.editorconfig index 0dd7ef8ed1..8f9d0ca9b0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,16 +12,171 @@ trim_trailing_whitespace = true #PascalCase for public and protected members dotnet_naming_style.pascalcase.capitalization = pascal_case -dotnet_naming_symbols.public_members.applicable_accessibilities = public,internal,protected,protected_internal -dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event,delegate -dotnet_naming_rule.public_members_pascalcase.severity = suggestion +dotnet_naming_symbols.public_members.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.public_members.applicable_kinds = property,method,field,event +dotnet_naming_rule.public_members_pascalcase.severity = error dotnet_naming_rule.public_members_pascalcase.symbols = public_members dotnet_naming_rule.public_members_pascalcase.style = pascalcase #camelCase for private members dotnet_naming_style.camelcase.capitalization = camel_case + dotnet_naming_symbols.private_members.applicable_accessibilities = private -dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event,delegate -dotnet_naming_rule.private_members_camelcase.severity = suggestion +dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event +dotnet_naming_rule.private_members_camelcase.severity = warning dotnet_naming_rule.private_members_camelcase.symbols = private_members -dotnet_naming_rule.private_members_camelcase.style = camelcase \ No newline at end of file +dotnet_naming_rule.private_members_camelcase.style = camelcase + +dotnet_naming_symbols.local_function.applicable_kinds = local_function +dotnet_naming_rule.local_function_camelcase.severity = warning +dotnet_naming_rule.local_function_camelcase.symbols = local_function +dotnet_naming_rule.local_function_camelcase.style = camelcase + +#all_lower for private and local constants/static readonlys +dotnet_naming_style.all_lower.capitalization = all_lower +dotnet_naming_style.all_lower.word_separator = _ + +dotnet_naming_symbols.private_constants.applicable_accessibilities = private +dotnet_naming_symbols.private_constants.required_modifiers = const +dotnet_naming_symbols.private_constants.applicable_kinds = field +dotnet_naming_rule.private_const_all_lower.severity = warning +dotnet_naming_rule.private_const_all_lower.symbols = private_constants +dotnet_naming_rule.private_const_all_lower.style = all_lower + +dotnet_naming_symbols.private_static_readonly.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly.required_modifiers = static,readonly +dotnet_naming_symbols.private_static_readonly.applicable_kinds = field +dotnet_naming_rule.private_static_readonly_all_lower.severity = warning +dotnet_naming_rule.private_static_readonly_all_lower.symbols = private_static_readonly +dotnet_naming_rule.private_static_readonly_all_lower.style = all_lower + +dotnet_naming_symbols.local_constants.applicable_kinds = local +dotnet_naming_symbols.local_constants.required_modifiers = const +dotnet_naming_rule.local_const_all_lower.severity = warning +dotnet_naming_rule.local_const_all_lower.symbols = local_constants +dotnet_naming_rule.local_const_all_lower.style = all_lower + +#ALL_UPPER for non private constants/static readonlys +dotnet_naming_style.all_upper.capitalization = all_upper +dotnet_naming_style.all_upper.word_separator = _ + +dotnet_naming_symbols.public_constants.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.public_constants.required_modifiers = const +dotnet_naming_symbols.public_constants.applicable_kinds = field +dotnet_naming_rule.public_const_all_upper.severity = warning +dotnet_naming_rule.public_const_all_upper.symbols = public_constants +dotnet_naming_rule.public_const_all_upper.style = all_upper + +dotnet_naming_symbols.public_static_readonly.applicable_accessibilities = public,internal,protected,protected_internal,private_protected +dotnet_naming_symbols.public_static_readonly.required_modifiers = static,readonly +dotnet_naming_symbols.public_static_readonly.applicable_kinds = field +dotnet_naming_rule.public_static_readonly_all_upper.severity = warning +dotnet_naming_rule.public_static_readonly_all_upper.symbols = public_static_readonly +dotnet_naming_rule.public_static_readonly_all_upper.style = all_upper + +#Roslyn formating options + +#Formatting - indentation options +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = false +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +#Formatting - new line options +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_open_brace = all +#csharp_new_line_before_members_in_anonymous_types = true +#csharp_new_line_before_members_in_object_initializers = true # Currently no effect in VS/dotnet format (16.4), and makes Rider confusing +csharp_new_line_between_query_expression_clauses = true + +#Formatting - organize using options +dotnet_sort_system_directives_first = true + +#Formatting - spacing options +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_parameter_list_parentheses = false + +#Formatting - wrapping options +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#Roslyn language styles + +#Style - type names +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +csharp_style_var_when_type_is_apparent = true:none +csharp_style_var_for_built_in_types = true:none +csharp_style_var_elsewhere = true:silent + +#Style - modifiers +dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning +csharp_preferred_modifier_order = public,private,protected,internal,new,abstract,virtual,sealed,override,static,readonly,extern,unsafe,volatile,async:warning + +#Style - parentheses +# Skipped because roslyn cannot separate +-*/ with << >> + +#Style - expression bodies +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_operators = true:silent +csharp_style_expression_bodied_properties = true:silent + +#Style - expression preferences +dotnet_style_object_initializer = true:warning +dotnet_style_collection_initializer = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_compound_assignment = true:warning + +#Style - null/type checks +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:warning +csharp_style_pattern_matching_over_is_with_cast_check = true:silent +csharp_style_pattern_matching_over_as_with_null_check = true:silent +csharp_style_throw_expression = true:silent +csharp_style_conditional_delegate_call = true:suggestion + +#Style - unused +dotnet_code_quality_unused_parameters = non_public:silent +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:suggestion + +#Style - variable declaration +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true:silent + +#Style - other C# 7.x features +csharp_style_expression_bodied_local_functions = true:silent +dotnet_style_prefer_inferred_tuple_names = true:warning +csharp_prefer_simple_default_expression = true:warning +csharp_style_pattern_local_over_anonymous_function = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent + +#Supressing roslyn built-in analyzers +# Suppress: EC112 + +#Field can be readonly +dotnet_diagnostic.IDE0044.severity = silent +#Private method is unused +dotnet_diagnostic.IDE0051.severity = silent +#Private member is unused +dotnet_diagnostic.IDE0052.severity = silent + +#Rules for disposable +dotnet_diagnostic.IDE0067.severity = none +dotnet_diagnostic.IDE0068.severity = none +dotnet_diagnostic.IDE0069.severity = none \ No newline at end of file diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index eb9e3ffafb..44c5c05bc0 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -12,7 +12,7 @@ HINT HINT WARNING - + WARNING True WARNING WARNING @@ -70,11 +70,20 @@ WARNING WARNING DO_NOT_SHOW + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING HINT WARNING DO_NOT_SHOW WARNING HINT + DO_NOT_SHOW HINT HINT ERROR @@ -125,6 +134,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING ERROR @@ -171,7 +181,7 @@ WARNING WARNING WARNING - HINT + WARNING WARNING WARNING WARNING @@ -201,6 +211,7 @@ HINT HINT + HINT WARNING WARNING WARNING @@ -218,9 +229,14 @@ WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) - Required - Required - Required + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline + RequiredForMultiline Explicit ExpressionBody ExpressionBody @@ -239,6 +255,10 @@ 1 NEXT_LINE MULTILINE + True + True + True + True NEXT_LINE 1 1 @@ -289,397 +309,397 @@ SHA SRGB TK - SS - PP - GMT - QAT - BNG + SS + PP + GMT + QAT + BNG UI False HINT <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> - <TypePattern DisplayName="COM interfaces or structs"> - <TypePattern.Match> - <Or> - <And> - <Kind Is="Interface" /> - <Or> - <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> - <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> - </Or> - </And> - <Kind Is="Struct" /> - </Or> - </TypePattern.Match> - </TypePattern> - <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - </And> - </TypePattern.Match> - <Entry DisplayName="Setup/Teardown Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="All other members" /> - <Entry Priority="100" DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - </TypePattern> - <TypePattern DisplayName="Default Pattern"> - <Group DisplayName="Fields/Properties"> - <Group DisplayName="Public Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Public Properties"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Internal Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Internal Properties"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Protected Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Protected Properties"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - <Group DisplayName="Private Fields"> - <Entry DisplayName="Constant Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Or> - <Kind Is="Constant" /> - <Readonly /> - <And> - <Static /> - <Readonly /> - </And> - </Or> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Static Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Not> - <Readonly /> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Normal Fields"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Or> - <Static /> - <Readonly /> - </Or> - </Not> - <Kind Is="Field" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Entry DisplayName="Private Properties"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Kind Is="Property" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Constructor/Destructor"> - <Entry DisplayName="Ctor"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - </Entry> - <Region Name="Disposal"> - <Entry DisplayName="Dtor"> - <Entry.Match> - <Kind Is="Destructor" /> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose()"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Dispose(true)"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Or> - <Virtual /> - <Override /> - </Or> - <Kind Is="Method" /> - <Name Is="Dispose" /> - </And> - </Entry.Match> - </Entry> - </Region> - </Group> - <Group DisplayName="Methods"> - <Group DisplayName="Public"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Internal"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Internal" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Protected"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Protected" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - <Group DisplayName="Private"> - <Entry DisplayName="Static Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Static /> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - <Entry DisplayName="Methods"> - <Entry.Match> - <And> - <Access Is="Private" /> - <Not> - <Static /> - </Not> - <Kind Is="Method" /> - </And> - </Entry.Match> - </Entry> - </Group> - </Group> - </TypePattern> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> </Patterns> Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. See the LICENCE file in the repository root for full licence text. @@ -774,7 +794,7 @@ Origin = Anchor.$anchor$, True InternalChildren = new Drawable[] { - $END$ + $END$ }; True True @@ -787,12 +807,12 @@ Origin = Anchor.$anchor$, True new GridContainer { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { $END$ }, - new Drawable[] { } - } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } }; True True @@ -805,12 +825,12 @@ Origin = Anchor.$anchor$, True new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } }, True True @@ -823,11 +843,11 @@ Origin = Anchor.$anchor$, True new Container { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - $END$ - } + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } }, True True @@ -841,7 +861,7 @@ Origin = Anchor.$anchor$, [BackgroundDependencyLoader] private void load() { - $END$ + $END$ } True True @@ -854,8 +874,8 @@ private void load() True new Box { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, }, True True @@ -868,7 +888,7 @@ private void load() True Children = new Drawable[] { - $END$ + $END$ }; True True From ccc8aa6fa4296bf6061527544269caf55c5baff6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 19:53:22 +0800 Subject: [PATCH 260/503] Apply brace style. --- .../TestSceneHyperDash.cs | 2 + .../Beatmaps/CatchBeatmapProcessor.cs | 4 ++ .../Objects/BananaShower.cs | 2 + .../Legacy/HitObjectPatternGenerator.cs | 4 ++ .../TestSceneDrawableJudgement.cs | 2 + .../TestSceneHitCircleLongCombo.cs | 2 + osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs | 4 ++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 + .../NonVisual/FramedReplayInputHandlerTest.cs | 2 + osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 2 + .../Online/TestSceneStandAloneChatDisplay.cs | 4 ++ .../SongSelect/TestSceneBeatmapCarousel.cs | 2 + .../SongSelect/TestScenePlaySongSelect.cs | 2 + osu.Game.Tests/Visual/TestSceneOsuGame.cs | 4 ++ .../TestSceneTournamentMatchChatDisplay.cs | 28 +++++------ .../Components/TournamentBeatmapPanel.cs | 2 + .../Components/TourneyVideo.cs | 2 + osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 + .../Screens/Editors/RoundEditorScreen.cs | 2 + .../Screens/Ladder/LadderScreen.cs | 6 ++- .../Screens/TeamIntro/TeamIntroScreen.cs | 2 + osu.Game.Tournament/TournamentGameBase.cs | 48 +++++++++++-------- .../Formats/LegacyStoryboardDecoder.cs | 24 +++++----- osu.Game/Beatmaps/WorkingBeatmap.cs | 6 ++- osu.Game/Database/ArchiveModelManager.cs | 8 ++++ .../Graphics/Containers/ShakeContainer.cs | 2 + .../Graphics/UserInterface/OsuTabControl.cs | 2 + .../Graphics/UserInterface/ScoreCounter.cs | 2 + osu.Game/Input/KeyBindingStore.cs | 2 + osu.Game/Online/Leaderboards/Leaderboard.cs | 6 +++ osu.Game/OsuGame.cs | 2 + osu.Game/OsuGameBase.cs | 2 + osu.Game/Overlays/Changelog/ChangelogBuild.cs | 6 +++ .../Changelog/ChangelogSingleBuild.cs | 2 + .../Overlays/Comments/CommentsContainer.cs | 2 + osu.Game/Overlays/Direct/DirectPanel.cs | 2 + osu.Game/Overlays/Mods/ModButton.cs | 2 + osu.Game/Overlays/Mods/ModSection.cs | 2 + .../Difficulty/Utils/LimitedCapacityStack.cs | 2 + .../Objects/Drawables/DrawableHitObject.cs | 2 + .../Objects/Legacy/ConvertHitObjectParser.cs | 2 + osu.Game/Rulesets/Objects/SliderPath.cs | 2 + osu.Game/Rulesets/RulesetStore.cs | 2 + osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 + osu.Game/Rulesets/UI/Playfield.cs | 4 ++ .../Screens/Multi/Components/BeatmapTitle.cs | 2 + .../Screens/Play/HUD/HoldForMenuButton.cs | 2 + osu.Game/Screens/Play/SkipOverlay.cs | 3 ++ .../Select/Carousel/CarouselBeatmap.cs | 4 ++ osu.Game/Screens/Select/SongSelect.cs | 4 ++ osu.Game/Skinning/LegacySkin.cs | 2 + osu.Game/Skinning/LegacySkinExtensions.cs | 6 ++- osu.Game/Skinning/SkinnableSound.cs | 8 ++++ osu.Game/Storyboards/CommandTimelineGroup.cs | 2 + osu.Game/Storyboards/StoryboardSprite.cs | 3 ++ .../Tests/Beatmaps/BeatmapConversionTest.cs | 4 ++ osu.Game/Tests/Visual/OsuGridTestScene.cs | 6 ++- osu.Game/Users/UserCoverBackground.cs | 2 + 58 files changed, 214 insertions(+), 52 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index 7b8c699f2c..da36673930 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -40,8 +40,10 @@ namespace osu.Game.Rulesets.Catch.Tests beatmap.HitObjects.Add(new Fruit { StartTime = 1008, X = 56 / 512f, }); for (int i = 0; i < 512; i++) + { if (i % 5 < 3) beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = 2000 + i * 100, NewCombo = i % 8 == 0 }); + } return beatmap; } diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 5ab47c1611..5d0c6116d7 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -196,9 +196,13 @@ namespace osu.Game.Rulesets.Catch.Beatmaps if (currentObject is Fruit) objectWithDroplets.Add(currentObject); if (currentObject is JuiceStream) + { foreach (var currentJuiceElement in currentObject.NestedHitObjects) + { if (!(currentJuiceElement is TinyDroplet)) objectWithDroplets.Add((CatchHitObject)currentJuiceElement); + } + } } objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 6d44e4660e..267e6d12c7 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -27,11 +27,13 @@ namespace osu.Game.Rulesets.Catch.Objects return; for (double i = StartTime; i <= EndTime; i += spacing) + { AddNested(new Banana { Samples = Samples, StartTime = i }); + } } public double EndTime => StartTime + Duration; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index decd159ee9..ada960a78d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -109,8 +109,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { // Generate a new pattern by copying the last hit objects in reverse-column order for (int i = RandomStart; i < TotalColumns; i++) + { if (PreviousPattern.ColumnHasObject(i)) addToPattern(pattern, RandomStart + TotalColumns - i - 1); + } return pattern; } @@ -132,8 +134,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { // Generate a new pattern by placing on the already filled columns for (int i = RandomStart; i < TotalColumns; i++) + { if (PreviousPattern.ColumnHasObject(i)) addToPattern(pattern, i); + } return pattern; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 433ec6bd25..ac627aa23e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -24,12 +24,14 @@ namespace osu.Game.Rulesets.Osu.Tests public TestSceneDrawableJudgement() { foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) + { AddStep("Show " + result.GetDescription(), () => SetContents(() => new DrawableOsuJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, })); + } } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 95c2810e94..b99cd523ff 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -29,8 +29,10 @@ namespace osu.Game.Rulesets.Osu.Tests }; for (int i = 0; i < 512; i++) + { if (i % 32 < 20) beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 }); + } return beatmap; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 17fcd03dd5..1664a37a66 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -55,8 +55,10 @@ namespace osu.Game.Rulesets.Osu.Mods } for (int i = 0; i < amountWiggles; i++) + { using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration, true)) wiggle(); + } // Keep wiggling sliders and spinners for their duration if (!(osuObject is IHasEndTime endTime)) @@ -65,8 +67,10 @@ namespace osu.Game.Rulesets.Osu.Mods amountWiggles = (int)(endTime.Duration / wiggle_duration); for (int i = 0; i < amountWiggles; i++) + { using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration, true)) wiggle(); + } } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index f60b7e67b2..3e23d09741 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -133,12 +133,14 @@ namespace osu.Game.Rulesets.Osu.Objects var sampleList = new List(); if (firstSample != null) + { sampleList.Add(new HitSampleInfo { Bank = firstSample.Bank, Volume = firstSample.Volume, Name = @"slidertick", }); + } switch (e.Type) { diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 18cbd4e7c5..7df7df22ea 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -225,8 +225,10 @@ namespace osu.Game.Tests.NonVisual private void fastForwardToPoint(double destination) { for (int i = 0; i < 1000; i++) + { if (handler.SetFrameFromTime(destination) == null) return; + } throw new TimeoutException("Seek was never fulfilled"); } diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index 0d96dd08da..ea9d51a9b8 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -26,6 +26,7 @@ namespace osu.Game.Tests.Skins List expectedColors; if (hasColours) + { expectedColors = new List { new Color4(142, 199, 255, 255), @@ -33,6 +34,7 @@ namespace osu.Game.Tests.Skins new Color4(128, 255, 255, 255), new Color4(100, 100, 100, 100), }; + } else expectedColors = new DefaultSkin().Configuration.ComboColours; diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 01400bf1d9..28b5693ef4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -130,12 +130,14 @@ namespace osu.Game.Tests.Visual.Online AddRepeatStep("add many messages", () => { for (int i = 0; i < messages_per_call; i++) + { testChannel.AddNewMessages(new Message(sequence++) { Sender = longUsernameUser, Content = "Many messages! " + Guid.NewGuid(), Timestamp = DateTimeOffset.Now }); + } }, Channel.MAX_HISTORY / messages_per_call + 5); AddAssert("Ensure no adjacent day separators", () => @@ -143,8 +145,10 @@ namespace osu.Game.Tests.Visual.Online var indices = chatDisplay.FillFlow.OfType().Select(ds => chatDisplay.FillFlow.IndexOf(ds)); foreach (var i in indices) + { if (i < chatDisplay.FillFlow.Count && chatDisplay.FillFlow[i + 1] is DrawableChannel.DaySeparator) return false; + } return true; }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 8b82567a8d..aa63bc1cf6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -467,8 +467,10 @@ namespace osu.Game.Tests.Visual.SongSelect private void advanceSelection(bool diff, int direction = 1, int count = 1) { if (count == 1) + { AddStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => carousel.SelectNext(direction, !diff)); + } else { AddRepeatStep($"select {(direction > 0 ? "next" : "prev")} {(diff ? "diff" : "set")}", () => diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index efe7fee5e4..794d135b06 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -132,11 +132,13 @@ namespace osu.Game.Tests.Visual.SongSelect changeRuleset(1); if (rulesetsInSameBeatmap) + { AddStep("import multi-ruleset map", () => { var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray(); manager.Import(createTestBeatmapSet(0, usableRulesets)).Wait(); }); + } else { addRulesetImportStep(1); diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/TestSceneOsuGame.cs index fcc3a3596f..36cd49d839 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuGame.cs @@ -109,16 +109,20 @@ namespace osu.Game.Tests.Visual AddAssert("check OsuGame DI members", () => { foreach (var type in requiredGameDependencies) + { if (game.Dependencies.Get(type) == null) throw new Exception($"{type} has not been cached"); + } return true; }); AddAssert("check OsuGameBase DI members", () => { foreach (var type in requiredGameBaseDependencies) + { if (gameBase.Dependencies.Get(type) == null) throw new Exception($"{type} has not been cached"); + } return true; }); diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index 41d32d9448..d77a0b75a5 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -103,20 +103,20 @@ namespace osu.Game.Tournament.Tests.Components })); AddStep("multiple messages", () => testChannel.AddNewMessages(new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!!!1" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!1!1" - })); + { + Sender = admin, + Content = "I spam you!" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!!!1" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!1!1" + })); AddStep("change channel to 2", () => chatDisplay.Channel.Value = testChannel2); diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index f6c1be0e36..0908814537 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -131,6 +131,7 @@ namespace osu.Game.Tournament.Components }); if (!string.IsNullOrEmpty(mods)) + { AddInternal(new Sprite { Texture = textures.Get($"mods/{mods}"), @@ -139,6 +140,7 @@ namespace osu.Game.Tournament.Components Margin = new MarginPadding(20), Scale = new Vector2(0.5f) }); + } } private void matchChanged(ValueChangedEvent match) diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index 8582b1634c..206689ca1a 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -29,12 +29,14 @@ namespace osu.Game.Tournament.Components }; } else + { InternalChild = video = new VideoSprite(stream) { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, Clock = new FramedClock(manualClock = new ManualClock()) }; + } } public bool Loop diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index e05d96e098..47f2bed77a 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -60,6 +60,7 @@ namespace osu.Game.Tournament.IPC const string file_ipc_channel_filename = "ipc-channel.txt"; if (Storage.Exists(file_ipc_filename)) + { scheduled = Scheduler.AddDelayed(delegate { try @@ -134,6 +135,7 @@ namespace osu.Game.Tournament.IPC // file might be in use. } }, 250, true); + } } catch (Exception e) { diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index b036350879..2c515edda7 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -266,12 +266,14 @@ namespace osu.Game.Tournament.Screens.Editors drawableContainer.Clear(); if (Model.BeatmapInfo != null) + { drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, Model.Mods) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Width = 300 }; + } } } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index 83a41a662f..66e68a0f37 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -81,8 +81,10 @@ namespace osu.Game.Tournament.Screens.Ladder LadderInfo.Matches.ItemsRemoved += matches => { foreach (var p in matches) - foreach (var d in MatchesContainer.Where(d => d.Match == p)) - d.Expire(); + { + foreach (var d in MatchesContainer.Where(d => d.Match == p)) + d.Expire(); + } layout.Invalidate(); }; diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index c901a5c7ef..47c923ff30 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -164,6 +164,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro if (team != null) { foreach (var p in team.Players) + { players.Add(new OsuSpriteText { Text = p.Username, @@ -172,6 +173,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft, Origin = left ? Anchor.CentreRight : Anchor.CentreLeft, }); + } } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 3b7718c61d..d34ea9648d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -164,15 +164,17 @@ namespace osu.Game.Tournament // link matches to rounds foreach (var round in ladder.Rounds) - foreach (var id in round.Matches) { - var found = ladder.Matches.FirstOrDefault(p => p.ID == id); - - if (found != null) + foreach (var id in round.Matches) { - found.Round.Value = round; - if (round.StartDate.Value > found.Date.Value) - found.Date.Value = round.StartDate.Value; + var found = ladder.Matches.FirstOrDefault(p => p.ID == id); + + if (found != null) + { + found.Round.Value = round; + if (round.StartDate.Value > found.Date.Value) + found.Date.Value = round.StartDate.Value; + } } } @@ -192,15 +194,19 @@ namespace osu.Game.Tournament bool addedInfo = false; foreach (var t in ladder.Teams) - foreach (var p in t.Players) - if (string.IsNullOrEmpty(p.Username)) + { + foreach (var p in t.Players) { - var req = new GetUserRequest(p.Id); - req.Perform(API); - p.Username = req.Result.Username; + if (string.IsNullOrEmpty(p.Username)) + { + var req = new GetUserRequest(p.Id); + req.Perform(API); + p.Username = req.Result.Username; - addedInfo = true; + addedInfo = true; + } } + } return addedInfo; } @@ -213,15 +219,19 @@ namespace osu.Game.Tournament bool addedInfo = false; foreach (var r in ladder.Rounds) - foreach (var b in r.Beatmaps) - if (b.BeatmapInfo == null && b.ID > 0) + { + foreach (var b in r.Beatmaps) { - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); - req.Perform(API); - b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore); + if (b.BeatmapInfo == null && b.ID > 0) + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID }); + req.Perform(API); + b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore); - addedInfo = true; + addedInfo = true; + } } + } return addedInfo; } diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 5dbd67d304..a86fa43f3c 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -144,16 +144,16 @@ namespace osu.Game.Beatmaps.Formats var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue; var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0; timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber); - } break; + } case "L": { var startTime = double.Parse(split[1], CultureInfo.InvariantCulture); var loopCount = int.Parse(split[2]); timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount); - } break; + } default: { @@ -172,7 +172,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); } - break; + break; case "S": { @@ -180,7 +180,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); } - break; + break; case "V": { @@ -190,7 +190,7 @@ namespace osu.Game.Beatmaps.Formats var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); } - break; + break; case "R": { @@ -198,7 +198,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue)); } - break; + break; case "M": { @@ -209,7 +209,7 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); } - break; + break; case "MX": { @@ -217,7 +217,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); } - break; + break; case "MY": { @@ -225,7 +225,7 @@ namespace osu.Game.Beatmaps.Formats var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); } - break; + break; case "C": { @@ -239,7 +239,7 @@ namespace osu.Game.Beatmaps.Formats new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); } - break; + break; case "P": { @@ -260,13 +260,13 @@ namespace osu.Game.Beatmaps.Formats break; } } - break; + break; default: throw new InvalidDataException($@"Unknown command type: {commandType}"); } } - break; + break; } } } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 3fc33e9f52..7c69a992dd 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -133,8 +133,10 @@ namespace osu.Game.Beatmaps obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty); foreach (var mod in mods.OfType()) - foreach (var obj in converted.HitObjects) - mod.ApplyToHitObject(obj); + { + foreach (var obj in converted.HitObjects) + mod.ApplyToHitObject(obj); + } processor?.PostProcess(); diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 9fed8e03ac..a262b76125 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -265,8 +265,10 @@ namespace osu.Game.Database // for now, concatenate all .osu files in the set to create a unique hash. MemoryStream hashable = new MemoryStream(); foreach (string file in reader.Filenames.Where(f => HashableFileTypes.Any(f.EndsWith))) + { using (Stream s = reader.GetStream(file)) s.CopyTo(hashable); + } return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : null; } @@ -485,12 +487,16 @@ namespace osu.Game.Database // import files to manager foreach (string file in reader.Filenames) + { using (Stream s = reader.GetStream(file)) + { fileInfos.Add(new TFileModel { Filename = FileSafety.PathStandardise(file.Substring(prefix.Length)), FileInfo = files.Add(s) }); + } + } return fileInfos; } @@ -651,8 +657,10 @@ namespace osu.Game.Database private void handleEvent(Action a) { if (delayingEvents) + { lock (queuedEvents) queuedEvents.Add(a); + } else a.Invoke(); } diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index e5a6bcc28e..dca9df1e98 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -43,9 +43,11 @@ namespace osu.Game.Graphics.Containers // if we don't have enough time for the second shake, skip it. if (!maximumLength.HasValue || maximumLength >= ShakeDuration * 4) + { sequence = sequence .MoveToX(shake_amount, ShakeDuration, Easing.InOutSine).Then() .MoveToX(-shake_amount, ShakeDuration, Easing.InOutSine).Then(); + } sequence.MoveToX(0, ShakeDuration / 2, Easing.InSine); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index c55d14456b..5d1bdc62e9 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -51,8 +51,10 @@ namespace osu.Game.Graphics.UserInterface }); if (isEnumType && AddEnumEntriesAutomatically) + { foreach (var val in (T[])Enum.GetValues(typeof(T))) AddItem(val); + } } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 63062cdc9d..ee96b78844 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -44,8 +44,10 @@ namespace osu.Game.Graphics.UserInterface { string format = new string('0', (int)LeadingZeroes); if (UseCommaSeparator) + { for (int i = format.Length - 3; i > 0; i -= 3) format = format.Insert(i, @","); + } return ((long)count).ToString(format); } diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index caddb1ae0d..b1c794a856 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -47,6 +47,7 @@ namespace osu.Game.Input foreach (var insertable in group.Skip(count).Take(aimCount - count)) // insert any defaults which are missing. + { usage.Context.DatabasedKeyBinding.Add(new DatabasedKeyBinding { KeyCombination = insertable.KeyCombination, @@ -54,6 +55,7 @@ namespace osu.Game.Input RulesetID = rulesetId, Variant = variant }); + } } } } diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 83de0635fb..d214743b30 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -75,8 +75,10 @@ namespace osu.Game.Online.Leaderboards int i = 0; foreach (var s in scrollFlow.Children) + { using (s.BeginDelayedSequence(i++ * 50, true)) s.Show(); + } scrollContainer.ScrollTo(0f, false); }, (showScoresCancellationSource = new CancellationTokenSource()).Token)); @@ -342,13 +344,17 @@ namespace osu.Game.Online.Leaderboards else { if (bottomY - fadeBottom > 0 && FadeBottom) + { c.Colour = ColourInfo.GradientVertical( Color4.White.Opacity(Math.Min(1 - (topY - fadeBottom) / LeaderboardScore.HEIGHT, 1)), Color4.White.Opacity(Math.Min(1 - (bottomY - fadeBottom) / LeaderboardScore.HEIGHT, 1))); + } else if (FadeTop) + { c.Colour = ColourInfo.GradientVertical( Color4.White.Opacity(Math.Min(1 - (fadeTop - topY) / LeaderboardScore.HEIGHT, 1)), Color4.White.Opacity(Math.Min(1 - (fadeTop - bottomY) / LeaderboardScore.HEIGHT, 1))); + } } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f823e6eba..7735030bbb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -402,8 +402,10 @@ namespace osu.Game nextBeatmap.Track.Completed += currentTrackCompleted; using (var oldBeatmap = beatmap.OldValue) + { if (oldBeatmap?.Track != null) oldBeatmap.Track.Completed -= currentTrackCompleted; + } nextBeatmap?.LoadBeatmapAsync(); } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 194a439b06..87321030a9 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -292,8 +292,10 @@ namespace osu.Game var extension = Path.GetExtension(paths.First())?.ToLowerInvariant(); foreach (var importer in fileImporters) + { if (importer.HandledExtensions.Contains(extension)) await importer.Import(paths); + } } public string[] HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions).ToArray(); diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index d8488b21ab..5a3ce6291e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -130,6 +130,7 @@ namespace osu.Game.Overlays.Changelog }); if (entry.GithubUser.UserId != null) + { title.AddUserLink(new User { Username = entry.GithubUser.OsuUsername, @@ -139,18 +140,23 @@ namespace osu.Game.Overlays.Changelog t.Font = fontMedium; t.Colour = entryColour; }); + } else if (entry.GithubUser.GithubUrl != null) + { title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, t => { t.Font = fontMedium; t.Colour = entryColour; }); + } else + { title.AddText(entry.GithubUser.DisplayName, t => { t.Font = fontSmall; t.Colour = entryColour; }); + } ChangelogEntries.Add(titleContainer); diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index adcd33fb48..3297b00322 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -68,11 +68,13 @@ namespace osu.Game.Overlays.Changelog } if (build != null) + { Children = new Drawable[] { new ChangelogBuildWithNavigation(build) { SelectBuild = SelectBuild }, new Comments(build) }; + } } public class ChangelogBuildWithNavigation : ChangelogBuild diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index abc1b7233d..560123eb55 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -162,10 +162,12 @@ namespace osu.Game.Overlays.Comments foreach (var c in response.Comments) { if (c.IsTopLevel) + { page.Add(new DrawableComment(c) { ShowDeleted = { BindTarget = ShowDeleted } }); + } } LoadComponentAsync(page, loaded => diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 3ffc3f332b..c1c5113c5e 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -149,8 +149,10 @@ namespace osu.Game.Overlays.Direct icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.FindAll(b => b.Ruleset.Equals(ruleset)), ruleset, this is DirectListPanel ? Color4.White : colours.Gray5)); } else + { foreach (var b in SetInfo.Beatmaps.OrderBy(beatmap => beatmap.StarDifficulty)) icons.Add(new DifficultyIcon(b)); + } return icons; } diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 58892cd0dd..8252020e9b 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -194,8 +194,10 @@ namespace osu.Game.Overlays.Mods start = Mods.Length - 1; for (int i = start; i < Mods.Length && i >= 0; i += direction) + { if (SelectAt(i)) return; + } Deselect(); } diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index dedd397fa5..5c2ab8e18c 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,6 +112,7 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) + { if (type.IsInstanceOfType(selected)) { if (immediate) @@ -119,6 +120,7 @@ namespace osu.Game.Overlays.Mods else Scheduler.AddDelayed(button.Deselect, delay += 50); } + } } } diff --git a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs index 95b7d9b19d..d47caf409b 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs @@ -81,8 +81,10 @@ namespace osu.Game.Rulesets.Difficulty.Utils yield return array[i]; if (Count == capacity) + { for (int i = 0; i < marker; ++i) yield return array[i]; + } } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1d9b66f88d..af1a2fb63a 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -113,8 +113,10 @@ namespace osu.Game.Rulesets.Objects.Drawables if (samples.Length > 0) { if (HitObject.SampleControlPoint == null) + { throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + } samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); foreach (var s in samples) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index e990938291..64f01952b1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -75,8 +75,10 @@ namespace osu.Game.Rulesets.Objects.Legacy int pointCount = 1; foreach (var t in pointSplit) + { if (t.Length > 1) pointCount++; + } var points = new Vector2[pointCount]; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index bc9571c85d..7763b0eaaf 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -185,8 +185,10 @@ namespace osu.Game.Rulesets.Objects ReadOnlySpan cpSpan = ControlPoints.Slice(start, end - start); foreach (Vector2 t in calculateSubpath(cpSpan)) + { if (calculatedPath.Count == 0 || calculatedPath.Last() != t) calculatedPath.Add(t); + } start = end; } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 23988ff0ff..7d13afe9e5 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -69,8 +69,10 @@ namespace osu.Game.Rulesets //add any other modes foreach (var r in instances.Where(r => r.LegacyID == null)) + { if (context.RulesetInfo.FirstOrDefault(ri => ri.InstantiationInfo == r.RulesetInfo.InstantiationInfo) == null) context.RulesetInfo.Add(r.RulesetInfo); + } context.SaveChanges(); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index e005eea831..d1749d33c0 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -436,8 +436,10 @@ namespace osu.Game.Rulesets.UI return h.HitWindows; foreach (var n in h.NestedHitObjects) + { if (h.HitWindows.WindowFor(HitResult.Miss) > 0) return n.HitWindows; + } } return null; diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index f2e7f51b52..ca4983e3d7 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -130,9 +130,13 @@ namespace osu.Game.Rulesets.UI base.Update(); if (beatmap != null) + { foreach (var mod in mods) + { if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); + } + } } /// diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index f79cac7649..b41b2d073e 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -57,11 +57,13 @@ namespace osu.Game.Screens.Multi.Components var beatmap = CurrentItem.Value?.Beatmap; if (beatmap == null) + { textFlow.AddText("No beatmap selected", s => { s.Font = s.Font.With(size: TextSize); s.Colour = colours.PinkLight; }); + } else { textFlow.AddLink(new[] diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index a05937801c..968b83e68c 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -100,9 +100,11 @@ namespace osu.Game.Screens.Play.HUD if (text.Alpha > 0 || button.Progress.Value > 0 || button.IsHovered) Alpha = 1; else + { Alpha = Interpolation.ValueAt( MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + } } private class Button : HoldToConfirmContainer, IKeyBindingHandler diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 31cdff5fb9..835867fe62 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -181,8 +181,11 @@ namespace osu.Game.Screens.Play this.FadeIn(500, Easing.OutExpo); if (!IsHovered && !IsDragged) + { using (BeginDelayedSequence(1000)) scheduledHide = Schedule(Hide); + } + break; case Visibility.Hidden: diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 6c3c9d20f3..afd6211dec 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -44,10 +44,14 @@ namespace osu.Game.Screens.Select.Carousel criteria.Artist.Matches(Beatmap.Metadata.ArtistUnicode); if (match) + { foreach (var criteriaTerm in criteria.SearchTerms) + { match &= Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; + } + } Filtered.Value = !match; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 409ea4bbbe..78ff150f08 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -251,11 +251,13 @@ namespace osu.Game.Screens.Select { // if we have no beatmaps but osu-stable is found, let's prompt the user to import. if (!beatmaps.GetAllUsableBeatmapSetsEnumerable().Any() && beatmaps.StableInstallationAvailable) + { dialogOverlay.Push(new ImportFromStablePopup(() => { Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion); Task.Run(skins.ImportFromStableAsync); })); + } }); } } @@ -333,11 +335,13 @@ namespace osu.Game.Screens.Select if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch + { if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value)) { Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; Carousel.SelectBeatmap(e.NewValue.BeatmapInfo); } + } } // We need to keep track of the last selected beatmap ignoring debounce to play the correct selection sounds. diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index fea15458e4..593b80c012 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -36,8 +36,10 @@ namespace osu.Game.Skinning { Stream stream = storage?.GetStream(filename); if (stream != null) + { using (LineBufferedReader reader = new LineBufferedReader(stream)) Configuration = new LegacySkinDecoder().Decode(reader); + } else Configuration = new DefaultSkinConfiguration(); diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index c5582af836..c758b699ed 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -22,17 +22,19 @@ namespace osu.Game.Skinning if (animatable) { - for (int i = 0;; i++) + for (int i = 0; true; i++) { if ((texture = getFrameTexture(i)) == null) break; if (animation == null) + { animation = new TextureAnimation { DefaultFrameLength = default_frame_time, Repeat = looping }; + } animation.AddFrame(texture); } @@ -42,10 +44,12 @@ namespace osu.Game.Skinning return animation; if ((texture = source.GetTexture(componentName)) != null) + { return new Sprite { Texture = texture }; + } return null; } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index bdf8be773b..6d23f22515 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -81,9 +81,13 @@ namespace osu.Game.Skinning var ch = skin.GetSample(s); if (ch == null && allowFallback) + { foreach (var lookup in s.LookupNames) + { if ((ch = samples.Get($"Gameplay/{lookup}")) != null) break; + } + } if (ch != null) { @@ -91,8 +95,10 @@ namespace osu.Game.Skinning ch.Volume.Value = s.Volume / 100.0; if (adjustments != null) + { foreach (var adjustment in adjustments) ch.AddAdjustment(adjustment.property, adjustment.bindable); + } } return ch; @@ -104,8 +110,10 @@ namespace osu.Game.Skinning base.Dispose(isDisposing); if (channels != null) + { foreach (var c in channels) c.Dispose(); + } } } } diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index 461ee762e9..364c971874 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -65,6 +65,7 @@ namespace osu.Game.Storyboards public virtual IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { if (offset != 0) + { return timelineSelector(this).Commands.Select(command => new CommandTimeline.TypedCommand { @@ -74,6 +75,7 @@ namespace osu.Game.Storyboards StartValue = command.StartValue, EndValue = command.EndValue, }); + } return timelineSelector(this).Commands; } diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 37c3ff495f..96c7ceea8d 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -106,8 +106,11 @@ namespace osu.Game.Storyboards foreach (var loop in loops) commands = commands.Concat(loop.GetCommands(timelineSelector)); if (triggeredGroups != null) + { foreach (var pair in triggeredGroups) commands = commands.Concat(pair.Item1.GetCommands(timelineSelector, pair.Item2)); + } + return commands; } diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index e99b5fc5fb..b144de35c5 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -72,11 +72,15 @@ namespace osu.Game.Tests.Beatmaps break; if (objectCounter >= ourMapping.Objects.Count) + { Assert.Fail($"The conversion did not generate a hitobject, but should have, for hitobject at time: {expectedMapping.StartTime}:\n" + $"Expected: {JsonConvert.SerializeObject(expectedMapping.Objects[objectCounter])}\n"); + } else if (objectCounter >= expectedMapping.Objects.Count) + { Assert.Fail($"The conversion generated a hitobject, but should not have, for hitobject at time: {ourMapping.StartTime}:\n" + $"Received: {JsonConvert.SerializeObject(ourMapping.Objects[objectCounter])}\n"); + } else if (!expectedMapping.Objects[objectCounter].Equals(ourMapping.Objects[objectCounter])) { Assert.Fail($"The conversion generated differing hitobjects for object at time: {expectedMapping.StartTime}:\n" diff --git a/osu.Game/Tests/Visual/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs index c09f4d6218..33ede9453e 100644 --- a/osu.Game/Tests/Visual/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -38,8 +38,10 @@ namespace osu.Game.Tests.Visual cells = new Drawable[rows, cols]; for (int r = 0; r < rows; r++) - for (int c = 0; c < cols; c++) - cells[r, c] = new Container { RelativeSizeAxes = Axes.Both }; + { + for (int c = 0; c < cols; c++) + cells[r, c] = new Container { RelativeSizeAxes = Axes.Both }; + } testContainer.Content = cells.ToJagged(); } diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index e583acac9f..a45fd85901 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -46,6 +46,7 @@ namespace osu.Game.Users }; } else + { InternalChild = new Sprite { RelativeSizeAxes = Axes.Both, @@ -54,6 +55,7 @@ namespace osu.Game.Users Anchor = Anchor.Centre, Origin = Anchor.Centre }; + } } protected override void LoadComplete() From d8482448dc91ecf93e63789075fc287e0b2c7258 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 19:53:41 +0800 Subject: [PATCH 261/503] Save iOS projects with BOM to avoid VS continuously changing them. --- .../osu.Game.Rulesets.Catch.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.iOS.csproj | 2 +- osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj | 2 +- osu.iOS/osu.iOS.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj index 708779986c..be6044bbd0 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj index 52e558931b..88ad484bc1 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index cacd035078..545abcec6c 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj index c20bd4fe02..8ee640cd99 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj index 583d188295..ca68369ebb 100644 --- a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -1,4 +1,4 @@ - + Debug diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 378ac231c2..d60a3475e7 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -1,4 +1,4 @@ - + Debug From e9b8cbb5165a65db0c779cc8ef4b97a580d8d3cc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 20:05:36 +0800 Subject: [PATCH 262/503] Apply other styles. --- .../Beatmaps/CatchBeatmapProcessor.cs | 1 + osu.Game.Tests/Skins/LegacySkinDecoderTest.cs | 1 + .../TestSceneTournamentMatchChatDisplay.cs | 31 ++++++++++--------- .../Formats/LegacyStoryboardDecoder.cs | 22 +++++++------ osu.Game/Database/ArchiveModelManager.cs | 1 + .../Graphics/UserInterface/ScoreCounter.cs | 1 + osu.Game/Input/KeyBindingStore.cs | 2 +- osu.Game/Online/Chat/ChannelManager.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 1 + osu.Game/Screens/Select/SongSelect.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 1 + osu.Game/Storyboards/StoryboardSprite.cs | 1 + osu.Game/Tests/Visual/OsuGridTestScene.cs | 1 + osu.iOS/AppDelegate.cs | 1 - 14 files changed, 39 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 5d0c6116d7..58bf811fac 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -195,6 +195,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps { if (currentObject is Fruit) objectWithDroplets.Add(currentObject); + if (currentObject is JuiceStream) { foreach (var currentJuiceElement in currentObject.NestedHitObjects) diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index ea9d51a9b8..085f502517 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -25,6 +25,7 @@ namespace osu.Game.Tests.Skins var comboColors = decoder.Decode(stream).ComboColours; List expectedColors; + if (hasColours) { expectedColors = new List diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index d77a0b75a5..9905e17824 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -102,21 +102,22 @@ namespace osu.Game.Tournament.Tests.Components Content = "Okay okay, calm down guys. Let's do this!" })); - AddStep("multiple messages", () => testChannel.AddNewMessages(new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!!!1" - }, - new Message(nextMessageId()) - { - Sender = admin, - Content = "I spam you!1!1" - })); + AddStep("multiple messages", () => testChannel.AddNewMessages( + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!!!1" + }, + new Message(nextMessageId()) + { + Sender = admin, + Content = "I spam you!1!1" + })); AddStep("change channel to 2", () => chatDisplay.Channel.Value = testChannel2); diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index a86fa43f3c..e3320f62ac 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -171,16 +171,16 @@ namespace osu.Game.Beatmaps.Formats var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); + break; } - break; case "S": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); + break; } - break; case "V": { @@ -189,16 +189,16 @@ namespace osu.Game.Beatmaps.Formats var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); + break; } - break; case "R": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue)); + break; } - break; case "M": { @@ -208,24 +208,24 @@ namespace osu.Game.Beatmaps.Formats var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); + break; } - break; case "MX": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); + break; } - break; case "MY": { var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); + break; } - break; case "C": { @@ -238,8 +238,8 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.Colour.Add(easing, startTime, endTime, new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); + break; } - break; case "P": { @@ -259,14 +259,16 @@ namespace osu.Game.Beatmaps.Formats timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break; } + + break; } - break; default: throw new InvalidDataException($@"Unknown command type: {commandType}"); } + + break; } - break; } } } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index a262b76125..8fa4eaf267 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -264,6 +264,7 @@ namespace osu.Game.Database { // for now, concatenate all .osu files in the set to create a unique hash. MemoryStream hashable = new MemoryStream(); + foreach (string file in reader.Filenames.Where(f => HashableFileTypes.Any(f.EndsWith))) { using (Stream s = reader.GetStream(file)) diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index ee96b78844..e291401670 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -43,6 +43,7 @@ namespace osu.Game.Graphics.UserInterface protected override string FormatCount(double count) { string format = new string('0', (int)LeadingZeroes); + if (UseCommaSeparator) { for (int i = format.Length - 3; i > 0; i -= 3) diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index b1c794a856..74b3134964 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -46,8 +46,8 @@ namespace osu.Game.Input continue; foreach (var insertable in group.Skip(count).Take(aimCount - count)) - // insert any defaults which are missing. { + // insert any defaults which are missing. usage.Context.DatabasedKeyBinding.Add(new DatabasedKeyBinding { KeyCombination = insertable.KeyCombination, diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index 4f6066cab1..1d8c5609d9 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -220,7 +220,7 @@ namespace osu.Game.Online.Chat break; } - var channel = availableChannels.Where(c => c.Name == content || c.Name == $"#{content}").FirstOrDefault(); + var channel = availableChannels.FirstOrDefault(c => c.Name == content || c.Name == $"#{content}"); if (channel == null) { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 64f01952b1..4049e40013 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -74,6 +74,7 @@ namespace osu.Game.Rulesets.Objects.Legacy string[] pointSplit = split[5].Split('|'); int pointCount = 1; + foreach (var t in pointSplit) { if (t.Length > 1) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 78ff150f08..375b994169 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -334,8 +334,8 @@ namespace osu.Game.Screens.Select if (e.NewValue is DummyWorkingBeatmap) return; if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) - // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch { + // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value)) { Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 593b80c012..67a83f19e2 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -35,6 +35,7 @@ namespace osu.Game.Skinning : base(skin) { Stream stream = storage?.GetStream(filename); + if (stream != null) { using (LineBufferedReader reader = new LineBufferedReader(stream)) diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 96c7ceea8d..d5e69fd103 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -105,6 +105,7 @@ namespace osu.Game.Storyboards var commands = TimelineGroup.GetCommands(timelineSelector); foreach (var loop in loops) commands = commands.Concat(loop.GetCommands(timelineSelector)); + if (triggeredGroups != null) { foreach (var pair in triggeredGroups) diff --git a/osu.Game/Tests/Visual/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs index 33ede9453e..48f85be6ba 100644 --- a/osu.Game/Tests/Visual/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -37,6 +37,7 @@ namespace osu.Game.Tests.Visual Add(testContainer = new GridContainer { RelativeSizeAxes = Axes.Both }); cells = new Drawable[rows, cols]; + for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 164a182ebe..14e3627752 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using Foundation; using osu.Framework.iOS; -using osu.Framework.Threading; using UIKit; namespace osu.iOS From d3858622676274c0c30d731099311a9bca1401d2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 20:32:32 +0800 Subject: [PATCH 263/503] Add dotnet format check. --- .config/dotnet-tools.json | 6 ++++++ build/build.cake | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1b70c949eb..6ba6ae82c8 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -7,6 +7,12 @@ "commands": [ "dotnet-cake" ] + }, + "dotnet-format": { + "version": "3.1.37601", + "commands": [ + "dotnet-format" + ] } } } \ No newline at end of file diff --git a/build/build.cake b/build/build.cake index 389ff4829d..274e57ef4e 100644 --- a/build/build.cake +++ b/build/build.cake @@ -11,6 +11,7 @@ var target = Argument("target", "Build"); var configuration = Argument("configuration", "Release"); var rootDirectory = new DirectoryPath(".."); +var sln = rootDirectory.CombineWithFilePath("osu.sln"); var desktopBuilds = rootDirectory.CombineWithFilePath("build/Desktop.proj"); var desktopSlnf = rootDirectory.CombineWithFilePath("osu.Desktop.slnf"); @@ -60,8 +61,12 @@ Task("CodeFileSanity") }); }); +Task("DotnetFormat") + .Does(() => DotNetCoreTool(sln.FullPath, "format", "--dry-run --check")); + Task("Build") .IsDependentOn("CodeFileSanity") + .IsDependentOn("DotnetFormat") .IsDependentOn("InspectCode") .IsDependentOn("Test"); From 1ef645a7105977268c17c5fe438341be1f59ab5a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 21:02:48 +0800 Subject: [PATCH 264/503] Turn off some more not applied styles. --- .editorconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8f9d0ca9b0..2c000d3881 100644 --- a/.editorconfig +++ b/.editorconfig @@ -140,7 +140,7 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning dotnet_style_prefer_auto_properties = true:silent dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent -dotnet_style_prefer_compound_assignment = true:warning +dotnet_style_prefer_compound_assignment = true:silent #Style - null/type checks dotnet_style_coalesce_expression = true:warning @@ -153,17 +153,17 @@ csharp_style_conditional_delegate_call = true:suggestion #Style - unused dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:silent #Style - variable declaration -csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true:silent csharp_style_deconstructed_variable_declaration = true:silent #Style - other C# 7.x features csharp_style_expression_bodied_local_functions = true:silent dotnet_style_prefer_inferred_tuple_names = true:warning csharp_prefer_simple_default_expression = true:warning -csharp_style_pattern_local_over_anonymous_function = true:warning +csharp_style_pattern_local_over_anonymous_function = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent #Supressing roslyn built-in analyzers From 3655f881806ee7b13cd6e22074439d7d07405885 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 17:56:57 +0300 Subject: [PATCH 265/503] Merge dependency --- .../Online/TestSceneLeaderboardModSelector.cs | 77 ++++++++ .../BeatmapSet/LeaderboardModSelector.cs | 165 ++++++++++++++++++ osu.Game/Rulesets/UI/ModIcon.cs | 19 +- 3 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs create mode 100644 osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs new file mode 100644 index 0000000000..799528220b --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -0,0 +1,77 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Overlays.BeatmapSet; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Bindables; +using osu.Game.Rulesets; +using osu.Framework.Extensions.IEnumerableExtensions; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneLeaderboardModSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(LeaderboardModSelector), + }; + + public TestSceneLeaderboardModSelector() + { + LeaderboardModSelector modSelector; + FillFlowContainer selectedMods; + Bindable ruleset = new Bindable(); + + Add(selectedMods = new FillFlowContainer + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + + Add(modSelector = new LeaderboardModSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Ruleset = { BindTarget = ruleset } + }); + + modSelector.SelectedMods.ItemsAdded += mods => + { + mods.ForEach(mod => selectedMods.Add(new SpriteText + { + Text = mod.Acronym, + })); + }; + + modSelector.SelectedMods.ItemsRemoved += mods => + { + mods.ForEach(mod => + { + foreach (var selected in selectedMods) + { + if (selected.Text == mod.Acronym) + { + selectedMods.Remove(selected); + break; + } + } + }); + }; + + AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("Deselect all", () => modSelector.DeselectAll()); + AddStep("null ruleset", () => ruleset.Value = null); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs new file mode 100644 index 0000000000..75c24cb710 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -0,0 +1,165 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Framework.Bindables; +using osu.Game.Rulesets; +using osuTK; +using osu.Game.Rulesets.UI; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; +using System; +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class LeaderboardModSelector : CompositeDrawable + { + public readonly BindableList SelectedMods = new BindableList(); + public readonly Bindable Ruleset = new Bindable(); + + private readonly FillFlowContainer modsContainer; + + public LeaderboardModSelector() + { + AutoSizeAxes = Axes.Both; + InternalChild = modsContainer = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Full, + Spacing = new Vector2(4), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Ruleset.BindValueChanged(onRulesetChanged, true); + } + + private void onRulesetChanged(ValueChangedEvent ruleset) + { + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset.NewValue == null) + return; + + modsContainer.Add(new ModButton(new NoMod())); + + ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => + { + if (mod.Ranked) + modsContainer.Add(new ModButton(mod)); + }); + + modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); + } + + private void selectionChanged(Mod mod, bool selected) + { + if (selected) + SelectedMods.Add(mod); + else + SelectedMods.Remove(mod); + + if (!SelectedMods.Any() && !IsHovered) + highlightAll(); + } + + protected override bool OnHover(HoverEvent e) + { + if (!SelectedMods.Any()) + modsContainer.ForEach(button => + { + if (!button.IsHovered) + button.Highlighted.Value = false; + }); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + if (!SelectedMods.Any()) + highlightAll(); + } + + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); + + private void highlightAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = true); + + private class ModButton : ModIcon + { + private const float mod_scale = 0.4f; + private const int duration = 200; + + public readonly BindableBool Selected = new BindableBool(); + public Action OnSelectionChanged; + + public ModButton(Mod mod) + : base(mod) + { + Scale = new Vector2(mod_scale); + Highlighted.Value = true; + Add(new HoverClickSounds()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Selected.BindValueChanged(selected => + { + updateState(); + OnSelectionChanged?.Invoke(Mod, selected.NewValue); + }); + } + + protected override bool OnClick(ClickEvent e) + { + Selected.Value = !Selected.Value; + return base.OnClick(e); + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateState(); + } + + private void updateState() => Highlighted.Value = IsHovered || Selected.Value; + + protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => + this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); + } + + private class NoMod : Mod + { + public override string Name => "NoMod"; + + public override string Acronym => "NM"; + + public override double ScoreMultiplier => 1; + + public override IconUsage Icon => FontAwesome.Solid.Ban; + + public override ModType Type => ModType.System; + } + } +} diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 88a2338b94..19211e0c80 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -34,9 +34,11 @@ namespace osu.Game.Rulesets.UI public virtual string TooltipText { get; } + protected Mod Mod { get; private set; } + public ModIcon(Mod mod) { - if (mod == null) throw new ArgumentNullException(nameof(mod)); + Mod = mod ?? throw new ArgumentNullException(nameof(mod)); type = mod.Type; @@ -98,13 +100,26 @@ namespace osu.Game.Rulesets.UI backgroundColour = colours.Pink; highlightedColour = colours.PinkLight; break; + + case ModType.System: + backgroundColour = colours.Gray6; + highlightedColour = colours.Gray7; + modIcon.Colour = colours.Yellow; + break; } + + background.Colour = backgroundColour; } protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Highlighted.BindValueChanged(OnHighlightedChanged, true); + } + + protected virtual void OnHighlightedChanged(ValueChangedEvent highlighted) + { + background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; } } } From 32b2f5e330e70fe7ef910bf28dec1f84255e93c1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:10:25 +0300 Subject: [PATCH 266/503] Use Bindable for ScoresContainer --- .../BeatmapSet/Scores/ScoresContainer.cs | 31 +++++++------------ osu.Game/Overlays/BeatmapSetOverlay.cs | 6 ++-- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 4bbcd8d631..580e863a0c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -13,6 +13,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Framework.Bindables; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -20,6 +21,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private const int spacing = 15; + public readonly Bindable Beatmap = new Bindable(); + private readonly Box background; private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; @@ -30,22 +33,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private GetScoresRequest getScoresRequest; - private BeatmapInfo beatmap; - - public BeatmapInfo Beatmap - { - get => beatmap; - set - { - if (beatmap == value) - return; - - beatmap = value; - - getScores(beatmap); - } - } - protected APILegacyScores Scores { set @@ -125,18 +112,24 @@ namespace osu.Game.Overlays.BeatmapSet.Scores background.Colour = colours.Gray2; } - private void getScores(BeatmapInfo beatmap) + protected override void LoadComplete() + { + base.LoadComplete(); + Beatmap.BindValueChanged(getScores, true); + } + + private void getScores(ValueChangedEvent beatmap) { getScoresRequest?.Cancel(); getScoresRequest = null; Scores = null; - if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap.Status <= BeatmapSetOnlineStatus.Pending) + if (beatmap.NewValue?.OnlineBeatmapID.HasValue != true || beatmap.NewValue.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest = new GetScoresRequest(beatmap.NewValue, beatmap.NewValue.Ruleset); getScoresRequest.Success += scores => { loadingAnimation.Hide(); diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index c20e6368d8..65d68e4c8c 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -59,7 +59,10 @@ namespace osu.Game.Overlays { Header = new Header(), info = new Info(), - scoreContainer = new ScoresContainer(), + scoreContainer = new ScoresContainer + { + Beatmap = { BindTarget = Header.Picker.Beatmap } + } }, }, }, @@ -71,7 +74,6 @@ namespace osu.Game.Overlays Header.Picker.Beatmap.ValueChanged += b => { info.Beatmap = b.NewValue; - scoreContainer.Beatmap = b.NewValue; scroll.ScrollToStart(); }; From e690a8a301d6c9e451b6723d215be23d9fdc4d14 Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Mon, 11 Nov 2019 22:15:19 +0700 Subject: [PATCH 267/503] Fix capitalisation in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 67eb3254e1..bc5beeb83d 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh ## Requirements - A desktop platform with the [.NET Core SDK 3.0](https://www.microsoft.com/net/learn/get-started) or higher installed. -- When running on linux, please have a system-wide ffmpeg installation available to support video decoding. +- When running on Linux, please have a system-wide ffmpeg installation available to support video decoding. - When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs. -- When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). +- When working with the codebase, we recommend using an IDE with IntelliSense and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). ## Running osu! From 00b92297375b3062337d303cdb9f6885e440fc71 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:21:07 +0300 Subject: [PATCH 268/503] Add mod filter to beatmap overlay --- .../BeatmapSet/Scores/ScoresContainer.cs | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 580e863a0c..acf0f08956 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -14,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; +using osu.Game.Rulesets; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -22,11 +23,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const int spacing = 15; public readonly Bindable Beatmap = new Bindable(); + private readonly Bindable ruleset = new Bindable(); private readonly Box background; private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; private readonly LoadingAnimation loadingAnimation; + private readonly FillFlowContainer modFilter; + private readonly LeaderboardModSelector modSelector; [Resolved] private IAPIProvider api { get; set; } @@ -84,6 +88,22 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { + modFilter = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Children = new Drawable[] + { + new LeaderboardScopeSelector(), + modSelector = new LeaderboardModSelector + { + Ruleset = { BindTarget = ruleset } + } + } + }, topScoresContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -115,21 +135,33 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override void LoadComplete() { base.LoadComplete(); - Beatmap.BindValueChanged(getScores, true); + Beatmap.BindValueChanged(onBeatmapChanged, true); } - private void getScores(ValueChangedEvent beatmap) + private void onBeatmapChanged(ValueChangedEvent beatmap) + { + var beatmapRuleset = beatmap.NewValue?.Ruleset; + + if (modSelector.Ruleset.Value?.Equals(beatmapRuleset) ?? false) + modSelector.DeselectAll(); + else + ruleset.Value = beatmapRuleset; + + getScores(beatmap.NewValue); + } + + private void getScores(BeatmapInfo beatmap) { getScoresRequest?.Cancel(); getScoresRequest = null; Scores = null; - if (beatmap.NewValue?.OnlineBeatmapID.HasValue != true || beatmap.NewValue.Status <= BeatmapSetOnlineStatus.Pending) + if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(beatmap.NewValue, beatmap.NewValue.Ruleset); + getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); getScoresRequest.Success += scores => { loadingAnimation.Hide(); From 2cfd54ca0d577da1872f74b92c83596a6001e1d1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:27:48 +0300 Subject: [PATCH 269/503] Handle scope changing --- .../BeatmapSet/Scores/ScoresContainer.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index acf0f08956..8058d0fc0f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -15,6 +15,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; using osu.Game.Rulesets; +using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -24,6 +25,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); + private readonly Bindable scope = new Bindable(); private readonly Box background; private readonly ScoreTable scoreTable; @@ -97,7 +99,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(0, spacing), Children = new Drawable[] { - new LeaderboardScopeSelector(), + new LeaderboardScopeSelector + { + Current = { BindTarget = scope } + }, modSelector = new LeaderboardModSelector { Ruleset = { BindTarget = ruleset } @@ -135,6 +140,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected override void LoadComplete() { base.LoadComplete(); + scope.BindValueChanged(_ => getScores()); Beatmap.BindValueChanged(onBeatmapChanged, true); } @@ -147,21 +153,21 @@ namespace osu.Game.Overlays.BeatmapSet.Scores else ruleset.Value = beatmapRuleset; - getScores(beatmap.NewValue); + getScores(); } - private void getScores(BeatmapInfo beatmap) + private void getScores() { getScoresRequest?.Cancel(); getScoresRequest = null; Scores = null; - if (beatmap?.OnlineBeatmapID.HasValue != true || beatmap.Status <= BeatmapSetOnlineStatus.Pending) + if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); + getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value); getScoresRequest.Success += scores => { loadingAnimation.Hide(); From 31191dadf1c9e487174bbc36a21199f697e721e2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:31:42 +0300 Subject: [PATCH 270/503] Handle mods change --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 8058d0fc0f..5c1f1ed7e4 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -141,6 +141,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { base.LoadComplete(); scope.BindValueChanged(_ => getScores()); + + modSelector.SelectedMods.ItemsAdded += _ => getScores(); + modSelector.SelectedMods.ItemsRemoved += _ => getScores(); + Beatmap.BindValueChanged(onBeatmapChanged, true); } @@ -167,7 +171,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; loadingAnimation.Show(); - getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value); + getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => { loadingAnimation.Hide(); From 851b414e9874fc5c6bb1e024b8eda2db3ddf94db Mon Sep 17 00:00:00 2001 From: recapitalverb <41869184+recapitalverb@users.noreply.github.com> Date: Mon, 11 Nov 2019 22:37:15 +0700 Subject: [PATCH 271/503] Update README.md Co-Authored-By: Joseph Madamba --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc5beeb83d..0ee1bedae4 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh - A desktop platform with the [.NET Core SDK 3.0](https://www.microsoft.com/net/learn/get-started) or higher installed. - When running on Linux, please have a system-wide ffmpeg installation available to support video decoding. - When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs. -- When working with the codebase, we recommend using an IDE with IntelliSense and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). +- When working with the codebase, we recommend using an IDE with IntelliSense and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). ## Running osu! From 5f5d130d1a7f2d7022424ce771ec1cc59795ed62 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:40:57 +0300 Subject: [PATCH 272/503] Update mod filter visibility on user change --- .../BeatmapSet/Scores/ScoresContainer.cs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 5c1f1ed7e4..1dd224e737 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -16,6 +16,7 @@ using osu.Game.Online.API.Requests; using osu.Framework.Bindables; using osu.Game.Rulesets; using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Users; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -145,7 +146,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores modSelector.SelectedMods.ItemsAdded += _ => getScores(); modSelector.SelectedMods.ItemsRemoved += _ => getScores(); - Beatmap.BindValueChanged(onBeatmapChanged, true); + Beatmap.BindValueChanged(onBeatmapChanged); + api.LocalUser.BindValueChanged(onUserChanged, true); } private void onBeatmapChanged(ValueChangedEvent beatmap) @@ -160,6 +162,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores getScores(); } + private void onUserChanged(ValueChangedEvent user) + { + scope.Value = BeatmapLeaderboardScope.Global; + modSelector.DeselectAll(); + updateModFilterVisibility(); + } + + private void updateModFilterVisibility() + { + modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter && !hasNoLeaderboard ? 1 : 0); + } + private void getScores() { getScoresRequest?.Cancel(); @@ -167,7 +181,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = null; - if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) + updateModFilterVisibility(); + + if (hasNoLeaderboard) return; loadingAnimation.Show(); @@ -179,5 +195,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; api.Queue(getScoresRequest); } + + private bool hasNoLeaderboard => Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending; } } From c5b64e26a306885caf7f10f2fdab073aa7cd005c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 18:51:29 +0300 Subject: [PATCH 273/503] Layout adjustment --- .../BeatmapSet/Scores/ScoresContainer.cs | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 1dd224e737..2f30cde5af 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -110,25 +110,44 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } }, - topScoresContainer = new FillFlowContainer + new Container { - RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - }, - scoreTable = new ScoreTable - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Children = new Drawable[] + { + topScoresContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + }, + scoreTable = new ScoreTable + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + } + } + }, + loadingAnimation = new LoadingAnimation + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + }, + } } } }, - loadingAnimation = new LoadingAnimation - { - Alpha = 0, - Margin = new MarginPadding(20), - }, }; } From 810cfab870dc042ec48e21361cc11dec7097cd1e Mon Sep 17 00:00:00 2001 From: recapitalverb Date: Mon, 11 Nov 2019 22:53:16 +0700 Subject: [PATCH 274/503] Fix capitalisation and grammar in README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0ee1bedae4..b8c6451c75 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh ## Requirements - A desktop platform with the [.NET Core SDK 3.0](https://www.microsoft.com/net/learn/get-started) or higher installed. -- When running on Linux, please have a system-wide ffmpeg installation available to support video decoding. +- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding. - When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs. -- When working with the codebase, we recommend using an IDE with IntelliSense and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). +- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). ## Running osu! @@ -68,7 +68,7 @@ dotnet run --project osu.Desktop If you are not interested in debugging osu!, you can add `-c Release` to gain performance. In this case, you must replace `Debug` with `Release` in any commands mentioned in this document. -If the build fails, try to restore nuget packages with `dotnet restore`. +If the build fails, try to restore NuGet packages with `dotnet restore`. ### Testing with resource/framework modifications @@ -76,11 +76,11 @@ Sometimes it may be necessary to cross-test changes in [osu-resources](https://g ### Code analysis -Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under windows due to [resharper cli shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install resharper or use rider to get inline support in your IDE of choice. +Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under Windows due to [ReSharper CLI shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install ReSharper or use Rider to get inline support in your IDE of choice. ## Contributing -We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention on having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted. +We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention of having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted. If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu/issues) (especially those with the ["good first issue"](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) label). From 32cc7b3d4d69926c49071c85c1113c6ef1625423 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 19:04:50 +0300 Subject: [PATCH 275/503] CI fix --- osu.Game/Overlays/BeatmapSetOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 65d68e4c8c..50fb2782d4 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -37,7 +37,6 @@ namespace osu.Game.Overlays { OsuScrollContainer scroll; Info info; - ScoresContainer scoreContainer; Children = new Drawable[] { @@ -59,7 +58,7 @@ namespace osu.Game.Overlays { Header = new Header(), info = new Info(), - scoreContainer = new ScoresContainer + new ScoresContainer { Beatmap = { BindTarget = Header.Picker.Beatmap } } From 0578f91a764733afafded1fb6b78c1e7990b81b6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 11 Nov 2019 19:06:46 +0300 Subject: [PATCH 276/503] Small logic adjustments --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 2f30cde5af..73253546bb 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -161,6 +161,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { base.LoadComplete(); scope.BindValueChanged(_ => getScores()); + ruleset.BindValueChanged(_ => getScores()); modSelector.SelectedMods.ItemsAdded += _ => getScores(); modSelector.SelectedMods.ItemsRemoved += _ => getScores(); @@ -173,12 +174,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { var beatmapRuleset = beatmap.NewValue?.Ruleset; - if (modSelector.Ruleset.Value?.Equals(beatmapRuleset) ?? false) + if (ruleset.Value?.Equals(beatmapRuleset) ?? false) modSelector.DeselectAll(); else ruleset.Value = beatmapRuleset; - getScores(); + scope.Value = BeatmapLeaderboardScope.Global; } private void onUserChanged(ValueChangedEvent user) From 9efcc6addde56b5080ea2ab6b34c8c7aa6b1e647 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 11 Nov 2019 08:53:05 -0800 Subject: [PATCH 277/503] Fix remaining proper nouns --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b8c6451c75..a078265d6c 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Before starting, please make sure you are familiar with the [development and tes Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as pain-free as possible. -For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via paypal or osu! supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project. +For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via PayPal or osu!supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project. ## Licence From 8402fb1490c32a920a2b3ae9a0df122a563560de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 10:02:42 +0900 Subject: [PATCH 278/503] Move to const and add some xmldoc for future visitors --- osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index e262fa3c60..3437af8c1e 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -16,6 +16,12 @@ namespace osu.Game.Rulesets.Osu.Edit { public class DrawableOsuEditRuleset : DrawableOsuRuleset { + /// + /// Hit objects are intentionally made to fade out at a constant slower rate than in gameplay. + /// This allows a mapper to gain better historical context and use recent hitobjects as reference / snap points. + /// + private const double editor_hit_object_fade_out_extension = 500; + public DrawableOsuEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { @@ -35,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Edit return; using (hitObject.BeginAbsoluteSequence(existing.StartTime)) - hitObject.FadeOut(500).Expire(); + hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire(); break; } } From 5bb65d0716ad1f0520b152e3ab14701b1f998fd8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 10:18:25 +0900 Subject: [PATCH 279/503] Rename button class --- .../TestSceneStatefulMenuItem.cs | 8 +++--- .../Graphics/UserInterface/TernaryState.cs | 2 +- ...ateMenuItem.cs => TernaryStateMenuItem.cs} | 26 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) rename osu.Game/Graphics/UserInterface/{ThreeStateMenuItem.cs => TernaryStateMenuItem.cs} (69%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 1eff30d15e..2ada5b927b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.UserInterface { typeof(OsuMenu), typeof(StatefulMenuItem), - typeof(ThreeStateMenuItem), + typeof(TernaryStateMenuItem), typeof(DrawableStatefulMenuItem), }; @@ -39,9 +39,9 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.Centre, Items = new[] { - new ThreeStateMenuItem("First"), - new ThreeStateMenuItem("Second") { State = { BindTarget = state } }, - new ThreeStateMenuItem("Third") { State = { Value = TernaryState.True } }, + new TernaryStateMenuItem("First"), + new TernaryStateMenuItem("Second") { State = { BindTarget = state } }, + new TernaryStateMenuItem("Third") { State = { Value = TernaryState.True } }, } }; }); diff --git a/osu.Game/Graphics/UserInterface/TernaryState.cs b/osu.Game/Graphics/UserInterface/TernaryState.cs index 784122e35c..d4de28044f 100644 --- a/osu.Game/Graphics/UserInterface/TernaryState.cs +++ b/osu.Game/Graphics/UserInterface/TernaryState.cs @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface /// /// The current state is a combination of and . - /// The state becomes if the is pressed. + /// The state becomes if the is pressed. /// Indeterminate, diff --git a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs b/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs similarity index 69% rename from osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs rename to osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs index c5b9edf3c4..2d9e2106d4 100644 --- a/osu.Game/Graphics/UserInterface/ThreeStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs @@ -9,37 +9,37 @@ namespace osu.Game.Graphics.UserInterface /// /// An with three possible states. /// - public class ThreeStateMenuItem : StatefulMenuItem + public class TernaryStateMenuItem : StatefulMenuItem { /// - /// Creates a new . + /// Creates a new . /// /// The text to display. - /// The type of action which this performs. - public ThreeStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) + /// The type of action which this performs. + public TernaryStateMenuItem(string text, MenuItemType type = MenuItemType.Standard) : this(text, type, null) { } /// - /// Creates a new . + /// Creates a new . /// /// The text to display. - /// The type of action which this performs. - /// A delegate to be invoked when this is pressed. - public ThreeStateMenuItem(string text, MenuItemType type, Action action) + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. + public TernaryStateMenuItem(string text, MenuItemType type, Action action) : this(text, getNextState, type, action) { } /// - /// Creates a new . + /// Creates a new . /// /// The text to display. - /// A function that mutates a state to another state after this is pressed. - /// The type of action which this performs. - /// A delegate to be invoked when this is pressed. - protected ThreeStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) + /// A function that mutates a state to another state after this is pressed. + /// The type of action which this performs. + /// A delegate to be invoked when this is pressed. + protected TernaryStateMenuItem(string text, Func changeStateFunc, MenuItemType type, Action action) : base(text, changeStateFunc, type, action) { } From a43b0ee01bc9b92db30ff4084c11c09b3547dd26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 10:45:46 +0900 Subject: [PATCH 280/503] Apply naming and styling changes --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 ++ .../Edit/Compose/Components/SelectionHandler.cs | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index f3399af2de..c6f5a075e0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -203,12 +203,14 @@ namespace osu.Game.Rulesets.Osu.Objects var sampleList = new List(); if (firstSample != null) + { sampleList.Add(new HitSampleInfo { Bank = firstSample.Bank, Volume = firstSample.Volume, Name = @"slidertick", }); + } foreach (var tick in NestedHitObjects.OfType()) tick.Samples = sampleList; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 7b61640c89..942643d116 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -241,36 +241,36 @@ namespace osu.Game.Screens.Edit.Compose.Components private MenuItem createHitSampleMenuItem(string name, string sampleName) { - return new ThreeStateMenuItem(name, MenuItemType.Standard, setHitSampleState) + return new TernaryStateMenuItem(name, MenuItemType.Standard, setHitSampleState) { State = { Value = getHitSampleState() } }; - void setHitSampleState(ThreeStates state) + void setHitSampleState(TernaryState state) { switch (state) { - case ThreeStates.Disabled: + case TernaryState.False: RemoveHitSample(sampleName); break; - case ThreeStates.Enabled: + case TernaryState.True: AddHitSample(sampleName); break; } } - ThreeStates getHitSampleState() + TernaryState getHitSampleState() { int countExisting = SelectedHitObjects.Count(h => h.Samples.Any(s => s.Name == sampleName)); if (countExisting == 0) - return ThreeStates.Disabled; + return TernaryState.False; if (countExisting < SelectedHitObjects.Count()) - return ThreeStates.Indeterminate; + return TernaryState.Indeterminate; - return ThreeStates.Enabled; + return TernaryState.True; } } From 2f8768a4b10af5290f94c80cba54184b2957b5d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 11:04:49 +0900 Subject: [PATCH 281/503] Move LabelledDropdown local to usage --- osu.Game.Tournament/Screens/SetupScreen.cs | 21 ++++++++++++++ .../UserInterfaceV2/LabelledDropdown.cs | 29 ------------------- 2 files changed, 21 insertions(+), 29 deletions(-) delete mode 100644 osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs index b511d572da..8e1481d87c 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/SetupScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -100,6 +101,26 @@ namespace osu.Game.Tournament.Screens }; } + public class LabelledDropdown : LabelledComponent, T> + { + public LabelledDropdown() + : base(true) + { + } + + public IEnumerable Items + { + get => Component.Items; + set => Component.Items = value; + } + + protected override OsuDropdown CreateComponent() => new OsuDropdown + { + RelativeSizeAxes = Axes.X, + Width = 0.5f, + }; + } + private class ActionableInfo : LabelledDrawable { private OsuButton button; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs deleted file mode 100644 index 7e50fa7bc6..0000000000 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Graphics.UserInterfaceV2 -{ - public class LabelledDropdown : LabelledComponent, T> - { - public LabelledDropdown() - : base(true) - { - } - - public IEnumerable Items - { - get => Component.Items; - set => Component.Items = value; - } - - protected override OsuDropdown CreateComponent() => new OsuDropdown - { - RelativeSizeAxes = Axes.X, - Width = 0.5f, - }; - } -} From 9f1d490ac9876457e7299ed758da3858f893b105 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 12:18:24 +0900 Subject: [PATCH 282/503] Only handle selection input on blueprints --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 942643d116..258304d775 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -90,6 +90,8 @@ namespace osu.Game.Screens.Edit.Compose.Components public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => selectedBlueprints.Any(b => b.IsHovered); + #endregion #region Selection Handling From 3f8928ca253660e6ae7a686e5c6f0d3faad60075 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 13:41:54 +0900 Subject: [PATCH 283/503] Suppress warnings --- osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs | 3 ++- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 ++ osu.Game/Rulesets/RulesetConfigCache.cs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs index 179cd5e2dc..5a3ad5e786 100644 --- a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Configuration.Tracking; namespace osu.Game.Rulesets.Configuration { - public interface IRulesetConfigManager : ITrackableConfigManager + public interface IRulesetConfigManager : ITrackableConfigManager, IDisposable { } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 818571bb23..35228e9ad1 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -149,8 +149,10 @@ namespace osu.Game.Rulesets.Objects.Drawables return; if (HitObject.SampleControlPoint == null) + { throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + } samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); foreach (var s in samples) diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index cdcd2666cf..d42428638c 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets // ensures any potential database operations are finalised before game destruction. foreach (var c in configCache.Values) - (c as IDisposable)?.Dispose(); + c?.Dispose(); } } } From b4525c1f6e95d61a56ca33b5a09cbeba38d60ab5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 14:42:30 +0900 Subject: [PATCH 284/503] Fix right clicking to select not showing context menu --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 258304d775..3a7c85d36c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -90,8 +90,6 @@ namespace osu.Game.Screens.Edit.Compose.Components public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => selectedBlueprints.Any(b => b.IsHovered); - #endregion #region Selection Handling @@ -223,7 +221,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { get { - if (!SelectedBlueprints.Any()) + if (!selectedBlueprints.Any(b => b.IsHovered)) return Array.Empty(); return new MenuItem[] From a69a4643c950526a0683120799c06f7051f478ba Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 12 Nov 2019 08:45:21 +0300 Subject: [PATCH 285/503] Simplify LINQ expressions --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 75c24cb710..a7128ca157 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -53,12 +53,7 @@ namespace osu.Game.Overlays.BeatmapSet return; modsContainer.Add(new ModButton(new NoMod())); - - ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => - { - if (mod.Ranked) - modsContainer.Add(new ModButton(mod)); - }); + modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); } @@ -77,11 +72,7 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnHover(HoverEvent e) { if (!SelectedMods.Any()) - modsContainer.ForEach(button => - { - if (!button.IsHovered) - button.Highlighted.Value = false; - }); + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); return base.OnHover(e); } From 461f76926f6e23015eaec30ae5344f3ea9085861 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 13:32:31 +0900 Subject: [PATCH 286/503] Add right-click menu to support control point addition --- .../Sliders/SliderSelectionBlueprint.cs | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 25362820a3..a77350714f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -1,8 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -10,10 +15,11 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderSelectionBlueprint : OsuSelectionBlueprint + public class SliderSelectionBlueprint : OsuSelectionBlueprint, IHasContextMenu { protected readonly SliderBodyPiece BodyPiece; protected readonly SliderCircleSelectionBlueprint HeadBlueprint; @@ -44,6 +50,48 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders BodyPiece.UpdateFrom(HitObject); } + private Vector2 rightClickPosition; + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (e.Button == MouseButton.Right) + rightClickPosition = e.MouseDownPosition; + + return false; + } + + private void addControlPoint() + { + Vector2 position = rightClickPosition - HitObject.Position; + + var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1]; + HitObject.Path.ControlPoints.CopyTo(controlPoints); + + // Find the index at which the point will be inserted, by increasing x-coordinates + int insertionIndex = Array.FindIndex(controlPoints, 0, controlPoints.Length - 1, c => c.X >= position.X); + + // If no index was found, it should be inserted at the end + if (insertionIndex == -1) + insertionIndex = controlPoints.Length - 1; + + // Move the control points from the insertion index onwards to make room for the insertion + Array.Copy(controlPoints, insertionIndex, controlPoints, insertionIndex + 1, controlPoints.Length - insertionIndex - 1); + + if (insertionIndex == 0) + { + // Special case for a new first control point being added - the entire slider moves + HitObject.Position += position; + + // The first control point is always at (0, 0), but all other control points need to be re-referenced + for (int i = 1; i < controlPoints.Length; i++) + controlPoints[i] -= position; + } + else + controlPoints[insertionIndex] = position; + + onNewControlPoints(controlPoints); + } + private void onNewControlPoints(Vector2[] controlPoints) { var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints); @@ -54,6 +102,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders UpdateHitObject(); } + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("Add control point", MenuItemType.Standard, addControlPoint), + }; + public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos); From 10fd5ef5a7137a66f037e0c49fdf19173986e0e8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 13:38:42 +0900 Subject: [PATCH 287/503] Merge context menus --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 5 ++--- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 6 ++++++ .../Screens/Edit/Compose/Components/SelectionHandler.cs | 7 ++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index a77350714f..e87145fdc3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; @@ -19,7 +18,7 @@ using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { - public class SliderSelectionBlueprint : OsuSelectionBlueprint, IHasContextMenu + public class SliderSelectionBlueprint : OsuSelectionBlueprint { protected readonly SliderBodyPiece BodyPiece; protected readonly SliderCircleSelectionBlueprint HeadBlueprint; @@ -102,7 +101,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders UpdateHitObject(); } - public MenuItem[] ContextMenuItems => new MenuItem[] + public override MenuItem[] ContextMenuItems => new MenuItem[] { new OsuMenuItem("Add control point", MenuItemType.Standard, addControlPoint), }; diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 2923411ce1..bf99f83e0b 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -104,6 +105,11 @@ namespace osu.Game.Rulesets.Edit public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.ReceivePositionalInputAt(screenSpacePos); + /// + /// The s to be displayed in the context menu for this . + /// + public virtual MenuItem[] ContextMenuItems => Array.Empty(); + /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 3a7c85d36c..d5bbeeb907 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -224,7 +224,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (!selectedBlueprints.Any(b => b.IsHovered)) return Array.Empty(); - return new MenuItem[] + var items = new List { new OsuMenuItem("Sound") { @@ -236,6 +236,11 @@ namespace osu.Game.Screens.Edit.Compose.Components } } }; + + if (selectedBlueprints.Count == 1) + items.AddRange(selectedBlueprints[0].ContextMenuItems); + + return items.ToArray(); } } From 13b11996e0f625cec223e18ebecf8a83a2898bd0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 14:37:07 +0900 Subject: [PATCH 288/503] Improve closest segment algorithm --- .../Sliders/SliderSelectionBlueprint.cs | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index e87145fdc3..9da684025f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -66,27 +66,33 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1]; HitObject.Path.ControlPoints.CopyTo(controlPoints); - // Find the index at which the point will be inserted, by increasing x-coordinates - int insertionIndex = Array.FindIndex(controlPoints, 0, controlPoints.Length - 1, c => c.X >= position.X); + int insertionIndex = 0; + float minDistance = float.MaxValue; - // If no index was found, it should be inserted at the end - if (insertionIndex == -1) - insertionIndex = controlPoints.Length - 1; + for (int i = 0; i < controlPoints.Length - 2; i++) + { + Vector2 p1 = controlPoints[i]; + Vector2 p2 = controlPoints[i + 1]; + + if (p1 == p2) + continue; + + Vector2 dir = p2 - p1; + float projLength = MathHelper.Clamp(Vector2.Dot(position - p1, dir) / dir.LengthSquared, 0, 1); + Vector2 proj = p1 + projLength * dir; + + float dist = Vector2.Distance(position, proj); + + if (dist < minDistance) + { + insertionIndex = i + 1; + minDistance = dist; + } + } // Move the control points from the insertion index onwards to make room for the insertion Array.Copy(controlPoints, insertionIndex, controlPoints, insertionIndex + 1, controlPoints.Length - insertionIndex - 1); - - if (insertionIndex == 0) - { - // Special case for a new first control point being added - the entire slider moves - HitObject.Position += position; - - // The first control point is always at (0, 0), but all other control points need to be re-referenced - for (int i = 1; i < controlPoints.Length; i++) - controlPoints[i] -= position; - } - else - controlPoints[insertionIndex] = position; + controlPoints[insertionIndex] = position; onNewControlPoints(controlPoints); } From 316dcae6145594ec2cc83ab2aed1b3c7fb1ba6c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 14:41:10 +0900 Subject: [PATCH 289/503] Use squared distance --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 9da684025f..0f058dc088 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -78,10 +78,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders continue; Vector2 dir = p2 - p1; + float projLength = MathHelper.Clamp(Vector2.Dot(position - p1, dir) / dir.LengthSquared, 0, 1); Vector2 proj = p1 + projLength * dir; - float dist = Vector2.Distance(position, proj); + float dist = Vector2.DistanceSquared(position, proj); if (dist < minDistance) { From 407ca41ba454f1bd644ecb3fc1f5eabf9f1fe564 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 14:44:11 +0900 Subject: [PATCH 290/503] Simplify using existing tools --- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 0f058dc088..34dc7ddc24 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; @@ -71,18 +72,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders for (int i = 0; i < controlPoints.Length - 2; i++) { - Vector2 p1 = controlPoints[i]; - Vector2 p2 = controlPoints[i + 1]; - - if (p1 == p2) - continue; - - Vector2 dir = p2 - p1; - - float projLength = MathHelper.Clamp(Vector2.Dot(position - p1, dir) / dir.LengthSquared, 0, 1); - Vector2 proj = p1 + projLength * dir; - - float dist = Vector2.DistanceSquared(position, proj); + float dist = new Line(controlPoints[i], controlPoints[i + 1]).DistanceToPoint(position); if (dist < minDistance) { From 93d8cd38ca4652f5082fdfbd3d87120e144bbc37 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 15:00:57 +0900 Subject: [PATCH 291/503] Implement addition via ctrl+click --- .../Sliders/SliderSelectionBlueprint.cs | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 34dc7ddc24..226afd68b1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; @@ -54,15 +55,47 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button == MouseButton.Right) - rightClickPosition = e.MouseDownPosition; + switch (e.Button) + { + case MouseButton.Right: + rightClickPosition = e.MouseDownPosition; + return false; // Allow right click to be handled by context menu + + case MouseButton.Left when e.ControlPressed: + placementControlPointIndex = addControlPoint(e.MousePosition); + return true; // Stop input from being handled and modifying the selection + } return false; } - private void addControlPoint() + private int? placementControlPointIndex; + + protected override bool OnDragStart(DragStartEvent e) => placementControlPointIndex != null; + + protected override bool OnDrag(DragEvent e) { - Vector2 position = rightClickPosition - HitObject.Position; + Debug.Assert(placementControlPointIndex != null); + + Vector2 position = e.MousePosition - HitObject.Position; + + var controlPoints = HitObject.Path.ControlPoints.ToArray(); + controlPoints[placementControlPointIndex.Value] = position; + + onNewControlPoints(controlPoints); + + return true; + } + + protected override bool OnDragEnd(DragEndEvent e) + { + placementControlPointIndex = null; + return true; + } + + private int addControlPoint(Vector2 position) + { + position -= HitObject.Position; var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1]; HitObject.Path.ControlPoints.CopyTo(controlPoints); @@ -86,6 +119,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders controlPoints[insertionIndex] = position; onNewControlPoints(controlPoints); + + return insertionIndex; } private void onNewControlPoints(Vector2[] controlPoints) @@ -100,7 +135,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders public override MenuItem[] ContextMenuItems => new MenuItem[] { - new OsuMenuItem("Add control point", MenuItemType.Standard, addControlPoint), + new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)), }; public override Vector2 SelectionPoint => HeadBlueprint.SelectionPoint; From 25eb9642904dfe8e640e85c2430c290de04e6462 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 15:03:58 +0900 Subject: [PATCH 292/503] Simplify overlay adding logic --- osu.Game/OsuGame.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fa97044c95..e2ece8422c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -593,14 +593,14 @@ namespace osu.Game loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); - var login = loadComponentSingleFile(new LoginOverlay + loadComponentSingleFile(new LoginOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, rightFloatingOverlayContent.Add, true); - var nowPlaying = loadComponentSingleFile(new NowPlayingOverlay + loadComponentSingleFile(new NowPlayingOverlay { GetToolbarHeight = () => ToolbarOffset, Anchor = Anchor.TopRight, @@ -615,10 +615,10 @@ namespace osu.Game Add(externalLinkOpener = new ExternalLinkOpener()); + // side overlays which cancel each other. var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications }; - overlays.AddRange(singleDisplaySideOverlays); - foreach (var overlay in singleDisplaySideOverlays) + foreach (var overlay in new OverlayContainer[] { Settings, notifications }) { overlay.State.ValueChanged += state => { @@ -630,7 +630,6 @@ namespace osu.Game // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time. var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile }; - overlays.AddRange(informationalOverlays); foreach (var overlay in informationalOverlays) { @@ -644,7 +643,6 @@ namespace osu.Game // ensure only one of these overlays are open at once. var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct, changelogOverlay }; - overlays.AddRange(singleDisplayOverlays); foreach (var overlay in singleDisplayOverlays) { @@ -659,8 +657,6 @@ namespace osu.Game }; } - overlays.AddRange(new OverlayContainer[] { login, nowPlaying }); - OverlayActivationMode.ValueChanged += mode => { if (mode.NewValue != OverlayActivation.All) CloseAllOverlays(); @@ -747,6 +743,9 @@ namespace osu.Game if (cache) dependencies.Cache(d); + if (d is OverlayContainer overlay) + overlays.Add(overlay); + // schedule is here to ensure that all component loads are done after LoadComplete is run (and thus all dependencies are cached). // with some better organisation of LoadComplete to do construction and dependency caching in one step, followed by calls to loadComponentSingleFile, // we could avoid the need for scheduling altogether. From 35351d7f7c34cb8f0395aa0992f245b7dfc52ddb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 15:04:51 +0900 Subject: [PATCH 293/503] Use variable instead of duplicated list --- 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 e2ece8422c..f6b8d5cfbb 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -618,7 +618,7 @@ namespace osu.Game // side overlays which cancel each other. var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications }; - foreach (var overlay in new OverlayContainer[] { Settings, notifications }) + foreach (var overlay in singleDisplaySideOverlays) { overlay.State.ValueChanged += state => { From a0884fe9d42a0815f642eb7203246b6bf608d838 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 15:07:54 +0900 Subject: [PATCH 294/503] Fix being able to add while not selected --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 226afd68b1..820d6c92d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders rightClickPosition = e.MouseDownPosition; return false; // Allow right click to be handled by context menu - case MouseButton.Left when e.ControlPressed: + case MouseButton.Left when e.ControlPressed && IsSelected: placementControlPointIndex = addControlPoint(e.MousePosition); return true; // Stop input from being handled and modifying the selection } From 47be20fa3773c1fed6ba2e521d9a71b4c93a3582 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 15:13:47 +0900 Subject: [PATCH 295/503] Private set on track for safety --- osu.Game/Audio/PreviewTrack.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index b39d2bc8f8..5df656e1e0 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -24,7 +24,7 @@ namespace osu.Game.Audio /// public event Action Started; - protected Track Track; + protected Track Track { get; private set; } private bool hasStarted; From 46d02d9077e75619b535975778118175fa704601 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 17:37:01 +0900 Subject: [PATCH 296/503] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6c40dc4812..6fab2e7868 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,6 +53,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index baa1c14071..af60da3e70 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,7 +21,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 0184e45c15..8124357312 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,6 +73,6 @@ - + From 58df6930b279791e6cad547718d4182bd91aa22c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 19:34:20 +0900 Subject: [PATCH 297/503] Get error message from server --- osu.Game/Online/API/APIRequest.cs | 23 +++++++++++++++++++ .../BeatmapSet/Buttons/FavouriteButton.cs | 13 ++++------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 4f613d5c3c..ea0d50511f 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using Newtonsoft.Json; using osu.Framework.IO.Network; using osu.Framework.Logging; @@ -112,6 +113,22 @@ namespace osu.Game.Online.API cancelled = true; WebRequest?.Abort(); + string responseString = WebRequest?.ResponseString; + + if (!string.IsNullOrEmpty(responseString)) + { + try + { + // attempt to decode a displayable error string. + var error = JsonConvert.DeserializeObject(responseString); + if (error != null) + e = new Exception(error.ErrorMessage, e); + } + catch + { + } + } + Logger.Log($@"Failing request {this} ({e})", LoggingTarget.Network); pendingFailure = () => Failure?.Invoke(e); checkAndScheduleFailure(); @@ -129,6 +146,12 @@ namespace osu.Game.Online.API pendingFailure = null; return true; } + + private class DisplayableError + { + [JsonProperty("error")] + public string ErrorMessage; + } } public delegate void APIFailureHandler(Exception e); diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index e2bc1ee008..f059e06214 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -71,15 +71,12 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons request.Success += () => favourited.Value = !favourited.Value; request.Failure += exception => { - if (exception.Message == "UnprocessableEntity") + notifications.Post(new SimpleNotification { - notifications.Post(new SimpleNotification - { - Text = @"You have too many favourited beatmaps! Please unfavourite some before trying again.", - Icon = FontAwesome.Solid.Times, - }); - loading.Hide(); - } + Text = exception.Message, + Icon = FontAwesome.Solid.Times, + }); + loading.Hide(); }; api.Queue(request); }; From bbeab6fa7650c07441dddb5bc648f58033634378 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 17:45:42 +0800 Subject: [PATCH 298/503] Use auto property. --- .editorconfig | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 8 +------- .../Objects/Drawables/Pieces/TaikoPiece.cs | 16 ++-------------- .../Gameplay/TestSceneSkinnableDrawable.cs | 6 ++---- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 6 ++---- osu.Game/OsuGameBase.cs | 12 +++++------- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 5 ++--- osu.Game/Overlays/Chat/ChatLine.cs | 9 ++++----- .../KeyBinding/VariantBindingsSubsection.cs | 5 ++--- osu.Game/Overlays/VolumeOverlay.cs | 7 +++---- osu.Game/Skinning/SkinnableSprite.cs | 6 ++---- .../Storyboards/Drawables/DrawableStoryboard.cs | 5 ++--- osu.sln.DotSettings | 4 +++- 13 files changed, 31 insertions(+), 60 deletions(-) diff --git a/.editorconfig b/.editorconfig index 2c000d3881..34217e6206 100644 --- a/.editorconfig +++ b/.editorconfig @@ -137,7 +137,7 @@ csharp_style_expression_bodied_properties = true:silent dotnet_style_object_initializer = true:warning dotnet_style_collection_initializer = true:warning dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning -dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_auto_properties = true:warning dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent dotnet_style_prefer_compound_assignment = true:silent diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 80a3af0aa0..33780427b6 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -116,13 +116,7 @@ namespace osu.Game.Rulesets.Catch.Objects public double Duration => EndTime - StartTime; - private SliderPath path; - - public SliderPath Path - { - get => path; - set => path = value; - } + public SliderPath Path { get; set; } public double Distance => Path.Distance; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs index 773e3ae907..8067054f8f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs @@ -10,27 +10,15 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { public class TaikoPiece : BeatSyncedContainer, IHasAccentColour { - private Color4 accentColour; - /// /// The colour of the inner circle and outer glows. /// - public virtual Color4 AccentColour - { - get => accentColour; - set => accentColour = value; - } - - private bool kiaiMode; + public virtual Color4 AccentColour { get; set; } /// /// Whether Kiai mode effects are enabled for this circle piece. /// - public virtual bool KiaiMode - { - get => kiaiMode; - set => kiaiMode = value; - } + public virtual bool KiaiMode { get; set; } public TaikoPiece() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index 8beb107269..ec94053679 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -335,16 +335,14 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestSkinComponent : ISkinComponent { - private readonly string name; - public TestSkinComponent(string name) { - this.name = name; + LookupName = name; } public string ComponentGroup => string.Empty; - public string LookupName => name; + public string LookupName { get; } } } } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 623db07938..6ac5219282 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -288,17 +288,15 @@ namespace osu.Game.Online.Leaderboards private class ScoreComponentLabel : Container, IHasTooltip { private const float icon_size = 20; - - private readonly string name; private readonly FillFlowContainer content; public override bool Contains(Vector2 screenSpacePos) => content.Contains(screenSpacePos); - public string TooltipText => name; + public string TooltipText { get; } public ScoreComponentLabel(LeaderboardScoreStatistic statistic) { - name = statistic.Name; + TooltipText = statistic.Name; AutoSizeAxes = Axes.Both; Child = content = new FillFlowContainer diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 4a432bf74e..0845a33639 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -74,8 +74,6 @@ namespace osu.Game protected Storage Storage { get; set; } - private Bindable beatmap; // cached via load() method - [Cached] [Cached(typeof(IBindable))] protected readonly Bindable Ruleset = new Bindable(); @@ -85,7 +83,7 @@ namespace osu.Game [Cached(Type = typeof(IBindable>))] protected readonly Bindable> Mods = new Bindable>(Array.Empty()); - protected Bindable Beatmap => beatmap; + protected Bindable Beatmap { get; private set; } // cached via load() method private Bindable fpsDisplayVisible; @@ -201,16 +199,16 @@ namespace osu.Game // this adds a global reduction of track volume for the time being. Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); - beatmap = new NonNullableBindable(defaultBeatmap); - beatmap.BindValueChanged(b => ScheduleAfterChildren(() => + Beatmap = new NonNullableBindable(defaultBeatmap); + Beatmap.BindValueChanged(b => ScheduleAfterChildren(() => { // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track) b.OldValue.RecycleTrack(); })); - dependencies.CacheAs>(beatmap); - dependencies.CacheAs(beatmap); + dependencies.CacheAs>(Beatmap); + dependencies.CacheAs(Beatmap); FileStore.Cleanup(); diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 5b10c4e0bb..7092b860a0 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -91,10 +91,9 @@ namespace osu.Game.Overlays.BeatmapSet private class Statistic : Container, IHasTooltip { - private readonly string name; private readonly OsuSpriteText value; - public string TooltipText => name; + public string TooltipText { get; } public string Value { @@ -104,7 +103,7 @@ namespace osu.Game.Overlays.BeatmapSet public Statistic(IconUsage icon, string name) { - this.name = name; + TooltipText = name; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index db378bde73..8abde8a24f 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -58,9 +58,8 @@ namespace osu.Game.Overlays.Chat private Message message; private OsuSpriteText username; - private LinkFlowContainer contentFlow; - public LinkFlowContainer ContentFlow => contentFlow; + public LinkFlowContainer ContentFlow { get; private set; } public Message Message { @@ -164,7 +163,7 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Left = MessagePadding + HorizontalPadding }, Children = new Drawable[] { - contentFlow = new LinkFlowContainer(t => + ContentFlow = new LinkFlowContainer(t => { t.Shadow = false; @@ -206,8 +205,8 @@ namespace osu.Game.Overlays.Chat // remove non-existent channels from the link list message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chatManager?.AvailableChannels.Any(c => c.Name == link.Argument) != true); - contentFlow.Clear(); - contentFlow.AddLinks(message.DisplayContent, message.Links); + ContentFlow.Clear(); + ContentFlow.AddLinks(message.DisplayContent, message.Links); } private class MessageSender : OsuClickableContainer, IHasContextMenu diff --git a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs index 07af657686..861d59c8f4 100644 --- a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs @@ -7,8 +7,7 @@ namespace osu.Game.Overlays.KeyBinding { public class VariantBindingsSubsection : KeyBindingsSubsection { - protected override string Header => variantName; - private readonly string variantName; + protected override string Header { get; } public VariantBindingsSubsection(RulesetInfo ruleset, int variant) : base(variant) @@ -17,7 +16,7 @@ namespace osu.Game.Overlays.KeyBinding var rulesetInstance = ruleset.CreateInstance(); - variantName = rulesetInstance.GetVariantName(variant); + Header = rulesetInstance.GetVariantName(variant); Defaults = rulesetInstance.GetDefaultKeyBindings(variant); } } diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index ca7665eba5..b484921cce 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -30,8 +30,7 @@ namespace osu.Game.Overlays private readonly BindableDouble muteAdjustment = new BindableDouble(); - private readonly Bindable isMuted = new Bindable(); - public Bindable IsMuted => isMuted; + public Bindable IsMuted { get; } = new Bindable(); [BackgroundDependencyLoader] private void load(AudioManager audio, OsuColour colours) @@ -66,7 +65,7 @@ namespace osu.Game.Overlays muteButton = new MuteButton { Margin = new MarginPadding { Top = 100 }, - Current = { BindTarget = isMuted } + Current = { BindTarget = IsMuted } } } }, @@ -76,7 +75,7 @@ namespace osu.Game.Overlays volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); - isMuted.BindValueChanged(muted => + IsMuted.BindValueChanged(muted => { if (muted.NewValue) audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment); diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 4b78493e97..e225bfc490 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -28,14 +28,12 @@ namespace osu.Game.Skinning private class SpriteComponent : ISkinComponent { - private readonly string textureName; - public SpriteComponent(string textureName) { - this.textureName = textureName; + LookupName = textureName; } - public string LookupName => textureName; + public string LookupName { get; } } } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 2b27a56844..7a84ac009a 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -16,8 +16,7 @@ namespace osu.Game.Storyboards.Drawables { public Storyboard Storyboard { get; private set; } - private readonly Container content; - protected override Container Content => content; + protected override Container Content { get; } protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); @@ -49,7 +48,7 @@ namespace osu.Game.Storyboards.Drawables Anchor = Anchor.Centre; Origin = Anchor.Centre; - AddInternal(content = new Container + AddInternal(Content = new Container { Size = new Vector2(640, 480), Anchor = Anchor.Centre, diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 44c5c05bc0..63d055702b 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -63,7 +63,9 @@ WARNING WARNING WARNING - HINT + WARNING + WARNING + WARNING WARNING WARNING HINT From 4b75e0bf6a5824668ee78921bf047a1f5ead940f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 17:50:50 +0800 Subject: [PATCH 299/503] Redundant assignment. --- .editorconfig | 2 +- .../Legacy/HitObjectPatternGenerator.cs | 24 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.editorconfig b/.editorconfig index 34217e6206..05927526d5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -153,7 +153,7 @@ csharp_style_conditional_delegate_call = true:suggestion #Style - unused dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_unused_value_assignment_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:suggestion #Style - variable declaration csharp_style_inlined_variable_declaration = true:silent diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index ada960a78d..be3c43699d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -168,43 +168,43 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } if (convertType.HasFlag(PatternType.KeepSingle)) - return pattern = generateRandomNotes(1); + return generateRandomNotes(1); if (convertType.HasFlag(PatternType.Mirror)) { if (ConversionDifficulty > 6.5) - return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); + return generateRandomPatternWithMirrored(0.12, 0.38, 0.12); if (ConversionDifficulty > 4) - return pattern = generateRandomPatternWithMirrored(0.12, 0.17, 0); + return generateRandomPatternWithMirrored(0.12, 0.17, 0); - return pattern = generateRandomPatternWithMirrored(0.12, 0, 0); + return generateRandomPatternWithMirrored(0.12, 0, 0); } if (ConversionDifficulty > 6.5) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.78, 0.42, 0, 0); + return generateRandomPattern(0.78, 0.42, 0, 0); - return pattern = generateRandomPattern(1, 0.62, 0, 0); + return generateRandomPattern(1, 0.62, 0, 0); } if (ConversionDifficulty > 4) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.35, 0.08, 0, 0); + return generateRandomPattern(0.35, 0.08, 0, 0); - return pattern = generateRandomPattern(0.52, 0.15, 0, 0); + return generateRandomPattern(0.52, 0.15, 0, 0); } if (ConversionDifficulty > 2) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.18, 0, 0, 0); + return generateRandomPattern(0.18, 0, 0, 0); - return pattern = generateRandomPattern(0.45, 0, 0, 0); + return generateRandomPattern(0.45, 0, 0, 0); } - return pattern = generateRandomPattern(0, 0, 0, 0); + return generateRandomPattern(0, 0, 0, 0); } finally { @@ -384,8 +384,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The amount of notes to be generated. The note to be added to the centre column will NOT be part of this count. private int getRandomNoteCountMirrored(double centreProbability, double p2, double p3, out bool addToCentre) { - addToCentre = false; - switch (TotalColumns) { case 2: From 7d7b9e36b25ea355c22b258e4fbee768b3274844 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 17:56:38 +0800 Subject: [PATCH 300/503] Use compound assignment. --- .editorconfig | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- .../Difficulty/Preprocessing/OsuDifficultyHitObject.cs | 2 +- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs | 2 +- osu.Game/Graphics/UserInterface/PercentageCounter.cs | 2 +- osu.Game/Graphics/UserInterface/ScoreCounter.cs | 2 +- osu.Game/Graphics/UserInterface/SimpleComboCounter.cs | 2 +- osu.Game/Screens/Play/HUD/ComboCounter.cs | 2 +- osu.Game/Screens/Play/HUD/ComboResultCounter.cs | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.editorconfig b/.editorconfig index 05927526d5..35cbfe769f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -140,7 +140,7 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning dotnet_style_prefer_auto_properties = true:warning dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent -dotnet_style_prefer_compound_assignment = true:silent +dotnet_style_prefer_compound_assignment = true:warning #Style - null/type checks dotnet_style_coalesce_expression = true:warning diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..435c5ac463 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -198,7 +198,7 @@ namespace osu.Game.Rulesets.Catch.UI var additive = createCatcherSprite(); additive.Anchor = Anchor; - additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. + additive.OriginPosition += new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. additive.Position = Position; additive.Scale = Scale; additive.Colour = HyperDashing ? Color4.Red : Color4.White; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6c5bb304bf..c3a8cbd274 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (TargetColumns >= 10) { - TargetColumns = TargetColumns / 2; + TargetColumns /= 2; Dual = true; } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..90dbe6ec8f 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Edit // Flip the vertical coordinate space when scrolling downwards if (scrollingInfo.Direction.Value == ScrollingDirection.Down) - targetPosition = targetPosition - referenceParent.DrawHeight; + targetPosition -= referenceParent.DrawHeight; float movementDelta = targetPosition - reference.DrawableObject.Position.Y; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 5ab07416a6..08f6049782 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Mania.UI foreach (var stage in stages) { - sum = sum + stage.Columns.Count; + sum += stage.Columns.Count; if (sum > column) return stage; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index eacac7ae6a..fa6c5c4d9c 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing if (progress % 2 >= 1) progress = 1 - progress % 1; else - progress = progress % 1; + progress %= 1; // ReSharper disable once PossibleInvalidOperationException (bugged in current r# version) var diff = slider.StackedPosition + slider.Path.PositionAt(progress) - slider.LazyEndPosition.Value; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 6962736157..8565506c75 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components newControlPoints[i] = newControlPoints[i] - first; // The slider's position defines the position of the first control point, and all further control points are relative to that point - slider.Position = slider.Position + first; + slider.Position += first; // Since pieces are re-used, they will not point to the deleted control points while remaining selected foreach (var piece in Pieces) diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..d1f7a1e8d3 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Tournament.Screens.Ladder { var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); - this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); + this.MoveTo(target -= e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); return true; diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 8254bdda7c..064c663d59 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index e291401670..24d8009f40 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -55,7 +55,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } diff --git a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs index 4717401c75..af03cbb63e 100644 --- a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs +++ b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(int amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } diff --git a/osu.Game/Screens/Play/HUD/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs index 5ac3dac5f7..ea50a4a578 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -114,7 +114,7 @@ namespace osu.Game.Screens.Play.HUD /// public void Increment(int amount = 1) { - Current.Value = Current.Value + amount; + Current.Value += amount; } /// diff --git a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs index 3f6b1e29e6..7ae8bc0ddf 100644 --- a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.HUD public override void Increment(long amount) { - Current.Value = Current.Value + amount; + Current.Value += amount; } } } From e5e8e70704936cf24e86f10c758590a63bd489c1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:16:51 +0800 Subject: [PATCH 301/503] Use pattern matching. --- .editorconfig | 4 +- .../Beatmaps/CatchBeatmapConverter.cs | 73 +++---- .../Beatmaps/ManiaBeatmapConverter.cs | 72 +++--- .../Legacy/DistanceObjectPatternGenerator.cs | 14 +- .../TestSceneSlider.cs | 33 ++- .../Beatmaps/OsuBeatmapConverter.cs | 81 ++++--- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 19 +- .../Beatmaps/TaikoBeatmapConverter.cs | 206 +++++++++--------- .../Replays/TaikoAutoGenerator.cs | 121 +++++----- .../Components/ScrollingTeamContainer.cs | 53 ++--- .../Sections/General/LoginSettings.cs | 6 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 8 +- .../Backgrounds/BackgroundScreenCustom.cs | 6 +- 13 files changed, 348 insertions(+), 348 deletions(-) diff --git a/.editorconfig b/.editorconfig index 35cbfe769f..b70f17887e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -145,8 +145,8 @@ dotnet_style_prefer_compound_assignment = true:warning #Style - null/type checks dotnet_style_coalesce_expression = true:warning dotnet_style_null_propagation = true:warning -csharp_style_pattern_matching_over_is_with_cast_check = true:silent -csharp_style_pattern_matching_over_as_with_null_check = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = true:warning csharp_style_throw_expression = true:silent csharp_style_conditional_delegate_call = true:suggestion diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 0d9a663b9f..b5497ea89f 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -8,6 +8,7 @@ using System; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -22,48 +23,44 @@ namespace osu.Game.Rulesets.Catch.Beatmaps protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) { - var curveData = obj as IHasCurve; var positionData = obj as IHasXPosition; var comboData = obj as IHasCombo; - var endTime = obj as IHasEndTime; - var legacyOffset = obj as IHasLegacyLastTickOffset; - if (curveData != null) + switch (obj) { - yield return new JuiceStream - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Path = curveData.Path, - NodeSamples = curveData.NodeSamples, - RepeatCount = curveData.RepeatCount, - X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - LegacyLastTickOffset = legacyOffset?.LegacyLastTickOffset ?? 0 - }; - } - else if (endTime != null) - { - yield return new BananaShower - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Duration = endTime.Duration, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - }; - } - else - { - yield return new Fruit - { - StartTime = obj.StartTime, - Samples = obj.Samples, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH - }; + case IHasCurve curveData: + return new JuiceStream + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Path = curveData.Path, + NodeSamples = curveData.NodeSamples, + RepeatCount = curveData.RepeatCount, + X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH, + NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, + LegacyLastTickOffset = (obj as IHasLegacyLastTickOffset)?.LegacyLastTickOffset ?? 0 + }.Yield(); + + case IHasEndTime endTime: + return new BananaShower + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Duration = endTime.Duration, + NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, + }.Yield(); + + default: + return new Fruit + { + StartTime = obj.StartTime, + Samples = obj.Samples, + NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, + X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH + }.Yield(); } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index c3a8cbd274..6e3d5761ac 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -156,37 +156,44 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// The hit objects generated. private IEnumerable generateConverted(HitObject original, IBeatmap originalBeatmap) { - var endTimeData = original as IHasEndTime; - var distanceData = original as IHasDistance; - var positionData = original as IHasPosition; - Patterns.PatternGenerator conversion = null; - if (distanceData != null) + switch (original) { - var generator = new DistanceObjectPatternGenerator(Random, original, beatmap, lastPattern, originalBeatmap); - conversion = generator; - - for (double time = original.StartTime; !Precision.DefinitelyBigger(time, generator.EndTime); time += generator.SegmentDuration) + case IHasDistance _: { - recordNote(time, positionData?.Position ?? Vector2.Zero); - computeDensity(time); + var generator = new DistanceObjectPatternGenerator(Random, original, beatmap, lastPattern, originalBeatmap); + conversion = generator; + + var positionData = original as IHasPosition; + + for (double time = original.StartTime; !Precision.DefinitelyBigger(time, generator.EndTime); time += generator.SegmentDuration) + { + recordNote(time, positionData?.Position ?? Vector2.Zero); + computeDensity(time); + } + + break; } - } - else if (endTimeData != null) - { - conversion = new EndTimeObjectPatternGenerator(Random, original, beatmap, originalBeatmap); - recordNote(endTimeData.EndTime, new Vector2(256, 192)); - computeDensity(endTimeData.EndTime); - } - else if (positionData != null) - { - computeDensity(original.StartTime); + case IHasEndTime endTimeData: + { + conversion = new EndTimeObjectPatternGenerator(Random, original, beatmap, originalBeatmap); - conversion = new HitObjectPatternGenerator(Random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair, originalBeatmap); + recordNote(endTimeData.EndTime, new Vector2(256, 192)); + computeDensity(endTimeData.EndTime); + break; + } - recordNote(original.StartTime, positionData.Position); + case IHasPosition positionData: + { + computeDensity(original.StartTime); + + conversion = new HitObjectPatternGenerator(Random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair, originalBeatmap); + + recordNote(original.StartTime, positionData.Position); + break; + } } if (conversion == null) @@ -219,14 +226,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private Pattern generate() { - var endTimeData = HitObject as IHasEndTime; var positionData = HitObject as IHasXPosition; int column = GetColumn(positionData?.X ?? 0); var pattern = new Pattern(); - if (endTimeData != null) + if (HitObject is IHasEndTime endTimeData) { pattern.Add(new HoldNote { @@ -237,7 +243,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps Tail = { Samples = sampleInfoListAt(endTimeData.EndTime) }, }); } - else if (positionData != null) + else if (HitObject is IHasXPosition) { pattern.Add(new Note { @@ -257,15 +263,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private IList sampleInfoListAt(double time) { - var curveData = HitObject as IHasCurve; + if (HitObject is IHasCurve curveData) + { + double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); - if (curveData == null) - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; + } - double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); - - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; + return HitObject.Samples; } } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 6297a68e08..4e98b08377 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -474,15 +474,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// private IList sampleInfoListAt(double time) { - var curveData = HitObject as IHasCurve; + if (HitObject is IHasCurve curveData) + { + double segmentTime = (EndTime - HitObject.StartTime) / spanCount; - if (curveData == null) - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; + } - double segmentTime = (EndTime - HitObject.StartTime) / spanCount; - - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; + return HitObject.Samples; } /// diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 5c656bf594..8e8fbf8976 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -379,26 +379,25 @@ namespace osu.Game.Rulesets.Osu.Tests private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { - var osuObject = judgedObject as DrawableOsuHitObject; - if (osuObject == null) - return; - - OsuSpriteText text; - Add(text = new OsuSpriteText + if (judgedObject is DrawableOsuHitObject osuObject) { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = result.IsHit ? "Hit!" : "Miss!", - Colour = result.IsHit ? Color4.Green : Color4.Red, - Font = OsuFont.GetFont(size: 30), - Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) - }); + OsuSpriteText text; + Add(text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = result.IsHit ? "Hit!" : "Miss!", + Colour = result.IsHit ? Color4.Green : Color4.Red, + Font = OsuFont.GetFont(size: 30), + Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) + }); - text.Delay(150) - .Then().FadeOut(200) - .Then().Expire(); + text.Delay(150) + .Then().FadeOut(200) + .Then().Expire(); - judgementOffsetDirection *= -1; + judgementOffsetDirection *= -1; + } } } } diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 6a41e93c35..2296030f81 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using osu.Game.Rulesets.Objects.Types; using System; using osu.Game.Rulesets.Osu.UI; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Osu.Beatmaps { @@ -23,52 +24,48 @@ namespace osu.Game.Rulesets.Osu.Beatmaps protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) { - var curveData = original as IHasCurve; - var endTimeData = original as IHasEndTime; var positionData = original as IHasPosition; var comboData = original as IHasCombo; - var legacyOffset = original as IHasLegacyLastTickOffset; - if (curveData != null) + switch (original) { - yield return new Slider - { - StartTime = original.StartTime, - Samples = original.Samples, - Path = curveData.Path, - NodeSamples = curveData.NodeSamples, - RepeatCount = curveData.RepeatCount, - Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false, - ComboOffset = comboData?.ComboOffset ?? 0, - LegacyLastTickOffset = legacyOffset?.LegacyLastTickOffset, - // prior to v8, speed multipliers don't adjust for how many ticks are generated over the same distance. - // this results in more (or less) ticks being generated in ().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; + for (int i = 0; i < slider.Path.ControlPoints.Length; i++) + newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); - var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; - for (int i = 0; i < slider.Path.ControlPoints.Length; i++) - newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); - - slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); + slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); + } } } } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 180e0d8309..10cc861b7e 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -73,127 +73,133 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps protected override IEnumerable ConvertHitObject(HitObject obj, IBeatmap beatmap) { - var distanceData = obj as IHasDistance; - var repeatsData = obj as IHasRepeats; - var endTimeData = obj as IHasEndTime; - var curveData = obj as IHasCurve; - // Old osu! used hit sounding to determine various hit type information IList samples = obj.Samples; bool strong = samples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); - if (distanceData != null) + switch (obj) { - // Number of spans of the object - one for the initial length and for each repeat - int spans = repeatsData?.SpanCount() ?? 1; - - TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); - DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(obj.StartTime); - - double speedAdjustment = difficultyPoint.SpeedMultiplier; - double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment; - - // The true distance, accounting for any repeats. This ends up being the drum roll distance later - double distance = distanceData.Distance * spans * legacy_velocity_multiplier; - - // The velocity of the taiko hit object - calculated as the velocity of a drum roll - double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; - // The duration of the taiko hit object - double taikoDuration = distance / taikoVelocity; - - // The velocity of the osu! hit object - calculated as the velocity of a slider - double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; - // The duration of the osu! hit object - double osuDuration = distance / osuVelocity; - - // osu-stable always uses the speed-adjusted beatlength to determine the velocities, but - // only uses it for tick rate if beatmap version < 8 - if (beatmap.BeatmapInfo.BeatmapVersion >= 8) - speedAdjustedBeatLength *= speedAdjustment; - - // If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat - double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / spans); - - if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) + case IHasDistance distanceData: { - List> allSamples = curveData != null ? curveData.NodeSamples : new List>(new[] { samples }); + // Number of spans of the object - one for the initial length and for each repeat + int spans = (obj as IHasRepeats)?.SpanCount() ?? 1; - int i = 0; + TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); + DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(obj.StartTime); - for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) + double speedAdjustment = difficultyPoint.SpeedMultiplier; + double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment; + + // The true distance, accounting for any repeats. This ends up being the drum roll distance later + double distance = distanceData.Distance * spans * legacy_velocity_multiplier; + + // The velocity of the taiko hit object - calculated as the velocity of a drum roll + double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; + // The duration of the taiko hit object + double taikoDuration = distance / taikoVelocity; + + // The velocity of the osu! hit object - calculated as the velocity of a slider + double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / speedAdjustedBeatLength; + // The duration of the osu! hit object + double osuDuration = distance / osuVelocity; + + // osu-stable always uses the speed-adjusted beatlength to determine the velocities, but + // only uses it for tick rate if beatmap version < 8 + if (beatmap.BeatmapInfo.BeatmapVersion >= 8) + speedAdjustedBeatLength *= speedAdjustment; + + // If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat + double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / spans); + + if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { - IList currentSamples = allSamples[i]; - bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); - strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); + List> allSamples = obj is IHasCurve curveData ? curveData.NodeSamples : new List>(new[] { samples }); - if (isRim) - { - yield return new RimHit - { - StartTime = j, - Samples = currentSamples, - IsStrong = strong - }; - } - else - { - yield return new CentreHit - { - StartTime = j, - Samples = currentSamples, - IsStrong = strong - }; - } + int i = 0; - i = (i + 1) % allSamples.Count; + for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) + { + IList currentSamples = allSamples[i]; + bool isRim = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); + strong = currentSamples.Any(s => s.Name == HitSampleInfo.HIT_FINISH); + + if (isRim) + { + yield return new RimHit + { + StartTime = j, + Samples = currentSamples, + IsStrong = strong + }; + } + else + { + yield return new CentreHit + { + StartTime = j, + Samples = currentSamples, + IsStrong = strong + }; + } + + i = (i + 1) % allSamples.Count; + } } - } - else - { - yield return new DrumRoll + else { - StartTime = obj.StartTime, - Samples = obj.Samples, - IsStrong = strong, - Duration = taikoDuration, - TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4 - }; - } - } - else if (endTimeData != null) - { - double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier; + yield return new DrumRoll + { + StartTime = obj.StartTime, + Samples = obj.Samples, + IsStrong = strong, + Duration = taikoDuration, + TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4 + }; + } - yield return new Swell - { - StartTime = obj.StartTime, - Samples = obj.Samples, - Duration = endTimeData.Duration, - RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier) - }; - } - else - { - bool isRim = samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); - - if (isRim) - { - yield return new RimHit - { - StartTime = obj.StartTime, - Samples = obj.Samples, - IsStrong = strong - }; + break; } - else + + case IHasEndTime endTimeData: { - yield return new CentreHit + double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier; + + yield return new Swell { StartTime = obj.StartTime, Samples = obj.Samples, - IsStrong = strong + Duration = endTimeData.Duration, + RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier) }; + + break; + } + + default: + { + bool isRim = samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP || s.Name == HitSampleInfo.HIT_WHISTLE); + + if (isRim) + { + yield return new RimHit + { + StartTime = obj.StartTime, + Samples = obj.Samples, + IsStrong = strong + }; + } + else + { + yield return new CentreHit + { + StartTime = obj.StartTime, + Samples = obj.Samples, + IsStrong = strong + }; + } + + break; } } } diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 299679b2c1..e61953aeb8 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -43,76 +43,83 @@ namespace osu.Game.Rulesets.Taiko.Replays IHasEndTime endTimeData = h as IHasEndTime; double endTime = endTimeData?.EndTime ?? h.StartTime; - Swell swell = h as Swell; - DrumRoll drumRoll = h as DrumRoll; - Hit hit = h as Hit; - - if (swell != null) + switch (h) { - int d = 0; - int count = 0; - int req = swell.RequiredHits; - double hitRate = Math.Min(swell_hit_speed, swell.Duration / req); - - for (double j = h.StartTime; j < endTime; j += hitRate) + case Swell swell: { - TaikoAction action; + int d = 0; + int count = 0; + int req = swell.RequiredHits; + double hitRate = Math.Min(swell_hit_speed, swell.Duration / req); - switch (d) + for (double j = h.StartTime; j < endTime; j += hitRate) { - default: - case 0: - action = TaikoAction.LeftCentre; - break; + TaikoAction action; - case 1: - action = TaikoAction.LeftRim; - break; + switch (d) + { + default: + case 0: + action = TaikoAction.LeftCentre; + break; - case 2: - action = TaikoAction.RightCentre; - break; + case 1: + action = TaikoAction.LeftRim; + break; - case 3: - action = TaikoAction.RightRim; + case 2: + action = TaikoAction.RightCentre; + break; + + case 3: + action = TaikoAction.RightRim; + break; + } + + Frames.Add(new TaikoReplayFrame(j, action)); + d = (d + 1) % 4; + if (++count == req) break; } - Frames.Add(new TaikoReplayFrame(j, action)); - d = (d + 1) % 4; - if (++count == req) - break; - } - } - else if (drumRoll != null) - { - foreach (var tick in drumRoll.NestedHitObjects.OfType()) - { - Frames.Add(new TaikoReplayFrame(tick.StartTime, hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre)); - hitButton = !hitButton; - } - } - else if (hit != null) - { - TaikoAction[] actions; - - if (hit is CentreHit) - { - actions = h.IsStrong - ? new[] { TaikoAction.LeftCentre, TaikoAction.RightCentre } - : new[] { hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre }; - } - else - { - actions = h.IsStrong - ? new[] { TaikoAction.LeftRim, TaikoAction.RightRim } - : new[] { hitButton ? TaikoAction.LeftRim : TaikoAction.RightRim }; + break; } - Frames.Add(new TaikoReplayFrame(h.StartTime, actions)); + case DrumRoll drumRoll: + { + foreach (var tick in drumRoll.NestedHitObjects.OfType()) + { + Frames.Add(new TaikoReplayFrame(tick.StartTime, hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre)); + hitButton = !hitButton; + } + + break; + } + + case Hit hit: + { + TaikoAction[] actions; + + if (hit is CentreHit) + { + actions = h.IsStrong + ? new[] { TaikoAction.LeftCentre, TaikoAction.RightCentre } + : new[] { hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre }; + } + else + { + actions = h.IsStrong + ? new[] { TaikoAction.LeftRim, TaikoAction.RightRim } + : new[] { hitButton ? TaikoAction.LeftRim : TaikoAction.RightRim }; + } + + Frames.Add(new TaikoReplayFrame(h.StartTime, actions)); + break; + } + + default: + throw new InvalidOperationException("Unknown hit object type."); } - else - throw new InvalidOperationException("Unknown hit object type."); var nextHitObject = GetNextObject(i); // Get the next object that requires pressing the same button diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index b147d680f0..fff73fcf70 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -125,22 +125,20 @@ namespace osu.Game.Tournament.Screens.Drawings.Components foreach (var c in Children) { - var stc = c as ScrollingTeam; - - if (stc == null) - continue; - - if (closest == null) + if (c is ScrollingTeam stc) { - closest = stc; - continue; + if (closest == null) + { + closest = stc; + continue; + } + + float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); + float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); + + if (o < lastOffset) + closest = stc; } - - float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); - float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); - - if (o < lastOffset) - closest = stc; } Trace.Assert(closest != null, "closest != null"); @@ -203,15 +201,13 @@ namespace osu.Game.Tournament.Screens.Drawings.Components foreach (var c in Children) { - ScrollingTeam st = c as ScrollingTeam; - - if (st == null) - continue; - - if (st.Team == team) + if (c is ScrollingTeam st) { - st.FadeOut(200); - st.Expire(); + if (st.Team == team) + { + st.FadeOut(200); + st.Expire(); + } } } } @@ -295,14 +291,13 @@ namespace osu.Game.Tournament.Screens.Drawings.Components { foreach (var c in Children) { - ScrollingTeam st = c as ScrollingTeam; - if (st == null) - continue; - - if (st.Selected) + if (c is ScrollingTeam st) { - st.Selected = false; - RemoveTeam(st.Team); + if (st.Selected) + { + st.Selected = false; + RemoveTeam(st.Team); + } } } } diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index a8bbccb168..d739035d46 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -297,10 +297,8 @@ namespace osu.Game.Overlays.Settings.Sections.General { set { - var h = Header as UserDropdownHeader; - if (h == null) return; - - h.StatusColour = value; + if (Header is UserDropdownHeader h) + h.StatusColour = value; } } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index f178c01fd6..31a0e3cb4e 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -148,13 +148,9 @@ namespace osu.Game.Rulesets.UI.Scrolling // Generate the timing points, making non-timing changes use the previous timing change and vice-versa var timingChanges = allPoints.Select(c => { - var timingPoint = c as TimingControlPoint; - var difficultyPoint = c as DifficultyControlPoint; - - if (timingPoint != null) + if (c is TimingControlPoint timingPoint) lastTimingPoint = timingPoint; - - if (difficultyPoint != null) + else if (c is DifficultyControlPoint difficultyPoint) lastDifficultyPoint = difficultyPoint; return new MultiplierControlPoint(c.Time) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs index 0cb41bc562..49c7934ed9 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs @@ -17,10 +17,10 @@ namespace osu.Game.Screens.Backgrounds public override bool Equals(BackgroundScreen other) { - var backgroundScreenCustom = other as BackgroundScreenCustom; - if (backgroundScreenCustom == null) return false; + if (other is BackgroundScreenCustom backgroundScreenCustom) + return base.Equals(other) && textureName == backgroundScreenCustom.textureName; - return base.Equals(other) && textureName == backgroundScreenCustom.textureName; + return false; } } } From 0d81b96c5f5dee2e2e8d9ae475f0ec3daea977c5 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:19:48 +0800 Subject: [PATCH 302/503] Use deconstruction declaration. --- .editorconfig | 2 +- osu.Game.Tournament/Components/SongBar.cs | 6 +++--- osu.Game/Skinning/SkinnableSound.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.editorconfig b/.editorconfig index b70f17887e..e6bef25e93 100644 --- a/.editorconfig +++ b/.editorconfig @@ -157,7 +157,7 @@ csharp_style_unused_value_assignment_preference = discard_variable:suggestion #Style - variable declaration csharp_style_inlined_variable_declaration = true:silent -csharp_style_deconstructed_variable_declaration = true:silent +csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features csharp_style_expression_bodied_local_functions = true:silent diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 7005c068ae..38094695fc 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -230,7 +230,7 @@ namespace osu.Game.Tournament.Components for (var i = 0; i < tuples.Length; i++) { - var tuple = tuples[i]; + var (heading, content) = tuples[i]; if (i > 0) { @@ -241,9 +241,9 @@ namespace osu.Game.Tournament.Components }); } - AddText(new OsuSpriteText { Text = tuple.heading }, s => cp(s, OsuColour.Gray(0.33f))); + AddText(new OsuSpriteText { Text = heading }, s => cp(s, OsuColour.Gray(0.33f))); AddText(" ", s => cp(s, OsuColour.Gray(0.33f))); - AddText(new OsuSpriteText { Text = tuple.content }, s => cp(s, OsuColour.Gray(0.5f))); + AddText(new OsuSpriteText { Text = content }, s => cp(s, OsuColour.Gray(0.5f))); } } } diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 6d23f22515..fc6afd0b27 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -96,8 +96,8 @@ namespace osu.Game.Skinning if (adjustments != null) { - foreach (var adjustment in adjustments) - ch.AddAdjustment(adjustment.property, adjustment.bindable); + foreach (var (property, bindable) in adjustments) + ch.AddAdjustment(property, bindable); } } From 31cc0d13da17951a324455b6923d964558c288a8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:22:35 +0800 Subject: [PATCH 303/503] Use 'out var'. --- .editorconfig | 2 +- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 3 +-- osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs | 4 +--- osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs | 4 +--- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 4 +--- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 4 +--- osu.Game/IO/Legacy/SerializationReader.cs | 4 +--- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 3 +-- osu.Game/Storyboards/Storyboard.cs | 3 +-- 9 files changed, 9 insertions(+), 22 deletions(-) diff --git a/.editorconfig b/.editorconfig index e6bef25e93..588661b59d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -156,7 +156,7 @@ csharp_style_unused_value_expression_statement_preference = discard_variable:sil csharp_style_unused_value_assignment_preference = discard_variable:suggestion #Style - variable declaration -csharp_style_inlined_variable_declaration = true:silent +csharp_style_inlined_variable_declaration = true:warning csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index be3c43699d..3b7a24726e 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -303,8 +303,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); - bool addToCentre; - int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out addToCentre); + int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out var addToCentre); int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2; int nextColumn = GetRandomColumn(upperBound: columnLimit); diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 2c515edda7..7119533743 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -225,9 +225,7 @@ namespace osu.Game.Tournament.Screens.Editors beatmapId.Value = Model.ID.ToString(); beatmapId.BindValueChanged(idString => { - int parsed; - - int.TryParse(idString.NewValue, out parsed); + int.TryParse(idString.NewValue, out var parsed); Model.ID = parsed; diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 11c2732d62..494dd73edd 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -267,9 +267,7 @@ namespace osu.Game.Tournament.Screens.Editors userId.Value = user.Id.ToString(); userId.BindValueChanged(idString => { - long parsed; - - long.TryParse(idString.NewValue, out parsed); + long.TryParse(idString.NewValue, out var parsed); user.Id = parsed; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index aeb5df46f8..838b1c2f07 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -293,9 +293,7 @@ namespace osu.Game.Beatmaps.Formats { string[] split = line.Split(','); - EventType type; - - if (!Enum.TryParse(split[0], out type)) + if (!Enum.TryParse(split[0], out EventType type)) throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index e3320f62ac..f94ab3f27b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -83,9 +83,7 @@ namespace osu.Game.Beatmaps.Formats { storyboardSprite = null; - EventType type; - - if (!Enum.TryParse(split[0], out type)) + if (!Enum.TryParse(split[0], out EventType type)) throw new InvalidDataException($@"Unknown event type: {split[0]}"); switch (type) diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index 7a84c11930..82b2c4be32 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -226,9 +226,7 @@ namespace osu.Game.IO.Legacy public override Type BindToType(string assemblyName, string typeName) { - Type typeToDeserialize; - - if (cache.TryGetValue(assemblyName + typeName, out typeToDeserialize)) + if (cache.TryGetValue(assemblyName + typeName, out var typeToDeserialize)) return typeToDeserialize; List tmpTypes = new List(); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 6c35b261d4..5e7d0d050a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -177,8 +177,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (i >= adds.Length) break; - int sound; - int.TryParse(adds[i], out sound); + int.TryParse(adds[i], out var sound); nodeSoundTypes[i] = (LegacySoundType)sound; } } diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 3d988c5fe3..a76eedfc78 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -27,8 +27,7 @@ namespace osu.Game.Storyboards public StoryboardLayer GetLayer(string name) { - StoryboardLayer layer; - if (!layers.TryGetValue(name, out layer)) + if (!layers.TryGetValue(name, out var layer)) layers[name] = layer = new StoryboardLayer(name, layers.Values.Min(l => l.Depth) - 1); return layer; From 8a1b70513c05be230fd593225f5d70623bc0e554 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:24:19 +0800 Subject: [PATCH 304/503] No this. qualification. --- .editorconfig | 6 ++++++ osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 588661b59d..abaa003115 100644 --- a/.editorconfig +++ b/.editorconfig @@ -111,6 +111,12 @@ csharp_preserve_single_line_statements = true #Roslyn language styles +#Style - this. qualification +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + #Style - type names dotnet_style_predefined_type_for_locals_parameters_members = true:silent dotnet_style_predefined_type_for_member_access = true:silent diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 0861e00d8d..7351187ab9 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.ControlPoints private ControlPointGroup controlPointGroup; - public void AttachGroup(ControlPointGroup pointGroup) => this.controlPointGroup = pointGroup; + public void AttachGroup(ControlPointGroup pointGroup) => controlPointGroup = pointGroup; public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); From ca52d09e815b776e9e021ae138049b88481063b5 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:26:42 +0800 Subject: [PATCH 305/503] Enforce expression body for typical simple ones. --- .editorconfig | 10 +++--- .../API/Requests/Responses/CommentBundle.cs | 13 +++---- .../BeatmapSet/Scores/ScoresContainer.cs | 35 +++++++++---------- osu.Game/Users/User.cs | 2 +- 4 files changed, 27 insertions(+), 33 deletions(-) diff --git a/.editorconfig b/.editorconfig index abaa003115..a555a3d2bc 100644 --- a/.editorconfig +++ b/.editorconfig @@ -132,12 +132,13 @@ csharp_preferred_modifier_order = public,private,protected,internal,new,abstract # Skipped because roslyn cannot separate +-*/ with << >> #Style - expression bodies -csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_accessors = true:warning csharp_style_expression_bodied_constructors = false:none -csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_indexers = true:warning csharp_style_expression_bodied_methods = true:silent -csharp_style_expression_bodied_operators = true:silent -csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_operators = true:warning +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_local_functions = true:silent #Style - expression preferences dotnet_style_object_initializer = true:warning @@ -166,7 +167,6 @@ csharp_style_inlined_variable_declaration = true:warning csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features -csharp_style_expression_bodied_local_functions = true:silent dotnet_style_prefer_inferred_tuple_names = true:warning csharp_prefer_simple_default_expression = true:warning csharp_style_pattern_local_over_anonymous_function = true:silent diff --git a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs index 7db3126ade..8db5d8d6ad 100644 --- a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -50,17 +50,14 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"user_votes")] private List userVotes { - set + set => value.ForEach(v => { - value.ForEach(v => + Comments.ForEach(c => { - Comments.ForEach(c => - { - if (v == c.Id) - c.IsVoted = true; - }); + if (v == c.Id) + c.IsVoted = true; }); - } + }); } private List users; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 4bbcd8d631..80de8f8230 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -48,31 +48,28 @@ namespace osu.Game.Overlays.BeatmapSet.Scores protected APILegacyScores Scores { - set + set => Schedule(() => { - Schedule(() => + topScoresContainer.Clear(); + + if (value?.Scores.Any() != true) { - topScoresContainer.Clear(); + scoreTable.Scores = null; + scoreTable.Hide(); + return; + } - if (value?.Scores.Any() != true) - { - scoreTable.Scores = null; - scoreTable.Hide(); - return; - } + scoreTable.Scores = value.Scores; + scoreTable.Show(); - scoreTable.Scores = value.Scores; - scoreTable.Show(); + var topScore = value.Scores.First(); + var userScore = value.UserScore; - var topScore = value.Scores.First(); - var userScore = value.UserScore; + topScoresContainer.Add(new DrawableTopScore(topScore)); - topScoresContainer.Add(new DrawableTopScore(topScore)); - - if (userScore != null && userScore.Score.OnlineScoreID != topScore.OnlineScoreID) - topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); - }); - } + if (userScore != null && userScore.Score.OnlineScoreID != topScore.OnlineScoreID) + topScoresContainer.Add(new DrawableTopScore(userScore.Score, userScore.Position)); + }); } public ScoresContainer() diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 1cb395fd75..b15789f324 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -129,7 +129,7 @@ namespace osu.Game.Users [JsonProperty] private string[] playstyle { - set { PlayStyles = value?.Select(str => Enum.Parse(typeof(PlayStyle), str, true)).Cast().ToArray(); } + set => PlayStyles = value?.Select(str => Enum.Parse(typeof(PlayStyle), str, true)).Cast().ToArray(); } public PlayStyle[] PlayStyles; From 205eda8566baf7566d5b315112e0d33ce47cd5e0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:30:25 +0800 Subject: [PATCH 306/503] Use readonly field when not reflected. --- .editorconfig | 3 +-- osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.editorconfig b/.editorconfig index a555a3d2bc..92d06da4f3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -158,6 +158,7 @@ csharp_style_throw_expression = true:silent csharp_style_conditional_delegate_call = true:suggestion #Style - unused +dotnet_style_readonly_field = true:silent dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent csharp_style_unused_value_assignment_preference = discard_variable:suggestion @@ -175,8 +176,6 @@ dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent #Supressing roslyn built-in analyzers # Suppress: EC112 -#Field can be readonly -dotnet_diagnostic.IDE0044.severity = silent #Private method is unused dotnet_diagnostic.IDE0051.severity = silent #Private member is unused diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 9869ddde41..7b2913b817 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -87,7 +87,7 @@ namespace osu.Game.Tests.NonVisual.Filtering Assert.IsNull(filterCriteria.BPM.Max); } - private static object[] lengthQueryExamples = + private static readonly object[] length_query_examples = { new object[] { "6ms", TimeSpan.FromMilliseconds(6), TimeSpan.FromMilliseconds(1) }, new object[] { "23s", TimeSpan.FromSeconds(23), TimeSpan.FromSeconds(1) }, @@ -97,7 +97,7 @@ namespace osu.Game.Tests.NonVisual.Filtering }; [Test] - [TestCaseSource(nameof(lengthQueryExamples))] + [TestCaseSource(nameof(length_query_examples))] public void TestApplyLengthQueries(string lengthQuery, TimeSpan expectedLength, TimeSpan scale) { string query = $"length={lengthQuery} time"; From 64fc5007fc447dd14c54f7c1985ff2c83fce87f0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:33:24 +0800 Subject: [PATCH 307/503] Use language primitive types. --- .editorconfig | 4 ++-- osu.Desktop/OsuGameDesktop.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- osu.Game/Tests/Visual/OsuTestScene.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.editorconfig b/.editorconfig index 92d06da4f3..2c68b0ca09 100644 --- a/.editorconfig +++ b/.editorconfig @@ -118,8 +118,8 @@ dotnet_style_qualification_for_method = false:warning dotnet_style_qualification_for_event = false:warning #Style - type names -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent +dotnet_style_predefined_type_for_locals_parameters_members = true:warning +dotnet_style_predefined_type_for_member_access = true:warning csharp_style_var_when_type_is_apparent = true:none csharp_style_var_for_built_in_types = true:none csharp_style_var_elsewhere = true:silent diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 7725ee6451..26a730b442 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -119,7 +119,7 @@ namespace osu.Desktop try { using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(String.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); + stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); if (checkExists(stableInstallPath)) return stableInstallPath; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 47f2bed77a..8ec8a21280 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -180,7 +180,7 @@ namespace osu.Game.Tournament.IPC try { using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(String.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); + stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); if (checkExists(stableInstallPath)) return stableInstallPath; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..e350b40c25 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual public IEnumerable GetAvailableResources() => throw new NotImplementedException(); - public Track GetVirtual(double length = Double.PositiveInfinity) + public Track GetVirtual(double length = double.PositiveInfinity) { var track = new TrackVirtualManual(referenceClock) { Length = length }; AddItem(track); From 2270f33c33ac80f9489545f016fa3085af126df9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 11 Nov 2019 21:20:18 +0800 Subject: [PATCH 308/503] Enable C# 8. --- Directory.Build.props | 2 +- osu.Android.props | 3 ++- osu.iOS.props | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b4baa2833e..cb0d0f05b0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 7.3 + 8.0 $(MSBuildThisFileDirectory)app.manifest diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..74f899e81d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -1,5 +1,6 @@ - + + 8.0 bin\$(Configuration) 4 2.0 diff --git a/osu.iOS.props b/osu.iOS.props index 8124357312..d529b5f4e2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -1,5 +1,6 @@ + 8.0 {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Resources PackageReference From dcfa98414f1a20b05a63fd9460c1b0937978c67a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:35:08 +0800 Subject: [PATCH 309/503] Use ??=. --- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 6 +++--- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs | 2 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 ++-- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Skinning/SkinManager.cs | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index fba52dfc32..f225173326 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -148,9 +148,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy protected int FindAvailableColumn(int initialColumn, int? lowerBound = null, int? upperBound = null, Func nextColumn = null, [InstantHandle] Func validation = null, params Pattern[] patterns) { - lowerBound = lowerBound ?? RandomStart; - upperBound = upperBound ?? TotalColumns; - nextColumn = nextColumn ?? (_ => GetRandomColumn(lowerBound, upperBound)); + lowerBound ??= RandomStart; + upperBound ??= TotalColumns; + nextColumn ??= (_ => GetRandomColumn(lowerBound, upperBound)); // Check for the initial column if (isValid(initialColumn)) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 84a7bfc53e..64f353c4d9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable testSingle(float circleSize, bool auto = false, double timeOffset = 0, Vector2? positionOffset = null) { - positionOffset = positionOffset ?? Vector2.Zero; + positionOffset ??= Vector2.Zero; var circle = new HitCircle { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index c46343c73c..a677cb6a72 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; private OsuInputManager osuActionInputManager; - internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); + internal OsuInputManager OsuActionInputManager => osuActionInputManager ??= GetContainingInputManager() as OsuInputManager; protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index b879b92f01..4924842e81 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps { try { - return (trackStore ?? (trackStore = AudioManager.GetTrackStore(store))).Get(getPathForFile(Metadata.AudioFile)); + return (trackStore ??= AudioManager.GetTrackStore(store)).Get(getPathForFile(Metadata.AudioFile)); } catch { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 7c69a992dd..44d6d33cef 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -150,7 +150,7 @@ namespace osu.Game.Beatmaps public bool BeatmapLoaded => beatmapLoadTask?.IsCompleted ?? false; - public Task LoadBeatmapAsync() => (beatmapLoadTask ?? (beatmapLoadTask = Task.Factory.StartNew(() => + public Task LoadBeatmapAsync() => beatmapLoadTask ??= Task.Factory.StartNew(() => { // Todo: Handle cancellation during beatmap parsing var b = GetBeatmap() ?? new Beatmap(); @@ -162,7 +162,7 @@ namespace osu.Game.Beatmaps b.BeatmapInfo = BeatmapInfo; return b; - }, beatmapCancellation.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default))); + }, beatmapCancellation.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); public IBeatmap Beatmap { diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..61c27d0fba 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -129,7 +129,7 @@ namespace osu.Game.Rulesets.Objects isInitialised = true; - controlPoints = controlPoints ?? Array.Empty(); + controlPoints ??= Array.Empty(); calculatedPath = new List(); cumulativeLength = new List(); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index aa3b3981c2..3d469ab6e1 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -96,7 +96,7 @@ namespace osu.Game.Skinning else { model.Name = model.Name.Replace(".osk", ""); - model.Creator = model.Creator ?? "Unknown"; + model.Creator ??= "Unknown"; } } From 144812669dd1e861c108bf8747a777c6ab853265 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:37:20 +0800 Subject: [PATCH 310/503] Use static local functions. --- .editorconfig | 3 +++ osu.Desktop/OsuGameDesktop.cs | 2 +- .../Objects/Drawable/DrawableFruit.cs | 2 +- .../Patterns/Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs | 9 +++++---- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 6 +++--- .../Online/TestSceneBeatmapSetOverlaySuccessRate.cs | 2 +- osu.Game.Tournament/Components/SongBar.cs | 2 +- osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- .../Screens/Ladder/Components/ProgressionPath.cs | 2 +- osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs | 2 +- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 +- 14 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.editorconfig b/.editorconfig index 2c68b0ca09..8c2dde00aa 100644 --- a/.editorconfig +++ b/.editorconfig @@ -173,6 +173,9 @@ csharp_prefer_simple_default_expression = true:warning csharp_style_pattern_local_over_anonymous_function = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +#Style _ C# 8 features +csharp_prefer_static_local_function = true:warning + #Supressing roslyn built-in analyzers # Suppress: EC112 diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 26a730b442..66e7bb381c 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -112,7 +112,7 @@ namespace osu.Desktop { protected override string LocateBasePath() { - bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); + static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); string stableInstallPath; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..a6da682aee 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable const float small_pulp = large_pulp_3 / 2; - Vector2 positionAt(float angle, float distance) => new Vector2( + static Vector2 positionAt(float angle, float distance) => new Vector2( distance * (float)Math.Sin(angle * Math.PI / 180), distance * (float)Math.Cos(angle * Math.PI / 180)); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 4e98b08377..0cbf5cf51c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -364,7 +364,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy break; } - bool isDoubleSample(HitSampleInfo sample) => sample.Name == HitSampleInfo.HIT_CLAP || sample.Name == HitSampleInfo.HIT_FINISH; + static bool isDoubleSample(HitSampleInfo sample) => sample.Name == HitSampleInfo.HIT_CLAP || sample.Name == HitSampleInfo.HIT_FINISH; bool canGenerateTwoNotes = !convertType.HasFlag(PatternType.LowProbability); canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample); diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index e9fdf924c3..0c55194250 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Tests break; } - ConvertValue createConvertValue(OsuHitObject obj) => new ConvertValue + static ConvertValue createConvertValue(OsuHitObject obj) => new ConvertValue { StartTime = obj.StartTime, EndTime = (obj as IHasEndTime)?.EndTime ?? obj.StartTime, diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 8e8fbf8976..88c9324d4c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -148,9 +148,9 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("repeat samples updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); - bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + static bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; - bool assertSamples(HitObject hitObject) + static bool assertSamples(HitObject hitObject) { return hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP) && hitObject.Samples.Any(s => s.Name == HitSampleInfo.HIT_WHISTLE); @@ -183,8 +183,9 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("repeat samples not updated", () => ((Slider)slider.HitObject).NestedHitObjects.OfType().All(assertSamples)); AddAssert("tail has no samples", () => ((Slider)slider.HitObject).TailCircle.Samples.Count == 0); - bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; - bool assertSamples(HitObject hitObject) => hitObject.Samples.All(s => s.Name != HitSampleInfo.HIT_CLAP && s.Name != HitSampleInfo.HIT_WHISTLE); + static bool assertTickSamples(SliderTick tick) => tick.Samples.Single().Name == "slidertick"; + + static bool assertSamples(HitObject hitObject) => hitObject.Samples.All(s => s.Name != HitSampleInfo.HIT_CLAP && s.Name != HitSampleInfo.HIT_WHISTLE); } private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 32c9e913c6..7f53340fb8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToDrawableHitObjects(IEnumerable drawables) { - void adjustFadeIn(OsuHitObject h) => h.TimeFadeIn = h.TimePreempt * fade_in_duration_multiplier; + static void adjustFadeIn(OsuHitObject h) => h.TimeFadeIn = h.TimePreempt * fade_in_duration_multiplier; foreach (var d in drawables.OfType()) { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 2ecc516919..26e70f19e4 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -413,7 +413,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("soft-hitnormal8", getTestableSampleInfo(hitObjects[4]).LookupNames.First()); } - HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] @@ -431,7 +431,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("normal-hitnormal3", getTestableSampleInfo(hitObjects[2]).LookupNames.First()); } - HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] @@ -451,7 +451,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(70, getTestableSampleInfo(hitObjects[3]).Volume); } - HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); } [Test] diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs index 05f5c117e4..80fad44593 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("set second set", () => successRate.Beatmap = secondBeatmap); AddAssert("ratings set", () => successRate.Graph.Metrics == secondBeatmap.Metrics); - BeatmapInfo createBeatmap() => new BeatmapInfo + static BeatmapInfo createBeatmap() => new BeatmapInfo { Metrics = new BeatmapMetrics { diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 38094695fc..61618aedc0 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -222,7 +222,7 @@ namespace osu.Game.Tournament.Components Margin = new MarginPadding { Horizontal = 15, Vertical = 1 }; AutoSizeAxes = Axes.Both; - void cp(SpriteText s, Color4 colour) + static void cp(SpriteText s, Color4 colour) { s.Colour = colour; s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 8ec8a21280..b19f2bedf0 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -152,7 +152,7 @@ namespace osu.Game.Tournament.IPC { protected override string LocateBasePath() { - bool checkExists(string p) + static bool checkExists(string p) { return File.Exists(Path.Combine(p, "ipc.txt")); } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 34e0dc770f..84a329085a 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -26,7 +26,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components { base.LoadComplete(); - Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); + static Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2); var q1 = Source.ScreenSpaceDrawQuad; var q2 = Destination.ScreenSpaceDrawQuad; diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 7a5fc2cd06..c3875716b8 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -120,7 +120,7 @@ namespace osu.Game.Tournament.Screens.MapPool pickColour = colour; pickType = choiceType; - Color4 setColour(bool active) => active ? Color4.White : Color4.Gray; + static Color4 setColour(bool active) => active ? Color4.White : Color4.Gray; buttonRedBan.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Ban); buttonBlueBan.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Ban); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 5e7d0d050a..5348ff1f02 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } // osu-stable special-cased colinear perfect curves to a CurveType.Linear - bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); + static bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y)); if (points.Length == 3 && pathType == PathType.PerfectCurve && isLinear(points)) pathType = PathType.Linear; From 5f3e9a791c6e44747ba3e9ff1e33cb50ced91425 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 18:45:19 +0800 Subject: [PATCH 311/503] Disable suggestions not applicable for this PR. --- .editorconfig | 6 +++++- osu.sln.DotSettings | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8c2dde00aa..3e7325e15b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -173,8 +173,12 @@ csharp_prefer_simple_default_expression = true:warning csharp_style_pattern_local_over_anonymous_function = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent -#Style _ C# 8 features +#Style - C# 8 features csharp_prefer_static_local_function = true:warning +csharp_prefer_simple_using_statement = true:silent +csharp_style_prefer_index_operator = false:none +csharp_style_prefer_range_operator = false:none +csharp_style_prefer_switch_expression = false:none #Supressing roslyn built-in analyzers # Suppress: EC112 diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 63d055702b..b08d314dbe 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -70,6 +70,7 @@ WARNING HINT WARNING + HINT WARNING DO_NOT_SHOW WARNING @@ -118,6 +119,7 @@ HINT HINT HINT + DO_NOT_SHOW HINT HINT WARNING @@ -132,7 +134,6 @@ DO_NOT_SHOW DO_NOT_SHOW WARNING - WARNING WARNING WARNING @@ -211,12 +212,13 @@ HINT HINT HINT - HINT HINT + DO_NOT_SHOW WARNING WARNING WARNING + DO_NOT_SHOW WARNING True From d60493a961dc44185702e5d101476fdd915f4752 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:03:21 +0800 Subject: [PATCH 312/503] Use discards. --- osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs | 2 +- osu.Game/Configuration/DatabasedConfigManager.cs | 2 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.sln.DotSettings | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs index b3863bcf44..669acc3202 100644 --- a/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Beatmaps.Formats { try { - var _ = int.Parse(input); + _ = int.Parse(input); } catch (Exception e) { diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 02382cfd2b..1ef4c2527a 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -36,7 +36,7 @@ namespace osu.Game.Configuration protected override void PerformLoad() { databasedSettings = settings.Query(ruleset?.ID, variant); - legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out var _)); + legacySettingsExist = databasedSettings.Any(s => int.TryParse(s.Key, out _)); } protected override bool PerformSave() diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index c3436ffd45..b58753bdbb 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Select newRoot.Filter(activeCriteria); // preload drawables as the ctor overhead is quite high currently. - var _ = newRoot.Drawables; + _ = newRoot.Drawables; root = newRoot; if (selectedBeatmapSet != null && !beatmapSets.Contains(selectedBeatmapSet.BeatmapSet)) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index b08d314dbe..9b400de390 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -17,6 +17,7 @@ WARNING WARNING HINT + DO_NOT_SHOW HINT HINT HINT From 42a98c5d87124ac18f6ec6228430ea88aec0db89 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:07:01 +0800 Subject: [PATCH 313/503] Use constants. --- osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Dialog/PopupDialog.cs | 4 ++-- osu.Game/Overlays/SearchableList/SearchableListOverlay.cs | 2 +- osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs | 2 +- osu.Game/Screens/Select/FooterButton.cs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index 621728830a..505d2d6f89 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Chat.Selection { public class ChannelSelectionOverlay : WaveOverlayContainer { - public static readonly float WIDTH_PADDING = 170; + public const float WIDTH_PADDING = 170; private const float transition_duration = 500; diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..a14765ee88 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Chat.Tabs { public class ChannelTabControl : OsuTabControl { - public static readonly float SHEAR_WIDTH = 10; + public const float SHEAR_WIDTH = 10; public Action OnRequestLeave; diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index cff887865a..ee88ff258a 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -21,8 +21,8 @@ namespace osu.Game.Overlays.Dialog { public abstract class PopupDialog : VisibilityContainer { - public static readonly float ENTER_DURATION = 500; - public static readonly float EXIT_DURATION = 200; + public const float ENTER_DURATION = 500; + public const float EXIT_DURATION = 200; private readonly Vector2 ringSize = new Vector2(100f); private readonly Vector2 ringMinifiedSize = new Vector2(20f); diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index 177f731f12..fb0c1d9808 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.SearchableList { public abstract class SearchableListOverlay : FullscreenOverlay { - public static readonly float WIDTH_PADDING = 80; + public const float WIDTH_PADDING = 80; } public abstract class SearchableListOverlay : SearchableListOverlay diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index bba72c7ee1..433e8ee398 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select { public class BeatmapDetailAreaTabControl : Container { - public static readonly float HEIGHT = 24; + public const float HEIGHT = 24; private readonly OsuTabControlCheckbox modsCheckbox; private readonly OsuTabControl tabs; private readonly Container tabsContainer; diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index c1478aa4ce..b77da36748 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select { public class FooterButton : OsuClickableContainer { - public static readonly float SHEAR_WIDTH = 7.5f; + public const float SHEAR_WIDTH = 7.5f; protected static readonly Vector2 SHEAR = new Vector2(SHEAR_WIDTH / Footer.HEIGHT, 0); From f3f5094c2686f7964c1613fc0b0f7799f4b3c7df Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:12:11 +0800 Subject: [PATCH 314/503] Convert delegate to local function. --- .editorconfig | 2 +- osu.Game/Screens/Menu/Disclaimer.cs | 3 +-- .../Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3e7325e15b..bfa071acd8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -170,7 +170,7 @@ csharp_style_deconstructed_variable_declaration = true:warning #Style - other C# 7.x features dotnet_style_prefer_inferred_tuple_names = true:warning csharp_prefer_simple_default_expression = true:warning -csharp_style_pattern_local_over_anonymous_function = true:silent +csharp_style_pattern_local_over_anonymous_function = true:warning dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent #Style - C# 8 features diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 17f999d519..bcab73715b 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -93,7 +92,7 @@ namespace osu.Game.Screens.Menu textFlow.AddParagraph("Things may not work as expected", t => t.Font = t.Font.With(size: 20)); textFlow.NewParagraph(); - Action format = t => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); + static void format(SpriteText t) => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); textFlow.AddParagraph("Detailed bug reports are welcomed via github issues.", format); textFlow.NewParagraph(); diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index d20b021fc6..e389611caf 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; @@ -77,12 +76,13 @@ namespace osu.Game.Screens.Multi.Ranking.Pages private void scoresLoaded(IEnumerable scores) { - Action gray = s => s.Colour = colours.GrayC; - Action white = s => + void gray(SpriteText s) => s.Colour = colours.GrayC; + + void white(SpriteText s) { s.Font = s.Font.With(size: s.Font.Size * 1.4f); s.Colour = colours.GrayF; - }; + } rankText.AddText(name + "\n", white); rankText.AddText("You are placed ", gray); From 2d46eed8aee992b136a5a20972cc109928948650 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:15:55 +0800 Subject: [PATCH 315/503] Turn on missing rules. --- .editorconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index bfa071acd8..b5333ad8e7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -155,13 +155,13 @@ dotnet_style_null_propagation = true:warning csharp_style_pattern_matching_over_is_with_cast_check = true:warning csharp_style_pattern_matching_over_as_with_null_check = true:warning csharp_style_throw_expression = true:silent -csharp_style_conditional_delegate_call = true:suggestion +csharp_style_conditional_delegate_call = true:warning #Style - unused dotnet_style_readonly_field = true:silent dotnet_code_quality_unused_parameters = non_public:silent csharp_style_unused_value_expression_statement_preference = discard_variable:silent -csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:warning #Style - variable declaration csharp_style_inlined_variable_declaration = true:warning From 61464c5c89723cbfe06dc975e760d207c2d8dc8b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 21:27:15 +0900 Subject: [PATCH 316/503] Fix potential nullref in unrelated test --- osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index c8c36789c4..5652b8d2bd 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online.API.Requests public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset, BeatmapSearchCategory searchCategory = BeatmapSearchCategory.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending) { - this.query = System.Uri.EscapeDataString(query); + this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query); this.ruleset = ruleset; this.searchCategory = searchCategory; this.sortCriteria = sortCriteria; From 1349289c0eae4e15db47ec3a807ef658cb7d7b59 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 20:32:41 +0800 Subject: [PATCH 317/503] Remove SharpRaven package and install Sentry. --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index af60da3e70..a64334c4cc 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,9 +22,9 @@ + - From 5110ae82a1cd76a970ef11bfebf7559dea0c9514 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 21:38:08 +0900 Subject: [PATCH 318/503] Tidy up implementation --- .../BeatmapSet/Buttons/FavouriteButton.cs | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index f059e06214..33df1fa485 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -1,6 +1,7 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { public readonly Bindable BeatmapSet = new Bindable(); - private readonly Bindable favourited = new Bindable(); + private readonly BindableBool favourited = new BindableBool(); private PostBeatmapFavouriteRequest request; private DimmedLoadingLayer loading; @@ -44,40 +45,45 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons loading = new DimmedLoadingLayer(), }); + favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; + BeatmapSet.BindValueChanged(setInfo => { - if (setInfo.NewValue?.OnlineInfo?.HasFavourited == null) - return; - - favourited.Value = setInfo.NewValue.OnlineInfo.HasFavourited; - }); - - favourited.ValueChanged += favourited => - { - loading.Hide(); - - icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; - }; + Enabled.Value = BeatmapSet.Value?.OnlineBeatmapSetID > 0; + favourited.Value = setInfo.NewValue?.OnlineInfo?.HasFavourited ?? false; + }, true); Action = () => { if (loading.State.Value == Visibility.Visible) return; + // guaranteed by disabled state abvove. + Debug.Assert(BeatmapSet.Value.OnlineBeatmapSetID != null); + loading.Show(); request?.Cancel(); - request = new PostBeatmapFavouriteRequest(BeatmapSet.Value?.OnlineBeatmapSetID ?? 0, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); - request.Success += () => favourited.Value = !favourited.Value; - request.Failure += exception => + + request = new PostBeatmapFavouriteRequest(BeatmapSet.Value.OnlineBeatmapSetID.Value, favourited.Value ? BeatmapFavouriteAction.UnFavourite : BeatmapFavouriteAction.Favourite); + + request.Success += () => + { + favourited.Toggle(); + loading.Hide(); + }; + + request.Failure += e => { notifications.Post(new SimpleNotification { - Text = exception.Message, + Text = e.Message, Icon = FontAwesome.Solid.Times, }); + loading.Hide(); }; + api.Queue(request); }; } From da819261e0063b6f3a98ed5c28821696c662dcdf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 21:38:16 +0900 Subject: [PATCH 319/503] Shrink and darken loading layer to better suit button --- osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs | 7 ++++--- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs index b7d2222f33..f7138827cc 100644 --- a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; +using osuTK; namespace osu.Game.Graphics.UserInterface { @@ -15,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface private readonly LoadingAnimation loading; - public DimmedLoadingLayer() + public DimmedLoadingLayer(float dimAmount = 0.5f, float iconScale = 1f) { RelativeSizeAxes = Axes.Both; Children = new Drawable[] @@ -23,9 +24,9 @@ namespace osu.Game.Graphics.UserInterface new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.5f), + Colour = Color4.Black.Opacity(dimAmount), }, - loading = new LoadingAnimation(), + loading = new LoadingAnimation { Scale = new Vector2(iconScale) }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 33df1fa485..cfb34e4adf 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Size = new Vector2(18), Shadow = false, }, - loading = new DimmedLoadingLayer(), + loading = new DimmedLoadingLayer(0.8f, 0.5f), }); favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; From de732c6c2447e6f1b231cd2d843fa74413819539 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 21:12:38 +0800 Subject: [PATCH 320/503] Change code to use Sentry client. --- osu.Game.Tests/Visual/TestSceneOsuGame.cs | 2 +- osu.Game/OsuGame.cs | 4 ++-- .../Utils/{RavenLogger.cs => SentryLogger.cs} | 22 +++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) rename osu.Game/Utils/{RavenLogger.cs => SentryLogger.cs} (84%) diff --git a/osu.Game.Tests/Visual/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/TestSceneOsuGame.cs index 36cd49d839..e495b2a95a 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuGame.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual private IReadOnlyList requiredGameDependencies => new[] { typeof(OsuGame), - typeof(RavenLogger), + typeof(SentryLogger), typeof(OsuLogo), typeof(IdleTracker), typeof(OnScreenDisplay), diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 328c964976..541050a30f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -71,7 +71,7 @@ namespace osu.Game [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); - protected RavenLogger RavenLogger; + protected SentryLogger RavenLogger; public virtual Storage GetStorageForStableInstall() => null; @@ -110,7 +110,7 @@ namespace osu.Game forwardLoggedErrorsToNotifications(); - RavenLogger = new RavenLogger(this); + RavenLogger = new SentryLogger(this); } private void updateBlockingOverlayFade() => diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/SentryLogger.cs similarity index 84% rename from osu.Game/Utils/RavenLogger.cs rename to osu.Game/Utils/SentryLogger.cs index 16178e63bd..9629e830bd 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -7,26 +7,26 @@ using System.IO; using System.Net; using System.Threading.Tasks; using osu.Framework.Logging; -using SharpRaven; -using SharpRaven.Data; +using Sentry; namespace osu.Game.Utils { /// /// Report errors to sentry. /// - public class RavenLogger : IDisposable + public class SentryLogger : IDisposable { - private readonly RavenClient raven = new RavenClient("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"); - private readonly List tasks = new List(); - public RavenLogger(OsuGame game) + public SentryLogger(OsuGame game) { - raven.Release = game.Version; - if (!game.IsDeployedBuild) return; + SentrySdk.Init(new SentryOptions + { + Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), + Release = game.Version + }); Exception lastException = null; Logger.NewEntry += entry => @@ -46,10 +46,10 @@ namespace osu.Game.Utils return; lastException = exception; - queuePendingTask(raven.CaptureAsync(new SentryEvent(exception) { Message = entry.Message })); + SentrySdk.CaptureEvent(new SentryEvent(exception) { Message = entry.Message }); } else - raven.AddTrail(new Breadcrumb(entry.Target.ToString(), BreadcrumbType.Navigation) { Message = entry.Message }); + SentrySdk.AddBreadcrumb(category: entry.Target.ToString(), type: "navigation", message: entry.Message); }; } @@ -93,7 +93,7 @@ namespace osu.Game.Utils #region Disposal - ~RavenLogger() + ~SentryLogger() { Dispose(false); } From e01a50e4b332a0ea70f2dead860f75faf266611a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 21:39:38 +0800 Subject: [PATCH 321/503] Correct disposal. --- osu.Game/Utils/SentryLogger.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 9629e830bd..256c52489b 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -16,13 +16,13 @@ namespace osu.Game.Utils /// public class SentryLogger : IDisposable { - private readonly List tasks = new List(); + private IDisposable sentry; public SentryLogger(OsuGame game) { if (!game.IsDeployedBuild) return; - SentrySdk.Init(new SentryOptions + sentry = SentrySdk.Init(new SentryOptions { Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), Release = game.Version @@ -81,16 +81,6 @@ namespace osu.Game.Utils return true; } - private void queuePendingTask(Task task) - { - lock (tasks) tasks.Add(task); - task.ContinueWith(_ => - { - lock (tasks) - tasks.Remove(task); - }); - } - #region Disposal ~SentryLogger() @@ -112,7 +102,8 @@ namespace osu.Game.Utils return; isDisposed = true; - lock (tasks) Task.WaitAll(tasks.ToArray(), 5000); + sentry.Dispose(); + sentry = null; } #endregion From 8276428efc0ff891a935acb69220b4f8e4bb7478 Mon Sep 17 00:00:00 2001 From: Ganendra Afrasya Date: Tue, 12 Nov 2019 20:48:26 +0700 Subject: [PATCH 322/503] Add IsPresent check when dialog popping out --- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index cff887865a..13eb677263 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -241,7 +241,7 @@ namespace osu.Game.Overlays.Dialog protected override void PopOut() { - if (!actionInvoked) + if (!actionInvoked && content.IsPresent) // In the case a user did not choose an action before a hide was triggered, press the last button. // This is presumed to always be a sane default "cancel" action. buttonsContainer.Last().Click(); From 70a02d27a99e86f4308f62aac12dbe10f75fa5bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Nov 2019 22:53:01 +0900 Subject: [PATCH 323/503] Update solution paths --- fastlane/Fastfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 7adf42a1eb..28a83fbbae 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -49,12 +49,12 @@ desc 'Deploy to play store' desc 'Compile the project' lane :build do |options| nuget_restore( - project_path: 'osu.Android.sln' + project_path: 'osu.sln' ) souyuz( build_configuration: 'Release', - solution_path: 'osu.Android.sln', + solution_path: 'osu.sln', platform: "android", output_path: "osu.Android/bin/Release/", keystore_path: options[:keystore_path], @@ -70,7 +70,7 @@ desc 'Deploy to play store' android_build = split.join('') app_version( - solution_path: 'osu.Android.sln', + solution_path: 'osu.sln', version: options[:version], build: android_build, ) @@ -106,7 +106,7 @@ platform :ios do desc 'Compile the project' lane :build do nuget_restore( - project_path: 'osu.iOS.sln' + project_path: 'osu.sln' ) souyuz( From 6ae6603dede8c6fb0c5e9b1671a1e65e5330ccd8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 22:08:16 +0800 Subject: [PATCH 324/503] Cleanup. --- osu.Game/OsuGame.cs | 8 ++++---- osu.Game/Utils/SentryLogger.cs | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 541050a30f..55768baa7e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -71,7 +71,7 @@ namespace osu.Game [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); - protected SentryLogger RavenLogger; + protected SentryLogger SentryLogger; public virtual Storage GetStorageForStableInstall() => null; @@ -110,7 +110,7 @@ namespace osu.Game forwardLoggedErrorsToNotifications(); - RavenLogger = new SentryLogger(this); + SentryLogger = new SentryLogger(this); } private void updateBlockingOverlayFade() => @@ -166,7 +166,7 @@ namespace osu.Game dependencies.CacheAs(this); - dependencies.Cache(RavenLogger); + dependencies.Cache(SentryLogger); dependencies.Cache(osuLogo = new OsuLogo { Alpha = 0 }); @@ -486,7 +486,7 @@ namespace osu.Game protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - RavenLogger.Dispose(); + SentryLogger.Dispose(); } protected override void LoadComplete() diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 256c52489b..5badd2546e 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -2,10 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.IO; using System.Net; -using System.Threading.Tasks; using osu.Framework.Logging; using Sentry; @@ -102,7 +100,7 @@ namespace osu.Game.Utils return; isDisposed = true; - sentry.Dispose(); + sentry?.Dispose(); sentry = null; } From 8a1276db3aa05c9188490f17e745156b28c1430e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 12 Nov 2019 22:16:48 +0800 Subject: [PATCH 325/503] Change to use instance API of sentry. --- osu.Game/Utils/SentryLogger.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 5badd2546e..7e879741d6 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -14,17 +14,21 @@ namespace osu.Game.Utils /// public class SentryLogger : IDisposable { - private IDisposable sentry; + private SentryClient sentry; + private Scope sentryScope; public SentryLogger(OsuGame game) { if (!game.IsDeployedBuild) return; - sentry = SentrySdk.Init(new SentryOptions + var options = new SentryOptions { Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), Release = game.Version - }); + }; + sentry = new SentryClient(options); + sentryScope = new Scope(options); + Exception lastException = null; Logger.NewEntry += entry => @@ -44,10 +48,10 @@ namespace osu.Game.Utils return; lastException = exception; - SentrySdk.CaptureEvent(new SentryEvent(exception) { Message = entry.Message }); + sentry.CaptureEvent(new SentryEvent(exception) { Message = entry.Message }, sentryScope); } else - SentrySdk.AddBreadcrumb(category: entry.Target.ToString(), type: "navigation", message: entry.Message); + sentryScope.AddBreadcrumb(DateTimeOffset.Now, entry.Message, entry.Target.ToString(), "navigation"); }; } @@ -102,6 +106,7 @@ namespace osu.Game.Utils isDisposed = true; sentry?.Dispose(); sentry = null; + sentryScope = null; } #endregion From dfd5c8807515bf6f5aec86610ff116e439b99d50 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:00:08 +0300 Subject: [PATCH 326/503] Typo fix --- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index cfb34e4adf..4c2a8652f3 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons if (loading.State.Value == Visibility.Visible) return; - // guaranteed by disabled state abvove. + // guaranteed by disabled state above. Debug.Assert(BeatmapSet.Value.OnlineBeatmapSetID != null); loading.Show(); From 3903e59f2fecca4c63de60897a66279763973936 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:01:13 +0300 Subject: [PATCH 327/503] Add null check for notification overlay --- osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 4c2a8652f3..163251d798 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons request.Failure += e => { - notifications.Post(new SimpleNotification + notifications?.Post(new SimpleNotification { Text = e.Message, Icon = FontAwesome.Solid.Times, From 27f721eec232a056e208d9ffcbbac1b8459db063 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:24:13 +0300 Subject: [PATCH 328/503] Use = instead of += for OnSelectionChanged Action --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index a7128ca157..09c388a3b0 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Add(new ModButton(new NoMod())); modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); } private void selectionChanged(Mod mod, bool selected) From 99ec84ed38643c504378ede2a10894cd0ae5f350 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:26:19 +0300 Subject: [PATCH 329/503] Update dependency --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 75c24cb710..bd639881e7 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -54,13 +54,9 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Add(new ModButton(new NoMod())); - ruleset.NewValue.CreateInstance().GetAllMods().ForEach(mod => - { - if (mod.Ranked) - modsContainer.Add(new ModButton(mod)); - }); + modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - modsContainer.ForEach(button => button.OnSelectionChanged += selectionChanged); + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); } private void selectionChanged(Mod mod, bool selected) @@ -77,11 +73,7 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnHover(HoverEvent e) { if (!SelectedMods.Any()) - modsContainer.ForEach(button => - { - if (!button.IsHovered) - button.Highlighted.Value = false; - }); + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); return base.OnHover(e); } From 5f609b48da9619025998a867882527b273e19905 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 00:29:28 +0300 Subject: [PATCH 330/503] Use local bindable for api.LocalUser --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 73253546bb..bc5daa39a0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -27,6 +27,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); private readonly Bindable scope = new Bindable(); + private readonly Bindable user = new Bindable(); private readonly Box background; private readonly ScoreTable scoreTable; @@ -155,6 +156,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void load(OsuColour colours) { background.Colour = colours.Gray2; + + user.BindTo(api.LocalUser); } protected override void LoadComplete() @@ -167,7 +170,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores modSelector.SelectedMods.ItemsRemoved += _ => getScores(); Beatmap.BindValueChanged(onBeatmapChanged); - api.LocalUser.BindValueChanged(onUserChanged, true); + user.BindValueChanged(onUserChanged, true); } private void onBeatmapChanged(ValueChangedEvent beatmap) From 2b8a105ec5cab7296966efab2cc87fcc2d01347e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 11:49:36 +0900 Subject: [PATCH 331/503] Fix osu!direct test fail Unsure how this occurred only now; may warrant further investigation. --- osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index c8c36789c4..5652b8d2bd 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -19,7 +19,7 @@ namespace osu.Game.Online.API.Requests public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset, BeatmapSearchCategory searchCategory = BeatmapSearchCategory.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending) { - this.query = System.Uri.EscapeDataString(query); + this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query); this.ruleset = ruleset; this.searchCategory = searchCategory; this.sortCriteria = sortCriteria; From 3c5008f94c20a968e6248dd0e5dcad74c649722d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 11:59:03 +0900 Subject: [PATCH 332/503] Add test --- .../Visual/Online/TestSceneFavouriteButton.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs new file mode 100644 index 0000000000..ae21245b59 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs @@ -0,0 +1,46 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Overlays.BeatmapSet.Buttons; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneFavouriteButton : OsuTestScene + { + private FavouriteButton favourite; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create button", () => Child = favourite = new FavouriteButton()); + } + + [Test] + public void TestLoggedOutIn() + { + AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 }); + AddStep("log out", () => API.Logout()); + checkEnabled(false); + AddStep("log in", () => API.Login("test", "test")); + checkEnabled(true); + } + + [Test] + public void TestBeatmapChange() + { + AddStep("log in", () => API.Login("test", "test")); + AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 }); + checkEnabled(true); + AddStep("set invalid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo()); + checkEnabled(true); + } + + private void checkEnabled(bool expected) + { + AddAssert("is " + (expected ? "enabled" : "disabled"), () => favourite.Enabled.Value == expected); + } + } +} From f18263aa70dc215af08e6b008c74a5be7a700d39 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 12:09:18 +0900 Subject: [PATCH 333/503] Add tests --- .../Visual/Online/TestSceneFavouriteButton.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs index ae21245b59..8e2ee4e28d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Overlays.BeatmapSet.Buttons; +using osuTK; namespace osu.Game.Tests.Visual.Online { @@ -15,7 +17,13 @@ namespace osu.Game.Tests.Visual.Online [SetUpSteps] public void SetUpSteps() { - AddStep("create button", () => Child = favourite = new FavouriteButton()); + AddStep("create button", () => Child = favourite = new FavouriteButton + { + RelativeSizeAxes = Axes.None, + Size = new Vector2(50), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); } [Test] @@ -35,7 +43,7 @@ namespace osu.Game.Tests.Visual.Online AddStep("set valid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo { OnlineBeatmapSetID = 88 }); checkEnabled(true); AddStep("set invalid beatmap", () => favourite.BeatmapSet.Value = new BeatmapSetInfo()); - checkEnabled(true); + checkEnabled(false); } private void checkEnabled(bool expected) From c751328665b1c5e1ff2b51f7aa359570518d6f8d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 12:13:33 +0900 Subject: [PATCH 334/503] Disable button when not logged in --- .../BeatmapSet/Buttons/FavouriteButton.cs | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 163251d798..af0987d183 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Notifications; +using osu.Game.Users; using osuTK; namespace osu.Game.Overlays.BeatmapSet.Buttons @@ -26,12 +27,23 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private PostBeatmapFavouriteRequest request; private DimmedLoadingLayer loading; - public string TooltipText => (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; + private readonly Bindable localUser = new Bindable(); + + public string TooltipText + { + get + { + if (!Enabled.Value) return string.Empty; + + return (favourited.Value ? "Unfavourite" : "Favourite") + " this beatmapset"; + } + } [BackgroundDependencyLoader(true)] private void load(IAPIProvider api, NotificationOverlay notifications) { SpriteIcon icon; + AddRange(new Drawable[] { icon = new SpriteIcon @@ -45,14 +57,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons loading = new DimmedLoadingLayer(0.8f, 0.5f), }); - favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; - - BeatmapSet.BindValueChanged(setInfo => - { - Enabled.Value = BeatmapSet.Value?.OnlineBeatmapSetID > 0; - favourited.Value = setInfo.NewValue?.OnlineInfo?.HasFavourited ?? false; - }, true); - Action = () => { if (loading.State.Value == Visibility.Visible) @@ -86,8 +90,22 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons api.Queue(request); }; + + favourited.ValueChanged += favourited => icon.Icon = favourited.NewValue ? FontAwesome.Solid.Heart : FontAwesome.Regular.Heart; + + localUser.BindTo(api.LocalUser); + localUser.BindValueChanged(_ => updateEnabled()); + + // must be run after setting the Action to ensure correct enabled state (setting an Action forces a button to be enabled). + BeatmapSet.BindValueChanged(setInfo => + { + updateEnabled(); + favourited.Value = setInfo.NewValue?.OnlineInfo?.HasFavourited ?? false; + }, true); } + private void updateEnabled() => Enabled.Value = !(localUser.Value is GuestUser) && BeatmapSet.Value?.OnlineBeatmapSetID > 0; + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); From 4c0bca5c070da01dfdd6800e93113e58c1bebed6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 12 Nov 2019 18:35:28 +0900 Subject: [PATCH 335/503] Add ability to delete control points via right-click option --- .../Components/PathControlPointPiece.cs | 10 +- .../Components/PathControlPointVisualiser.cs | 102 +++++++++++------- 2 files changed, 69 insertions(+), 43 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 155e814596..70b4842089 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osuTK; using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { @@ -129,6 +130,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnMouseDown(MouseDownEvent e) { + if (e.Button != MouseButton.Left) + return false; + if (RequestSelection != null) { RequestSelection.Invoke(Index); @@ -138,11 +142,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } - protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null; + protected override bool OnMouseUp(MouseUpEvent e) => e.Button == MouseButton.Left && RequestSelection != null; - protected override bool OnClick(ClickEvent e) => RequestSelection != null; + protected override bool OnClick(ClickEvent e) => e.Button == MouseButton.Left && RequestSelection != null; - protected override bool OnDragStart(DragStartEvent e) => true; + protected override bool OnDragStart(DragStartEvent e) => e.Button == MouseButton.Left; protected override bool OnDrag(DragEvent e) { diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 6962736157..f3fbb1f93f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -3,19 +3,23 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { - public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler + public class PathControlPointVisualiser : CompositeDrawable, IKeyBindingHandler, IHasContextMenu { public Action ControlPointsChanged; @@ -73,6 +77,19 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components return false; } + public bool OnPressed(PlatformAction action) + { + switch (action.ActionMethod) + { + case PlatformActionMethod.Delete: + return deleteSelected(); + } + + return false; + } + + public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + private void selectPiece(int index) { if (inputManager.CurrentState.Keyboard.ControlPressed) @@ -84,50 +101,55 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } } - public bool OnPressed(PlatformAction action) + private bool deleteSelected() { - switch (action.ActionMethod) + var newControlPoints = new List(); + + foreach (var piece in Pieces) { - case PlatformActionMethod.Delete: - var newControlPoints = new List(); - - foreach (var piece in Pieces) - { - if (!piece.IsSelected.Value) - newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); - } - - // Ensure that there are any points to be deleted - if (newControlPoints.Count == slider.Path.ControlPoints.Length) - return false; - - // If there are 0 remaining control points, treat the slider as being deleted - if (newControlPoints.Count == 0) - { - placementHandler?.Delete(slider); - return true; - } - - // Make control points relative - Vector2 first = newControlPoints[0]; - for (int i = 0; i < newControlPoints.Count; i++) - newControlPoints[i] = newControlPoints[i] - first; - - // The slider's position defines the position of the first control point, and all further control points are relative to that point - slider.Position = slider.Position + first; - - // Since pieces are re-used, they will not point to the deleted control points while remaining selected - foreach (var piece in Pieces) - piece.IsSelected.Value = false; - - ControlPointsChanged?.Invoke(newControlPoints.ToArray()); - - return true; + if (!piece.IsSelected.Value) + newControlPoints.Add(slider.Path.ControlPoints[piece.Index]); } - return false; + // Ensure that there are any points to be deleted + if (newControlPoints.Count == slider.Path.ControlPoints.Length) + return false; + + // If there are 0 remaining control points, treat the slider as being deleted + if (newControlPoints.Count == 0) + { + placementHandler?.Delete(slider); + return true; + } + + // Make control points relative + Vector2 first = newControlPoints[0]; + for (int i = 0; i < newControlPoints.Count; i++) + newControlPoints[i] = newControlPoints[i] - first; + + // The slider's position defines the position of the first control point, and all further control points are relative to that point + slider.Position = slider.Position + first; + + // Since pieces are re-used, they will not point to the deleted control points while remaining selected + foreach (var piece in Pieces) + piece.IsSelected.Value = false; + + ControlPointsChanged?.Invoke(newControlPoints.ToArray()); + return true; } - public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; + public MenuItem[] ContextMenuItems + { + get + { + if (!Pieces.Any(p => p.IsSelected.Value)) + return Array.Empty(); + + return new MenuItem[] + { + new OsuMenuItem("Delete control points", MenuItemType.Destructive, () => deleteSelected()) + }; + } + } } } From 9c52d239b44c06a2bdfeb9336e531fed5a1c9eb5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 16:56:48 +0900 Subject: [PATCH 336/503] Return null to allow passthrough --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index f3fbb1f93f..fd14e6dc23 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components get { if (!Pieces.Any(p => p.IsSelected.Value)) - return Array.Empty(); + return null; return new MenuItem[] { From 76ab0ecd3c0b5e27bf87750981bf30ed83cb2a79 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:21:48 +0900 Subject: [PATCH 337/503] Disallow deselections with right clicks --- .../Edit/Compose/Components/BlueprintContainer.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 2be4ca684a..195bc663f1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -313,14 +313,15 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Attempts to select any hovered blueprints. /// /// The input event that triggered this selection. - private void beginClickSelection(UIEvent e) + private void beginClickSelection(MouseButtonEvent e) { Debug.Assert(!clickSelectionBegan); - // If a select blueprint is already hovered, disallow changes in selection. - // Exception is made when holding control, as deselection should still be allowed. - if (!e.CurrentState.Keyboard.ControlPressed && - selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) + // Deselections are only allowed for control + left clicks + bool allowDeselection = e.ControlPressed && e.Button == MouseButton.Left; + + // Todo: This is probably incorrectly disallowing multiple selections on stacked objects + if (!allowDeselection && selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) return; foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveBlueprints) From c56503ee88c2969c90df8a5679774f870371782e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:28:18 +0900 Subject: [PATCH 338/503] Select single control point on right click --- .../Components/PathControlPointPiece.cs | 20 ++++++++++++------- .../Components/PathControlPointVisualiser.cs | 5 +++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 70b4842089..0ccf020300 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { public class PathControlPointPiece : BlueprintPiece { - public Action RequestSelection; + public Action RequestSelection; public Action ControlPointsChanged; public readonly BindableBool IsSelected = new BindableBool(); @@ -130,21 +130,27 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button != MouseButton.Left) + if (RequestSelection == null) return false; - if (RequestSelection != null) + switch (e.Button) { - RequestSelection.Invoke(Index); - return true; + case MouseButton.Left: + RequestSelection.Invoke(Index, e); + return true; + + case MouseButton.Right: + if (!IsSelected.Value) + RequestSelection.Invoke(Index, e); + return false; // Allow context menu to show } return false; } - protected override bool OnMouseUp(MouseUpEvent e) => e.Button == MouseButton.Left && RequestSelection != null; + protected override bool OnMouseUp(MouseUpEvent e) => RequestSelection != null; - protected override bool OnClick(ClickEvent e) => e.Button == MouseButton.Left && RequestSelection != null; + protected override bool OnClick(ClickEvent e) => RequestSelection != null; protected override bool OnDragStart(DragStartEvent e) => e.Button == MouseButton.Left; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index fd14e6dc23..97c756417c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -16,6 +16,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { @@ -90,9 +91,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components public bool OnReleased(PlatformAction action) => action.ActionMethod == PlatformActionMethod.Delete; - private void selectPiece(int index) + private void selectPiece(int index, MouseButtonEvent e) { - if (inputManager.CurrentState.Keyboard.ControlPressed) + if (e.Button == MouseButton.Left && inputManager.CurrentState.Keyboard.ControlPressed) Pieces[index].IsSelected.Toggle(); else { From d835def4abfc5d52d22d604e35f7f596e3c54a48 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:36:46 +0900 Subject: [PATCH 339/503] Add point count to the menu item text --- .../Sliders/Components/PathControlPointVisualiser.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 97c756417c..8d598f1ab3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Humanizer; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -143,12 +144,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { get { - if (!Pieces.Any(p => p.IsSelected.Value)) + int selectedPoints = Pieces.Count(p => p.IsSelected.Value); + + if (selectedPoints == 0) return null; return new MenuItem[] { - new OsuMenuItem("Delete control points", MenuItemType.Destructive, () => deleteSelected()) + new OsuMenuItem($"Delete {"control point".ToQuantity(selectedPoints)}", MenuItemType.Destructive, () => deleteSelected()) }; } } From 031b686ee96386d8d7bd5b00d4f5a336037ea874 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 13 Nov 2019 17:38:34 +0900 Subject: [PATCH 340/503] Only accept input while hovered --- .../Sliders/Components/PathControlPointVisualiser.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 8d598f1ab3..2bcce99c89 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -144,6 +144,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components { get { + if (!Pieces.Any(p => p.IsHovered)) + return null; + int selectedPoints = Pieces.Count(p => p.IsSelected.Value); if (selectedPoints == 0) From bca1be0bfa69c0c6c6e5bb1a756eb573f1e0d0e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 18:54:33 +0900 Subject: [PATCH 341/503] Add failing test --- .../SongSelect/TestScenePlaySongSelect.cs | 53 +++++++++++++------ osu.Game/Screens/Select/SongSelect.cs | 4 +- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 794d135b06..2d1a786bb9 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -57,23 +57,6 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(DrawableCarouselBeatmapSet), }; - private class TestSongSelect : PlaySongSelect - { - public Action StartRequested; - - public new Bindable Ruleset => base.Ruleset; - - public WorkingBeatmap CurrentBeatmap => Beatmap.Value; - public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; - public new BeatmapCarousel Carousel => base.Carousel; - - protected override bool OnStart() - { - StartRequested?.Invoke(); - return base.OnStart(); - } - } - private TestSongSelect songSelect; [BackgroundDependencyLoader] @@ -101,6 +84,17 @@ namespace osu.Game.Tests.Visual.SongSelect manager?.Delete(manager.GetAllUsableBeatmapSets()); }); + [Test] + public void TestSingleFilterOnEnter() + { + addRulesetImportStep(0); + addRulesetImportStep(0); + + createSongSelect(); + + AddAssert("filter count is 1", () => songSelect.FilterCount == 1); + } + [Test] public void TestAudioResuming() { @@ -357,5 +351,30 @@ namespace osu.Game.Tests.Visual.SongSelect base.Dispose(isDisposing); rulesets?.Dispose(); } + + private class TestSongSelect : PlaySongSelect + { + public Action StartRequested; + + public new Bindable Ruleset => base.Ruleset; + + public WorkingBeatmap CurrentBeatmap => Beatmap.Value; + public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; + public new BeatmapCarousel Carousel => base.Carousel; + + protected override bool OnStart() + { + StartRequested?.Invoke(); + return base.OnStart(); + } + + public int FilterCount; + + protected override void ApplyFilterToCarousel(FilterCriteria criteria) + { + FilterCount++; + base.ApplyFilterToCarousel(criteria); + } + } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..6810f77b93 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.X, Height = FilterControl.HEIGHT, - FilterChanged = c => Carousel.Filter(c), + FilterChanged = ApplyFilterToCarousel, Background = { Width = 2 }, }, } @@ -217,6 +217,8 @@ namespace osu.Game.Screens.Select BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); } + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { From 280c1a0eb42b16954c4ffd98257bfb7e92ec0440 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 18:00:45 +0900 Subject: [PATCH 342/503] Fix carousel filtering twice on startup due to unpopulated ruleset --- osu.Game/Screens/Select/SongSelect.cs | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6810f77b93..269fb1b683 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -46,40 +46,40 @@ namespace osu.Game.Screens.Select protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; - public readonly FilterControl FilterControl; + public FilterControl FilterControl; protected virtual bool ShowFooter => true; /// /// Can be null if is false. /// - protected readonly BeatmapOptionsOverlay BeatmapOptions; + protected BeatmapOptionsOverlay BeatmapOptions; /// /// Can be null if is false. /// - protected readonly Footer Footer; + protected Footer Footer; /// /// Contains any panel which is triggered by a footer button. /// Helps keep them located beneath the footer itself. /// - protected readonly Container FooterPanels; + protected Container FooterPanels; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); - protected readonly BeatmapCarousel Carousel; - private readonly BeatmapInfoWedge beatmapInfoWedge; + protected BeatmapCarousel Carousel; + private BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; private BeatmapManager beatmaps; - protected readonly ModSelectOverlay ModSelect; + protected ModSelectOverlay ModSelect; protected SampleChannel SampleConfirm; private SampleChannel sampleChangeDifficulty; private SampleChannel sampleChangeBeatmap; - protected readonly BeatmapDetailArea BeatmapDetails; + protected BeatmapDetailArea BeatmapDetails; private readonly Bindable decoupledRuleset = new Bindable(); @@ -90,8 +90,14 @@ namespace osu.Game.Screens.Select [Cached(Type = typeof(IBindable>))] private readonly Bindable> mods = new Bindable>(Array.Empty()); // Bound to the game's mods, but is not reset on exiting - protected SongSelect() + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + + [BackgroundDependencyLoader(true)] + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { + // transfer initial value so filter is in a good state (it uses our re-cached bindables). + transferRulesetValue(); + AddRangeInternal(new Drawable[] { new ParallaxContainer @@ -215,13 +221,7 @@ namespace osu.Game.Screens.Select } BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); - } - protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); - - [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) - { if (Footer != null) { Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect); @@ -640,7 +640,7 @@ namespace osu.Game.Screens.Select return; // manual binding to parent ruleset to allow for delayed load in the incoming direction. - rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + transferRulesetValue(); Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; @@ -652,6 +652,11 @@ namespace osu.Game.Screens.Select boundLocalBindables = true; } + private void transferRulesetValue() + { + rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + } + private void delete(BeatmapSetInfo beatmap) { if (beatmap == null || beatmap.ID <= 0) return; From 2cd156f3d4d005e445e7015de7af4171d716f013 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 19:09:03 +0900 Subject: [PATCH 343/503] Clean up carousel tests --- .../SongSelect/TestSceneBeatmapCarousel.cs | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index aa63bc1cf6..783bd8ae39 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; @@ -51,11 +52,6 @@ namespace osu.Game.Tests.Visual.SongSelect private void load(RulesetStore rulesets) { this.rulesets = rulesets; - - Add(carousel = new TestBeatmapCarousel - { - RelativeSizeAxes = Axes.Both, - }); } /// @@ -375,6 +371,8 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestSelectingFilteredRuleset() { + createCarousel(); + var testMixed = createTestBeatmapSet(set_count + 1); AddStep("add mixed ruleset beatmapset", () => { @@ -429,6 +427,8 @@ namespace osu.Game.Tests.Visual.SongSelect private void loadBeatmaps(List beatmapSets = null) { + createCarousel(); + if (beatmapSets == null) { beatmapSets = new List(); @@ -448,6 +448,17 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("Wait for load", () => changed); } + private void createCarousel(Container target = null) + { + AddStep($"Create carousel", () => + { + (target ?? this).Child = carousel = new TestBeatmapCarousel + { + RelativeSizeAxes = Axes.Both, + }; + }); + } + private void ensureRandomFetchSuccess() => AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet); From 110c155fa0daa22ebbb54e89f7e22ee4c07cee1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 19:42:05 +0900 Subject: [PATCH 344/503] Fix background loading twice when entering song select --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..b814253f25 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -66,7 +66,7 @@ namespace osu.Game.Screens.Select /// protected readonly Container FooterPanels; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); protected readonly BeatmapCarousel Carousel; private readonly BeatmapInfoWedge beatmapInfoWedge; From 2fe068174ab434634a29c124ff15910cd3906c2e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Nov 2019 19:42:33 +0900 Subject: [PATCH 345/503] Fix unnecessary string interpolation --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 783bd8ae39..14077c8e53 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -450,7 +450,7 @@ namespace osu.Game.Tests.Visual.SongSelect private void createCarousel(Container target = null) { - AddStep($"Create carousel", () => + AddStep("Create carousel", () => { (target ?? this).Child = carousel = new TestBeatmapCarousel { From 8f7fd9993d787c9be72fb088acd57e57a22c49d5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 13 Nov 2019 14:24:22 +0300 Subject: [PATCH 346/503] Fix preview track manager potentially not updating --- osu.Game/Audio/PreviewTrackManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 72b33c4073..ede84e18fb 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -24,6 +24,8 @@ namespace osu.Game.Audio private TrackManagerPreviewTrack current; + public override bool IsPresent => Scheduler.HasPendingTasks; + [BackgroundDependencyLoader] private void load(AudioManager audio) { From 6715b25ddd767c1a1d2b8891033b827765ce2ac7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 16:04:15 +0300 Subject: [PATCH 347/503] Apply suggestions --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 09c388a3b0..b400141abf 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -118,14 +118,14 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnClick(ClickEvent e) { - Selected.Value = !Selected.Value; - return base.OnClick(e); + Selected.Toggle(); + return true; } protected override bool OnHover(HoverEvent e) { updateState(); - return base.OnHover(e); + return false; } protected override void OnHoverLost(HoverLostEvent e) From 2dbee5da79e027b3903acb8fd280b6fa9aa85333 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 16:06:37 +0300 Subject: [PATCH 348/503] Update dependency --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index bd639881e7..b400141abf 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -53,7 +53,6 @@ namespace osu.Game.Overlays.BeatmapSet return; modsContainer.Add(new ModButton(new NoMod())); - modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); @@ -119,14 +118,14 @@ namespace osu.Game.Overlays.BeatmapSet protected override bool OnClick(ClickEvent e) { - Selected.Value = !Selected.Value; - return base.OnClick(e); + Selected.Toggle(); + return true; } protected override bool OnHover(HoverEvent e) { updateState(); - return base.OnHover(e); + return false; } protected override void OnHoverLost(HoverLostEvent e) From 47cbd516f392b8d824d4cd8782bce0ecb88e0e44 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 13 Nov 2019 16:11:13 +0300 Subject: [PATCH 349/503] Revert "Fix preview track manager potentially not updating" This reverts commit 8f7fd9993d787c9be72fb088acd57e57a22c49d5. --- osu.Game/Audio/PreviewTrackManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index ede84e18fb..72b33c4073 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -24,8 +24,6 @@ namespace osu.Game.Audio private TrackManagerPreviewTrack current; - public override bool IsPresent => Scheduler.HasPendingTasks; - [BackgroundDependencyLoader] private void load(AudioManager audio) { From 172e777416e551c2a9ea177fb4e6cf6838d2c71b Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 13 Nov 2019 16:16:06 +0300 Subject: [PATCH 350/503] Fix preview track manager permanently muting game tracks --- osu.Game/Audio/PreviewTrackManager.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 72b33c4073..201671849a 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -80,7 +80,6 @@ namespace osu.Game.Audio return; current.Stop(); - current = null; } /// From 4e90daf212d718d3a64611d1e153bcca292fce53 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 16:39:33 +0300 Subject: [PATCH 351/503] Implement NoScoresPlaceholder --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 50 +++++++++++++++++++ .../BeatmapSet/Scores/ScoresContainer.cs | 13 +++++ 2 files changed, 63 insertions(+) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs new file mode 100644 index 0000000000..b34e54b301 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -0,0 +1,50 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Framework.Bindables; +using osu.Game.Screens.Select.Leaderboards; +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class NoScoresPlaceholder : Container + { + public readonly Bindable Scope = new Bindable(); + + private readonly SpriteText text; + + public NoScoresPlaceholder() + { + AutoSizeAxes = Axes.Both; + Child = text = new SpriteText + { + Font = OsuFont.GetFont(), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Scope.BindValueChanged(scope => text.Text = getText(scope.NewValue), true); + } + + private string getText(BeatmapLeaderboardScope scope) + { + switch (scope) + { + default: + case BeatmapLeaderboardScope.Global: + return @"No scores yet. Maybe should try setting some?"; + + case BeatmapLeaderboardScope.Friend: + return @"None of your friends has set a score on this map yet!"; + + case BeatmapLeaderboardScope.Country: + return @"No one from your country has set a score on this map yet!"; + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index bc5daa39a0..62ec9ca609 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -35,6 +35,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly LoadingAnimation loadingAnimation; private readonly FillFlowContainer modFilter; private readonly LeaderboardModSelector modSelector; + private readonly NoScoresPlaceholder noScoresPlaceholder; [Resolved] private IAPIProvider api { get; set; } @@ -125,6 +126,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(0, spacing), Children = new Drawable[] { + noScoresPlaceholder = new NoScoresPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + Scope = { BindTarget = scope } + }, topScoresContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -204,6 +212,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = null; + noScoresPlaceholder.Hide(); + updateModFilterVisibility(); if (hasNoLeaderboard) @@ -215,6 +225,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { loadingAnimation.Hide(); Scores = scores; + + if (!scores.Scores.Any()) + noScoresPlaceholder.Show(); }; api.Queue(getScoresRequest); } From 3f6140db6dbe88f0412ca7e08c8206a1657c2b1f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:18:58 +0300 Subject: [PATCH 352/503] Improve loading animation --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 20 +++----- .../BeatmapSet/Scores/ScoresContainer.cs | 50 +++++++++++-------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index b34e54b301..4241ea3e54 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Framework.Bindables; using osu.Game.Screens.Select.Leaderboards; using osu.Framework.Graphics.Sprites; @@ -12,8 +11,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { public class NoScoresPlaceholder : Container { - public readonly Bindable Scope = new Bindable(); - private readonly SpriteText text; public NoScoresPlaceholder() @@ -25,25 +22,22 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; } - protected override void LoadComplete() - { - base.LoadComplete(); - Scope.BindValueChanged(scope => text.Text = getText(scope.NewValue), true); - } - - private string getText(BeatmapLeaderboardScope scope) + public void UpdateText(BeatmapLeaderboardScope scope) { switch (scope) { default: case BeatmapLeaderboardScope.Global: - return @"No scores yet. Maybe should try setting some?"; + text.Text = @"No scores yet. Maybe should try setting some?"; + return; case BeatmapLeaderboardScope.Friend: - return @"None of your friends has set a score on this map yet!"; + text.Text = @"None of your friends has set a score on this map yet!"; + return; case BeatmapLeaderboardScope.Country: - return @"No one from your country has set a score on this map yet!"; + text.Text = @"No one from your country has set a score on this map yet!"; + return; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 62ec9ca609..c74c4e3df0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -23,6 +23,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoresContainer : CompositeDrawable { private const int spacing = 15; + private const int duration = 200; public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly Box background; private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; - private readonly LoadingAnimation loadingAnimation; + private readonly DimmedLoadingLayer loading; private readonly FillFlowContainer modFilter; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; @@ -89,7 +90,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AutoSizeAxes = Axes.Y, Width = 0.95f, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, spacing), Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { @@ -116,8 +116,17 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { + noScoresPlaceholder = new NoScoresPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + AlwaysPresent = true, + Margin = new MarginPadding { Vertical = 10 } + }, new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -126,13 +135,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Spacing = new Vector2(0, spacing), Children = new Drawable[] { - noScoresPlaceholder = new NoScoresPlaceholder - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Alpha = 0, - Scope = { BindTarget = scope } - }, topScoresContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -147,12 +149,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } }, - loadingAnimation = new LoadingAnimation + new Container { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Alpha = 0, - }, + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 10, + Child = loading = new DimmedLoadingLayer(iconScale: 0.8f) + { + Alpha = 0, + }, + } } } } @@ -210,24 +216,28 @@ namespace osu.Game.Overlays.BeatmapSet.Scores getScoresRequest?.Cancel(); getScoresRequest = null; - Scores = null; - - noScoresPlaceholder.Hide(); + noScoresPlaceholder.FadeOut(duration, Easing.OutQuint); updateModFilterVisibility(); if (hasNoLeaderboard) + { + Scores = null; return; + } - loadingAnimation.Show(); + loading.Show(); getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => { - loadingAnimation.Hide(); + loading.Hide(); Scores = scores; if (!scores.Scores.Any()) - noScoresPlaceholder.Show(); + { + noScoresPlaceholder.UpdateText(scope.Value); + noScoresPlaceholder.FadeIn(duration, Easing.OutQuint); + } }; api.Queue(getScoresRequest); } From 8005ee73af2f77b9cb12f00cdeb07e40b05c9e77 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:23:46 +0300 Subject: [PATCH 353/503] Trim whitespace --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index c74c4e3df0..bc950a0c0c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Vertical = spacing }, + Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { noScoresPlaceholder = new NoScoresPlaceholder From f90a9db2b226bfc929430333898c7dc1e5195a7c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 22:29:44 +0800 Subject: [PATCH 354/503] Add BannedApiAnalyzer --- CodeAnalysis/BannedSymbols.txt | 4 ++++ Directory.Build.props | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 CodeAnalysis/BannedSymbols.txt diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt new file mode 100644 index 0000000000..9fb86485d2 --- /dev/null +++ b/CodeAnalysis/BannedSymbols.txt @@ -0,0 +1,4 @@ +M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. +M:System.Object.Equals(System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. +M:System.ValueType.Equals(System.Object)~System.Boolean;Don't use object.Equals(Fallbacks to ValueType). Use IEquatable or EqualityComparer.Default instead. +T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. diff --git a/Directory.Build.props b/Directory.Build.props index b4baa2833e..9735c78913 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -14,6 +14,10 @@ + + + + From d1853ea55bfc0ddd04c7785ebb246a9865877389 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:29:50 +0300 Subject: [PATCH 355/503] Fix incorrect formatting for switch/case --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index 4241ea3e54..aefff5d567 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -28,16 +28,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { default: case BeatmapLeaderboardScope.Global: - text.Text = @"No scores yet. Maybe should try setting some?"; - return; + text.Text = @"No scores yet. Maybe should try setting some?"; + return; case BeatmapLeaderboardScope.Friend: - text.Text = @"None of your friends has set a score on this map yet!"; - return; + text.Text = @"None of your friends has set a score on this map yet!"; + return; case BeatmapLeaderboardScope.Country: - text.Text = @"No one from your country has set a score on this map yet!"; - return; + text.Text = @"No one from your country has set a score on this map yet!"; + return; } } } From 87d40cf8d019756114e91708e082fc34feb30878 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 22:35:50 +0800 Subject: [PATCH 356/503] Resolve equals usages. --- osu.Game/Online/Leaderboards/Leaderboard.cs | 2 +- osu.Game/Overlays/DirectOverlay.cs | 2 +- osu.Game/Overlays/SocialOverlay.cs | 2 +- osu.Game/Screens/Menu/MenuSideFlashes.cs | 2 +- osu.Game/Screens/Play/KeyCounterAction.cs | 6 ++++-- osu.Game/Screens/Select/SongSelect.cs | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index d214743b30..94c50185da 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -101,7 +101,7 @@ namespace osu.Game.Online.Leaderboards get => scope; set { - if (value.Equals(scope)) + if (EqualityComparer.Default.Equals(value, scope)) return; scope = value; diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 7dcf76e41f..494bfcb2cc 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays get => beatmapSets; set { - if (beatmapSets?.Equals(value) ?? false) return; + if (beatmapSets?.SequenceEqual(value) ?? false) return; beatmapSets = value?.ToList(); diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 6f468bbeb7..5987a5f138 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays get => users; set { - if (users?.Equals(value) ?? false) + if (users?.SequenceEqual(value) ?? false) return; users = value?.ToList(); diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 55a6a33e89..3a88cda4ef 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Menu private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes) { - d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time) + d.FadeTo(Math.Max(0, ((ReferenceEquals(d, leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time) .Then() .FadeOut(beatLength, Easing.In); } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index f60ad7aa5a..33d675358c 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; + namespace osu.Game.Screens.Play { public class KeyCounterAction : KeyCounter @@ -16,7 +18,7 @@ namespace osu.Game.Screens.Play public bool OnPressed(T action, bool forwards) { - if (!action.Equals(Action)) + if (!EqualityComparer.Default.Equals(action, Action)) return false; IsLit = true; @@ -27,7 +29,7 @@ namespace osu.Game.Screens.Play public bool OnReleased(T action, bool forwards) { - if (!action.Equals(Action)) + if (!EqualityComparer.Default.Equals(action, Action)) return false; IsLit = false; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..fb057fcf18 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -405,7 +405,7 @@ namespace osu.Game.Screens.Select // 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 (!Equals(beatmap, Beatmap.Value.BeatmapInfo)) + if (!beatmap.Equals(Beatmap.Value.BeatmapInfo)) { Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\""); From 633c497602db249d5113eb2e35a725f1a53fff3d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 13 Nov 2019 17:36:08 +0300 Subject: [PATCH 357/503] Hide content if beatmap has no leaderboard --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index bc950a0c0c..32e5314fba 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -37,6 +37,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly FillFlowContainer modFilter; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; + private readonly FillFlowContainer content; [Resolved] private IAPIProvider api { get; set; } @@ -82,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { RelativeSizeAxes = Axes.Both, }, - new FillFlowContainer + content = new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -223,9 +224,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (hasNoLeaderboard) { Scores = null; + content.Hide(); return; } + content.Show(); loading.Show(); getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => From 2d3fadc1a8d21ed1895db93542bec2b597a50645 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 14 Nov 2019 00:38:37 +0300 Subject: [PATCH 358/503] Don't update mod filter visibility on every beatmap change --- .../Overlays/BeatmapSet/Scores/ScoresContainer.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 32e5314fba..3e3f823368 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -204,12 +204,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - updateModFilterVisibility(); - } - - private void updateModFilterVisibility() - { - modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter && !hasNoLeaderboard ? 1 : 0); + modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); } private void getScores() @@ -219,9 +214,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores noScoresPlaceholder.FadeOut(duration, Easing.OutQuint); - updateModFilterVisibility(); - - if (hasNoLeaderboard) + if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) { Scores = null; content.Hide(); @@ -244,7 +237,5 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; api.Queue(getScoresRequest); } - - private bool hasNoLeaderboard => Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending; } } From a580b9079a7995718fb7a1083882a9288a339ea7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 08:28:41 +0900 Subject: [PATCH 359/503] Reword comment --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 269fb1b683..1f16b134c4 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -95,7 +95,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { - // transfer initial value so filter is in a good state (it uses our re-cached bindables). + // initial value transfer is requried for FilterControl (it uses our re-cached bindables in its asynd loac for the initial filter). transferRulesetValue(); AddRangeInternal(new Drawable[] From d8a5750e5d1f3462bf7edc4d7d48ba5f35341fd1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 08:38:01 +0900 Subject: [PATCH 360/503] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 1f16b134c4..b595003f0a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -95,7 +95,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { - // initial value transfer is requried for FilterControl (it uses our re-cached bindables in its asynd loac for the initial filter). + // initial value transfer is required for FilterControl (it uses our re-cached bindables in its async load for the initial filter). transferRulesetValue(); AddRangeInternal(new Drawable[] From 1109d201c3b41c5fb134b075965c064bc78f0d6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 13:28:13 +0900 Subject: [PATCH 361/503] Add failing test --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 794d135b06..d45b1bdba2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -242,6 +242,22 @@ namespace osu.Game.Tests.Visual.SongSelect void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex++; } + [Test] + public void TestModsRetainedBetweenSongSelect() + { + AddAssert("empty mods", () => !Mods.Value.Any()); + + createSongSelect(); + + addRulesetImportStep(0); + + changeMods(new OsuModHardRock()); + + createSongSelect(); + + AddAssert("mods retained", () => Mods.Value.Any()); + } + [Test] public void TestStartAfterUnMatchingFilterDoesNotStart() { From c15f909d8383ccae1a670a6b0e673cb576b4bfcf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 13:29:06 +0900 Subject: [PATCH 362/503] Remove local bindable at song select, along with misplaced reset logic --- osu.Game/Screens/Select/SongSelect.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 375b994169..00f2cc7e5b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -30,7 +30,6 @@ using osuTK; using osuTK.Graphics; using osuTK.Input; using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; @@ -86,10 +85,6 @@ namespace osu.Game.Screens.Select [Resolved(canBeNull: true)] private MusicController music { get; set; } - [Cached] - [Cached(Type = typeof(IBindable>))] - private readonly Bindable> mods = new Bindable>(Array.Empty()); // Bound to the game's mods, but is not reset on exiting - protected SongSelect() { AddRangeInternal(new Drawable[] @@ -222,7 +217,7 @@ namespace osu.Game.Screens.Select { if (Footer != null) { - Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect); + Footer.AddButton(new FooterButtonMods { Current = Mods }, ModSelect); Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); @@ -262,13 +257,6 @@ namespace osu.Game.Screens.Select } } - protected override void LoadComplete() - { - base.LoadComplete(); - - mods.BindTo(Mods); - } - private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -390,7 +378,7 @@ namespace osu.Game.Screens.Select { Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); - mods.Value = Array.Empty(); + Mods.Value = Array.Empty(); decoupledRuleset.Value = ruleset; // force a filter before attempting to change the beatmap. @@ -538,9 +526,6 @@ namespace osu.Game.Screens.Select if (Beatmap.Value.Track != null) Beatmap.Value.Track.Looping = false; - mods.UnbindAll(); - Mods.Value = Array.Empty(); - return false; } From bf567e6df56fad7ef637a03b274cad2a1afa10fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 14:19:55 +0900 Subject: [PATCH 363/503] Make settings textboxes commit on focus lost --- osu.Game/Overlays/Settings/SettingsTextBox.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index 0f257c2bfb..5e700a1d6b 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.cs @@ -12,6 +12,7 @@ namespace osu.Game.Overlays.Settings { Margin = new MarginPadding { Top = 5 }, RelativeSizeAxes = Axes.X, + CommitOnFocusLost = true, }; } } From 677717875e924aa1450954346ad04091489c2b0b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 14 Nov 2019 17:35:02 +0800 Subject: [PATCH 364/503] Change a case to EqualityComparer.Default to handle null properly. --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 8c92f57b68..12ae395cea 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -405,7 +405,7 @@ namespace osu.Game.Screens.Select // 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)) + if (!EqualityComparer.Default.Equals(beatmap, Beatmap.Value.BeatmapInfo)) { Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\""); From 81033e1fdf4fccf8e5f5947d79c4660477ed3822 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 18:52:07 +0900 Subject: [PATCH 365/503] Add extra logging --- osu.Game/Beatmaps/BeatmapManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6e485f642a..7a616ed8f2 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -129,9 +129,12 @@ namespace osu.Game.Beatmaps { var beatmapIds = beatmapSet.Beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList(); + LogForModel(beatmapSet, "Validating online IDs..."); + // ensure all IDs are unique if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1)) { + LogForModel(beatmapSet, "Found non-unique IDs, resetting..."); resetIds(); return; } @@ -144,8 +147,12 @@ namespace osu.Game.Beatmaps // reset the import ids (to force a re-fetch) *unless* they match the candidate CheckForExisting set. // we can ignore the case where the new ids are contained by the CheckForExisting set as it will either be used (import skipped) or deleted. var existing = CheckForExisting(beatmapSet); + if (existing == null || existingBeatmaps.Any(b => !existing.Beatmaps.Contains(b))) + { + LogForModel(beatmapSet, "Found existing import with IDs already, resetting..."); resetIds(); + } } void resetIds() => beatmapSet.Beatmaps.ForEach(b => b.OnlineBeatmapID = null); From 1bc0eae2a6fa08edf390f47a4f40cc80f71af3f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 18:53:22 +0900 Subject: [PATCH 366/503] Fix beatmap online retrieval response running incorrectly scheduled --- osu.Game/Beatmaps/BeatmapManager.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7a616ed8f2..80d41c5267 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -387,22 +387,21 @@ namespace osu.Game.Beatmaps var req = new GetBeatmapRequest(beatmap); - req.Success += res => - { - LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); - - beatmap.Status = res.Status; - beatmap.BeatmapSet.Status = res.BeatmapSet.Status; - beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; - beatmap.OnlineBeatmapID = res.OnlineBeatmapID; - }; - req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); }; try { // intentionally blocking to limit web request concurrency req.Perform(api); + + var res = req.Result; + + beatmap.Status = res.Status; + beatmap.BeatmapSet.Status = res.BeatmapSet.Status; + beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; + beatmap.OnlineBeatmapID = res.OnlineBeatmapID; + + LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); } catch (Exception e) { From fbf81207d4a634bb4213d9794cdd72ed491c1ab5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 18:54:03 +0900 Subject: [PATCH 367/503] Don't assign server-fetched online id if it was assigned elsewhere --- osu.Game/Beatmaps/BeatmapManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 80d41c5267..7057bd46bb 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -399,7 +399,11 @@ namespace osu.Game.Beatmaps beatmap.Status = res.Status; beatmap.BeatmapSet.Status = res.BeatmapSet.Status; beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; - beatmap.OnlineBeatmapID = res.OnlineBeatmapID; + + // note that this check only needs to be here if two identical hashed beatmaps exist int he same import. + // probably fine to leave it for safety. + if (set.Beatmaps.All(b => b.OnlineBeatmapID != res.OnlineBeatmapID)) + beatmap.OnlineBeatmapID = res.OnlineBeatmapID; LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); } From 9f62ec869a6b8f6fed16e8cc6266df12e27e8e94 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 19:15:15 +0900 Subject: [PATCH 368/503] Add failing test --- .../Beatmaps/IO/ImportBeatmapTest.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 4e81954f50..4766411cbd 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -411,6 +411,48 @@ namespace osu.Game.Tests.Beatmaps.IO } } + [Test] + public async Task TestImportWithDuplicateHashes() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportNestedStructure))) + { + try + { + var osu = loadOsu(host); + + var temp = TestResources.GetTestBeatmapForImport(); + + string extractedFolder = $"{temp}_extracted"; + Directory.CreateDirectory(extractedFolder); + + try + { + using (var zip = ZipArchive.Open(temp)) + zip.WriteToDirectory(extractedFolder); + + using (var zip = ZipArchive.Create()) + { + zip.AddAllFromDirectory(extractedFolder); + zip.AddEntry("duplicate.osu", Directory.GetFiles(extractedFolder, "*.osu").First()); + zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); + } + + await osu.Dependencies.Get().Import(temp); + + ensureLoaded(osu); + } + finally + { + Directory.Delete(extractedFolder, true); + } + } + finally + { + host.Exit(); + } + } + } + [Test] public async Task TestImportNestedStructure() { From 12243aaa9aa32933e1c6ca3ff3a82629212a0851 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Nov 2019 19:02:11 +0900 Subject: [PATCH 369/503] Dedupe .osu files with same hash in same set --- osu.Game/Beatmaps/BeatmapManager.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6e485f642a..524e4c7bf2 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -296,8 +296,13 @@ namespace osu.Game.Beatmaps var decoder = Decoder.GetDecoder(sr); IBeatmap beatmap = decoder.Decode(sr); + string hash = ms.ComputeSHA2Hash(); + + if (beatmapInfos.Any(b => b.Hash == hash)) + continue; + beatmap.BeatmapInfo.Path = file.Filename; - beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); + beatmap.BeatmapInfo.Hash = hash; beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash(); var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); From 4e79bbad6b030f712242e3d2221c39e072e1be6a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 14 Nov 2019 14:19:42 +0300 Subject: [PATCH 370/503] Add inline comment --- osu.Game/Audio/PreviewTrackManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 201671849a..56d507ef0e 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -80,6 +80,8 @@ namespace osu.Game.Audio return; current.Stop(); + // CurrentTrack must not change until the scheduled stopped event has been invoked. + // To ensure that this doesn't early-return on (CurrentTrack != track) check. } /// From d2ce0878bc5c99629ae29a9f6e833af21e869289 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 14 Nov 2019 14:20:29 +0300 Subject: [PATCH 371/503] Change 'current' accessibility to protected --- osu.Game/Audio/PreviewTrackManager.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 56d507ef0e..d85df42d2b 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -22,7 +22,7 @@ namespace osu.Game.Audio private AudioManager audio; private PreviewTrackStore trackStore; - private TrackManagerPreviewTrack current; + protected TrackManagerPreviewTrack CurrentTrack; [BackgroundDependencyLoader] private void load(AudioManager audio) @@ -48,17 +48,17 @@ namespace osu.Game.Audio track.Started += () => Schedule(() => { - current?.Stop(); - current = track; + CurrentTrack?.Stop(); + CurrentTrack = track; audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable); }); track.Stopped += () => Schedule(() => { - if (current != track) + if (CurrentTrack != track) return; - current = null; + CurrentTrack = null; audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); }); @@ -76,10 +76,10 @@ namespace osu.Game.Audio /// The which may be the owner of the . public void StopAnyPlaying(IPreviewTrackOwner source) { - if (current == null || current.Owner != source) + if (CurrentTrack == null || CurrentTrack.Owner != source) return; - current.Stop(); + CurrentTrack.Stop(); // CurrentTrack must not change until the scheduled stopped event has been invoked. // To ensure that this doesn't early-return on (CurrentTrack != track) check. } From 08e9813192f52d68cc0694f2c92e6661b0a9d742 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 14 Nov 2019 14:23:52 +0300 Subject: [PATCH 372/503] Add test ensuring correct changing behaviour --- .../TestScenePreviewTrackManager.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 3a9fce90cd..0c5b485728 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Components { public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner { - private readonly PreviewTrackManager trackManager = new TestPreviewTrackManager(); + private readonly TestPreviewTrackManager trackManager = new TestPreviewTrackManager(); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { @@ -108,6 +108,26 @@ namespace osu.Game.Tests.Visual.Components AddAssert("track stopped", () => !track.IsRunning); } + /// + /// Ensures that changes correctly. + /// + [Test] + public void TestCurrentTrackChanges() + { + PreviewTrack track = null; + TestTrackOwner owner = null; + + AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); + AddUntilStep("wait loaded", () => track.IsLoaded); + AddStep("start track", () => track.Start()); + AddAssert("current is track", () => trackManager.CurrentTrack == track); + AddStep("pause manager updates", () => trackManager.AllowUpdate = false); + AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner)); + AddAssert("current not changed", () => trackManager.CurrentTrack == track); + AddStep("resume manager updates", () => trackManager.AllowUpdate = true); + AddAssert("current is null", () => trackManager.CurrentTrack == null); + } + private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); private TestPreviewTrack getOwnedTrack() @@ -144,8 +164,20 @@ namespace osu.Game.Tests.Visual.Components public class TestPreviewTrackManager : PreviewTrackManager { + public bool AllowUpdate = true; + + public new PreviewTrack CurrentTrack => base.CurrentTrack; + protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore); + public override bool UpdateSubTree() + { + if (!AllowUpdate) + return true; + + return base.UpdateSubTree(); + } + public class TestPreviewTrack : TrackManagerPreviewTrack { private readonly ITrackStore trackManager; From 0998afdbdb68eb3b5861b31a6370572e28d264e2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 14 Nov 2019 19:23:19 +0800 Subject: [PATCH 373/503] Use ReferenceEquals instead of SequenceEqual. --- osu.Game/Overlays/DirectOverlay.cs | 2 +- osu.Game/Overlays/SocialOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 494bfcb2cc..aedbd1b08b 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays get => beatmapSets; set { - if (beatmapSets?.SequenceEqual(value) ?? false) return; + if (ReferenceEquals(beatmapSets, value)) return; beatmapSets = value?.ToList(); diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 5987a5f138..da05cc7f9b 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays get => users; set { - if (users?.SequenceEqual(value) ?? false) + if (ReferenceEquals(users, value)) return; users = value?.ToList(); From 8ae869b788c70474726438935bfa78e59d65fd66 Mon Sep 17 00:00:00 2001 From: Gerard Dalmau Date: Thu, 14 Nov 2019 21:14:59 +0100 Subject: [PATCH 374/503] ADD version badge --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a078265d6c..65fb97eb5d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,10 @@ # osu! -[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy) +[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) +[![GitHub release](https://img.shields.io/github/release/ppy/osu.svg)]() +[![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) +[![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy) Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename "osu!lazer". Pew pew. From 8f02e57d1f799aadcbcfdc747e15a1be2a4e1f1a Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Fri, 15 Nov 2019 01:08:40 +0300 Subject: [PATCH 375/503] Add test ensuring correct muting behaviour --- .../TestScenePreviewTrackManager.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 0c5b485728..5dac40104a 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Containers; using osu.Game.Audio; @@ -15,6 +16,8 @@ namespace osu.Game.Tests.Visual.Components { private readonly TestPreviewTrackManager trackManager = new TestPreviewTrackManager(); + private AudioManager audio; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -24,8 +27,10 @@ namespace osu.Game.Tests.Visual.Components } [BackgroundDependencyLoader] - private void load() + private void load(AudioManager audio) { + this.audio = audio; + Add(trackManager); } @@ -128,6 +133,29 @@ namespace osu.Game.Tests.Visual.Components AddAssert("current is null", () => trackManager.CurrentTrack == null); } + /// + /// Ensures that mutes game-wide audio tracks correctly. + /// + [TestCase(false)] + [TestCase(true)] + public void TestEnsureMutingCorrectly(bool stopAnyPlaying) + { + PreviewTrack track = null; + TestTrackOwner owner = null; + + AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); + AddUntilStep("wait loaded", () => track.IsLoaded); + AddStep("start track", () => track.Start()); + AddAssert("game is muted", () => audio.Tracks.AggregateVolume.Value == 0); + + if (stopAnyPlaying) + AddStep("stop any playing", () => trackManager.StopAnyPlaying(owner)); + else + AddStep("stop track", () => track.Stop()); + + AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0); + } + private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); private TestPreviewTrack getOwnedTrack() From 956fb9912d71168e8c579d698150a49deeefa78e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 08:23:56 +0900 Subject: [PATCH 376/503] Hook up multiplayer search filter --- .../Screens/Multi/Lounge/Components/RoomsContainer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 99a6de0064..f5f43a52b1 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -24,6 +24,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly FillFlowContainer roomFlow; public IReadOnlyList Rooms => roomFlow; + [Resolved] + private Bindable filter { get; set; } + [Resolved] private Bindable currentRoom { get; set; } @@ -57,6 +60,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components addRooms(rooms); } + protected override void LoadComplete() + { + filter.BindValueChanged(f => Filter(f.NewValue), true); + } + private FilterCriteria currentFilter; public void Filter(FilterCriteria criteria) From 6d5484646297c146f5202cae667552416d5edac1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 10:18:47 +0900 Subject: [PATCH 377/503] Null online id on lookup failure --- osu.Game/Beatmaps/BeatmapManager.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 7057bd46bb..77fcf44a9b 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -387,7 +387,7 @@ namespace osu.Game.Beatmaps var req = new GetBeatmapRequest(beatmap); - req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); }; + req.Failure += fail; try { @@ -399,16 +399,18 @@ namespace osu.Game.Beatmaps beatmap.Status = res.Status; beatmap.BeatmapSet.Status = res.BeatmapSet.Status; beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; - - // note that this check only needs to be here if two identical hashed beatmaps exist int he same import. - // probably fine to leave it for safety. - if (set.Beatmaps.All(b => b.OnlineBeatmapID != res.OnlineBeatmapID)) - beatmap.OnlineBeatmapID = res.OnlineBeatmapID; + beatmap.OnlineBeatmapID = res.OnlineBeatmapID; LogForModel(set, $"Online retrieval mapped {beatmap} to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}."); } catch (Exception e) { + fail(e); + } + + void fail(Exception e) + { + beatmap.OnlineBeatmapID = null; LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); } } From f0b7b2e1c42d9a1fa5e0b257f5eac057922173c6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 11:07:16 +0900 Subject: [PATCH 378/503] Fix broken test case --- osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index f5f43a52b1..4e9f645732 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly FillFlowContainer roomFlow; public IReadOnlyList Rooms => roomFlow; - [Resolved] + [Resolved(CanBeNull = true)] private Bindable filter { get; set; } [Resolved] @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { - filter.BindValueChanged(f => Filter(f.NewValue), true); + filter?.BindValueChanged(f => Filter(f.NewValue), true); } private FilterCriteria currentFilter; From 22c3be2c6f2ea039d11007778113464adc8884ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 11:18:19 +0900 Subject: [PATCH 379/503] Clear count variables on carousel creation --- osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 14077c8e53..7ec76cdd2f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -452,6 +452,9 @@ namespace osu.Game.Tests.Visual.SongSelect { AddStep("Create carousel", () => { + selectedSets.Clear(); + eagerSelectedIDs.Clear(); + (target ?? this).Child = carousel = new TestBeatmapCarousel { RelativeSizeAxes = Axes.Both, From e81dfcad4c62faf6844c1d20340c4026ed53b6f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 11:46:32 +0900 Subject: [PATCH 380/503] Fix remaining cases of pollution --- .../SongSelect/TestSceneBeatmapCarousel.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 7ec76cdd2f..132b104afb 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -334,10 +334,19 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestHiding() { - BeatmapSetInfo hidingSet = createTestBeatmapSet(1); - hidingSet.Beatmaps[1].Hidden = true; + BeatmapSetInfo hidingSet = null; + List hiddenList = new List(); - loadBeatmaps(new List { hidingSet }); + AddStep("create hidden set", () => + { + hidingSet = createTestBeatmapSet(1); + hidingSet.Beatmaps[1].Hidden = true; + + hiddenList.Clear(); + hiddenList.Add(hidingSet); + }); + + loadBeatmaps(hiddenList); setSelected(1, 1); @@ -371,11 +380,14 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestSelectingFilteredRuleset() { + BeatmapSetInfo testMixed = null; + createCarousel(); - var testMixed = createTestBeatmapSet(set_count + 1); AddStep("add mixed ruleset beatmapset", () => { + testMixed = createTestBeatmapSet(set_count + 1); + for (int i = 0; i <= 2; i++) { testMixed.Beatmaps[i].Ruleset = rulesets.AvailableRulesets.ElementAt(i); From 6d06b444bae4f8ccfbb7b00cd0ee16390e47d458 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 13:47:14 +0900 Subject: [PATCH 381/503] Allow screen to specify whether to apply audio rate adjustments from mods --- osu.Game/OsuGame.cs | 2 ++ osu.Game/Overlays/MusicController.cs | 27 ++++++++++++++++++++++++--- osu.Game/Screens/IOsuScreen.cs | 5 +++++ osu.Game/Screens/Menu/MainMenu.cs | 2 ++ osu.Game/Screens/OsuScreen.cs | 2 ++ osu.Game/Screens/StartupScreen.cs | 2 ++ 6 files changed, 37 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 328c964976..20e343ac0a 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -925,6 +925,8 @@ namespace osu.Game { OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode; + musicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments; + if (newOsuScreen.HideOverlaysOnEnter) CloseAllOverlays(); else diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 9ec0364420..0db05ae6f7 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays private OnScreenDisplay onScreenDisplay { get; set; } [BackgroundDependencyLoader] - private void load() + private void load(OsuGame game) { beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; @@ -233,6 +233,24 @@ namespace osu.Game.Overlays queuedDirection = null; } + private bool allowRateAdjustments; + + /// + /// Whether mod rate adjustments are allowed to be applied. + /// + public bool AllowRateAdjustments + { + get => allowRateAdjustments; + set + { + if (allowRateAdjustments == value) + return; + + allowRateAdjustments = value; + ResetTrackAdjustments(); + } + } + public void ResetTrackAdjustments() { var track = current?.Track; @@ -241,8 +259,11 @@ namespace osu.Game.Overlays track.ResetSpeedAdjustments(); - foreach (var mod in mods.Value.OfType()) - mod.ApplyToClock(track); + if (allowRateAdjustments) + { + foreach (var mod in mods.Value.OfType()) + mod.ApplyToClock(track); + } } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 9fc907c2a4..22fe0ad816 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -51,5 +51,10 @@ namespace osu.Game.Screens Bindable Beatmap { get; } Bindable Ruleset { get; } + + /// + /// Whether mod rate adjustments are allowed to be applied. + /// + bool AllowRateAdjustments { get; } } } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c195ed6cb6..08338845e6 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.Menu public override bool AllowExternalScreenChange => true; + public override bool AllowRateAdjustments => false; + private Screen songSelect; private MenuSideFlashes sideFlashes; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 328631ff9c..94165fe4b7 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -91,6 +91,8 @@ namespace osu.Game.Screens public Bindable Ruleset { get; private set; } + public virtual bool AllowRateAdjustments => true; + public Bindable> Mods { get; private set; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index 797f185a37..c3e36c8e9d 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -16,6 +16,8 @@ namespace osu.Game.Screens public override bool CursorVisible => false; + public override bool AllowRateAdjustments => false; + public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; } } From 2c3109980ab69e08eb0a25b1e86a57b5df5dcdb2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 13:51:39 +0900 Subject: [PATCH 382/503] Fix broken merge --- osu.Game/Screens/Select/SongSelect.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 862f8f9aa8..e3cd98454a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -30,6 +30,7 @@ using osuTK; using osuTK.Graphics; using osuTK.Input; using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; From c7d0b88854a66cfacab8ac91c2e885088a606ca3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 14:15:09 +0900 Subject: [PATCH 383/503] Update test scene --- .../Visual/Gameplay/{TestCaseLeadIn.cs => TestSceneLeadIn.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/Gameplay/{TestCaseLeadIn.cs => TestSceneLeadIn.cs} (97%) diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs similarity index 97% rename from osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs rename to osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 41cd80ed8c..3522c2265a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestCaseLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -15,7 +15,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { - public class TestCaseLeadIn : RateAdjustedBeatmapTestScene + public class TestSceneLeadIn : RateAdjustedBeatmapTestScene { private Ruleset ruleset; From dbfec215e7acdf716f4c11c42f3ab8bd6c7711d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 14:47:28 +0900 Subject: [PATCH 384/503] Improve test quality --- .../Visual/Gameplay/TestSceneLeadIn.cs | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 3522c2265a..addf7c3b28 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -1,61 +1,55 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; -using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { public class TestSceneLeadIn : RateAdjustedBeatmapTestScene { - private Ruleset ruleset; - private LeadInPlayer player; - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - Add(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Depth = int.MaxValue - }); - - ruleset = rulesets.AvailableRulesets.First().CreateInstance(); - } - [Test] public void TestShortLeadIn() { - AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 1000 } })); - AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == 0); + loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = { AudioLeadIn = 1000 } + }); + + AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1); + + AddAssert("correct lead-in", () => player.FirstFrameClockTime == 0); } [Test] public void TestLongLeadIn() { - AddStep("create player", () => loadPlayerWithBeatmap(new TestBeatmap(ruleset.RulesetInfo) { BeatmapInfo = { AudioLeadIn = 10000 } })); - AddUntilStep("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); + loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) + { + BeatmapInfo = { AudioLeadIn = 10000 } + }); + + AddAssert("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); } private void loadPlayerWithBeatmap(IBeatmap beatmap) { - Beatmap.Value = new TestWorkingBeatmap(beatmap); + AddStep("create player", () => + { + Beatmap.Value = CreateWorkingBeatmap(beatmap); + LoadScreen(player = new LeadInPlayer()); + }); - LoadScreen(player = new LeadInPlayer()); + AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1); } - private class LeadInPlayer : Player + private class LeadInPlayer : TestPlayer { public LeadInPlayer() : base(false, false) From 813aebca1df0a46c4008b6cadcf5d536764cf086 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 14:51:01 +0900 Subject: [PATCH 385/503] Remove unintentional dependency --- osu.Game/Overlays/MusicController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 0db05ae6f7..5e0a67c2f7 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays private OnScreenDisplay onScreenDisplay { get; set; } [BackgroundDependencyLoader] - private void load(OsuGame game) + private void load() { beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; From 1b4bcb81c895da963e7fbc655493864abbc3b96b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 17:49:02 +0900 Subject: [PATCH 386/503] Fix filtering breaking on secondary filters --- .../Screens/Multi/Lounge/Components/DrawableRoom.cs | 10 ++++++++-- .../Screens/Multi/Lounge/Components/RoomsContainer.cs | 8 ++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 6ec8f2bfe5..f6cbe300f3 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -74,7 +74,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components set { matchingFilter = value; - this.FadeTo(MatchingFilter ? 1 : 0, 200); + + if (IsLoaded) + this.FadeTo(MatchingFilter ? 1 : 0, 200); } } @@ -203,7 +205,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { base.LoadComplete(); - this.FadeInFromZero(transition_duration); + + if (matchingFilter) + this.FadeInFromZero(transition_duration); + else + Alpha = 0; } private class RoomName : OsuSpriteText diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 4e9f645732..77f4632bf1 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -65,8 +65,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components filter?.BindValueChanged(f => Filter(f.NewValue), true); } - private FilterCriteria currentFilter; - public void Filter(FilterCriteria criteria) { roomFlow.Children.ForEach(r => @@ -82,15 +80,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components { default: case SecondaryFilter.Public: - r.MatchingFilter = r.Room.Availability.Value == RoomAvailability.Public; + matchingFilter &= r.Room.Availability.Value == RoomAvailability.Public; break; } r.MatchingFilter = matchingFilter; } }); - - currentFilter = criteria; } private void addRooms(IEnumerable rooms) @@ -98,7 +94,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components foreach (var r in rooms) roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) }); - Filter(currentFilter); + filter?.TriggerChange(); } private void removeRooms(IEnumerable rooms) From 1218d41b50ee6d1e52552c533c110448b312e63d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 11:52:49 +0300 Subject: [PATCH 387/503] Make Ruleset a property --- .../BeatmapSet/LeaderboardModSelector.cs | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index b400141abf..660d957e1a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -21,7 +21,34 @@ namespace osu.Game.Overlays.BeatmapSet public class LeaderboardModSelector : CompositeDrawable { public readonly BindableList SelectedMods = new BindableList(); - public readonly Bindable Ruleset = new Bindable(); + + private RulesetInfo ruleset; + + public RulesetInfo Ruleset + { + get => ruleset; + set + { + if (ruleset == value) + { + DeselectAll(); + return; + } + + ruleset = value; + + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset == null) + return; + + modsContainer.Add(new ModButton(new NoMod())); + modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); + + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); + } + } private readonly FillFlowContainer modsContainer; @@ -38,26 +65,6 @@ namespace osu.Game.Overlays.BeatmapSet }; } - protected override void LoadComplete() - { - base.LoadComplete(); - Ruleset.BindValueChanged(onRulesetChanged, true); - } - - private void onRulesetChanged(ValueChangedEvent ruleset) - { - SelectedMods.Clear(); - modsContainer.Clear(); - - if (ruleset.NewValue == null) - return; - - modsContainer.Add(new ModButton(new NoMod())); - modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - - modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); - } - private void selectionChanged(Mod mod, bool selected) { if (selected) From 2592a0489b05fb4a7d5dfe112adc1802e5c27694 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 11:57:40 +0300 Subject: [PATCH 388/503] Use existing ModNoMod --- .../Online/TestSceneLeaderboardModSelector.cs | 12 +++++------- .../BeatmapSet/LeaderboardModSelector.cs | 16 +--------------- osu.Game/Rulesets/Mods/ModNoMod.cs | 4 ++++ 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 799528220b..94540eeb5b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -28,7 +28,6 @@ namespace osu.Game.Tests.Visual.Online { LeaderboardModSelector modSelector; FillFlowContainer selectedMods; - Bindable ruleset = new Bindable(); Add(selectedMods = new FillFlowContainer { @@ -40,7 +39,6 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Ruleset = { BindTarget = ruleset } }); modSelector.SelectedMods.ItemsAdded += mods => @@ -66,12 +64,12 @@ namespace osu.Game.Tests.Visual.Online }); }; - AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); - AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); - AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); - AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => modSelector.Ruleset = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => modSelector.Ruleset = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => modSelector.Ruleset = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => modSelector.Ruleset = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); - AddStep("null ruleset", () => ruleset.Value = null); + AddStep("null ruleset", () => modSelector.Ruleset = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 660d957e1a..c96840c959 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -14,7 +14,6 @@ using osuTK.Graphics; using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { @@ -43,7 +42,7 @@ namespace osu.Game.Overlays.BeatmapSet if (ruleset == null) return; - modsContainer.Add(new ModButton(new NoMod())); + modsContainer.Add(new ModButton(new ModNoMod())); modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); @@ -146,18 +145,5 @@ namespace osu.Game.Overlays.BeatmapSet protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } - - private class NoMod : Mod - { - public override string Name => "NoMod"; - - public override string Acronym => "NM"; - - public override double ScoreMultiplier => 1; - - public override IconUsage Icon => FontAwesome.Solid.Ban; - - public override ModType Type => ModType.System; - } } } diff --git a/osu.Game/Rulesets/Mods/ModNoMod.cs b/osu.Game/Rulesets/Mods/ModNoMod.cs index 0ddbd2a8cb..487985b2b3 100644 --- a/osu.Game/Rulesets/Mods/ModNoMod.cs +++ b/osu.Game/Rulesets/Mods/ModNoMod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.Sprites; + namespace osu.Game.Rulesets.Mods { /// @@ -11,5 +13,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "No Mod"; public override string Acronym => "NM"; public override double ScoreMultiplier => 1; + public override IconUsage Icon => FontAwesome.Solid.Ban; + public override ModType Type => ModType.System; } } From 10287eb66dfe31fb02a864e3343ce7373d2914bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Nov 2019 17:58:47 +0900 Subject: [PATCH 389/503] Add debounce logic in several places --- .../Multi/Lounge/Components/RoomsContainer.cs | 17 ++++++++++++++++- osu.Game/Screens/Multi/RoomManager.cs | 11 ++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 77f4632bf1..3dde9452e4 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osuTK; @@ -62,7 +63,10 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { - filter?.BindValueChanged(f => Filter(f.NewValue), true); + filter?.BindValueChanged(f => scheduleFilter()); + + if (filter != null) + Filter(filter.Value); } public void Filter(FilterCriteria criteria) @@ -89,6 +93,17 @@ namespace osu.Game.Screens.Multi.Lounge.Components }); } + private ScheduledDelegate scheduledFilter; + + private void scheduleFilter() + { + if (filter == null) + return; + + scheduledFilter?.Cancel(); + scheduledFilter = Scheduler.AddDelayed(() => Filter(filter.Value), 200); + } + private void addRooms(IEnumerable rooms) { foreach (var r in rooms) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index cdaba85b9e..d6d3ec37ef 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Online; using osu.Game.Online.API; @@ -44,7 +45,7 @@ namespace osu.Game.Screens.Multi currentFilter.BindValueChanged(_ => { if (IsLoaded) - PollImmediately(); + schedulePoll(); }); } @@ -157,6 +158,14 @@ namespace osu.Game.Screens.Multi return tcs.Task; } + private ScheduledDelegate scheduledPoll; + + private void schedulePoll() + { + scheduledPoll?.Cancel(); + scheduledPoll = Scheduler.AddDelayed(PollImmediately, 200); + } + /// /// Updates a local with a remote copy. /// From 18f77008dbcafb9c69d1b09a25bf31fdb95c67b0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 12:04:01 +0300 Subject: [PATCH 390/503] Update dependency --- .../Online/TestSceneLeaderboardModSelector.cs | 14 ++--- .../BeatmapSet/LeaderboardModSelector.cs | 63 +++++++++---------- .../BeatmapSet/Scores/ScoresContainer.cs | 13 +--- osu.Game/Rulesets/Mods/ModNoMod.cs | 4 ++ 4 files changed, 39 insertions(+), 55 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 799528220b..c0c18c2583 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -11,8 +11,6 @@ using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.Catch; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Bindables; -using osu.Game.Rulesets; using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Tests.Visual.Online @@ -28,7 +26,6 @@ namespace osu.Game.Tests.Visual.Online { LeaderboardModSelector modSelector; FillFlowContainer selectedMods; - Bindable ruleset = new Bindable(); Add(selectedMods = new FillFlowContainer { @@ -40,7 +37,6 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Ruleset = { BindTarget = ruleset } }); modSelector.SelectedMods.ItemsAdded += mods => @@ -66,12 +62,12 @@ namespace osu.Game.Tests.Visual.Online }); }; - AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); - AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); - AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); - AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => modSelector.Ruleset = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => modSelector.Ruleset = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => modSelector.Ruleset = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => modSelector.Ruleset = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); - AddStep("null ruleset", () => ruleset.Value = null); + AddStep("null ruleset", () => modSelector.Ruleset = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index b400141abf..c96840c959 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -14,14 +14,40 @@ using osuTK.Graphics; using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { public class LeaderboardModSelector : CompositeDrawable { public readonly BindableList SelectedMods = new BindableList(); - public readonly Bindable Ruleset = new Bindable(); + + private RulesetInfo ruleset; + + public RulesetInfo Ruleset + { + get => ruleset; + set + { + if (ruleset == value) + { + DeselectAll(); + return; + } + + ruleset = value; + + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset == null) + return; + + modsContainer.Add(new ModButton(new ModNoMod())); + modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); + + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); + } + } private readonly FillFlowContainer modsContainer; @@ -38,26 +64,6 @@ namespace osu.Game.Overlays.BeatmapSet }; } - protected override void LoadComplete() - { - base.LoadComplete(); - Ruleset.BindValueChanged(onRulesetChanged, true); - } - - private void onRulesetChanged(ValueChangedEvent ruleset) - { - SelectedMods.Clear(); - modsContainer.Clear(); - - if (ruleset.NewValue == null) - return; - - modsContainer.Add(new ModButton(new NoMod())); - modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - - modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); - } - private void selectionChanged(Mod mod, bool selected) { if (selected) @@ -139,18 +145,5 @@ namespace osu.Game.Overlays.BeatmapSet protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } - - private class NoMod : Mod - { - public override string Name => "NoMod"; - - public override string Acronym => "NM"; - - public override double ScoreMultiplier => 1; - - public override IconUsage Icon => FontAwesome.Solid.Ban; - - public override ModType Type => ModType.System; - } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 3e3f823368..bdcf536e39 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -107,10 +107,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Current = { BindTarget = scope } }, - modSelector = new LeaderboardModSelector - { - Ruleset = { BindTarget = ruleset } - } + modSelector = new LeaderboardModSelector() } }, new Container @@ -190,13 +187,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void onBeatmapChanged(ValueChangedEvent beatmap) { - var beatmapRuleset = beatmap.NewValue?.Ruleset; - - if (ruleset.Value?.Equals(beatmapRuleset) ?? false) - modSelector.DeselectAll(); - else - ruleset.Value = beatmapRuleset; - + ruleset.Value = modSelector.Ruleset = beatmap.NewValue?.Ruleset; scope.Value = BeatmapLeaderboardScope.Global; } diff --git a/osu.Game/Rulesets/Mods/ModNoMod.cs b/osu.Game/Rulesets/Mods/ModNoMod.cs index 0ddbd2a8cb..487985b2b3 100644 --- a/osu.Game/Rulesets/Mods/ModNoMod.cs +++ b/osu.Game/Rulesets/Mods/ModNoMod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.Sprites; + namespace osu.Game.Rulesets.Mods { /// @@ -11,5 +13,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "No Mod"; public override string Acronym => "NM"; public override double ScoreMultiplier => 1; + public override IconUsage Icon => FontAwesome.Solid.Ban; + public override ModType Type => ModType.System; } } From e51fd00d588cd2b7488995b15f15b5533a8d759d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 12:09:31 +0300 Subject: [PATCH 391/503] CI fix --- osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs | 2 -- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index 94540eeb5b..c0c18c2583 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -11,8 +11,6 @@ using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.Catch; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Bindables; -using osu.Game.Rulesets; using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Tests.Visual.Online diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index c96840c959..e62a754e92 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet get => ruleset; set { - if (ruleset == value) + if (ruleset?.Equals(value) ?? false) { DeselectAll(); return; From f2862e95e0be0544027118cbf47cac3f00b99fa9 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 15 Nov 2019 12:15:51 +0300 Subject: [PATCH 392/503] CI fix --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index c96840c959..e62a754e92 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.BeatmapSet get => ruleset; set { - if (ruleset == value) + if (ruleset?.Equals(value) ?? false) { DeselectAll(); return; From e9e37fc821b1ce075d3cc2fba3ff92f5a260f8cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Nov 2019 18:23:35 +0900 Subject: [PATCH 393/503] Add private setter for FilterControl --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 974120e658..089510513b 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Select protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; - public FilterControl FilterControl; + public FilterControl FilterControl { get; private set; } protected virtual bool ShowFooter => true; From 509440ea14bf0f6e9540953d1f8dbcb77328f420 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 16 Nov 2019 18:02:34 +0300 Subject: [PATCH 394/503] TotalCommentsCounter implementation --- .../Online/TestSceneTotalCommentsCounter.cs | 36 +++++++++ .../Overlays/Comments/TotalCommentsCounter.cs | 80 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs create mode 100644 osu.Game/Overlays/Comments/TotalCommentsCounter.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs new file mode 100644 index 0000000000..4702d24125 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Game.Overlays.Comments; +using osu.Framework.MathUtils; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneTotalCommentsCounter : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(TotalCommentsCounter), + }; + + public TestSceneTotalCommentsCounter() + { + var count = new BindableInt(); + + Add(new TotalCommentsCounter + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = count } + }); + + AddStep(@"Set 100", () => count.Value = 100); + AddStep(@"Set 0", () => count.Value = 0); + AddStep(@"Set random", () => count.Value = RNG.Next(0, int.MaxValue)); + } + } +} diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs new file mode 100644 index 0000000000..c71ca762e1 --- /dev/null +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -0,0 +1,80 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; +using osuTK; +using osu.Framework.Allocation; +using osu.Framework.Bindables; + +namespace osu.Game.Overlays.Comments +{ + public class TotalCommentsCounter : CompositeDrawable + { + public readonly BindableInt Current = new BindableInt(); + + private readonly SpriteText counter; + + public TotalCommentsCounter() + { + RelativeSizeAxes = Axes.X; + Height = 50; + AddInternal(new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Margin = new MarginPadding { Left = 50 }, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new SpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.GetFont(size: 20, italics: true), + Text = @"Comments" + }, + new CircularContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.05f) + }, + counter = new SpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Margin = new MarginPadding { Horizontal = 10, Vertical = 5 }, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) + } + }, + } + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + counter.Colour = colours.BlueLighter; + } + + protected override void LoadComplete() + { + Current.BindValueChanged(value => counter.Text = value.NewValue.ToString("N0"), true); + base.LoadComplete(); + } + } +} From 5727963f8642989bf87b915f48fe00053efd19d6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:43:34 +0800 Subject: [PATCH 395/503] Turn on xmldoc warning, and use appendive syntax for NoWarn. --- Directory.Build.props | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 9735c78913..838851b712 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,10 +18,14 @@ + + true + $(NoWarn);CS1591 + - NU1701 + $(NoWarn);NU1701 ppy Pty Ltd From f05b83d7d450c458077cafeaf012a8cb57283b00 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:48:23 +0800 Subject: [PATCH 396/503] Use typeparamref. --- osu.Game/Beatmaps/Formats/Decoder.cs | 2 +- osu.Game/Database/ArchiveModelManager.cs | 12 ++++++------ .../DownloadableArchiveModelManager.cs | 12 ++++++------ osu.Game/Database/IModelDownloader.cs | 18 +++++++++--------- osu.Game/Database/IModelManager.cs | 2 +- .../Database/MutableDatabaseBackedStore.cs | 8 ++++---- .../Graphics/UserInterface/OsuTabControl.cs | 2 +- .../Bindings/DatabasedKeyBindingContainer.cs | 2 +- osu.Game/Online/DownloadTrackingComposite.cs | 4 ++-- osu.Game/Rulesets/UI/DrawableRuleset.cs | 4 ++-- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 40c329eb7e..45122f6312 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps.Formats /// /// Registers a fallback decoder instantiation function. /// The fallback will be returned if the first non-empty line of the decoded stream does not match any known magic. - /// Calling this method will overwrite any existing global fallback registration for type - use with caution. + /// Calling this method will overwrite any existing global fallback registration for type - use with caution. /// /// Type of object being decoded. /// A function that constructs the fallback. diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 8fa4eaf267..7cce2fb92f 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -54,13 +54,13 @@ namespace osu.Game.Database public Action PostNotification { protected get; set; } /// - /// Fired when a new becomes available in the database. + /// Fired when a new becomes available in the database. /// This is not guaranteed to run on the update thread. /// public event Action ItemAdded; /// - /// Fired when a is removed from the database. + /// Fired when a is removed from the database. /// This is not guaranteed to run on the update thread. /// public event Action ItemRemoved; @@ -95,7 +95,7 @@ namespace osu.Game.Database } /// - /// Import one or more items from filesystem . + /// Import one or more items from filesystem . /// This will post notifications tracking progress. /// /// One or more archive locations on disk. @@ -173,7 +173,7 @@ namespace osu.Game.Database } /// - /// Import one from the filesystem and delete the file on success. + /// Import one from the filesystem and delete the file on success. /// /// The archive location on disk. /// An optional cancellation token. @@ -275,7 +275,7 @@ namespace osu.Game.Database } /// - /// Import an item from a . + /// Import an item from a . /// /// The model to be imported. /// An optional archive to use for model population. @@ -589,7 +589,7 @@ namespace osu.Game.Database protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); /// - /// After an existing is found during an import process, the default behaviour is to restore the existing + /// After an existing is found during an import process, the default behaviour is to restore the existing /// item and skip the import. This method allows changing that behaviour. /// /// The existing model. diff --git a/osu.Game/Database/DownloadableArchiveModelManager.cs b/osu.Game/Database/DownloadableArchiveModelManager.cs index a81dff3475..0b7d63f469 100644 --- a/osu.Game/Database/DownloadableArchiveModelManager.cs +++ b/osu.Game/Database/DownloadableArchiveModelManager.cs @@ -41,17 +41,17 @@ namespace osu.Game.Database } /// - /// Creates the download request for this . + /// Creates the download request for this . /// - /// The to be downloaded. + /// The to be downloaded. /// Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle. /// The request object. protected abstract ArchiveDownloadRequest CreateDownloadRequest(TModel model, bool minimiseDownloadSize); /// - /// Begin a download for the requested . + /// Begin a download for the requested . /// - /// The to be downloaded. + /// The to be downloaded. /// Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle. /// Whether the download was started. public bool Download(TModel model, bool minimiseDownloadSize = false) @@ -131,9 +131,9 @@ namespace osu.Game.Database /// /// Performs implementation specific comparisons to determine whether a given model is present in the local store. /// - /// The whose existence needs to be checked. + /// The whose existence needs to be checked. /// The usable items present in the store. - /// Whether the exists. + /// Whether the exists. protected abstract bool CheckLocalAvailability(TModel model, IQueryable items); public ArchiveDownloadRequest GetExistingDownload(TModel model) => currentDownloads.Find(r => r.Model.Equals(model)); diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index f6f4b0aa42..17f1ccab06 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -14,34 +14,34 @@ namespace osu.Game.Database where TModel : class { /// - /// Fired when a download begins. + /// Fired when a download begins. /// event Action> DownloadBegan; /// - /// Fired when a download is interrupted, either due to user cancellation or failure. + /// Fired when a download is interrupted, either due to user cancellation or failure. /// event Action> DownloadFailed; /// - /// Checks whether a given is already available in the local store. + /// Checks whether a given is already available in the local store. /// - /// The whose existence needs to be checked. - /// Whether the exists. + /// The whose existence needs to be checked. + /// Whether the exists. bool IsAvailableLocally(TModel model); /// - /// Begin a download for the requested . + /// Begin a download for the requested . /// - /// The to be downloaded. + /// The to be downloaded. /// Whether this download should be optimised for slow connections. Generally means extras are not included in the download bundle.. /// Whether the download was started. bool Download(TModel model, bool minimiseDownloadSize); /// - /// Gets an existing download request if it exists. + /// Gets an existing download request if it exists. /// - /// The whose request is wanted. + /// The whose request is wanted. /// The object if it exists, otherwise null. ArchiveDownloadRequest GetExistingDownload(TModel model); } diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 884814cb38..1bdbbb48e6 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -6,7 +6,7 @@ using System; namespace osu.Game.Database { /// - /// Represents a model manager that publishes events when s are added or removed. + /// Represents a model manager that publishes events when s are added or removed. /// /// The model type. public interface IModelManager diff --git a/osu.Game/Database/MutableDatabaseBackedStore.cs b/osu.Game/Database/MutableDatabaseBackedStore.cs index 39a48b5be6..4ca1eef989 100644 --- a/osu.Game/Database/MutableDatabaseBackedStore.cs +++ b/osu.Game/Database/MutableDatabaseBackedStore.cs @@ -30,7 +30,7 @@ namespace osu.Game.Database public IQueryable ConsumableItems => AddIncludesForConsumption(ContextFactory.Get().Set()); /// - /// Add a to the database. + /// Add a to the database. /// /// The item to add. public void Add(T item) @@ -45,7 +45,7 @@ namespace osu.Game.Database } /// - /// Update a in the database. + /// Update a in the database. /// /// The item to update. public void Update(T item) @@ -58,7 +58,7 @@ namespace osu.Game.Database } /// - /// Delete a from the database. + /// Delete a from the database. /// /// The item to delete. public bool Delete(T item) @@ -77,7 +77,7 @@ namespace osu.Game.Database } /// - /// Restore a from a deleted state. + /// Restore a from a deleted state. /// /// The item to undelete. public bool Undelete(T item) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 5d1bdc62e9..585a46f3e1 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.UserInterface protected virtual float StripHeight() => 1; /// - /// Whether entries should be automatically populated if is an type. + /// Whether entries should be automatically populated if is an type. /// protected virtual bool AddEnumEntriesAutomatically => true; diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index f34b8f14b0..ea274284ac 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -30,7 +30,7 @@ namespace osu.Game.Input.Bindings /// /// A reference to identify the current . Used to lookup mappings. Null for global mappings. /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. - /// Specify how to deal with multiple matches of s and s. + /// Specify how to deal with multiple matches of s and s. public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) : base(simultaneousMode) { diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index 7bfdc7ff69..dcec17788a 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -11,7 +11,7 @@ using osu.Game.Online.API; namespace osu.Game.Online { /// - /// A component which tracks a through potential download/import/deletion. + /// A component which tracks a through potential download/import/deletion. /// public abstract class DownloadTrackingComposite : CompositeDrawable where TModel : class, IEquatable @@ -22,7 +22,7 @@ namespace osu.Game.Online private TModelManager manager; /// - /// Holds the current download state of the , whether is has already been downloaded, is in progress, or is not downloaded. + /// Holds the current download state of the , whether is has already been downloaded, is in progress, or is not downloaded. /// protected readonly Bindable State = new Bindable(); diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d1749d33c0..aec0e58a10 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -246,9 +246,9 @@ namespace osu.Game.Rulesets.UI } /// - /// Creates and adds the visual representation of a to this . + /// Creates and adds the visual representation of a to this . /// - /// The to add the visual representation for. + /// The to add the visual representation for. private void addHitObject(TObject hitObject) { var drawableObject = CreateDrawableRepresentation(hitObject); From b1b234c6fbbdc55c7ceef31193350ea63baa437e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:49:36 +0800 Subject: [PATCH 397/503] Use paramref. --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 2 +- osu.Game/Overlays/OnScreenDisplay.cs | 2 +- .../Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index c3e2b469ae..ce2783004c 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -218,7 +218,7 @@ namespace osu.Game.Beatmaps.ControlPoints } /// - /// Check whether should be added. + /// Check whether should be added. /// /// The time to find the timing control point at. /// A point to be added. diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index a92320945e..e6708093c4 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -86,7 +86,7 @@ namespace osu.Game.Overlays /// The object that registered the to be tracked. /// The that is being tracked. /// If is null. - /// If is not being tracked from the same . + /// If is not being tracked from the same . public void StopTracking(object source, ITrackableConfigManager configManager) { if (configManager == null) throw new ArgumentNullException(nameof(configManager)); diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs index b7a5eedc22..5f053975c7 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// /// The point in time. /// The amount of visible time. - /// The time at which enters . + /// The time at which enters . double GetDisplayStartTime(double time, double timeRange); /// @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// The start time. /// The end time. /// The amount of visible time. - /// The absolute spatial length through . + /// The absolute spatial length through . /// The absolute spatial length. float GetLength(double startTime, double endTime, double timeRange, float scrollLength); @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// The time to compute the spatial position of. /// The current time. /// The amount of visible time. - /// The absolute spatial length through . + /// The absolute spatial length through . /// The absolute spatial position. float PositionAt(double time, double currentTime, double timeRange, float scrollLength); @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms /// The absolute spatial position. /// The current time. /// The amount of visible time. - /// The absolute spatial length through . + /// The absolute spatial length through . /// The time at which == . double TimeAt(float position, double currentTime, double timeRange, float scrollLength); From b04bca7db653c6e925313d567f813be8e898b252 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 20:55:40 +0800 Subject: [PATCH 398/503] Reference elements in origin definition. --- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 4 ++-- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 4 ++-- osu.Game/Graphics/UserInterface/IconButton.cs | 4 ++-- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index fba52dfc32..149dafe449 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// A function to retrieve the next column. If null, a randomisation scheme will be used. /// A function to perform additional validation checks to determine if a column is a valid candidate for a . /// The minimum column index. If null, is used. - /// The maximum column index. If null, is used. + /// The maximum column index. If null, is used. /// A list of patterns for which the validity of a column should be checked against. /// A column is not a valid candidate if a occupies the same column in any of the patterns. /// A column which has passed the check and for which there are no @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// Returns a random column index in the range [, ). /// /// The minimum column index. If null, is used. - /// The maximum column index. If null, is used. + /// The maximum column index. If null, is used. protected int GetRandomColumn(int? lowerBound = null, int? upperBound = null) => Random.Next(lowerBound ?? RandomStart, upperBound ?? TotalColumns); /// diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index ed771bb03f..bd1a7791e8 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Sprites public static class OsuSpriteTextTransformExtensions { /// - /// Sets to a new value after a duration. + /// Sets to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this T spriteText, string newText, double duration = 0, Easing easing = Easing.None) @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Sprites => spriteText.TransformTo(nameof(OsuSpriteText.Text), newText, duration, easing); /// - /// Sets to a new value after a duration. + /// Sets to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this TransformSequence t, string newText, double duration = 0, Easing easing = Easing.None) diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 27427581fd..8600c5dcb1 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface private Color4? iconColour; /// - /// The icon colour. This does not affect . + /// The icon colour. This does not affect . /// public Color4 IconColour { @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.UserInterface } /// - /// The icon scale. This does not affect . + /// The icon scale. This does not affect . /// public Vector2 IconScale { diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index c3436ffd45..fa0ca3d9b3 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -351,7 +351,7 @@ namespace osu.Game.Screens.Select /// /// Half the height of the visible content. /// - /// This is different from the height of , since + /// This is different from the height of .displayableContent, since /// the beatmap carousel bleeds into the and the /// /// From 4d1513cef60c2c0d74632ab08202a913dcbf652b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Nov 2019 21:01:56 +0800 Subject: [PATCH 399/503] Sadly, xmldoc doesn't support tuple elements. --- osu.Game/Beatmaps/BeatmapDifficulty.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 8727431e0e..c56fec67aa 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -56,10 +56,22 @@ namespace osu.Game.Beatmaps /// Maps a difficulty value [0, 10] to a two-piece linear range of values. /// /// The difficulty value to be mapped. - /// The values that define the two linear ranges. - /// Minimum of the resulting range which will be achieved by a difficulty value of 0. - /// Midpoint of the resulting range which will be achieved by a difficulty value of 5. - /// Maximum of the resulting range which will be achieved by a difficulty value of 10. + /// The values that define the two linear ranges. + /// + /// + /// od0 + /// Minimum of the resulting range which will be achieved by a difficulty value of 0. + /// + /// + /// od5 + /// Midpoint of the resulting range which will be achieved by a difficulty value of 5. + /// + /// + /// od10 + /// Maximum of the resulting range which will be achieved by a difficulty value of 10. + /// + /// + /// /// Value to which the difficulty value maps in the specified range. public static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range) => DifficultyRange(difficulty, range.od0, range.od5, range.od10); From 53bc2dcab7a064ca0678497cf85c40a50c6e7a21 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 18 Nov 2019 15:29:18 +0800 Subject: [PATCH 400/503] Use costum displaying text for inherited references. --- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 2 +- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 4 ++-- osu.Game/Graphics/UserInterface/IconButton.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index 149dafe449..f989f22298 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// A function to retrieve the next column. If null, a randomisation scheme will be used. /// A function to perform additional validation checks to determine if a column is a valid candidate for a . /// The minimum column index. If null, is used. - /// The maximum column index. If null, is used. + /// The maximum column index. If null, TotalColumns is used. /// A list of patterns for which the validity of a column should be checked against. /// A column is not a valid candidate if a occupies the same column in any of the patterns. /// A column which has passed the check and for which there are no diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index bd1a7791e8..cd988c347b 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.Sprites public static class OsuSpriteTextTransformExtensions { /// - /// Sets to a new value after a duration. + /// Sets Text to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this T spriteText, string newText, double duration = 0, Easing easing = Easing.None) @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Sprites => spriteText.TransformTo(nameof(OsuSpriteText.Text), newText, duration, easing); /// - /// Sets to a new value after a duration. + /// Sets Text to a new value after a duration. /// /// A to which further transforms can be added. public static TransformSequence TransformTextTo(this TransformSequence t, string newText, double duration = 0, Easing easing = Easing.None) diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 8600c5dcb1..d7e5666545 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -16,7 +16,7 @@ namespace osu.Game.Graphics.UserInterface private Color4? iconColour; /// - /// The icon colour. This does not affect . + /// The icon colour. This does not affect Colour. /// public Color4 IconColour { @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.UserInterface } /// - /// The icon scale. This does not affect . + /// The icon scale. This does not affect Scale. /// public Vector2 IconScale { From 140278bf4c4753e749ccca2884479b6493b7e8bd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 18:15:16 +0800 Subject: [PATCH 401/503] Bump Xamarin.Android version to 10.0 --- osu.Android.props | 2 +- osu.Android/Properties/AndroidManifest.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..d06e04aea4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ Off True Xamarin.Android.Net.AndroidClientHandler - v9.0 + v10.0 false true armeabi-v7a;x86;arm64-v8a diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index acd21f9587..770eaf2222 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + From 608785b99aecb959aeab0dbe470d1181890090de Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Nov 2019 18:28:56 +0800 Subject: [PATCH 402/503] Update .Net Standard projects to 2.1 --- osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 2 +- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 2 +- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 2 +- osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 2 +- osu.Game.Tournament/osu.Game.Tournament.csproj | 2 +- osu.Game/osu.Game.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index f24cf1def9..b19affbf9f 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true catch the fruit. to the beat. diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 0af200d19b..07ef1022ae 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true smash the keys. to the beat. diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index fb3fe8808d..bffeaabb55 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true click the circles. to the beat. diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 0a2b189c3a..ebed8c6d7c 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true bash the drum. to the beat. diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index f5306facaf..8e881fdd9c 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true tools for tournaments. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index af60da3e70..8e3858d0f1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true From efbab5420667370d995e5b9f3a1315040ebff1bc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 18 Nov 2019 18:48:29 +0800 Subject: [PATCH 403/503] Bump Android test projects version. --- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- osu.Game.Tests.Android/Properties/AndroidManifest.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index db95e18f13..0fa3b7730d 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml index e6728c801d..de7935b2ef 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml index aad907b241..3ce17ccc27 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml index cd4b74aa16..d9de0fde4e 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index bb996dc5ca..4a63f0c357 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file From 465c8c26186aba9f98688fa048165046adbe66ad Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Tue, 19 Nov 2019 13:47:29 +0900 Subject: [PATCH 404/503] Re-add package references to osu.iOS.props --- osu.iOS.props | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.iOS.props b/osu.iOS.props index 8124357312..6965b16303 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -75,4 +75,17 @@ + + + + + + + + + + + + + From 08b8cedfdf4766b4d29c2e36bd4ed33277c3cd33 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 20 Nov 2019 01:15:40 +0300 Subject: [PATCH 405/503] Add setter to legacy skin configuration access --- osu.Game/Skinning/LegacySkin.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 35aca3aa7b..0ee41e654e 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,7 +26,11 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; - protected new LegacySkinConfiguration Configuration => (LegacySkinConfiguration)base.Configuration; + protected new LegacySkinConfiguration Configuration + { + get => base.Configuration as LegacySkinConfiguration; + set => base.Configuration = value; + } public LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager) : this(skin, new LegacySkinResourceStore(skin, storage), audioManager, "skin.ini") @@ -41,10 +45,10 @@ namespace osu.Game.Skinning if (stream != null) { using (LineBufferedReader reader = new LineBufferedReader(stream)) - base.Configuration = new LegacySkinDecoder().Decode(reader); + Configuration = new LegacySkinDecoder().Decode(reader); } else - base.Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION }; + Configuration = new LegacySkinConfiguration { LegacyVersion = LegacySkinConfiguration.LATEST_VERSION }; if (storage != null) { From 76ed573c56793b267fdbc74832daafb46826044b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 20 Nov 2019 12:21:49 +0900 Subject: [PATCH 406/503] Fix crash when loading results after gameplay --- osu.Game/Scoring/ScoreInfo.cs | 5 ++++- osu.Game/Scoring/ScoreManager.cs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d3c37bd4f4..ab344c7791 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -183,6 +183,9 @@ namespace osu.Game.Scoring public override string ToString() => $"{User} playing {Beatmap}"; - public bool Equals(ScoreInfo other) => other?.OnlineScoreID == OnlineScoreID; + public bool Equals(ScoreInfo other) => + other?.OnlineScoreID == OnlineScoreID + && other?.BeatmapInfoID == BeatmapInfoID + && other.Hash == Hash; } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 8475158c78..3279af05b6 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -69,6 +69,6 @@ namespace osu.Game.Scoring protected override ArchiveDownloadRequest CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score); - protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID && s.Files.Any()); + protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.Equals(model) && s.Files.Any()); } } From 6288e6da566a29e5e61f1cc0e64fc4478838bf39 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 20 Nov 2019 13:42:54 +0900 Subject: [PATCH 407/503] Add null check --- osu.Game/Scoring/ScoreInfo.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index ab344c7791..f7bac82e74 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -184,8 +184,9 @@ namespace osu.Game.Scoring public override string ToString() => $"{User} playing {Beatmap}"; public bool Equals(ScoreInfo other) => - other?.OnlineScoreID == OnlineScoreID - && other?.BeatmapInfoID == BeatmapInfoID + other != null + && other.OnlineScoreID == OnlineScoreID + && other.BeatmapInfoID == BeatmapInfoID && other.Hash == Hash; } } From bcb1504110f732679752f43254f2bdf1f9b0fd0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 15:40:35 +0900 Subject: [PATCH 408/503] Fix naming --- osu.Game/Skinning/LegacySkin.cs | 4 ++-- osu.Game/Skinning/LegacySkinConfiguration.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 0ee41e654e..7ffed18d7b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -80,10 +80,10 @@ namespace osu.Game.Skinning case GlobalSkinColour colour: return SkinUtils.As(getCustomColour(colour.ToString())); - case LegacySkinConfigurations legacy: + case LegacySkinConfiguration.LegacySetting legacy: switch (legacy) { - case LegacySkinConfigurations.Version: + case LegacySkinConfiguration.LegacySetting.Version: if (Configuration.LegacyVersion is decimal version) return SkinUtils.As(new Bindable(version)); diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 33c29cd47c..6a667e69f4 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -11,10 +11,10 @@ namespace osu.Game.Skinning /// Legacy version of this skin. Null if no version was set to allow fallback to a parent skin version. /// public decimal? LegacyVersion { get; internal set; } - } - public enum LegacySkinConfigurations - { - Version, + public enum LegacySetting + { + Version, + } } } From e0f59d8e24ea0c0f2f64dcda6fc8a6ddf5e72cf9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 15:43:00 +0900 Subject: [PATCH 409/503] Move method --- osu.Game/Screens/Select/SongSelect.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 089510513b..b5e62740f2 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -88,8 +88,6 @@ namespace osu.Game.Screens.Select [Resolved(canBeNull: true)] private MusicController music { get; set; } - protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); - [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { @@ -262,6 +260,8 @@ namespace osu.Game.Screens.Select } } + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 5b416eb7ba35c261810368b2115079e375d17dd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 17:24:43 +0900 Subject: [PATCH 410/503] Move initial filter to run on entering --- osu.Game/Screens/Select/SongSelect.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b5e62740f2..a52edb70db 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -260,7 +260,11 @@ namespace osu.Game.Screens.Select } } - protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) => Carousel.Filter(criteria); + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) + { + if (this.IsCurrentScreen()) + Carousel.Filter(criteria); + } private DependencyContainer dependencies; @@ -433,6 +437,8 @@ namespace osu.Game.Screens.Select { base.OnEntering(last); + Carousel.Filter(FilterControl.CreateCriteria(), false); + this.FadeInFromZero(250); FilterControl.Activate(); } From 3ba9f840fdbae2ba70b6f23edf0f12806ac23917 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Nov 2019 19:38:39 +0900 Subject: [PATCH 411/503] Fix song select not always scrolling to the correct location --- osu.Game/Screens/Select/BeatmapCarousel.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..beffa5b33f 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -452,9 +452,6 @@ namespace osu.Game.Screens.Select if (!itemsCache.IsValid) updateItems(); - if (!scrollPositionCache.IsValid) - updateScrollPosition(); - // Remove all items that should no longer be on-screen scrollableContent.RemoveAll(p => p.Y < visibleUpperBound - p.DrawHeight || p.Y > visibleBottomBound || !p.IsPresent); @@ -519,6 +516,14 @@ namespace osu.Game.Screens.Select updateItem(p); } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + if (!scrollPositionCache.IsValid) + updateScrollPosition(); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -637,8 +642,11 @@ namespace osu.Game.Screens.Select private void updateScrollPosition() { - if (scrollTarget != null) scroll.ScrollTo(scrollTarget.Value); - scrollPositionCache.Validate(); + if (scrollTarget != null) + { + scroll.ScrollTo(scrollTarget.Value); + scrollPositionCache.Validate(); + } } /// From 6cace0c5f5cba38be8c97a65368031a22330a8d8 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 12:43:14 +0100 Subject: [PATCH 412/503] Replace all Mathhelper.Clamp usages with Math.Clamp --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 5 ++--- .../Difficulty/CatchPerformanceCalculator.cs | 2 +- osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ++-- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 6 +++--- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 3 ++- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 3 ++- .../Objects/Drawables/DrawableSliderHead.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 3 ++- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 3 +-- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 3 ++- osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs | 3 ++- osu.Game/Graphics/Containers/ParallaxContainer.cs | 3 ++- osu.Game/Graphics/UserInterface/Bar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- .../Overlays/Profile/Header/Components/SupporterIcon.cs | 4 ++-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- osu.Game/Rulesets/Objects/SliderEventGenerator.cs | 2 +- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 2 +- .../UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs | 4 ++-- .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 3 ++- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 2 +- .../Compose/Components/Timeline/ZoomableScrollContainer.cs | 4 ++-- osu.Game/Screens/Edit/EditorClock.cs | 3 +-- osu.Game/Screens/Menu/Button.cs | 2 +- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 4 ++-- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 6 +++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.Game/Screens/Select/Details/FailRetryGraph.cs | 4 ++-- osu.Game/Tests/Visual/OsuTestScene.cs | 3 +-- 42 files changed, 65 insertions(+), 63 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 58bf811fac..db52fbac1b 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -8,7 +8,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; -using osuTK; using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Mods; @@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps catchObject.XOffset = 0; if (catchObject is TinyDroplet) - catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); + catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); else if (catchObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } @@ -230,7 +229,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps else { currentObject.DistanceToHyperDash = distanceToHyper; - lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); + lastExcess = Math.Clamp(distanceToHyper, 0, halfCatcherWidth); } lastDirection = thisDirection; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 5a640f6d1a..638fd3f603 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return value; } - private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index d146153294..800346280d 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills if (lastPlayerPosition == null) lastPlayerPosition = catchCurrent.LastNormalizedPosition; - float playerPosition = MathHelper.Clamp( + float playerPosition = Math.Clamp( lastPlayerPosition.Value, catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..eae652573b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { base.Update(); - border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); + border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); } private Color4 colourForRepresentation(FruitVisualRepresentation representation) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..d330add1c4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Y -= RNG.NextSingle() * diff; } - fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); + fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); caughtFruit.Add(fruit); } @@ -378,7 +378,7 @@ namespace osu.Game.Rulesets.Catch.UI double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index f989f22298..eadf60b10b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -54,11 +54,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// @@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy drainTime = 10000; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; - conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; + conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); return conversionDifficulty.Value; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..53f7e30dfd 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Timing; @@ -9,7 +10,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using osuTK; namespace osu.Game.Rulesets.Mania.Edit { @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Edit maxColumn = obj.Column; } - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 1eb37f8119..63110b2797 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; } - private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; + private float calculateGap(float value) => Math.Clamp(value, 0, target_clamp) * targetBreakMultiplier; // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 7fa3dbe07e..778c2f7d43 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods var destination = e.MousePosition; FlashlightPosition = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + Math.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); return base.OnMouseMove(e); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 84d2a4af9b..122975d55e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables else { // If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly). - Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); + Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 433d29f2e4..69189758a6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -165,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.Value = Ball.Tracking; - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); Body.UpdateProgress(completionProgress); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 66b6f0f9ac..a10c66d1df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.Update(); - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!IsHit) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d1b9ee6cb4..1261d3d19a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => Math.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 70a1bad4a3..f2150280b3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; + double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; if (span >= slider.SpanCount() - 1) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index cc0d6829ba..338fd9e20f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; using osuTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables else rollingHits--; - rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); + rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); MainPiece.FadeAccent(newColour, 100); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 9c9dfc5f9e..fa39819199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; @@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var completion = (float)numHits / HitObject.RequiredHits; expandingRing - .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) + .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) .Then() .FadeTo(completion / 8, 2000, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 84464b199e..980f5ea340 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; using osuTK; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.UI { base.Update(); - float aspectAdjust = MathHelper.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; + float aspectAdjust = Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; Size = new Vector2(1, default_relative_height * aspectAdjust); } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..724612ebce 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnScroll(ScrollEvent e) { - var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); + var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 86f922e4b8..f8c21eabc2 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Input; @@ -71,7 +72,7 @@ namespace osu.Game.Graphics.Containers const float parallax_duration = 100; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index f8d5955503..0be928cf83 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using System; namespace osu.Game.Graphics.UserInterface { @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface get => length; set { - length = MathHelper.Clamp(value, 0, 1); + length = Math.Clamp(value, 0, 1); updateBarLength(); } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 11aba80d76..7412224f6c 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -175,9 +175,9 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - leftBox.Scale = new Vector2(MathHelper.Clamp( + leftBox.Scale = new Vector2(Math.Clamp( Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); - rightBox.Scale = new Vector2(MathHelper.Clamp( + rightBox.Scale = new Vector2(Math.Clamp( DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 585a46f3e1..064cba6adf 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface // dont bother calculating if the strip is invisible if (strip.Colour.MaxAlpha > 0) - strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); + strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); } public class OsuTabItem : TabItem, IHasAccentColour diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..583db460f4 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void tabCloseRequested(TabItem tab) { int totalTabs = TabContainer.Count - 1; // account for selectorTab - int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); + int currentIndex = Math.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index e3acd31626..83528298b1 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Music break; } - dstIndex = MathHelper.Clamp(dstIndex, 0, items.Count - 1); + dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1); if (srcIndex == dstIndex) return; diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index fa60a37ddb..d581e2750c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,7 +9,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { set { - int count = MathHelper.Clamp(value, 0, 3); + int count = Math.Clamp(value, 0, 3); if (count == 0) { diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 9edf57ad00..f217512965 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osuTK; namespace osu.Game.Rulesets.Mods { @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mods /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) { - double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); switch (clock) { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 0d8796b4cb..1a671e8041 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Objects const double max_length = 100000; var length = Math.Min(max_length, totalDistance); - tickDistance = MathHelper.Clamp(tickDistance, 0, length); + tickDistance = Math.Clamp(tickDistance, 0, length); var minDistanceFromEnd = velocity * 10; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..e8ef16e825 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -246,7 +246,7 @@ namespace osu.Game.Rulesets.Objects private double progressToDistance(double progress) { - return MathHelper.Clamp(progress, 0, 1) * Distance; + return Math.Clamp(progress, 0, 1) * Distance; } private Vector2 interpolateVertices(int i, double d) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 4c011388fa..cb89653675 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Replays private int? currentFrameIndex; - private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; + private int nextFrameIndex => currentFrameIndex.HasValue ? Math.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; protected FramedReplayInputHandler(Replay replay) { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 5316585493..fe22a86fad 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,9 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -using osuTK; namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } } - i = MathHelper.Clamp(i, 0, controlPoints.Count - 1); + i = Math.Clamp(i, 0, controlPoints.Count - 1); return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 07d307f293..79ada40a89 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts if (Beatmap.Value == null) return; - float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); + float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 0f2bae6305..fc7d51db4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index cffb6bedf3..54922fec5e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline get => zoomTarget; set { - value = MathHelper.Clamp(value, MinZoom, MaxZoom); + value = Math.Clamp(value, MinZoom, MaxZoom); if (IsLoaded) setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void setZoomTarget(float newZoom, float focusPoint) { - zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); + zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom); transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index bd2db4ae2b..93a5f19121 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -7,7 +7,6 @@ using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osuTK; namespace osu.Game.Screens.Edit { @@ -125,7 +124,7 @@ namespace osu.Game.Screens.Edit seekTime = nextTimingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); + seekTime = Math.Clamp(seekTime, 0, TrackLength); Seek(seekTime); } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index ffeadb96c7..fac6b69e1f 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu protected override void Update() { - iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); + iconText.Alpha = Math.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); base.Update(); } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 968b83e68c..640224c057 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -102,8 +102,8 @@ namespace osu.Game.Screens.Play.HUD else { Alpha = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), - Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + Math.Clamp(Clock.ElapsedFrameTime, 0, 200), + Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 33c7595b37..cdf495e257 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 05f6128ac2..715ba3c065 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Play { Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; - int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); + int countFilled = (int)Math.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); for (int i = 0; i < drawableRows.Count; i++) drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index e4971221c4..3d8fd5dad7 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -87,9 +87,9 @@ namespace osu.Game.Screens private static Color4 getColourFor(object type) { int hash = type.GetHashCode(); - byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); - byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); - byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); + byte r = (byte)Math.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); + byte g = (byte)Math.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); + byte b = (byte)Math.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..c328eebca7 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -677,7 +677,7 @@ namespace osu.Game.Screens.Select // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can // layer transformations on top, with a similar reasoning to the previous comment. - p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1)); + p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1)); } private class CarouselRoot : CarouselGroupEagerSelect diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 34297d89a4..121f8efe5a 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select.Details retryGraph.MaxValue = maxValue; failGraph.Values = fails.Select(f => (float)f); - retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); + retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + Math.Clamp(fail, 0, maxValue)); } } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..13e08c7d22 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -22,7 +22,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { @@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; From b7d5e3689015b584c7464f312f33c7cfa87268d3 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 13:18:03 +0100 Subject: [PATCH 413/503] Remove unused Using directives --- osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs | 1 - osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs | 1 - .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 1 - osu.Game/Rulesets/Objects/SliderEventGenerator.cs | 1 - osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 1 - 5 files changed, 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 638fd3f603..a7f0d358ed 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty { diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index 800346280d..7cd569035b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index eadf60b10b..b9984a8b90 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; -using osuTK; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 1a671e8041..e9ee3833b7 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osuTK; namespace osu.Game.Rulesets.Objects { diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index cb89653675..7e17396fde 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; using osu.Game.Replays; -using osuTK; namespace osu.Game.Rulesets.Replays { From da41b70d438108d09b058bdc05b8f6f93c8d1f19 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 13:19:49 +0100 Subject: [PATCH 414/503] .NET Standard 2.1 implements Math.Clamp , use it instead of MathHelper.Clamp from osuTK. --- osu.Android.props | 2 +- osu.Android/Properties/AndroidManifest.xml | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Beatmaps/CatchBeatmapProcessor.cs | 5 +- .../Difficulty/CatchPerformanceCalculator.cs | 3 +- .../Difficulty/Skills/Movement.cs | 3 +- .../Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 +- .../osu.Game.Rulesets.Catch.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Patterns/Legacy/PatternGenerator.cs | 7 ++- .../Edit/ManiaSelectionHandler.cs | 4 +- .../osu.Game.Rulesets.Mania.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 +- .../Mods/OsuModFlashlight.cs | 3 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSlider.cs | 3 +- .../Objects/Drawables/DrawableSliderHead.cs | 2 +- .../Objects/Drawables/DrawableSpinner.cs | 3 +- .../Drawables/Pieces/SnakingSliderBody.cs | 2 +- .../osu.Game.Rulesets.Osu.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 4 +- .../Objects/Drawables/DrawableSwell.cs | 3 +- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 3 +- .../osu.Game.Rulesets.Taiko.csproj | 2 +- .../Properties/AndroidManifest.xml | 2 +- .../SongSelect/TestScenePlaySongSelect.cs | 53 +++++++++++++------ .../Screens/Ladder/LadderDragContainer.cs | 3 +- .../osu.Game.Tournament.csproj | 2 +- .../Graphics/Containers/ParallaxContainer.cs | 3 +- osu.Game/Graphics/UserInterface/Bar.cs | 4 +- .../Graphics/UserInterface/OsuSliderBar.cs | 4 +- .../Graphics/UserInterface/OsuTabControl.cs | 2 +- .../Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- .../Header/Components/SupporterIcon.cs | 4 +- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +- .../Rulesets/Objects/SliderEventGenerator.cs | 3 +- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- .../Replays/FramedReplayInputHandler.cs | 3 +- .../Algorithms/OverlappingScrollAlgorithm.cs | 4 +- osu.Game/Scoring/ScoreInfo.cs | 6 ++- osu.Game/Scoring/ScoreManager.cs | 2 +- .../Timelines/Summary/Parts/MarkerPart.cs | 3 +- .../Components/CircularDistanceSnapGrid.cs | 2 +- .../Timeline/ZoomableScrollContainer.cs | 4 +- osu.Game/Screens/Edit/EditorClock.cs | 3 +- osu.Game/Screens/Menu/Button.cs | 2 +- .../Screens/Play/HUD/HoldForMenuButton.cs | 4 +- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 6 +-- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- .../Screens/Select/Details/FailRetryGraph.cs | 4 +- osu.Game/Screens/Select/SongSelect.cs | 47 ++++++++++------ osu.Game/Tests/Visual/OsuTestScene.cs | 3 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 13 +++++ 60 files changed, 164 insertions(+), 116 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..d06e04aea4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ Off True Xamarin.Android.Net.AndroidClientHandler - v9.0 + v10.0 false true armeabi-v7a;x86;arm64-v8a diff --git a/osu.Android/Properties/AndroidManifest.xml b/osu.Android/Properties/AndroidManifest.xml index acd21f9587..770eaf2222 100644 --- a/osu.Android/Properties/AndroidManifest.xml +++ b/osu.Android/Properties/AndroidManifest.xml @@ -1,6 +1,6 @@  - + diff --git a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml index db95e18f13..0fa3b7730d 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 58bf811fac..db52fbac1b 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -8,7 +8,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; -using osuTK; using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Mods; @@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps catchObject.XOffset = 0; if (catchObject is TinyDroplet) - catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); + catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); else if (catchObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } @@ -230,7 +229,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps else { currentObject.DistanceToHyperDash = distanceToHyper; - lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); + lastExcess = Math.Clamp(distanceToHyper, 0, halfCatcherWidth); } lastDirection = thisDirection; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 5a640f6d1a..a7f0d358ed 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty { @@ -96,7 +95,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return value; } - private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index d146153294..7cd569035b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { @@ -31,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills if (lastPlayerPosition == null) lastPlayerPosition = catchCurrent.LastNormalizedPosition; - float playerPosition = MathHelper.Clamp( + float playerPosition = Math.Clamp( lastPlayerPosition.Value, catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..eae652573b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { base.Update(); - border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); + border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); } private Color4 colourForRepresentation(FruitVisualRepresentation representation) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..d330add1c4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Y -= RNG.NextSingle() * diff; } - fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); + fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); caughtFruit.Add(fruit); } @@ -378,7 +378,7 @@ namespace osu.Game.Rulesets.Catch.UI double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index f24cf1def9..b19affbf9f 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true catch the fruit. to the beat. diff --git a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml index e6728c801d..de7935b2ef 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index f989f22298..b9984a8b90 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; -using osuTK; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -54,11 +53,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// @@ -113,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy drainTime = 10000; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; - conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; + conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); return conversionDifficulty.Value; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..53f7e30dfd 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Timing; @@ -9,7 +10,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using osuTK; namespace osu.Game.Rulesets.Mania.Edit { @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Edit maxColumn = obj.Column; } - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 0af200d19b..07ef1022ae 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true smash the keys. to the beat. diff --git a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml index aad907b241..3ce17ccc27 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 1eb37f8119..63110b2797 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; } - private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; + private float calculateGap(float value) => Math.Clamp(value, 0, target_clamp) * targetBreakMultiplier; // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 7fa3dbe07e..778c2f7d43 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods var destination = e.MousePosition; FlashlightPosition = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + Math.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); return base.OnMouseMove(e); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 84d2a4af9b..122975d55e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables else { // If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly). - Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); + Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 433d29f2e4..69189758a6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -165,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.Value = Ball.Tracking; - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); Body.UpdateProgress(completionProgress); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 66b6f0f9ac..a10c66d1df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.Update(); - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!IsHit) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d1b9ee6cb4..1261d3d19a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => Math.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 70a1bad4a3..f2150280b3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; + double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; if (span >= slider.SpanCount() - 1) { diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index fb3fe8808d..bffeaabb55 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true click the circles. to the beat. diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml index cd4b74aa16..d9de0fde4e 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index cc0d6829ba..338fd9e20f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; using osuTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables else rollingHits--; - rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); + rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); MainPiece.FadeAccent(newColour, 100); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 9c9dfc5f9e..fa39819199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; @@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var completion = (float)numHits / HitObject.RequiredHits; expandingRing - .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) + .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) .Then() .FadeTo(completion / 8, 2000, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 84464b199e..980f5ea340 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; using osuTK; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.UI { base.Update(); - float aspectAdjust = MathHelper.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; + float aspectAdjust = Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; Size = new Vector2(1, default_relative_height * aspectAdjust); } } diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 0a2b189c3a..ebed8c6d7c 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true bash the drum. to the beat. diff --git a/osu.Game.Tests.Android/Properties/AndroidManifest.xml b/osu.Game.Tests.Android/Properties/AndroidManifest.xml index bb996dc5ca..4a63f0c357 100644 --- a/osu.Game.Tests.Android/Properties/AndroidManifest.xml +++ b/osu.Game.Tests.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index d45b1bdba2..a4b8d1a24a 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -57,23 +57,6 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(DrawableCarouselBeatmapSet), }; - private class TestSongSelect : PlaySongSelect - { - public Action StartRequested; - - public new Bindable Ruleset => base.Ruleset; - - public WorkingBeatmap CurrentBeatmap => Beatmap.Value; - public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; - public new BeatmapCarousel Carousel => base.Carousel; - - protected override bool OnStart() - { - StartRequested?.Invoke(); - return base.OnStart(); - } - } - private TestSongSelect songSelect; [BackgroundDependencyLoader] @@ -101,6 +84,17 @@ namespace osu.Game.Tests.Visual.SongSelect manager?.Delete(manager.GetAllUsableBeatmapSets()); }); + [Test] + public void TestSingleFilterOnEnter() + { + addRulesetImportStep(0); + addRulesetImportStep(0); + + createSongSelect(); + + AddAssert("filter count is 1", () => songSelect.FilterCount == 1); + } + [Test] public void TestAudioResuming() { @@ -373,5 +367,30 @@ namespace osu.Game.Tests.Visual.SongSelect base.Dispose(isDisposing); rulesets?.Dispose(); } + + private class TestSongSelect : PlaySongSelect + { + public Action StartRequested; + + public new Bindable Ruleset => base.Ruleset; + + public WorkingBeatmap CurrentBeatmap => Beatmap.Value; + public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; + public new BeatmapCarousel Carousel => base.Carousel; + + protected override bool OnStart() + { + StartRequested?.Invoke(); + return base.OnStart(); + } + + public int FilterCount; + + protected override void ApplyFilterToCarousel(FilterCriteria criteria) + { + FilterCount++; + base.ApplyFilterToCarousel(criteria); + } + } } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..724612ebce 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnScroll(ScrollEvent e) { - var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); + var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index f5306facaf..8e881fdd9c 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true tools for tournaments. diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 86f922e4b8..f8c21eabc2 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Input; @@ -71,7 +72,7 @@ namespace osu.Game.Graphics.Containers const float parallax_duration = 100; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index f8d5955503..0be928cf83 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using System; namespace osu.Game.Graphics.UserInterface { @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface get => length; set { - length = MathHelper.Clamp(value, 0, 1); + length = Math.Clamp(value, 0, 1); updateBarLength(); } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 11aba80d76..7412224f6c 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -175,9 +175,9 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - leftBox.Scale = new Vector2(MathHelper.Clamp( + leftBox.Scale = new Vector2(Math.Clamp( Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); - rightBox.Scale = new Vector2(MathHelper.Clamp( + rightBox.Scale = new Vector2(Math.Clamp( DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 585a46f3e1..064cba6adf 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface // dont bother calculating if the strip is invisible if (strip.Colour.MaxAlpha > 0) - strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); + strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); } public class OsuTabItem : TabItem, IHasAccentColour diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..583db460f4 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void tabCloseRequested(TabItem tab) { int totalTabs = TabContainer.Count - 1; // account for selectorTab - int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); + int currentIndex = Math.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index e3acd31626..83528298b1 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Music break; } - dstIndex = MathHelper.Clamp(dstIndex, 0, items.Count - 1); + dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1); if (srcIndex == dstIndex) return; diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index fa60a37ddb..d581e2750c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,7 +9,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { set { - int count = MathHelper.Clamp(value, 0, 3); + int count = Math.Clamp(value, 0, 3); if (count == 0) { diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 9edf57ad00..f217512965 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osuTK; namespace osu.Game.Rulesets.Mods { @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mods /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) { - double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); switch (clock) { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 0d8796b4cb..e9ee3833b7 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osuTK; namespace osu.Game.Rulesets.Objects { @@ -18,7 +17,7 @@ namespace osu.Game.Rulesets.Objects const double max_length = 100000; var length = Math.Min(max_length, totalDistance); - tickDistance = MathHelper.Clamp(tickDistance, 0, length); + tickDistance = Math.Clamp(tickDistance, 0, length); var minDistanceFromEnd = velocity * 10; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..e8ef16e825 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -246,7 +246,7 @@ namespace osu.Game.Rulesets.Objects private double progressToDistance(double progress) { - return MathHelper.Clamp(progress, 0, 1) * Distance; + return Math.Clamp(progress, 0, 1) * Distance; } private Vector2 interpolateVertices(int i, double d) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 4c011388fa..7e17396fde 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; using osu.Game.Replays; -using osuTK; namespace osu.Game.Rulesets.Replays { @@ -52,7 +51,7 @@ namespace osu.Game.Rulesets.Replays private int? currentFrameIndex; - private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; + private int nextFrameIndex => currentFrameIndex.HasValue ? Math.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; protected FramedReplayInputHandler(Replay replay) { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 5316585493..fe22a86fad 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,9 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -using osuTK; namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } } - i = MathHelper.Clamp(i, 0, controlPoints.Count - 1); + i = Math.Clamp(i, 0, controlPoints.Count - 1); return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d3c37bd4f4..f7bac82e74 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -183,6 +183,10 @@ namespace osu.Game.Scoring public override string ToString() => $"{User} playing {Beatmap}"; - public bool Equals(ScoreInfo other) => other?.OnlineScoreID == OnlineScoreID; + public bool Equals(ScoreInfo other) => + other != null + && other.OnlineScoreID == OnlineScoreID + && other.BeatmapInfoID == BeatmapInfoID + && other.Hash == Hash; } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 8475158c78..3279af05b6 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -69,6 +69,6 @@ namespace osu.Game.Scoring protected override ArchiveDownloadRequest CreateDownloadRequest(ScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score); - protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.OnlineScoreID == model.OnlineScoreID && s.Files.Any()); + protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items) => items.Any(s => s.Equals(model) && s.Files.Any()); } } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 07d307f293..79ada40a89 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts if (Beatmap.Value == null) return; - float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); + float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 0f2bae6305..fc7d51db4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index cffb6bedf3..54922fec5e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline get => zoomTarget; set { - value = MathHelper.Clamp(value, MinZoom, MaxZoom); + value = Math.Clamp(value, MinZoom, MaxZoom); if (IsLoaded) setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void setZoomTarget(float newZoom, float focusPoint) { - zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); + zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom); transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index bd2db4ae2b..93a5f19121 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -7,7 +7,6 @@ using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osuTK; namespace osu.Game.Screens.Edit { @@ -125,7 +124,7 @@ namespace osu.Game.Screens.Edit seekTime = nextTimingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); + seekTime = Math.Clamp(seekTime, 0, TrackLength); Seek(seekTime); } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index ffeadb96c7..fac6b69e1f 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu protected override void Update() { - iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); + iconText.Alpha = Math.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); base.Update(); } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 968b83e68c..640224c057 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -102,8 +102,8 @@ namespace osu.Game.Screens.Play.HUD else { Alpha = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), - Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + Math.Clamp(Clock.ElapsedFrameTime, 0, 200), + Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 33c7595b37..cdf495e257 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 05f6128ac2..715ba3c065 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Play { Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; - int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); + int countFilled = (int)Math.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); for (int i = 0; i < drawableRows.Count; i++) drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index e4971221c4..3d8fd5dad7 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -87,9 +87,9 @@ namespace osu.Game.Screens private static Color4 getColourFor(object type) { int hash = type.GetHashCode(); - byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); - byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); - byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); + byte r = (byte)Math.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); + byte g = (byte)Math.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); + byte b = (byte)Math.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..c328eebca7 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -677,7 +677,7 @@ namespace osu.Game.Screens.Select // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can // layer transformations on top, with a similar reasoning to the previous comment. - p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1)); + p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1)); } private class CarouselRoot : CarouselGroupEagerSelect diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 34297d89a4..121f8efe5a 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select.Details retryGraph.MaxValue = maxValue; failGraph.Values = fails.Select(f => (float)f); - retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); + retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + Math.Clamp(fail, 0, maxValue)); } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index e3cd98454a..a52edb70db 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -46,48 +46,54 @@ namespace osu.Game.Screens.Select protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; - public readonly FilterControl FilterControl; + public FilterControl FilterControl { get; private set; } protected virtual bool ShowFooter => true; /// /// Can be null if is false. /// - protected readonly BeatmapOptionsOverlay BeatmapOptions; + protected BeatmapOptionsOverlay BeatmapOptions { get; private set; } /// /// Can be null if is false. /// - protected readonly Footer Footer; + protected Footer Footer { get; private set; } /// /// Contains any panel which is triggered by a footer button. /// Helps keep them located beneath the footer itself. /// - protected readonly Container FooterPanels; + protected Container FooterPanels { get; private set; } protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); - protected readonly BeatmapCarousel Carousel; - private readonly BeatmapInfoWedge beatmapInfoWedge; + protected BeatmapCarousel Carousel { get; private set; } + + private BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; private BeatmapManager beatmaps; - protected readonly ModSelectOverlay ModSelect; + protected ModSelectOverlay ModSelect { get; private set; } + + protected SampleChannel SampleConfirm { get; private set; } - protected SampleChannel SampleConfirm; private SampleChannel sampleChangeDifficulty; private SampleChannel sampleChangeBeatmap; - protected readonly BeatmapDetailArea BeatmapDetails; + protected BeatmapDetailArea BeatmapDetails { get; private set; } private readonly Bindable decoupledRuleset = new Bindable(); [Resolved(canBeNull: true)] private MusicController music { get; set; } - protected SongSelect() + [BackgroundDependencyLoader(true)] + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { + // initial value transfer is required for FilterControl (it uses our re-cached bindables in its async load for the initial filter). + transferRulesetValue(); + AddRangeInternal(new Drawable[] { new ParallaxContainer @@ -161,7 +167,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.X, Height = FilterControl.HEIGHT, - FilterChanged = c => Carousel.Filter(c), + FilterChanged = ApplyFilterToCarousel, Background = { Width = 2 }, }, } @@ -211,11 +217,7 @@ namespace osu.Game.Screens.Select } BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); - } - [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) - { if (Footer != null) { Footer.AddButton(new FooterButtonMods { Current = Mods }, ModSelect); @@ -258,6 +260,12 @@ namespace osu.Game.Screens.Select } } + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) + { + if (this.IsCurrentScreen()) + Carousel.Filter(criteria); + } + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -429,6 +437,8 @@ namespace osu.Game.Screens.Select { base.OnEntering(last); + Carousel.Filter(FilterControl.CreateCriteria(), false); + this.FadeInFromZero(250); FilterControl.Activate(); } @@ -624,7 +634,7 @@ namespace osu.Game.Screens.Select return; // manual binding to parent ruleset to allow for delayed load in the incoming direction. - rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + transferRulesetValue(); Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; @@ -636,6 +646,11 @@ namespace osu.Game.Screens.Select boundLocalBindables = true; } + private void transferRulesetValue() + { + rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + } + private void delete(BeatmapSetInfo beatmap) { if (beatmap == null || beatmap.ID <= 0) return; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..13e08c7d22 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -22,7 +22,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { @@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index af60da3e70..8e3858d0f1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.1 Library true diff --git a/osu.iOS.props b/osu.iOS.props index 8124357312..6965b16303 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -75,4 +75,17 @@ + + + + + + + + + + + + + From 6cab517b2df2c8296d311a931ed21ddfc8f2c0ca Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 13:19:49 +0100 Subject: [PATCH 415/503] .NET Standard 2.1 implements Math.Clamp , use it instead of MathHelper.Clamp from osuTK. --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs | 5 ++--- .../Difficulty/CatchPerformanceCalculator.cs | 3 +-- osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs | 3 +-- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ++-- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 7 +++---- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs | 3 ++- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 3 ++- .../Objects/Drawables/DrawableSliderHead.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 3 ++- .../Objects/Drawables/Pieces/SnakingSliderBody.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 4 ++-- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 3 +-- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 3 ++- osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs | 3 ++- osu.Game/Graphics/Containers/ParallaxContainer.cs | 3 ++- osu.Game/Graphics/UserInterface/Bar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 4 ++-- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 2 +- osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- .../Overlays/Profile/Header/Components/SupporterIcon.cs | 4 ++-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- osu.Game/Rulesets/Objects/SliderEventGenerator.cs | 3 +-- osu.Game/Rulesets/Objects/SliderPath.cs | 2 +- osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs | 3 +-- .../UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs | 4 ++-- .../Edit/Components/Timelines/Summary/Parts/MarkerPart.cs | 3 ++- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 2 +- .../Compose/Components/Timeline/ZoomableScrollContainer.cs | 4 ++-- osu.Game/Screens/Edit/EditorClock.cs | 3 +-- osu.Game/Screens/Menu/Button.cs | 2 +- osu.Game/Screens/Play/HUD/HoldForMenuButton.cs | 4 ++-- osu.Game/Screens/Play/SongProgressBar.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 2 +- osu.Game/Screens/ScreenWhiteBox.cs | 6 +++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- osu.Game/Screens/Select/Details/FailRetryGraph.cs | 4 ++-- osu.Game/Tests/Visual/OsuTestScene.cs | 3 +-- 42 files changed, 65 insertions(+), 68 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 58bf811fac..db52fbac1b 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -8,7 +8,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; -using osuTK; using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Mods; @@ -78,7 +77,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps catchObject.XOffset = 0; if (catchObject is TinyDroplet) - catchObject.XOffset = MathHelper.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); + catchObject.XOffset = Math.Clamp(rng.Next(-20, 20) / CatchPlayfield.BASE_WIDTH, -catchObject.X, 1 - catchObject.X); else if (catchObject is Droplet) rng.Next(); // osu!stable retrieved a random droplet rotation } @@ -230,7 +229,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps else { currentObject.DistanceToHyperDash = distanceToHyper; - lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth); + lastExcess = Math.Clamp(distanceToHyper, 0, halfCatcherWidth); } lastDirection = thisDirection; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 5a640f6d1a..a7f0d358ed 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty { @@ -96,7 +95,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty return value; } - private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index d146153294..7cd569035b 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { @@ -31,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills if (lastPlayerPosition == null) lastPlayerPosition = catchCurrent.LastNormalizedPosition; - float playerPosition = MathHelper.Clamp( + float playerPosition = Math.Clamp( lastPlayerPosition.Value, catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 1af77b75fc..eae652573b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -278,7 +278,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { base.Update(); - border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); + border.Alpha = (float)Math.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); } private Color4 colourForRepresentation(FruitVisualRepresentation representation) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 56c8b33e02..d330add1c4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Y -= RNG.NextSingle() * diff; } - fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); + fruit.X = Math.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); caughtFruit.Add(fruit); } @@ -378,7 +378,7 @@ namespace osu.Game.Rulesets.Catch.UI double speed = BASE_SPEED * dashModifier * hyperDashModifier; Scale = new Vector2(Math.Abs(Scale.X) * direction, Scale.Y); - X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); + X = (float)Math.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index f989f22298..b9984a8b90 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; -using osuTK; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -54,11 +53,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// @@ -113,7 +112,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy drainTime = 10000; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; - conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; + conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); return conversionDifficulty.Value; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9cdf045b5b..53f7e30dfd 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Timing; @@ -9,7 +10,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using osuTK; namespace osu.Game.Rulesets.Mania.Edit { @@ -119,7 +119,7 @@ namespace osu.Game.Rulesets.Mania.Edit maxColumn = obj.Column; } - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 1eb37f8119..63110b2797 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +14,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Mods }; } - private float calculateGap(float value) => MathHelper.Clamp(value, 0, target_clamp) * targetBreakMultiplier; + private float calculateGap(float value) => Math.Clamp(value, 0, target_clamp) * targetBreakMultiplier; // lagrange polinominal for (0,0) (0.6,0.4) (1,1) should make a good curve private static float applyAdjustmentCurve(float value) => 0.6f * value * value + 0.4f * value; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 7fa3dbe07e..778c2f7d43 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -55,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Mods var destination = e.MousePosition; FlashlightPosition = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); + Math.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out); return base.OnMouseMove(e); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 84d2a4af9b..122975d55e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables else { // If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly). - Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); + Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 433d29f2e4..69189758a6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -165,7 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.Value = Ball.Tracking; - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); Body.UpdateProgress(completionProgress); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 66b6f0f9ac..a10c66d1df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.Update(); - double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. if (!IsHit) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d1b9ee6cb4..1261d3d19a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -136,7 +137,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables positionBindable.BindTo(HitObject.PositionBindable); } - public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); + public float Progress => Math.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); protected override void CheckForResult(bool userTriggered, double timeOffset) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 70a1bad4a3..f2150280b3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; + double end = SnakingIn.Value ? Math.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / (slider.TimePreempt / 3), 0, 1) : 1; if (span >= slider.SpanCount() - 1) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index cc0d6829ba..338fd9e20f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osuTK; using osuTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables else rollingHits--; - rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); + rollingHits = Math.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour); Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1); MainPiece.FadeAccent(newColour, 100); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 9c9dfc5f9e..fa39819199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; @@ -179,7 +178,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var completion = (float)numHits / HitObject.RequiredHits; expandingRing - .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) + .FadeTo(expandingRing.Alpha + Math.Clamp(completion / 16, 0.1f, 0.6f), 50) .Then() .FadeTo(completion / 8, 2000, Easing.OutQuint); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 84464b199e..980f5ea340 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Game.Rulesets.UI; using osuTK; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.UI { base.Update(); - float aspectAdjust = MathHelper.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; + float aspectAdjust = Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; Size = new Vector2(1, default_relative_height * aspectAdjust); } } diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f613ce5f46..724612ebce 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -32,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Ladder protected override bool OnScroll(ScrollEvent e) { - var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); + var newScale = Math.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale); this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint); this.ScaleTo(scale = newScale, 2000, Easing.OutQuint); diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 86f922e4b8..f8c21eabc2 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Input; @@ -71,7 +72,7 @@ namespace osu.Game.Graphics.Containers const float parallax_duration = 100; - double elapsed = MathHelper.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); + double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index f8d5955503..0be928cf83 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using System; namespace osu.Game.Graphics.UserInterface { @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface get => length; set { - length = MathHelper.Clamp(value, 0, 1); + length = Math.Clamp(value, 0, 1); updateBarLength(); } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 11aba80d76..7412224f6c 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -175,9 +175,9 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - leftBox.Scale = new Vector2(MathHelper.Clamp( + leftBox.Scale = new Vector2(Math.Clamp( Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); - rightBox.Scale = new Vector2(MathHelper.Clamp( + rightBox.Scale = new Vector2(Math.Clamp( DrawWidth - Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 585a46f3e1..064cba6adf 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface // dont bother calculating if the strip is invisible if (strip.Colour.MaxAlpha > 0) - strip.Width = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); + strip.Width = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 1000), strip.Width, StripWidth(), 0, 500, Easing.OutQuint); } public class OsuTabItem : TabItem, IHasAccentColour diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index 8b88d81b88..583db460f4 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void tabCloseRequested(TabItem tab) { int totalTabs = TabContainer.Count - 1; // account for selectorTab - int currentIndex = MathHelper.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); + int currentIndex = Math.Clamp(TabContainer.IndexOf(tab), 1, totalTabs); if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index e3acd31626..83528298b1 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Music break; } - dstIndex = MathHelper.Clamp(dstIndex, 0, items.Count - 1); + dstIndex = Math.Clamp(dstIndex, 0, items.Count - 1); if (srcIndex == dstIndex) return; diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index fa60a37ddb..d581e2750c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -8,7 +9,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osuTK; namespace osu.Game.Overlays.Profile.Header.Components { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { set { - int count = MathHelper.Clamp(value, 0, 3); + int count = Math.Clamp(value, 0, 3); if (count == 0) { diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 9edf57ad00..f217512965 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osuTK; namespace osu.Game.Rulesets.Mods { @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Mods /// The amount of adjustment to apply (from 0..1). private void applyAdjustment(double amount) { - double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + double adjust = 1 + (Math.Sign(FinalRateAdjustment) * Math.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); switch (clock) { diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index 0d8796b4cb..e9ee3833b7 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using osuTK; namespace osu.Game.Rulesets.Objects { @@ -18,7 +17,7 @@ namespace osu.Game.Rulesets.Objects const double max_length = 100000; var length = Math.Min(max_length, totalDistance); - tickDistance = MathHelper.Clamp(tickDistance, 0, length); + tickDistance = Math.Clamp(tickDistance, 0, length); var minDistanceFromEnd = velocity * 10; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 7763b0eaaf..e8ef16e825 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -246,7 +246,7 @@ namespace osu.Game.Rulesets.Objects private double progressToDistance(double progress) { - return MathHelper.Clamp(progress, 0, 1) * Distance; + return Math.Clamp(progress, 0, 1) * Distance; } private Vector2 interpolateVertices(int i, double d) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 4c011388fa..7e17396fde 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; using osu.Game.Replays; -using osuTK; namespace osu.Game.Rulesets.Replays { @@ -52,7 +51,7 @@ namespace osu.Game.Rulesets.Replays private int? currentFrameIndex; - private int nextFrameIndex => currentFrameIndex.HasValue ? MathHelper.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; + private int nextFrameIndex => currentFrameIndex.HasValue ? Math.Clamp(currentFrameIndex.Value + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1) : 0; protected FramedReplayInputHandler(Replay replay) { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 5316585493..fe22a86fad 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,9 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -using osuTK; namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } } - i = MathHelper.Clamp(i, 0, controlPoints.Count - 1); + i = Math.Clamp(i, 0, controlPoints.Count - 1); return controlPoints[i].StartTime + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 07d307f293..79ada40a89 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts if (Beatmap.Value == null) return; - float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); + float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); adjustableClock.Seek(markerPos / DrawWidth * Beatmap.Value.Track.Length); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 0f2bae6305..fc7d51db4b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = MathHelper.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index cffb6bedf3..54922fec5e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline get => zoomTarget; set { - value = MathHelper.Clamp(value, MinZoom, MaxZoom); + value = Math.Clamp(value, MinZoom, MaxZoom); if (IsLoaded) setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void setZoomTarget(float newZoom, float focusPoint) { - zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); + zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom); transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index bd2db4ae2b..93a5f19121 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -7,7 +7,6 @@ using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osuTK; namespace osu.Game.Screens.Edit { @@ -125,7 +124,7 @@ namespace osu.Game.Screens.Edit seekTime = nextTimingPoint.Time; // Ensure the sought point is within the boundaries - seekTime = MathHelper.Clamp(seekTime, 0, TrackLength); + seekTime = Math.Clamp(seekTime, 0, TrackLength); Seek(seekTime); } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index ffeadb96c7..fac6b69e1f 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -236,7 +236,7 @@ namespace osu.Game.Screens.Menu protected override void Update() { - iconText.Alpha = MathHelper.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); + iconText.Alpha = Math.Clamp((box.Scale.X - 0.5f) / 0.3f, 0, 1); base.Update(); } diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 968b83e68c..640224c057 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -102,8 +102,8 @@ namespace osu.Game.Screens.Play.HUD else { Alpha = Interpolation.ValueAt( - MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 200), - Alpha, MathHelper.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); + Math.Clamp(Clock.ElapsedFrameTime, 0, 200), + Alpha, Math.Clamp(1 - positionalAdjust, 0.04f, 1), 0, 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 33c7595b37..cdf495e257 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -116,7 +116,7 @@ namespace osu.Game.Screens.Play { base.Update(); - float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, MathHelper.Clamp(Time.Elapsed / 40, 0, 1)); + float newX = (float)Interpolation.Lerp(handleBase.X, NormalizedValue * UsableWidth, Math.Clamp(Time.Elapsed / 40, 0, 1)); fill.Width = newX; handleBase.X = newX; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 05f6128ac2..715ba3c065 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -256,7 +256,7 @@ namespace osu.Game.Screens.Play { Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; - int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); + int countFilled = (int)Math.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); for (int i = 0; i < drawableRows.Count; i++) drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index e4971221c4..3d8fd5dad7 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -87,9 +87,9 @@ namespace osu.Game.Screens private static Color4 getColourFor(object type) { int hash = type.GetHashCode(); - byte r = (byte)MathHelper.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); - byte g = (byte)MathHelper.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); - byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); + byte r = (byte)Math.Clamp(((hash & 0xFF0000) >> 16) * 0.8f, 20, 255); + byte g = (byte)Math.Clamp(((hash & 0x00FF00) >> 8) * 0.8f, 20, 255); + byte b = (byte)Math.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index fa0ca3d9b3..c328eebca7 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -677,7 +677,7 @@ namespace osu.Game.Screens.Select // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can // layer transformations on top, with a similar reasoning to the previous comment. - p.SetMultiplicativeAlpha(MathHelper.Clamp(1.75f - 1.5f * dist, 0, 1)); + p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1)); } private class CarouselRoot : CarouselGroupEagerSelect diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 34297d89a4..121f8efe5a 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Select.Details retryGraph.MaxValue = maxValue; failGraph.Values = fails.Select(f => (float)f); - retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); + retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + Math.Clamp(fail, 0, maxValue)); } } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 345fff90aa..13e08c7d22 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -22,7 +22,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { @@ -250,7 +249,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; From 66a3837ff4fe6c0cea4b12bb37f344885badf1ee Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Wed, 20 Nov 2019 14:25:44 +0100 Subject: [PATCH 416/503] Fix CI --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index f8c21eabc2..bf743b90ed 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.Containers if (!parallaxEnabled.Value) { content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); - content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); + content.Scale = new Vector2(1 + Math.Abs(ParallaxAmount)); } }; } @@ -75,7 +75,7 @@ namespace osu.Game.Graphics.Containers double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration); content.Position = Interpolation.ValueAt(elapsed, content.Position, offset, 0, parallax_duration, Easing.OutQuint); - content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + System.Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); + content.Scale = Interpolation.ValueAt(elapsed, content.Scale, new Vector2(1 + Math.Abs(ParallaxAmount)), 0, 1000, Easing.OutQuint); } firstUpdate = false; From e820ddd3e8c34da3b6f3d292062340942274589d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 19:27:34 +0300 Subject: [PATCH 417/503] Implement settings keywords --- .../Settings/Sections/Audio/AudioDevicesSettings.cs | 5 ++++- .../Overlays/Settings/Sections/Audio/VolumeSettings.cs | 2 ++ .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 1 + .../Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 3 ++- .../Settings/Sections/Gameplay/SongSelectSettings.cs | 7 +++++-- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 4 +++- .../Settings/Sections/Graphics/RendererSettings.cs | 2 ++ osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 6 ++++-- osu.Game/Overlays/Settings/SettingsItem.cs | 7 ++++++- osu.Game/Overlays/Settings/SettingsSubsection.cs | 7 ++++++- 10 files changed, 35 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 2c25808170..e9ae784061 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -60,7 +60,10 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Children = new Drawable[] { - dropdown = new AudioDeviceSettingsDropdown() + dropdown = new AudioDeviceSettingsDropdown + { + Keywords = new[] { "Speaker" } + } }; updateItems(); diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 0124f7090e..c297f694c0 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.01f }, }; + + Keywords = new[] { "Sound" }; } } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 520a8852b3..3ebfae05b2 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,6 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), + Keywords = new[] { "bar" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 2c6b2663c6..06d120762b 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -18,7 +18,8 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay new SettingsCheckbox { LabelText = "Increase visibility of first object when visual impairment mods are enabled", - Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) + Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), + Keywords = new[] { "Hidden", "Traceable" } }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index 3e2272dba6..fce0e3dea8 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -26,18 +26,21 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show converted beatmaps", Bindable = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), + Keywords = new[] { "Converts" } }, new SettingsSlider { LabelText = "Display beatmaps from", Bindable = config.GetBindable(OsuSetting.DisplayStarsMinimum), - KeyboardStep = 0.1f + KeyboardStep = 0.1f, + Keywords = new[] { "Stars" } }, new SettingsSlider { LabelText = "up to", Bindable = config.GetBindable(OsuSetting.DisplayStarsMaximum), - KeyboardStep = 0.1f + KeyboardStep = 0.1f, + Keywords = new[] { "Stars" } }, new SettingsEnumDropdown { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index f4de4c0c41..8275d6dc0a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -75,12 +75,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "UI Scaling", TransferValueOnCommit = true, Bindable = osuConfig.GetBindable(OsuSetting.UIScale), - KeyboardStep = 0.01f + KeyboardStep = 0.01f, + Keywords = new[] { "Scale" }, }, new SettingsEnumDropdown { LabelText = "Screen Scaling", Bindable = osuConfig.GetBindable(OsuSetting.Scaling), + Keywords = new[] { "Scale" }, }, scalingSettings = new FillFlowContainer> { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 7317076c54..1aee9a8efe 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -30,6 +30,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay) }, }; + + Keywords = new[] { "fps" }; } } } diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 4f2f3dfd1a..f1071314c6 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -27,12 +27,14 @@ namespace osu.Game.Overlays.Settings.Sections.Input new SettingsCheckbox { LabelText = "Raw input", - Bindable = rawInputToggle + Bindable = rawInputToggle, + Keywords = new[] { "Speed" } }, sensitivity = new SensitivitySetting { LabelText = "Cursor sensitivity", - Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity) + Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity), + Keywords = new[] { "Speed" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index d48c0b6b66..9a50185e11 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -76,7 +76,12 @@ namespace osu.Game.Overlays.Settings } } - public virtual IEnumerable FilterTerms => new[] { LabelText }; + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText } : new List(Keywords) + { + LabelText + }.ToArray(); + + public IEnumerable Keywords { get; set; } public bool MatchingFilter { diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index c9c763e8d4..0023888b91 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -21,7 +21,12 @@ namespace osu.Game.Overlays.Settings protected abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public IEnumerable FilterTerms => new[] { Header }; + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) + { + Header + }.ToArray(); + + public IEnumerable Keywords { get; set; } public bool MatchingFilter { From 7d8252183eed2a85ef2a0ee89615fcff9d8c1cb2 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 19:42:57 +0300 Subject: [PATCH 418/503] CI fix --- osu.Game/Overlays/Settings/SettingsItem.cs | 5 +---- osu.Game/Overlays/Settings/SettingsSubsection.cs | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 9a50185e11..8863e43cca 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -76,10 +76,7 @@ namespace osu.Game.Overlays.Settings } } - public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText } : new List(Keywords) - { - LabelText - }.ToArray(); + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText } : new List(Keywords) { LabelText }.ToArray(); public IEnumerable Keywords { get; set; } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 0023888b91..15f20d252c 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -21,10 +21,8 @@ namespace osu.Game.Overlays.Settings protected abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) - { - Header - }.ToArray(); + + public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) { Header }.ToArray(); public IEnumerable Keywords { get; set; } From f3d9abc84aa1226c56f85861682e23cfd4a2eac3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 19:57:02 +0300 Subject: [PATCH 419/503] Capitalize Bar for consistency --- osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 3ebfae05b2..ad9f3eec68 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), - Keywords = new[] { "bar" } + Keywords = new[] { "Bar" } }, new SettingsCheckbox { From 6b3010535fc289d2e5d1cd0c7836302e78122911 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 20 Nov 2019 21:03:31 +0300 Subject: [PATCH 420/503] Simplify Keywords usage for SettingsSubsection --- osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs | 6 ++++-- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 6 ++++-- osu.Game/Overlays/Settings/SettingsSubsection.cs | 5 +---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index c297f694c0..7bfec0fad8 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; @@ -12,6 +14,8 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override string Header => "Volume"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); + [BackgroundDependencyLoader] private void load(AudioManager audio, OsuConfigManager config) { @@ -22,8 +26,6 @@ namespace osu.Game.Overlays.Settings.Sections.Audio new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.01f }, new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.01f }, }; - - Keywords = new[] { "Sound" }; } } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 1aee9a8efe..92f4823142 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -12,6 +14,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override string Header => "Renderer"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "FPS" }); + [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig) { @@ -30,8 +34,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay) }, }; - - Keywords = new[] { "fps" }; } } } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 15f20d252c..9b3b2f570c 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -21,10 +21,7 @@ namespace osu.Game.Overlays.Settings protected abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - - public virtual IEnumerable FilterTerms => Keywords == null ? new[] { Header } : new List(Keywords) { Header }.ToArray(); - - public IEnumerable Keywords { get; set; } + public virtual IEnumerable FilterTerms => new[] { Header }; public bool MatchingFilter { From f066d8434cafcce2335518085b3d212933bc3e0d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 00:26:39 +0300 Subject: [PATCH 421/503] Apply suggestions --- osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs | 4 ---- osu.Game/Overlays/Settings/Sections/AudioSection.cs | 5 +++++ .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 2 +- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 4 ---- osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs | 6 ++---- osu.Game/Overlays/Settings/SettingsSection.cs | 2 +- 7 files changed, 10 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 7bfec0fad8..0124f7090e 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; @@ -14,8 +12,6 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override string Header => "Volume"; - public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); - [BackgroundDependencyLoader] private void load(AudioManager audio, OsuConfigManager config) { diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 7ca313a751..254af6ea21 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Settings.Sections.Audio; @@ -10,6 +12,9 @@ namespace osu.Game.Overlays.Settings.Sections public class AudioSection : SettingsSection { public override string Header => "Audio"; + + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); + public override IconUsage Icon => FontAwesome.Solid.VolumeUp; public AudioSection() diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index ad9f3eec68..0ac145ffe2 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), - Keywords = new[] { "Bar" } + Keywords = new[] { "Bar", "Hp" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 06d120762b..a71919a2fc 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Increase visibility of first object when visual impairment mods are enabled", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), - Keywords = new[] { "Hidden", "Traceable" } + Keywords = new[] { "Mod" } }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 92f4823142..7317076c54 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -14,8 +12,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override string Header => "Renderer"; - public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "FPS" }); - [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig) { diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index f1071314c6..4f2f3dfd1a 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -27,14 +27,12 @@ namespace osu.Game.Overlays.Settings.Sections.Input new SettingsCheckbox { LabelText = "Raw input", - Bindable = rawInputToggle, - Keywords = new[] { "Speed" } + Bindable = rawInputToggle }, sensitivity = new SensitivitySetting { LabelText = "Cursor sensitivity", - Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity), - Keywords = new[] { "Speed" } + Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity) }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index c878a9fc65..be3696029e 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings public abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public IEnumerable FilterTerms => new[] { Header }; + public virtual IEnumerable FilterTerms => new[] { Header }; private const int header_size = 26; private const int header_margin = 25; From 4a4f5ccbb2ecb5adee902922c3d6d43fe3bd7ac5 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 21 Nov 2019 02:35:58 +0300 Subject: [PATCH 422/503] Implement IAggregateAudioAdjustments properties for FallbackSampleStore --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index d1749d33c0..bb8149a57d 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -517,6 +517,12 @@ namespace osu.Game.Rulesets.UI public BindableDouble Frequency => throw new NotImplementedException(); + public IBindable AggregateVolume => throw new NotImplementedException(); + + public IBindable AggregateBalance => throw new NotImplementedException(); + + public IBindable AggregateFrequency => throw new NotImplementedException(); + public int PlaybackConcurrency { get => throw new NotImplementedException(); From ebae92db7b2fcafb6ce94f8f81f56af1b7b8d897 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 21 Nov 2019 03:18:31 +0300 Subject: [PATCH 423/503] Revert "Implement IAggregateAudioAdjustments properties for FallbackSampleStore" This reverts commit 4a4f5ccbb2ecb5adee902922c3d6d43fe3bd7ac5. --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index bb8149a57d..d1749d33c0 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -517,12 +517,6 @@ namespace osu.Game.Rulesets.UI public BindableDouble Frequency => throw new NotImplementedException(); - public IBindable AggregateVolume => throw new NotImplementedException(); - - public IBindable AggregateBalance => throw new NotImplementedException(); - - public IBindable AggregateFrequency => throw new NotImplementedException(); - public int PlaybackConcurrency { get => throw new NotImplementedException(); From 5391c752b4e896b44ca8782dd6c795d4c57dc447 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 21 Nov 2019 02:35:58 +0300 Subject: [PATCH 424/503] Implement IAggregateAudioAdjustments properties for FallbackSampleStore --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index aec0e58a10..e0aeff8330 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -517,6 +517,12 @@ namespace osu.Game.Rulesets.UI public BindableDouble Frequency => throw new NotImplementedException(); + public IBindable AggregateVolume => throw new NotImplementedException(); + + public IBindable AggregateBalance => throw new NotImplementedException(); + + public IBindable AggregateFrequency => throw new NotImplementedException(); + public int PlaybackConcurrency { get => throw new NotImplementedException(); From 76e63722cc51cb0a683fefab2b946198b4aa46a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:26:10 +0900 Subject: [PATCH 425/503] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6fab2e7868..cd317b76f4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,6 +53,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index af60da3e70..515edf6f9d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,7 +21,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 8124357312..9ea6576957 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,6 +73,6 @@ - + From be62e482964c08479d13d173793ad95ec57cf6a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:35:10 +0900 Subject: [PATCH 426/503] Fix tests not working if main or audio volume is zero --- .../Visual/Components/TestScenePreviewTrackManager.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 5dac40104a..d76905dab8 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -143,6 +143,17 @@ namespace osu.Game.Tests.Visual.Components PreviewTrack track = null; TestTrackOwner owner = null; + AddStep("ensure volume not zero", () => + { + if (audio.Volume.Value == 0) + audio.Volume.Value = 1; + + if (audio.VolumeTrack.Value == 0) + audio.VolumeTrack.Value = 1; + }); + + AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0); + AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); AddUntilStep("wait loaded", () => track.IsLoaded); AddStep("start track", () => track.Start()); From cf0f0f8a1bf534f7bfaab3a2c69a502143311f6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:37:50 +0900 Subject: [PATCH 427/503] Reword comment --- osu.Game/Audio/PreviewTrackManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index d85df42d2b..6f0b62543d 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -80,8 +80,7 @@ namespace osu.Game.Audio return; CurrentTrack.Stop(); - // CurrentTrack must not change until the scheduled stopped event has been invoked. - // To ensure that this doesn't early-return on (CurrentTrack != track) check. + // CurrentTrack should not be set to null here as it will result in incorrect handling in the track.Stopped callback above. } /// From 19dfbb0a45ba3a208ad34ba6b0e6b1507e3e605e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 10:55:31 +0900 Subject: [PATCH 428/503] Update obsolete usages --- osu.Game/Online/API/APIAccess.cs | 2 +- osu.Game/Online/API/APIRequest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index d722c7a98a..b6127027cc 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -227,7 +227,7 @@ namespace osu.Game.Online.API { try { - return JObject.Parse(req.ResponseString).SelectToken("form_error", true).ToObject(); + return JObject.Parse(req.GetResponseString()).SelectToken("form_error", true).ToObject(); } catch { diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index ea0d50511f..53b23f5922 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -113,7 +113,7 @@ namespace osu.Game.Online.API cancelled = true; WebRequest?.Abort(); - string responseString = WebRequest?.ResponseString; + string responseString = WebRequest?.GetResponseString(); if (!string.IsNullOrEmpty(responseString)) { From 0cbe29dbecb7ab231480726edc515e33955ea313 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 21 Nov 2019 11:05:18 +0900 Subject: [PATCH 429/503] Refactor / cleanup debouncing --- .../Multi/Lounge/Components/FilterControl.cs | 11 +++++++++- .../Multi/Lounge/Components/RoomsContainer.cs | 20 +++---------------- osu.Game/Screens/Multi/RoomManager.cs | 11 +--------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index d0d983bbff..1f92806fbb 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -37,10 +38,18 @@ namespace osu.Game.Screens.Multi.Lounge.Components { base.LoadComplete(); - Search.Current.BindValueChanged(_ => updateFilter()); + Search.Current.BindValueChanged(_ => scheduleUpdateFilter()); Tabs.Current.BindValueChanged(_ => updateFilter(), true); } + private ScheduledDelegate scheduledFilterUpdate; + + private void scheduleUpdateFilter() + { + scheduledFilterUpdate?.Cancel(); + scheduledFilterUpdate = Scheduler.AddDelayed(updateFilter, 200); + } + private void updateFilter() { filter.Value = new FilterCriteria diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 3dde9452e4..607b081653 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -9,7 +9,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osuTK; @@ -63,10 +62,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override void LoadComplete() { - filter?.BindValueChanged(f => scheduleFilter()); - - if (filter != null) - Filter(filter.Value); + filter?.BindValueChanged(f => Filter(f.NewValue), true); } public void Filter(FilterCriteria criteria) @@ -93,23 +89,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components }); } - private ScheduledDelegate scheduledFilter; - - private void scheduleFilter() - { - if (filter == null) - return; - - scheduledFilter?.Cancel(); - scheduledFilter = Scheduler.AddDelayed(() => Filter(filter.Value), 200); - } - private void addRooms(IEnumerable rooms) { foreach (var r in rooms) roomFlow.Add(new DrawableRoom(r) { Action = () => selectRoom(r) }); - filter?.TriggerChange(); + if (filter != null) + Filter(filter.Value); } private void removeRooms(IEnumerable rooms) diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index d6d3ec37ef..cdaba85b9e 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; -using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Online; using osu.Game.Online.API; @@ -45,7 +44,7 @@ namespace osu.Game.Screens.Multi currentFilter.BindValueChanged(_ => { if (IsLoaded) - schedulePoll(); + PollImmediately(); }); } @@ -158,14 +157,6 @@ namespace osu.Game.Screens.Multi return tcs.Task; } - private ScheduledDelegate scheduledPoll; - - private void schedulePoll() - { - scheduledPoll?.Cancel(); - scheduledPoll = Scheduler.AddDelayed(PollImmediately, 200); - } - /// /// Updates a local with a remote copy. /// From 2325f0382ca4413059b2ec68a1f0db4eb34b8dda Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 13:46:45 +0900 Subject: [PATCH 430/503] Cancel a potentially pending filter update when an update occurs --- osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 1f92806fbb..29d41132a7 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -52,6 +52,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void updateFilter() { + scheduledFilterUpdate?.Cancel(); + filter.Value = new FilterCriteria { SearchString = Search.Current.Value ?? string.Empty, From 8369be90f20842c6b9a6aaf4eba5a4671c0c2915 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 15:19:06 +0900 Subject: [PATCH 431/503] Allow skip button to actuate more than once --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 13 +--------- .../Screens/Play/GameplayClockContainer.cs | 26 ++++++++++++++++--- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 20 +++----------- 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index b152c21454..0d62d9a520 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay { skip = new SkipOverlay(6000) { - RequestSeek = _ => requestCount++ + RequestSkip = () => requestCount++ } }, }; @@ -60,17 +60,6 @@ namespace osu.Game.Tests.Visual.Gameplay checkRequestCount(1); } - [Test] - public void TestClickOnlyActuatesOnce() - { - AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); - checkRequestCount(1); - } - [Test] public void TestDoesntFadeOnMouseDown() { diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 671711f5a4..e1f4d8fa94 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -89,6 +89,11 @@ namespace osu.Game.Screens.Play private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + /// + /// Duration before gameplay start time required before skip button displays. + /// + public const double MINIMUM_SKIP_TIME = 1000; + private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); [BackgroundDependencyLoader] @@ -104,11 +109,9 @@ namespace osu.Game.Screens.Play startTime = Math.Min(startTime, 0); Seek(startTime); + adjustableClock.ProcessFrame(); - UserPlaybackRate.ValueChanged += _ => updateRate(); - - Seek(Math.Min(-beatmap.BeatmapInfo.AudioLeadIn, gameplayStartTime)); } public void Restart() @@ -139,6 +142,23 @@ namespace osu.Game.Screens.Play this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); } + /// + /// Skip forwardto the next valid skip point. + /// + public void Skip() + { + if (GameplayClock.CurrentTime > gameplayStartTime - MINIMUM_SKIP_TIME) + return; + + double skipTarget = gameplayStartTime - MINIMUM_SKIP_TIME; + + if (GameplayClock.CurrentTime < 0 && skipTarget > 6000) + // double skip exception for storyboards with very long intros + skipTarget = 0; + + Seek(skipTarget); + } + /// /// Seek to a specific time in gameplay. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a9b0649fab..d6488dc209 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -203,7 +203,7 @@ namespace osu.Game.Screens.Play }, new SkipOverlay(DrawableRuleset.GameplayStartTime) { - RequestSeek = GameplayClockContainer.Seek + RequestSkip = GameplayClockContainer.Skip }, FailOverlay = new FailOverlay { diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 835867fe62..3abe61d1a9 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play { private readonly double startTime; - public Action RequestSeek; + public Action RequestSkip; private Button button; private Box remainingTimeBox; @@ -90,11 +90,6 @@ namespace osu.Game.Screens.Play }; } - /// - /// Duration before gameplay start time required before skip button displays. - /// - private const double skip_buffer = 1000; - private const double fade_time = 300; private double beginFadeTime => startTime - fade_time; @@ -104,7 +99,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); // skip is not required if there is no extra "empty" time to skip. - if (Clock.CurrentTime > beginFadeTime - skip_buffer) + if (Clock.CurrentTime > beginFadeTime - GameplayClockContainer.MINIMUM_SKIP_TIME) { Alpha = 0; Expire(); @@ -115,10 +110,9 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(beginFadeTime)) this.FadeOut(fade_time); - button.Action = () => RequestSeek?.Invoke(beginFadeTime); + button.Action = () => RequestSkip?.Invoke(); displayTime = Time.Current; - Expire(); } @@ -335,13 +329,7 @@ namespace osu.Game.Screens.Play box.FlashColour(Color4.White, 500, Easing.OutQuint); aspect.ScaleTo(1.2f, 2000, Easing.OutQuint); - bool result = base.OnClick(e); - - // for now, let's disable the skip button after the first press. - // this will likely need to be contextual in the future (bound from external components). - Enabled.Value = false; - - return result; + return base.OnClick(e); } } } From 586e31efc256964b722de2112d55d367ee88ea56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 15:56:08 +0900 Subject: [PATCH 432/503] Update tests --- osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index addf7c3b28..9275dc636c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu; @@ -22,9 +23,7 @@ namespace osu.Game.Tests.Visual.Gameplay BeatmapInfo = { AudioLeadIn = 1000 } }); - AddUntilStep("player loaded", () => player.IsLoaded && player.Alpha == 1); - - AddAssert("correct lead-in", () => player.FirstFrameClockTime == 0); + AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, 0, 100)); } [Test] @@ -35,7 +34,7 @@ namespace osu.Game.Tests.Visual.Gameplay BeatmapInfo = { AudioLeadIn = 10000 } }); - AddAssert("correct lead-in", () => player.FirstFrameClockTime == player.GameplayStartTime - 10000); + AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, player.GameplayStartTime - 10000, 100)); } private void loadPlayerWithBeatmap(IBeatmap beatmap) From 9acfc2587aa6a8dcd34a2535f3fc4bcf928bac1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 15:59:59 +0900 Subject: [PATCH 433/503] Switch android to using managed network components --- osu.Android.props | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Android.props b/osu.Android.props index 4a1165d57f..0f0e82d56a 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -16,6 +16,8 @@ armeabi-v7a;x86;arm64-v8a true cjk,mideast,other,rare,west + System.Net.Http.HttpClientHandler + legacy SdkOnly prompt From 2dd2e3d861706d22991174ed0e068f7f3c738ae9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 16:55:18 +0900 Subject: [PATCH 434/503] Add correct AudioLeadIn support --- osu.Game/Screens/Play/GameplayClockContainer.cs | 17 +++++++++++++---- osu.Game/Screens/Play/Player.cs | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index e1f4d8fa94..bc6f649492 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -41,6 +41,8 @@ namespace osu.Game.Screens.Play private readonly double gameplayStartTime; + private readonly double firstHitObjectTime; + public readonly Bindable UserPlaybackRate = new BindableDouble(1) { Default = 1, @@ -61,11 +63,12 @@ namespace osu.Game.Screens.Play private readonly FramedOffsetClock platformOffsetClock; - public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime) + public GameplayClockContainer(WorkingBeatmap beatmap, IReadOnlyList mods, double gameplayStartTime, double firstHitObjectTime) { this.beatmap = beatmap; this.mods = mods; this.gameplayStartTime = gameplayStartTime; + this.firstHitObjectTime = firstHitObjectTime; RelativeSizeAxes = Axes.Both; @@ -102,11 +105,17 @@ namespace osu.Game.Screens.Play userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true); - double startTime = -beatmap.BeatmapInfo.AudioLeadIn; + // sane default provided by ruleset. + double startTime = Math.Min(0, gameplayStartTime); + // if a storyboard is present, it may dictate the appropriate start time by having events in negative time space. + // this is commonly used to display an intro before the audio track start. startTime = Math.Min(startTime, beatmap.Storyboard.FirstEventTime); - startTime = Math.Min(startTime, gameplayStartTime); - startTime = Math.Min(startTime, 0); + + // some beatmaps specify a current lead-in time which should be used instead of the ruleset-provided value when available. + // this is not available as an option in the live editor but can still be applied via .osu editing. + if (beatmap.BeatmapInfo.AudioLeadIn > 0) + startTime = Math.Min(startTime, firstHitObjectTime - beatmap.BeatmapInfo.AudioLeadIn); Seek(startTime); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d6488dc209..cb71693312 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -129,7 +129,7 @@ namespace osu.Game.Screens.Play if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime); + InternalChild = GameplayClockContainer = new GameplayClockContainer(working, Mods.Value, DrawableRuleset.GameplayStartTime, DrawableRuleset.Objects.First().StartTime); addUnderlayComponents(GameplayClockContainer); addGameplayComponents(GameplayClockContainer, working); From 29d23749285dfc0773a152ee81536a061cc0c9ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 17:12:29 +0900 Subject: [PATCH 435/503] Add back skip button actuation count tests --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 51 +++++++++++++++++-- osu.Game/Screens/Play/SkipOverlay.cs | 2 + 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 0d62d9a520..1b4b0b4dcc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -18,27 +18,41 @@ namespace osu.Game.Tests.Visual.Gameplay private SkipOverlay skip; private int requestCount; + private FramedOffsetClock offsetClock; + private StopwatchClock stopwatchClock; + + private double increment; + [SetUp] public void SetUp() => Schedule(() => { requestCount = 0; + increment = 6000; + Child = new Container { RelativeSizeAxes = Axes.Both, - Clock = new FramedOffsetClock(Clock) - { - Offset = -Clock.CurrentTime, - }, + Clock = offsetClock = new FramedOffsetClock(stopwatchClock = new StopwatchClock(true)), Children = new Drawable[] { skip = new SkipOverlay(6000) { - RequestSkip = () => requestCount++ + RequestSkip = () => + { + requestCount++; + offsetClock.Offset += increment; + } } }, }; }); + protected override void Update() + { + if (stopwatchClock != null) + stopwatchClock.Rate = Clock.Rate; + } + [Test] public void TestFadeOnIdle() { @@ -60,6 +74,33 @@ namespace osu.Game.Tests.Visual.Gameplay checkRequestCount(1); } + [Test] + public void TestClickOnlyActuatesOnce() + { + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => + { + increment = 6000 - offsetClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; + InputManager.Click(MouseButton.Left); + }); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(1); + } + + [Test] + public void TestClickOnlyActuatesMultipleTimes() + { + AddStep("set increment lower", () => increment = 3000); + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(2); + } + [Test] public void TestDoesntFadeOnMouseDown() { diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 3abe61d1a9..2c6b33be39 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -124,6 +124,8 @@ namespace osu.Game.Screens.Play { base.Update(); remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); + + button.Enabled.Value = Time.Current < startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; } protected override bool OnMouseMove(MouseMoveEvent e) From 4e53bca8dd1e8ad8392a13010af04a9e42b69e50 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 18:21:49 +0900 Subject: [PATCH 436/503] Simplify tests --- .../Visual/Gameplay/TestSceneLeadIn.cs | 31 +++++++++++-------- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 9275dc636c..6434387f51 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; +using System.Linq; using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Beatmaps; @@ -15,26 +17,26 @@ namespace osu.Game.Tests.Visual.Gameplay { private LeadInPlayer player; - [Test] - public void TestShortLeadIn() + private const double lenience_ms = 10; + + private const double first_hit_object = 2170; + + [TestCase(1000, 0)] + [TestCase(2000, 0)] + [TestCase(3000, first_hit_object - 3000)] + [TestCase(10000, first_hit_object - 10000)] + public void TestLeadInProducesCorrectStartTime(double leadIn, double expectedStartTime) { loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) { - BeatmapInfo = { AudioLeadIn = 1000 } + BeatmapInfo = { AudioLeadIn = leadIn } }); - AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, 0, 100)); - } - - [Test] - public void TestLongLeadIn() - { - loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo) + AddAssert($"first frame is {expectedStartTime}", () => { - BeatmapInfo = { AudioLeadIn = 10000 } + Debug.Assert(player.FirstFrameClockTime != null); + return Precision.AlmostEquals(player.FirstFrameClockTime.Value, expectedStartTime, lenience_ms); }); - - AddAssert("correct lead-in", () => Precision.AlmostEquals(player.FirstFrameClockTime.Value, player.GameplayStartTime - 10000, 100)); } private void loadPlayerWithBeatmap(IBeatmap beatmap) @@ -61,6 +63,8 @@ namespace osu.Game.Tests.Visual.Gameplay public double GameplayStartTime => DrawableRuleset.GameplayStartTime; + public double FirstHitObjectTime => DrawableRuleset.Objects.First().StartTime; + public double GameplayClockTime => GameplayClockContainer.GameplayClock.CurrentTime; protected override void UpdateAfterChildren() @@ -73,6 +77,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddInternal(new OsuSpriteText { Text = $"GameplayStartTime: {DrawableRuleset.GameplayStartTime} " + + $"FirstHitObjectTime: {FirstHitObjectTime} " + $"LeadInTime: {Beatmap.Value.BeatmapInfo.AudioLeadIn} " + $"FirstFrameClockTime: {FirstFrameClockTime}" }); diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 198046df4f..6e82c465dc 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -76,7 +76,7 @@ namespace osu.Game.Beatmaps public string MD5Hash { get; set; } // General - public int AudioLeadIn { get; set; } + public double AudioLeadIn { get; set; } public bool Countdown { get; set; } = true; public float StackLeniency { get; set; } = 0.7f; public bool SpecialStyle { get; set; } From 8d1b11d4bd86b644c683bd74eac0dc893f61823a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 18:50:54 +0900 Subject: [PATCH 437/503] Add storyboard lead-in tests --- .../TestSceneSkinFallbacks.cs | 7 +++-- .../TestSceneSpinnerRotation.cs | 5 ++-- .../Visual/Gameplay/TestSceneAutoplay.cs | 5 ++-- .../Gameplay/TestSceneGameplayRewinding.cs | 5 ++-- .../Visual/Gameplay/TestSceneLeadIn.cs | 29 +++++++++++++++++-- .../TestScenePlayerReferenceLeaking.cs | 5 ++-- .../Drawables/DrawableStoryboardSprite.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 10 +++++-- osu.Game/Tests/Visual/OsuTestScene.cs | 14 +++++---- 9 files changed, 60 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 02c65db6ad..7ca311118e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -19,6 +19,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Screens.Play; using osu.Game.Skinning; +using osu.Game.Storyboards; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests @@ -75,14 +76,14 @@ namespace osu.Game.Rulesets.Osu.Tests protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin); - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => new CustomSkinWorkingBeatmap(beatmap, Clock, audio, testBeatmapSkin); + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, audio, testBeatmapSkin); public class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap { private readonly ISkinSource skin; - public CustomSkinWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin) - : base(beatmap, frameBasedClock, audio) + public CustomSkinWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin) + : base(beatmap, storyboard, frameBasedClock, audio) { this.skin = skin; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index cded7f0e95..d0ce0c33c2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -15,6 +15,7 @@ using osu.Game.Tests.Visual; using osuTK; using System.Collections.Generic; using System.Linq; +using osu.Game.Storyboards; using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; namespace osu.Game.Rulesets.Osu.Tests @@ -28,9 +29,9 @@ namespace osu.Game.Rulesets.Osu.Tests protected override bool Autoplay => true; - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); track = (TrackVirtualManual)working.Track; return working; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index f94071a7a9..5ee109e3dd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -7,6 +7,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { @@ -29,9 +30,9 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); } - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = base.CreateWorkingBeatmap(beatmap); + var working = base.CreateWorkingBeatmap(beatmap, storyboard); track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index ffc025a942..b2b58a63fb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; +using osu.Game.Storyboards; using osuTK; namespace osu.Game.Tests.Visual.Gameplay @@ -35,9 +36,9 @@ namespace osu.Game.Tests.Visual.Gameplay private Track track; - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = new ClockBackedTestWorkingBeatmap(beatmap, new FramedClock(new ManualClock { Rate = 1 }), audioManager); + var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audioManager); track = working.Track; return working; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index 6434387f51..0150c6ea74 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -4,12 +4,15 @@ using System.Diagnostics; using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; +using osu.Game.Storyboards; using osu.Game.Tests.Beatmaps; +using osuTK; namespace osu.Game.Tests.Visual.Gameplay { @@ -39,11 +42,33 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private void loadPlayerWithBeatmap(IBeatmap beatmap) + [TestCase(1000, 0)] + [TestCase(0, 0)] + [TestCase(-1000, -1000)] + [TestCase(-10000, -10000)] + public void TestStoryboardProducesCorrectStartTime(double firstStoryboardEvent, double expectedStartTime) + { + var storyboard = new Storyboard(); + + var sprite = new StoryboardSprite("unknown", Anchor.TopLeft, Vector2.Zero); + sprite.TimelineGroup.Alpha.Add(Easing.None, firstStoryboardEvent, firstStoryboardEvent + 500, 0, 1); + + storyboard.GetLayer("Background").Add(sprite); + + loadPlayerWithBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo), storyboard); + + AddAssert($"first frame is {expectedStartTime}", () => + { + Debug.Assert(player.FirstFrameClockTime != null); + return Precision.AlmostEquals(player.FirstFrameClockTime.Value, expectedStartTime, lenience_ms); + }); + } + + private void loadPlayerWithBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { AddStep("create player", () => { - Beatmap.Value = CreateWorkingBeatmap(beatmap); + Beatmap.Value = CreateWorkingBeatmap(beatmap, storyboard); LoadScreen(player = new LeadInPlayer()); }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index 65b56319e8..4d701f56a9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -6,6 +6,7 @@ using osu.Framework.Lists; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Screens.Play; +using osu.Game.Storyboards; namespace osu.Game.Tests.Visual.Gameplay { @@ -42,9 +43,9 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) { - var working = base.CreateWorkingBeatmap(beatmap); + var working = base.CreateWorkingBeatmap(beatmap, storyboard); workingWeakReferences.Add(working); return working; } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 5f1f5ddacb..3a117d1713 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -66,7 +66,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(IBindable beatmap, TextureStore textureStore) { - var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; + var path = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.InvariantCultureIgnoreCase))?.FileInfo.StoragePath; if (path == null) return; diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 0d9f4f51be..871d8ee3f1 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -5,25 +5,31 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; +using osu.Game.Storyboards; namespace osu.Game.Tests.Beatmaps { public class TestWorkingBeatmap : WorkingBeatmap { private readonly IBeatmap beatmap; + private readonly Storyboard storyboard; /// /// Create an instance which provides the when requested. /// - /// The beatmap - public TestWorkingBeatmap(IBeatmap beatmap) + /// The beatmap. + /// An optional storyboard. + public TestWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) : base(beatmap.BeatmapInfo, null) { this.beatmap = beatmap; + this.storyboard = storyboard; } protected override IBeatmap GetBeatmap() => beatmap; + protected override Storyboard GetStoryboard() => storyboard ?? base.GetStoryboard(); + protected override Texture GetBackground() => null; protected override VideoSprite GetVideo() => null; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 13e08c7d22..be67c2fe23 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -21,6 +21,7 @@ using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Storyboards; using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Visual @@ -119,10 +120,10 @@ namespace osu.Game.Tests.Visual protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) => - CreateWorkingBeatmap(CreateBeatmap(ruleset)); + CreateWorkingBeatmap(CreateBeatmap(ruleset), null); - protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => - new ClockBackedTestWorkingBeatmap(beatmap, Clock, audio); + protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => + new ClockBackedTestWorkingBeatmap(beatmap, storyboard, Clock, audio); [BackgroundDependencyLoader] private void load(RulesetStore rulesets) @@ -168,7 +169,7 @@ namespace osu.Game.Tests.Visual /// A clock which should be used instead of a stopwatch for virtual time progression. /// Audio manager. Required if a reference clock isn't provided. public ClockBackedTestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock, AudioManager audio) - : this(new TestBeatmap(ruleset), referenceClock, audio) + : this(new TestBeatmap(ruleset), null, referenceClock, audio) { } @@ -176,11 +177,12 @@ namespace osu.Game.Tests.Visual /// Create an instance which provides the when requested. /// /// The beatmap + /// The storyboard. /// An optional clock which should be used instead of a stopwatch for virtual time progression. /// Audio manager. Required if a reference clock isn't provided. /// The length of the returned virtual track. - public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock referenceClock, AudioManager audio, double length = 60000) - : base(beatmap) + public ClockBackedTestWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard, IFrameBasedClock referenceClock, AudioManager audio, double length = 60000) + : base(beatmap, storyboard) { if (referenceClock != null) { From 46a94821d44129975336136556b2b18e9e791e1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 18:57:19 +0900 Subject: [PATCH 438/503] Add support for consecutive skips --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 42 ++++++++++++++++--- .../Screens/Play/GameplayClockContainer.cs | 22 ++++++++++ osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Play/SkipOverlay.cs | 22 +++------- 4 files changed, 65 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index b152c21454..1b4b0b4dcc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -18,27 +18,41 @@ namespace osu.Game.Tests.Visual.Gameplay private SkipOverlay skip; private int requestCount; + private FramedOffsetClock offsetClock; + private StopwatchClock stopwatchClock; + + private double increment; + [SetUp] public void SetUp() => Schedule(() => { requestCount = 0; + increment = 6000; + Child = new Container { RelativeSizeAxes = Axes.Both, - Clock = new FramedOffsetClock(Clock) - { - Offset = -Clock.CurrentTime, - }, + Clock = offsetClock = new FramedOffsetClock(stopwatchClock = new StopwatchClock(true)), Children = new Drawable[] { skip = new SkipOverlay(6000) { - RequestSeek = _ => requestCount++ + RequestSkip = () => + { + requestCount++; + offsetClock.Offset += increment; + } } }, }; }); + protected override void Update() + { + if (stopwatchClock != null) + stopwatchClock.Rate = Clock.Rate; + } + [Test] public void TestFadeOnIdle() { @@ -64,13 +78,29 @@ namespace osu.Game.Tests.Visual.Gameplay public void TestClickOnlyActuatesOnce() { AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); - AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => + { + increment = 6000 - offsetClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; + InputManager.Click(MouseButton.Left); + }); AddStep("click", () => InputManager.Click(MouseButton.Left)); AddStep("click", () => InputManager.Click(MouseButton.Left)); AddStep("click", () => InputManager.Click(MouseButton.Left)); checkRequestCount(1); } + [Test] + public void TestClickOnlyActuatesMultipleTimes() + { + AddStep("set increment lower", () => increment = 3000); + AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + AddStep("click", () => InputManager.Click(MouseButton.Left)); + checkRequestCount(2); + } + [Test] public void TestDoesntFadeOnMouseDown() { diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 2f2028ff53..6903ccf06d 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -89,6 +89,11 @@ namespace osu.Game.Screens.Play private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; + /// + /// Duration before gameplay start time required before skip button displays. + /// + public const double MINIMUM_SKIP_TIME = 1000; + private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1); [BackgroundDependencyLoader] @@ -130,6 +135,23 @@ namespace osu.Game.Screens.Play this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); } + /// + /// Skip forward to the next valid skip point. + /// + public void Skip() + { + if (GameplayClock.CurrentTime > gameplayStartTime - MINIMUM_SKIP_TIME) + return; + + double skipTarget = gameplayStartTime - MINIMUM_SKIP_TIME; + + if (GameplayClock.CurrentTime < 0 && skipTarget > 6000) + // double skip exception for storyboards with very long intros + skipTarget = 0; + + Seek(skipTarget); + } + /// /// Seek to a specific time in gameplay. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a9b0649fab..d6488dc209 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -203,7 +203,7 @@ namespace osu.Game.Screens.Play }, new SkipOverlay(DrawableRuleset.GameplayStartTime) { - RequestSeek = GameplayClockContainer.Seek + RequestSkip = GameplayClockContainer.Skip }, FailOverlay = new FailOverlay { diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 835867fe62..2c6b33be39 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play { private readonly double startTime; - public Action RequestSeek; + public Action RequestSkip; private Button button; private Box remainingTimeBox; @@ -90,11 +90,6 @@ namespace osu.Game.Screens.Play }; } - /// - /// Duration before gameplay start time required before skip button displays. - /// - private const double skip_buffer = 1000; - private const double fade_time = 300; private double beginFadeTime => startTime - fade_time; @@ -104,7 +99,7 @@ namespace osu.Game.Screens.Play base.LoadComplete(); // skip is not required if there is no extra "empty" time to skip. - if (Clock.CurrentTime > beginFadeTime - skip_buffer) + if (Clock.CurrentTime > beginFadeTime - GameplayClockContainer.MINIMUM_SKIP_TIME) { Alpha = 0; Expire(); @@ -115,10 +110,9 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(beginFadeTime)) this.FadeOut(fade_time); - button.Action = () => RequestSeek?.Invoke(beginFadeTime); + button.Action = () => RequestSkip?.Invoke(); displayTime = Time.Current; - Expire(); } @@ -130,6 +124,8 @@ namespace osu.Game.Screens.Play { base.Update(); remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); + + button.Enabled.Value = Time.Current < startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; } protected override bool OnMouseMove(MouseMoveEvent e) @@ -335,13 +331,7 @@ namespace osu.Game.Screens.Play box.FlashColour(Color4.White, 500, Easing.OutQuint); aspect.ScaleTo(1.2f, 2000, Easing.OutQuint); - bool result = base.OnClick(e); - - // for now, let's disable the skip button after the first press. - // this will likely need to be contextual in the future (bound from external components). - Enabled.Value = false; - - return result; + return base.OnClick(e); } } } From bd6831624a58802f022eccc616d90f977c9155e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 19:51:22 +0900 Subject: [PATCH 439/503] Decouple skip button animations from gameplay clock --- .../Visual/Gameplay/TestSceneSkipOverlay.cs | 32 +++++++-------- osu.Game/Screens/Play/SkipOverlay.cs | 40 +++++++++---------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index 1b4b0b4dcc..a21f55e361 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -4,8 +4,8 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Timing; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; using osuTK; using osuTK.Input; @@ -18,40 +18,38 @@ namespace osu.Game.Tests.Visual.Gameplay private SkipOverlay skip; private int requestCount; - private FramedOffsetClock offsetClock; - private StopwatchClock stopwatchClock; - private double increment; + private GameplayClockContainer gameplayClockContainer; + private GameplayClock gameplayClock; + + private const double skip_time = 6000; + [SetUp] public void SetUp() => Schedule(() => { requestCount = 0; - increment = 6000; + increment = skip_time; - Child = new Container + Child = gameplayClockContainer = new GameplayClockContainer(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), new Mod[] { }, 0) { RelativeSizeAxes = Axes.Both, - Clock = offsetClock = new FramedOffsetClock(stopwatchClock = new StopwatchClock(true)), Children = new Drawable[] { - skip = new SkipOverlay(6000) + skip = new SkipOverlay(skip_time) { RequestSkip = () => { requestCount++; - offsetClock.Offset += increment; + gameplayClockContainer.Seek(gameplayClock.CurrentTime + increment); } } }, }; - }); - protected override void Update() - { - if (stopwatchClock != null) - stopwatchClock.Rate = Clock.Rate; - } + gameplayClockContainer.Start(); + gameplayClock = gameplayClockContainer.GameplayClock; + }); [Test] public void TestFadeOnIdle() @@ -80,7 +78,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); AddStep("click", () => { - increment = 6000 - offsetClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; + increment = skip_time - gameplayClock.CurrentTime - GameplayClockContainer.MINIMUM_SKIP_TIME / 2; InputManager.Click(MouseButton.Left); }); AddStep("click", () => InputManager.Click(MouseButton.Left)); diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 2c6b33be39..1a5ed20953 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -19,6 +19,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.MathUtils; using osu.Game.Input.Bindings; namespace osu.Game.Screens.Play @@ -35,6 +36,9 @@ namespace osu.Game.Screens.Play private FadeContainer fadeContainer; private double displayTime; + [Resolved] + private GameplayClock gameplayClock { get; set; } + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; /// @@ -45,8 +49,6 @@ namespace osu.Game.Screens.Play { this.startTime = startTime; - Show(); - RelativePositionAxes = Axes.Both; RelativeSizeAxes = Axes.X; @@ -57,13 +59,8 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, GameplayClock clock) + private void load(OsuColour colours) { - var baseClock = Clock; - - if (clock != null) - Clock = clock; - Children = new Drawable[] { fadeContainer = new FadeContainer @@ -73,7 +70,6 @@ namespace osu.Game.Screens.Play { button = new Button { - Clock = baseClock, Anchor = Anchor.Centre, Origin = Anchor.Centre, }, @@ -92,40 +88,40 @@ namespace osu.Game.Screens.Play private const double fade_time = 300; - private double beginFadeTime => startTime - fade_time; + private double fadeOutBeginTime => startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; protected override void LoadComplete() { base.LoadComplete(); // skip is not required if there is no extra "empty" time to skip. - if (Clock.CurrentTime > beginFadeTime - GameplayClockContainer.MINIMUM_SKIP_TIME) + // we may need to remove this if rewinding before the initial player load position becomes a thing. + if (fadeOutBeginTime < gameplayClock.CurrentTime) { - Alpha = 0; Expire(); return; } - this.FadeInFromZero(fade_time); - using (BeginAbsoluteSequence(beginFadeTime)) - this.FadeOut(fade_time); - button.Action = () => RequestSkip?.Invoke(); + displayTime = gameplayClock.CurrentTime; - displayTime = Time.Current; - Expire(); + Show(); } - protected override void PopIn() => this.FadeIn(); + protected override void PopIn() => this.FadeIn(fade_time); - protected override void PopOut() => this.FadeOut(); + protected override void PopOut() => this.FadeOut(fade_time); protected override void Update() { base.Update(); - remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); - button.Enabled.Value = Time.Current < startTime - GameplayClockContainer.MINIMUM_SKIP_TIME; + var progress = Math.Max(0, 1 - (gameplayClock.CurrentTime - displayTime) / (fadeOutBeginTime - displayTime)); + + remainingTimeBox.Width = (float)Interpolation.Lerp(remainingTimeBox.Width, progress, Math.Clamp(Time.Elapsed / 40, 0, 1)); + + button.Enabled.Value = progress > 0; + State.Value = progress > 0 ? Visibility.Visible : Visibility.Hidden; } protected override bool OnMouseMove(MouseMoveEvent e) From 71a64da566a685cce2ad929d989afab589c2b60e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:07:37 +0900 Subject: [PATCH 440/503] Fix test regressions --- osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index a21f55e361..875e7b9758 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre)); AddStep("button down", () => InputManager.PressButton(MouseButton.Left)); - AddUntilStep("wait for overlay disapper", () => !skip.IsAlive); + AddUntilStep("wait for overlay disappear", () => !skip.IsPresent); AddAssert("ensure button didn't disappear", () => skip.Children.First().Alpha > 0); AddStep("button up", () => InputManager.ReleaseButton(MouseButton.Left)); checkRequestCount(0); From 8b1fb2d5a1ab47fdf05f46e6f24b713d739440ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:35:15 +0900 Subject: [PATCH 441/503] Standardise keyword specifications --- .../Settings/Sections/Audio/AudioDevicesSettings.cs | 2 +- osu.Game/Overlays/Settings/Sections/AudioSection.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 5 ++++- .../Settings/Sections/Gameplay/SongSelectSettings.cs | 6 +++--- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 4 ++-- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index e9ae784061..0612f028bc 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { dropdown = new AudioDeviceSettingsDropdown { - Keywords = new[] { "Speaker" } + Keywords = new[] { "speaker", "headphone", "output" } } }; diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 254af6ea21..b18488b616 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections { public override string Header => "Audio"; - public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "Sound" }); + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "sound" }); public override IconUsage Icon => FontAwesome.Solid.VolumeUp; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 0ac145ffe2..f4aa9a0144 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show health display even when you can't fail", Bindable = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), - Keywords = new[] { "Bar", "Hp" } + Keywords = new[] { "hp", "bar" } }, new SettingsCheckbox { diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index a71919a2fc..0babb98066 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Game.Configuration; @@ -10,6 +12,8 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { protected override string Header => "Mods"; + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new[] { "mod" }); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -19,7 +23,6 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Increase visibility of first object when visual impairment mods are enabled", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), - Keywords = new[] { "Mod" } }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index fce0e3dea8..f4a861141f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -26,21 +26,21 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show converted beatmaps", Bindable = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), - Keywords = new[] { "Converts" } + Keywords = new[] { "convert" } }, new SettingsSlider { LabelText = "Display beatmaps from", Bindable = config.GetBindable(OsuSetting.DisplayStarsMinimum), KeyboardStep = 0.1f, - Keywords = new[] { "Stars" } + Keywords = new[] { "star", "difficulty" } }, new SettingsSlider { LabelText = "up to", Bindable = config.GetBindable(OsuSetting.DisplayStarsMaximum), KeyboardStep = 0.1f, - Keywords = new[] { "Stars" } + Keywords = new[] { "star", "difficulty" } }, new SettingsEnumDropdown { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 8275d6dc0a..02b9edd975 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -76,13 +76,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics TransferValueOnCommit = true, Bindable = osuConfig.GetBindable(OsuSetting.UIScale), KeyboardStep = 0.01f, - Keywords = new[] { "Scale" }, + Keywords = new[] { "scale", "letterbox" }, }, new SettingsEnumDropdown { LabelText = "Screen Scaling", Bindable = osuConfig.GetBindable(OsuSetting.Scaling), - Keywords = new[] { "Scale" }, + Keywords = new[] { "scale", "letterbox" }, }, scalingSettings = new FillFlowContainer> { From d7cb23a9094304d2e1f70172c2c2093c886de11f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:51:00 +0900 Subject: [PATCH 442/503] Remove redundant keyword --- .../Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index f4a861141f..a5f56ae76e 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -26,7 +26,6 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { LabelText = "Show converted beatmaps", Bindable = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), - Keywords = new[] { "convert" } }, new SettingsSlider { From 4475307707251bc591335cd02424274430fb6777 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 Nov 2019 22:55:31 +0900 Subject: [PATCH 443/503] Fix spacing --- osu.Game/Utils/SentryLogger.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 7e879741d6..981251784e 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -26,6 +26,7 @@ namespace osu.Game.Utils Dsn = new Dsn("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"), Release = game.Version }; + sentry = new SentryClient(options); sentryScope = new Scope(options); From 737c2bd1c8fa1a66bcf47160cc675fe082985941 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 18:50:29 +0300 Subject: [PATCH 444/503] Remove pointless const --- osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index e62a754e92..ac8952bebb 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -97,7 +97,6 @@ namespace osu.Game.Overlays.BeatmapSet private class ModButton : ModIcon { - private const float mod_scale = 0.4f; private const int duration = 200; public readonly BindableBool Selected = new BindableBool(); @@ -106,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet public ModButton(Mod mod) : base(mod) { - Scale = new Vector2(mod_scale); + Scale = new Vector2(0.4f); Highlighted.Value = true; Add(new HoverClickSounds()); } From 20f01ff3e9c68ea9ffd45cc60e76121ae1101038 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 21 Nov 2019 23:46:39 +0800 Subject: [PATCH 445/503] Revert false positives of 'unused assignment'. --- .../Legacy/HitObjectPatternGenerator.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 3b7a24726e..ba9aa9e87f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -168,43 +168,43 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } if (convertType.HasFlag(PatternType.KeepSingle)) - return generateRandomNotes(1); + return pattern = generateRandomNotes(1); if (convertType.HasFlag(PatternType.Mirror)) { if (ConversionDifficulty > 6.5) - return generateRandomPatternWithMirrored(0.12, 0.38, 0.12); + return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); if (ConversionDifficulty > 4) - return generateRandomPatternWithMirrored(0.12, 0.17, 0); + return pattern = generateRandomPatternWithMirrored(0.12, 0.17, 0); - return generateRandomPatternWithMirrored(0.12, 0, 0); + return pattern = generateRandomPatternWithMirrored(0.12, 0, 0); } if (ConversionDifficulty > 6.5) { if (convertType.HasFlag(PatternType.LowProbability)) - return generateRandomPattern(0.78, 0.42, 0, 0); + return pattern = generateRandomPattern(0.78, 0.42, 0, 0); - return generateRandomPattern(1, 0.62, 0, 0); + return pattern = generateRandomPattern(1, 0.62, 0, 0); } if (ConversionDifficulty > 4) { if (convertType.HasFlag(PatternType.LowProbability)) - return generateRandomPattern(0.35, 0.08, 0, 0); + return pattern = generateRandomPattern(0.35, 0.08, 0, 0); - return generateRandomPattern(0.52, 0.15, 0, 0); + return pattern = generateRandomPattern(0.52, 0.15, 0, 0); } if (ConversionDifficulty > 2) { if (convertType.HasFlag(PatternType.LowProbability)) - return generateRandomPattern(0.18, 0, 0, 0); + return pattern = generateRandomPattern(0.18, 0, 0, 0); - return generateRandomPattern(0.45, 0, 0, 0); + return pattern = generateRandomPattern(0.45, 0, 0, 0); } - return generateRandomPattern(0, 0, 0, 0); + return pattern = generateRandomPattern(0, 0, 0, 0); } finally { From 984ec11a78ca071e70d04cd5899ee7b07cfad140 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 18:56:48 +0300 Subject: [PATCH 446/503] Make Ruleset a bindable --- .../Online/TestSceneLeaderboardModSelector.cs | 14 ++++-- .../BeatmapSet/LeaderboardModSelector.cs | 49 ++++++++----------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index c0c18c2583..ebe233a5f4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -12,6 +12,8 @@ using osu.Game.Rulesets.Catch; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Bindables; +using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Online { @@ -26,6 +28,7 @@ namespace osu.Game.Tests.Visual.Online { LeaderboardModSelector modSelector; FillFlowContainer selectedMods; + var ruleset = new Bindable(); Add(selectedMods = new FillFlowContainer { @@ -37,6 +40,7 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Ruleset = { BindTarget = ruleset } }); modSelector.SelectedMods.ItemsAdded += mods => @@ -62,12 +66,12 @@ namespace osu.Game.Tests.Visual.Online }); }; - AddStep("osu ruleset", () => modSelector.Ruleset = new OsuRuleset().RulesetInfo); - AddStep("mania ruleset", () => modSelector.Ruleset = new ManiaRuleset().RulesetInfo); - AddStep("taiko ruleset", () => modSelector.Ruleset = new TaikoRuleset().RulesetInfo); - AddStep("catch ruleset", () => modSelector.Ruleset = new CatchRuleset().RulesetInfo); + AddStep("osu ruleset", () => ruleset.Value = new OsuRuleset().RulesetInfo); + AddStep("mania ruleset", () => ruleset.Value = new ManiaRuleset().RulesetInfo); + AddStep("taiko ruleset", () => ruleset.Value = new TaikoRuleset().RulesetInfo); + AddStep("catch ruleset", () => ruleset.Value = new CatchRuleset().RulesetInfo); AddStep("Deselect all", () => modSelector.DeselectAll()); - AddStep("null ruleset", () => modSelector.Ruleset = null); + AddStep("null ruleset", () => ruleset.Value = null); } } } diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index ac8952bebb..ba42e8c310 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -20,34 +20,7 @@ namespace osu.Game.Overlays.BeatmapSet public class LeaderboardModSelector : CompositeDrawable { public readonly BindableList SelectedMods = new BindableList(); - - private RulesetInfo ruleset; - - public RulesetInfo Ruleset - { - get => ruleset; - set - { - if (ruleset?.Equals(value) ?? false) - { - DeselectAll(); - return; - } - - ruleset = value; - - SelectedMods.Clear(); - modsContainer.Clear(); - - if (ruleset == null) - return; - - modsContainer.Add(new ModButton(new ModNoMod())); - modsContainer.AddRange(ruleset.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); - - modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); - } - } + public readonly Bindable Ruleset = new Bindable(); private readonly FillFlowContainer modsContainer; @@ -64,6 +37,26 @@ namespace osu.Game.Overlays.BeatmapSet }; } + protected override void LoadComplete() + { + base.LoadComplete(); + Ruleset.BindValueChanged(onRulesetChanged, true); + } + + private void onRulesetChanged(ValueChangedEvent ruleset) + { + SelectedMods.Clear(); + modsContainer.Clear(); + + if (ruleset.NewValue == null) + return; + + modsContainer.Add(new ModButton(new ModNoMod())); + modsContainer.AddRange(ruleset.NewValue.CreateInstance().GetAllMods().Where(m => m.Ranked).Select(m => new ModButton(m))); + + modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); + } + private void selectionChanged(Mod mod, bool selected) { if (selected) From 23fc7b198782d79333edfa849a29bfe27f9805cd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 19:02:24 +0300 Subject: [PATCH 447/503] Implement updateHighlighted method --- .../BeatmapSet/LeaderboardModSelector.cs | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index ba42e8c310..0a053c98db 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -64,24 +64,34 @@ namespace osu.Game.Overlays.BeatmapSet else SelectedMods.Remove(mod); - if (!SelectedMods.Any() && !IsHovered) + updateHighlighted(); + } + + private void updateHighlighted() + { + if (SelectedMods.Any()) + return; + + if (IsHovered) + { + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); + } + else + { highlightAll(); + } } protected override bool OnHover(HoverEvent e) { - if (!SelectedMods.Any()) - modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); - + updateHighlighted(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - - if (!SelectedMods.Any()) - highlightAll(); + updateHighlighted(); } public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); From 4cd7d67fe4eef0213128dfc619091c1844b50c63 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Nov 2019 00:02:40 +0800 Subject: [PATCH 448/503] Use early return for if-pattern-matching. --- .../Beatmaps/ManiaBeatmapConverter.cs | 12 +++---- .../Legacy/DistanceObjectPatternGenerator.cs | 12 +++---- .../TestSceneSlider.cs | 32 +++++++++---------- osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs | 18 +++++------ .../Components/ScrollingTeamContainer.cs | 24 +++++++------- 5 files changed, 47 insertions(+), 51 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6e3d5761ac..f5bd52146c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -263,15 +263,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private IList sampleInfoListAt(double time) { - if (HitObject is IHasCurve curveData) - { - double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); + if (!(HitObject is IHasCurve curveData)) + return HitObject.Samples; - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; - } + double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; } } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 0cbf5cf51c..cf75441200 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -474,15 +474,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// private IList sampleInfoListAt(double time) { - if (HitObject is IHasCurve curveData) - { - double segmentTime = (EndTime - HitObject.StartTime) / spanCount; + if (!(HitObject is IHasCurve curveData)) + return HitObject.Samples; - int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); - return curveData.NodeSamples[index]; - } + double segmentTime = (EndTime - HitObject.StartTime) / spanCount; - return HitObject.Samples; + int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); + return curveData.NodeSamples[index]; } /// diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 88c9324d4c..a9d5c03517 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -380,25 +380,25 @@ namespace osu.Game.Rulesets.Osu.Tests private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (judgedObject is DrawableOsuHitObject osuObject) + if (!(judgedObject is DrawableOsuHitObject osuObject)) + return; + + OsuSpriteText text; + Add(text = new OsuSpriteText { - OsuSpriteText text; - Add(text = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = result.IsHit ? "Hit!" : "Miss!", - Colour = result.IsHit ? Color4.Green : Color4.Red, - Font = OsuFont.GetFont(size: 30), - Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) - }); + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = result.IsHit ? "Hit!" : "Miss!", + Colour = result.IsHit ? Color4.Green : Color4.Red, + Font = OsuFont.GetFont(size: 30), + Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) + }); - text.Delay(150) - .Then().FadeOut(200) - .Then().Expire(); + text.Delay(150) + .Then().FadeOut(200) + .Then().Expire(); - judgementOffsetDirection *= -1; - } + judgementOffsetDirection *= -1; } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index b031707248..3d566362ae 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -22,17 +22,17 @@ namespace osu.Game.Rulesets.Osu.Mods osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y); - if (hitObject is Slider slider) - { - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + if (!(hitObject is Slider slider)) + return; - var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; - for (int i = 0; i < slider.Path.ControlPoints.Length; i++) - newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); + slider.NestedHitObjects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y)); - slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); - } + var newControlPoints = new Vector2[slider.Path.ControlPoints.Length]; + for (int i = 0; i < slider.Path.ControlPoints.Length; i++) + newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y); + + slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance); } } } diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index fff73fcf70..a345f93896 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -125,20 +125,20 @@ namespace osu.Game.Tournament.Screens.Drawings.Components foreach (var c in Children) { - if (c is ScrollingTeam stc) + if (!(c is ScrollingTeam stc)) + continue; + + if (closest == null) { - if (closest == null) - { - closest = stc; - continue; - } - - float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); - float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); - - if (o < lastOffset) - closest = stc; + closest = stc; + continue; } + + float o = Math.Abs(c.Position.X + c.DrawWidth / 2f - DrawWidth / 2f); + float lastOffset = Math.Abs(closest.Position.X + closest.DrawWidth / 2f - DrawWidth / 2f); + + if (o < lastOffset) + closest = stc; } Trace.Assert(closest != null, "closest != null"); From 8239c2da61228e0045a23b06a55ce4c1a3461e56 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Nov 2019 00:12:03 +0800 Subject: [PATCH 449/503] Refactor to avoid using try-finally as control flow. --- .../Legacy/HitObjectPatternGenerator.cs | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index ba9aa9e87f..84f950997d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -88,15 +89,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy public override IEnumerable Generate() { - yield return generate(); - } - - private Pattern generate() - { - var pattern = new Pattern(); - - try + Pattern generateCore() { + var pattern = new Pattern(); + if (TotalColumns == 1) { addToPattern(pattern, 0); @@ -168,54 +164,56 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } if (convertType.HasFlag(PatternType.KeepSingle)) - return pattern = generateRandomNotes(1); + return generateRandomNotes(1); if (convertType.HasFlag(PatternType.Mirror)) { if (ConversionDifficulty > 6.5) - return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); + return generateRandomPatternWithMirrored(0.12, 0.38, 0.12); if (ConversionDifficulty > 4) - return pattern = generateRandomPatternWithMirrored(0.12, 0.17, 0); + return generateRandomPatternWithMirrored(0.12, 0.17, 0); - return pattern = generateRandomPatternWithMirrored(0.12, 0, 0); + return generateRandomPatternWithMirrored(0.12, 0, 0); } if (ConversionDifficulty > 6.5) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.78, 0.42, 0, 0); + return generateRandomPattern(0.78, 0.42, 0, 0); - return pattern = generateRandomPattern(1, 0.62, 0, 0); + return generateRandomPattern(1, 0.62, 0, 0); } if (ConversionDifficulty > 4) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.35, 0.08, 0, 0); + return generateRandomPattern(0.35, 0.08, 0, 0); - return pattern = generateRandomPattern(0.52, 0.15, 0, 0); + return generateRandomPattern(0.52, 0.15, 0, 0); } if (ConversionDifficulty > 2) { if (convertType.HasFlag(PatternType.LowProbability)) - return pattern = generateRandomPattern(0.18, 0, 0, 0); + return generateRandomPattern(0.18, 0, 0, 0); - return pattern = generateRandomPattern(0.45, 0, 0, 0); + return generateRandomPattern(0.45, 0, 0, 0); } - return pattern = generateRandomPattern(0, 0, 0, 0); + return generateRandomPattern(0, 0, 0, 0); } - finally + + var p = generateCore(); + + foreach (var obj in p.HitObjects) { - foreach (var obj in pattern.HitObjects) - { - if (convertType.HasFlag(PatternType.Stair) && obj.Column == TotalColumns - 1) - StairType = PatternType.ReverseStair; - if (convertType.HasFlag(PatternType.ReverseStair) && obj.Column == RandomStart) - StairType = PatternType.Stair; - } + if (convertType.HasFlag(PatternType.Stair) && obj.Column == TotalColumns - 1) + StairType = PatternType.ReverseStair; + if (convertType.HasFlag(PatternType.ReverseStair) && obj.Column == RandomStart) + StairType = PatternType.Stair; } + + return p.Yield(); } /// From e22a71c6b80125e63660b3a0799b7325bce50348 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 19:42:07 +0300 Subject: [PATCH 450/503] Add visual difference between hovered and selected states --- .../BeatmapSet/LeaderboardModSelector.cs | 44 ++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 0a053c98db..0e9e848e7a 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -72,14 +72,7 @@ namespace osu.Game.Overlays.BeatmapSet if (SelectedMods.Any()) return; - if (IsHovered) - { - modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = false); - } - else - { - highlightAll(); - } + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.IsActive.Value = !IsHovered); } protected override bool OnHover(HoverEvent e) @@ -94,22 +87,19 @@ namespace osu.Game.Overlays.BeatmapSet updateHighlighted(); } - public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); - - private void highlightAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = true); + public void DeselectAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = false); private class ModButton : ModIcon { private const int duration = 200; - public readonly BindableBool Selected = new BindableBool(); + public readonly BindableBool IsActive = new BindableBool(); public Action OnSelectionChanged; public ModButton(Mod mod) : base(mod) { Scale = new Vector2(0.4f); - Highlighted.Value = true; Add(new HoverClickSounds()); } @@ -117,35 +107,39 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); - Selected.BindValueChanged(selected => + IsActive.BindValueChanged(hovered => { - updateState(); - OnSelectionChanged?.Invoke(Mod, selected.NewValue); - }); + if (Highlighted.Value) + return; + + this.FadeColour(hovered.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); + }, true); + } + + protected override void OnHighlightedChanged(ValueChangedEvent highlighted) + { + base.OnHighlightedChanged(highlighted); + OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); + IsActive.TriggerChange(); } protected override bool OnClick(ClickEvent e) { - Selected.Toggle(); + Highlighted.Toggle(); return true; } protected override bool OnHover(HoverEvent e) { - updateState(); + IsActive.Value = true; return false; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - updateState(); + IsActive.Value = false; } - - private void updateState() => Highlighted.Value = IsHovered || Selected.Value; - - protected override void OnHighlightedChanged(ValueChangedEvent highlighted) => - this.FadeColour(highlighted.NewValue ? Color4.White : Color4.Gray, duration, Easing.OutQuint); } } } From c7c8527f5ff780ccf012b41720545084757486b8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 20:22:15 +0300 Subject: [PATCH 451/503] Remove OnHighlightedChanged function --- .../Overlays/BeatmapSet/LeaderboardModSelector.cs | 11 +++++------ osu.Game/Rulesets/UI/ModIcon.cs | 9 +-------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 0e9e848e7a..bb6f889c40 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -114,13 +114,12 @@ namespace osu.Game.Overlays.BeatmapSet this.FadeColour(hovered.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); }, true); - } - protected override void OnHighlightedChanged(ValueChangedEvent highlighted) - { - base.OnHighlightedChanged(highlighted); - OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); - IsActive.TriggerChange(); + Highlighted.BindValueChanged(highlighted => + { + OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); + IsActive.TriggerChange(); + }, true); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 19211e0c80..cf1bbadb57 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -107,19 +107,12 @@ namespace osu.Game.Rulesets.UI modIcon.Colour = colours.Yellow; break; } - - background.Colour = backgroundColour; } protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(OnHighlightedChanged, true); - } - - protected virtual void OnHighlightedChanged(ValueChangedEvent highlighted) - { - background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour; + Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); } } } From f390e558c76532b4ac2d784a9cc02af0058122bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 02:32:02 +0900 Subject: [PATCH 452/503] Combine and simplify beatmap change logic --- osu.Game/Graphics/Containers/ScalingContainer.cs | 10 ---------- .../Screens/Backgrounds/BackgroundScreenDefault.cs | 1 + osu.Game/Screens/Menu/MainMenu.cs | 11 ----------- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 023d295b08..8f07c3a656 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -6,7 +6,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; @@ -155,15 +154,6 @@ namespace osu.Game.Graphics.Containers private class ScalingBackgroundScreen : BackgroundScreenDefault { - private IBindable beatmap; - - [BackgroundDependencyLoader] - private void load(IBindable beatmap) - { - this.beatmap = beatmap.GetBoundCopy(); - this.beatmap.ValueChanged += _ => Next(); - } - public override void OnEntering(IScreen last) { this.FadeInFromZero(4000, Easing.OutQuint); diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 93590b0543..d49751f511 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -46,6 +46,7 @@ namespace osu.Game.Screens.Backgrounds user.ValueChanged += _ => Next(); skin.ValueChanged += _ => Next(); mode.ValueChanged += _ => Next(); + beatmap.ValueChanged += _ => Next(); currentDisplay = RNG.Next(0, background_count); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 08338845e6..231115d1e1 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Platform; using osu.Framework.Screens; -using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -170,8 +169,6 @@ namespace osu.Game.Screens.Menu track.Start(); } } - - Beatmap.ValueChanged += beatmap_ValueChanged; } private bool exitConfirmed; @@ -220,14 +217,6 @@ namespace osu.Game.Screens.Menu seq.OnAbort(_ => buttons.SetOsuLogo(null)); } - private void beatmap_ValueChanged(ValueChangedEvent e) - { - if (!this.IsCurrentScreen()) - return; - - ((BackgroundScreenDefault)Background).Next(); - } - public override void OnSuspending(IScreen next) { base.OnSuspending(next); From 0f1a3d97c8d5c7a6daf9330663e3d81677d6d3f6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 20:34:19 +0300 Subject: [PATCH 453/503] Naming adjustments --- .../BeatmapSet/LeaderboardModSelector.cs | 32 +++++++++---------- osu.Game/Overlays/Mods/ModButton.cs | 2 +- osu.Game/Rulesets/UI/ModIcon.cs | 4 +-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index bb6f889c40..a6f69617d0 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -72,7 +72,7 @@ namespace osu.Game.Overlays.BeatmapSet if (SelectedMods.Any()) return; - modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.IsActive.Value = !IsHovered); + modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = !IsHovered); } protected override bool OnHover(HoverEvent e) @@ -87,13 +87,13 @@ namespace osu.Game.Overlays.BeatmapSet updateHighlighted(); } - public void DeselectAll() => modsContainer.ForEach(mod => mod.Highlighted.Value = false); + public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); private class ModButton : ModIcon { private const int duration = 200; - public readonly BindableBool IsActive = new BindableBool(); + public readonly BindableBool Highlighted = new BindableBool(); public Action OnSelectionChanged; public ModButton(Mod mod) @@ -107,37 +107,37 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); - IsActive.BindValueChanged(hovered => - { - if (Highlighted.Value) - return; - - this.FadeColour(hovered.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); - }, true); - Highlighted.BindValueChanged(highlighted => { - OnSelectionChanged?.Invoke(Mod, highlighted.NewValue); - IsActive.TriggerChange(); + if (Selected.Value) + return; + + this.FadeColour(highlighted.NewValue ? Color4.White : Color4.DimGray, duration, Easing.OutQuint); + }, true); + + Selected.BindValueChanged(selected => + { + OnSelectionChanged?.Invoke(Mod, selected.NewValue); + Highlighted.TriggerChange(); }, true); } protected override bool OnClick(ClickEvent e) { - Highlighted.Toggle(); + Selected.Toggle(); return true; } protected override bool OnHover(HoverEvent e) { - IsActive.Value = true; + Highlighted.Value = true; return false; } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - IsActive.Value = false; + Highlighted.Value = false; } } } diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 8252020e9b..c6b4787ff1 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Mods } } - foregroundIcon.Highlighted.Value = Selected; + foregroundIcon.Selected.Value = Selected; SelectionChanged?.Invoke(SelectedMod); return true; diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index cf1bbadb57..1be70ff48f 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.UI { public class ModIcon : Container, IHasTooltip { - public readonly BindableBool Highlighted = new BindableBool(); + public readonly BindableBool Selected = new BindableBool(); private readonly SpriteIcon modIcon; private readonly SpriteIcon background; @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Highlighted.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Selected.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); } } } From eb2f7c1d0a63f2bd0aa21cc56eeb61f58a066d5a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 21 Nov 2019 20:37:02 +0300 Subject: [PATCH 454/503] Rename forgotten variable --- osu.Game/Rulesets/UI/ModIcon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 1be70ff48f..945dbe4cc9 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.UI protected override void LoadComplete() { base.LoadComplete(); - Selected.BindValueChanged(highlighted => background.Colour = highlighted.NewValue ? highlightedColour : backgroundColour, true); + Selected.BindValueChanged(selected => background.Colour = selected.NewValue ? highlightedColour : backgroundColour, true); } } } From ab42fac43abe3250ece9eb306e07ad2a49db94cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 02:38:31 +0900 Subject: [PATCH 455/503] Improve naming --- .../{BackgroundMode.cs => BackgroundSource.cs} | 4 ++-- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Overlays/Settings/Sections/Audio/MainMenuSettings.cs | 8 ++++---- osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) rename osu.Game/Configuration/{BackgroundMode.cs => BackgroundSource.cs} (81%) diff --git a/osu.Game/Configuration/BackgroundMode.cs b/osu.Game/Configuration/BackgroundSource.cs similarity index 81% rename from osu.Game/Configuration/BackgroundMode.cs rename to osu.Game/Configuration/BackgroundSource.cs index 50d54f1eb2..5726e96eb1 100644 --- a/osu.Game/Configuration/BackgroundMode.cs +++ b/osu.Game/Configuration/BackgroundSource.cs @@ -3,9 +3,9 @@ namespace osu.Game.Configuration { - public enum BackgroundMode + public enum BackgroundSource { - Default, + Skin, Beatmap } } diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index b847f96a1f..b71463841a 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -118,7 +118,7 @@ namespace osu.Game.Configuration Set(OsuSetting.IntroSequence, IntroSequence.Triangles); - Set(OsuSetting.BackgroundMode, BackgroundMode.Default); + Set(OsuSetting.MenuBackgroundSource, BackgroundSource.Skin); } public OsuConfigManager(Storage storage) @@ -189,6 +189,6 @@ namespace osu.Game.Configuration IntroSequence, UIHoldActivationDelay, HitLighting, - BackgroundMode + MenuBackgroundSource } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs index 76a6aafe45..a303f93b34 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs @@ -34,11 +34,11 @@ namespace osu.Game.Overlays.Settings.Sections.Audio Bindable = config.GetBindable(OsuSetting.IntroSequence), Items = Enum.GetValues(typeof(IntroSequence)).Cast() }, - new SettingsDropdown + new SettingsDropdown { - LabelText = "Background", - Bindable = config.GetBindable(OsuSetting.BackgroundMode), - Items = Enum.GetValues(typeof(BackgroundMode)).Cast() + LabelText = "Background source", + Bindable = config.GetBindable(OsuSetting.MenuBackgroundSource), + Items = Enum.GetValues(typeof(BackgroundSource)).Cast() } }; } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index d49751f511..095985e9d1 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Backgrounds private Bindable user; private Bindable skin; - private Bindable mode; + private Bindable mode; [Resolved] private IBindable beatmap { get; set; } @@ -41,7 +41,7 @@ namespace osu.Game.Screens.Backgrounds { user = api.LocalUser.GetBoundCopy(); skin = skinManager.CurrentSkin.GetBoundCopy(); - mode = config.GetBindable(OsuSetting.BackgroundMode); + mode = config.GetBindable(OsuSetting.MenuBackgroundSource); user.ValueChanged += _ => Next(); skin.ValueChanged += _ => Next(); @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Backgrounds { switch (mode.Value) { - case BackgroundMode.Beatmap: + case BackgroundSource.Beatmap: newBackground = new BeatmapBackground(beatmap.Value, backgroundName); break; From 57d38c5c74c956e36920f43de95a4af9c11a0f9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 02:39:54 +0900 Subject: [PATCH 456/503] Add final newline --- osu.Game/Graphics/Backgrounds/BeatmapBackground.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index 40c6dae43c..387e189dc4 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -25,4 +25,4 @@ namespace osu.Game.Graphics.Backgrounds Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName); } } -} \ No newline at end of file +} From e170cd289269f9a028fb699953f2a28551a3e570 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 10:29:16 +0900 Subject: [PATCH 457/503] Move private methods below --- .../BeatmapSet/LeaderboardModSelector.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index a6f69617d0..60fd520681 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -57,6 +57,18 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.ForEach(button => button.OnSelectionChanged = selectionChanged); } + protected override bool OnHover(HoverEvent e) + { + updateHighlighted(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + updateHighlighted(); + } + private void selectionChanged(Mod mod, bool selected) { if (selected) @@ -75,18 +87,6 @@ namespace osu.Game.Overlays.BeatmapSet modsContainer.Children.Where(button => !button.IsHovered).ForEach(button => button.Highlighted.Value = !IsHovered); } - protected override bool OnHover(HoverEvent e) - { - updateHighlighted(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - updateHighlighted(); - } - public void DeselectAll() => modsContainer.ForEach(mod => mod.Selected.Value = false); private class ModButton : ModIcon From d8260f4a6511ce6118507f114e06eed4cd0bc229 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 10:51:49 +0900 Subject: [PATCH 458/503] Reduce carousel scroll motion on initial display --- osu.Game/Screens/Select/BeatmapCarousel.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 538656a5fa..17736e7819 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -640,10 +640,19 @@ namespace osu.Game.Screens.Select itemsCache.Validate(); } + private bool firstScroll = true; + private void updateScrollPosition() { if (scrollTarget != null) { + if (firstScroll) + { + // reduce movement when first displaying the carousel. + scroll.ScrollTo(scrollTarget.Value - 200, false); + firstScroll = false; + } + scroll.ScrollTo(scrollTarget.Value); scrollPositionCache.Validate(); } From da425c93fac6a629490690a3555d8d84e64e4118 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 05:08:50 +0300 Subject: [PATCH 459/503] Fix beatmap switch doesn't trigger scores update --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 3e3f823368..b33b5feb4d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -193,7 +193,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var beatmapRuleset = beatmap.NewValue?.Ruleset; if (ruleset.Value?.Equals(beatmapRuleset) ?? false) + { modSelector.DeselectAll(); + ruleset.TriggerChange(); + } else ruleset.Value = beatmapRuleset; From 745047fd193ce406f4c6d2896429279918536d67 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 05:10:47 +0300 Subject: [PATCH 460/503] Remove useless line from ModIcon --- osu.Game/Rulesets/UI/ModIcon.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index c22120d6e0..945dbe4cc9 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -107,8 +107,6 @@ namespace osu.Game.Rulesets.UI modIcon.Colour = colours.Yellow; break; } - - background.Colour = backgroundColour; } protected override void LoadComplete() From f079ebe857ebf708c5aae6ee0a7c102ea4c9c5f5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 16:13:48 +0900 Subject: [PATCH 461/503] Simplify beatmap lookup to use a single endpoint --- osu.Game/Online/API/Requests/GetBeatmapRequest.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index b37a6804fe..8e92cf0611 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -10,13 +10,11 @@ namespace osu.Game.Online.API.Requests { private readonly BeatmapInfo beatmap; - private string lookupString => beatmap.OnlineBeatmapID > 0 ? beatmap.OnlineBeatmapID.ToString() : $@"lookup?checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path)}"; - public GetBeatmapRequest(BeatmapInfo beatmap) { this.beatmap = beatmap; } - protected override string Target => $@"beatmaps/{lookupString}"; + protected override string Target => $@"beatmaps/lookup?id={beatmap.OnlineBeatmapID}&checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path)}"; } } From 0cc1698b6d1764b183e663db9d27f7d3e2b5ee0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:05:12 +0900 Subject: [PATCH 462/503] Rename incorrectly named container --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index b33b5feb4d..ac39671f56 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; private readonly DimmedLoadingLayer loading; - private readonly FillFlowContainer modFilter; + private readonly FillFlowContainer filterControls; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; private readonly FillFlowContainer content; @@ -94,7 +94,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { - modFilter = new FillFlowContainer + filterControls = new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -207,7 +207,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - modFilter.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); + filterControls.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); } private void getScores() From 16bdf4e6bd250ac5dd9cb6fa497d80e984002af1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:07:56 +0900 Subject: [PATCH 463/503] Update english to be more readable --- osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index aefff5d567..9cfce4ef5b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -27,16 +27,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores switch (scope) { default: - case BeatmapLeaderboardScope.Global: - text.Text = @"No scores yet. Maybe should try setting some?"; + text.Text = @"No scores have been set yet. Maybe you can be the first!"; return; case BeatmapLeaderboardScope.Friend: - text.Text = @"None of your friends has set a score on this map yet!"; + text.Text = @"None of your friends have set a score on this map yet."; return; case BeatmapLeaderboardScope.Country: - text.Text = @"No one from your country has set a score on this map yet!"; + text.Text = @"No one from your country has set a score on this map yet."; return; } } From dad2e5c678dc6f781ea46d4e6acf82411da46bd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:10:44 +0900 Subject: [PATCH 464/503] Improve legibility of NoScroesPlaceholder --- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 21 +++++++++++-------- .../BeatmapSet/Scores/ScoresContainer.cs | 8 ++----- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index 9cfce4ef5b..391ba93a4b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -3,9 +3,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; using osu.Game.Screens.Select.Leaderboards; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet.Scores { @@ -16,27 +16,30 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public NoScoresPlaceholder() { AutoSizeAxes = Axes.Both; - Child = text = new SpriteText - { - Font = OsuFont.GetFont(), - }; + Child = text = new OsuSpriteText(); } - public void UpdateText(BeatmapLeaderboardScope scope) + public override void Show() => this.FadeIn(200, Easing.OutQuint); + + public override void Hide() => this.FadeOut(200, Easing.OutQuint); + + public void ShowWithScope(BeatmapLeaderboardScope scope) { + Show(); + switch (scope) { default: text.Text = @"No scores have been set yet. Maybe you can be the first!"; - return; + break; case BeatmapLeaderboardScope.Friend: text.Text = @"None of your friends have set a score on this map yet."; - return; + break; case BeatmapLeaderboardScope.Country: text.Text = @"No one from your country has set a score on this map yet."; - return; + break; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index ac39671f56..86fb455eb8 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -23,7 +23,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoresContainer : CompositeDrawable { private const int spacing = 15; - private const int duration = 200; public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); @@ -215,7 +214,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores getScoresRequest?.Cancel(); getScoresRequest = null; - noScoresPlaceholder.FadeOut(duration, Easing.OutQuint); + noScoresPlaceholder.Hide(); if (Beatmap.Value?.OnlineBeatmapID.HasValue != true || Beatmap.Value.Status <= BeatmapSetOnlineStatus.Pending) { @@ -233,10 +232,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Scores = scores; if (!scores.Scores.Any()) - { - noScoresPlaceholder.UpdateText(scope.Value); - noScoresPlaceholder.FadeIn(duration, Easing.OutQuint); - } + noScoresPlaceholder.ShowWithScope(scope.Value); }; api.Queue(getScoresRequest); } From 66e2a259f0fcdcf7e349816f8f83a918edd7fcea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:21:40 +0900 Subject: [PATCH 465/503] Fix usage of SpriteText instead of OsuSpriteText --- CodeAnalysis/BannedSymbols.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index 9fb86485d2..3ad8d5db5b 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -2,3 +2,4 @@ M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use obj M:System.Object.Equals(System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. M:System.ValueType.Equals(System.Object)~System.Boolean;Don't use object.Equals(Fallbacks to ValueType). Use IEquatable or EqualityComparer.Default instead. T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. +T:osu.Framework.Graphics.Sprites.SpriteText;Use OsuSpriteText. From b026197859bd0fb362f80323621f7a53576d3fbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 18:23:48 +0900 Subject: [PATCH 466/503] Add spacing --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 86fb455eb8..f6f4b39c14 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -225,6 +225,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores content.Show(); loading.Show(); + getScoresRequest = new GetScoresRequest(Beatmap.Value, Beatmap.Value.Ruleset, scope.Value, modSelector.SelectedMods); getScoresRequest.Success += scores => { @@ -234,6 +235,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (!scores.Scores.Any()) noScoresPlaceholder.ShowWithScope(scope.Value); }; + api.Queue(getScoresRequest); } } From 6469199f0dd594049208f1634d127d4d04a4b5ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 19:47:21 +0900 Subject: [PATCH 467/503] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 0f0e82d56a..0da3e66236 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -55,6 +55,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 28ef7d3d92..449b4dc4e3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,7 +21,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 364b0b2c78..871a9238e3 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + From c2e85a205733bfad5d8433d5688dd94dd81f0012 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 19:49:20 +0900 Subject: [PATCH 468/503] Apply CornerExponent fixes --- .../Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs | 2 ++ .../Objects/Drawables/Connections/FollowPoint.cs | 3 +-- .../Objects/Drawables/Pieces/CirclePiece.cs | 2 ++ osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs | 3 +-- osu.Game.Tournament/Components/SongBar.cs | 2 ++ osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 1 + osu.Game/Overlays/Comments/DrawableComment.cs | 1 + osu.Game/Overlays/Volume/MuteButton.cs | 1 + osu.Game/Screens/Edit/Components/CircularButton.cs | 1 + osu.Game/Users/Drawables/UpdateableAvatar.cs | 6 ++++++ 10 files changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 2b6b93a590..2868ddeaa4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -17,7 +17,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components Origin = Anchor.Centre; Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + CornerRadius = Size.X / 2; + CornerExponent = 2; InternalChild = new RingPiece(); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index db34ae1d87..7e530ca047 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -25,11 +25,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { Origin = Anchor.Centre; - Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container + Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new CircularContainer { Masking = true, AutoSizeAxes = Axes.Both, - CornerRadius = width / 2, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index 210d5ff839..aab01f45d4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -16,7 +16,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Masking = true; + CornerRadius = Size.X / 2; + CornerExponent = 2; Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index c97b74756a..82e4383143 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs @@ -18,10 +18,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; Origin = Anchor.Centre; - InternalChild = new Container + InternalChild = new CircularContainer { Masking = true, - CornerRadius = Size.X / 2, BorderThickness = 10, BorderColour = Color4.White, RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 7005c068ae..43958aca7a 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -106,6 +106,7 @@ namespace osu.Game.Tournament.Components Width = main_width, Height = TournamentBeatmapPanel.HEIGHT, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + CornerExponent = 2, Children = new Drawable[] { new Box @@ -126,6 +127,7 @@ namespace osu.Game.Tournament.Components { Masking = true, CornerRadius = TournamentBeatmapPanel.HEIGHT / 2, + CornerExponent = 2, Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 0908814537..51483a0964 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -52,6 +52,7 @@ namespace osu.Game.Tournament.Components currentMatch.BindTo(ladder.CurrentMatch); CornerRadius = HEIGHT / 2; + CornerExponent = 2; Masking = true; AddRangeInternal(new Drawable[] diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3fb9867f0e..0d00f7c63b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -100,6 +100,7 @@ namespace osu.Game.Overlays.Comments Size = new Vector2(avatar_size), Masking = true, CornerRadius = avatar_size / 2f, + CornerExponent = 2, }, } }, diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index 6d876a77b1..bcc9394aba 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -43,6 +43,7 @@ namespace osu.Game.Overlays.Volume { Content.BorderThickness = 3; Content.CornerRadius = HEIGHT / 2; + Content.CornerExponent = 2; Size = new Vector2(width, HEIGHT); diff --git a/osu.Game/Screens/Edit/Components/CircularButton.cs b/osu.Game/Screens/Edit/Components/CircularButton.cs index 931c7d03a0..40b5ac663a 100644 --- a/osu.Game/Screens/Edit/Components/CircularButton.cs +++ b/osu.Game/Screens/Edit/Components/CircularButton.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Edit.Components { base.Update(); Content.CornerRadius = DrawHeight / 2f; + Content.CornerExponent = 2; } } } diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 795b90ba11..59fbb5f910 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -31,6 +31,12 @@ namespace osu.Game.Users.Drawables set => base.CornerRadius = value; } + public new float CornerExponent + { + get => base.CornerExponent; + set => base.CornerExponent = value; + } + public new EdgeEffectParameters EdgeEffect { get => base.EdgeEffect; From d0002cc1c25e9da8ede3277257c588b884a28c65 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 19:50:30 +0900 Subject: [PATCH 469/503] Update performance logging setting --- osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index 7eec971b62..457f064f89 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug new SettingsCheckbox { LabelText = "Performance logging", - Bindable = frameworkConfig.GetBindable(FrameworkSetting.PerformanceLogging) + Bindable = config.GetBindable(DebugSetting.PerformanceLogging) }, new SettingsCheckbox { From 4063135a3a894e262f880cca2b91904c51fb33c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Nov 2019 20:45:05 +0900 Subject: [PATCH 470/503] Fix result mode button's corner exponent --- osu.Game/Screens/Ranking/ResultModeButton.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index 1383511241..38636b0c3b 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -36,7 +36,9 @@ namespace osu.Game.Screens.Ranking Size = new Vector2(50); Masking = true; + CornerRadius = 25; + CornerExponent = 2; activeColour = colours.PinkDarker; inactiveColour = OsuColour.Gray(0.8f); From 4cb09df754aa0b03e145936660cd518117b1959d Mon Sep 17 00:00:00 2001 From: Albie Spriddell Date: Fri, 22 Nov 2019 18:23:48 +0000 Subject: [PATCH 471/503] increase padding --- osu.Game/Overlays/Mods/ModSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 3b16189e73..9c0a164ad6 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -167,7 +167,7 @@ namespace osu.Game.Overlays.Mods Spacing = new Vector2(50f, 0f), Margin = new MarginPadding { - Top = 6, + Top = 20, }, AlwaysPresent = true }, From d6c9387bebcc44dafc92693e6e6d6ceb3f46117e Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 21:55:21 +0300 Subject: [PATCH 472/503] Implement NotSupporterPlaceholder --- .../Online/TestSceneBeatmapSetOverlay.cs | 1 + .../Scores/NotSupporterPlaceholder.cs | 51 +++++++++++++++++++ .../BeatmapSet/Scores/ScoresContainer.cs | 1 + 3 files changed, 53 insertions(+) create mode 100644 osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 286971bc90..5ca2c9868f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.Online typeof(BeatmapAvailability), typeof(BeatmapRulesetSelector), typeof(BeatmapRulesetTabItem), + typeof(NotSupporterPlaceholder) }; protected override bool UseOnlineAPI => true; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs new file mode 100644 index 0000000000..86b02c0cff --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osuTK; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Overlays.BeatmapSet.Scores +{ + public class NotSupporterPlaceholder : Container + { + public NotSupporterPlaceholder() + { + LinkFlowContainer text; + + AutoSizeAxes = Axes.Both; + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = @"You need to be an osu!supporter to access the friend and country rankings!", + Font = OsuFont.GetFont(weight: FontWeight.Bold), + }, + text = new LinkFlowContainer(t => t.Font = t.Font.With(size: 12)) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + } + } + }; + + text.AddText("Click "); + text.AddLink("here", "/home/support"); + text.AddText(" to see all the fancy features that you can get!"); + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index f6f4b39c14..fe42ef2975 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -106,6 +106,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Current = { BindTarget = scope } }, + new NotSupporterPlaceholder(), modSelector = new LeaderboardModSelector { Ruleset = { BindTarget = ruleset } From aede1b183a597b0a354f2919e7787928eb409445 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 22:04:58 +0300 Subject: [PATCH 473/503] Make ScopeSelector always visible --- .../Scores/NotSupporterPlaceholder.cs | 2 -- .../BeatmapSet/Scores/ScoresContainer.cs | 22 +++++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs index 86b02c0cff..ba08a78a61 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -17,8 +17,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores LinkFlowContainer text; AutoSizeAxes = Axes.Both; - Anchor = Anchor.TopCentre; - Origin = Anchor.TopCentre; Child = new FillFlowContainer { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index fe42ef2975..0389d4cf25 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -33,10 +33,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ScoreTable scoreTable; private readonly FillFlowContainer topScoresContainer; private readonly DimmedLoadingLayer loading; - private readonly FillFlowContainer filterControls; private readonly LeaderboardModSelector modSelector; private readonly NoScoresPlaceholder noScoresPlaceholder; private readonly FillFlowContainer content; + private readonly NotSupporterPlaceholder notSupporterPlaceholder; [Resolved] private IAPIProvider api { get; set; } @@ -93,22 +93,30 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Margin = new MarginPadding { Vertical = spacing }, Children = new Drawable[] { - filterControls = new FillFlowContainer + new FillFlowContainer { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Spacing = new Vector2(0, spacing), Children = new Drawable[] { new LeaderboardScopeSelector { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Current = { BindTarget = scope } }, - new NotSupporterPlaceholder(), + notSupporterPlaceholder = new NotSupporterPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + }, modSelector = new LeaderboardModSelector { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Ruleset = { BindTarget = ruleset } } } @@ -207,7 +215,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - filterControls.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); + modSelector.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); } private void getScores() From 2e161f7e997538dea478ca788a895473006ebd27 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 22 Nov 2019 22:25:58 +0300 Subject: [PATCH 474/503] Hook up the rest of the logic --- .../BeatmapSet/Scores/ScoresContainer.cs | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 0389d4cf25..e91d12b9fc 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public readonly Bindable Beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); - private readonly Bindable scope = new Bindable(); + private readonly Bindable scope = new Bindable(BeatmapLeaderboardScope.Global); private readonly Bindable user = new Bindable(); private readonly Box background; @@ -107,12 +107,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.TopCentre, Current = { BindTarget = scope } }, - notSupporterPlaceholder = new NotSupporterPlaceholder - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Alpha = 0, - }, modSelector = new LeaderboardModSelector { Anchor = Anchor.TopCentre, @@ -136,6 +130,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AlwaysPresent = true, Margin = new MarginPadding { Vertical = 10 } }, + notSupporterPlaceholder = new NotSupporterPlaceholder + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + }, new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -213,9 +213,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void onUserChanged(ValueChangedEvent user) { - scope.Value = BeatmapLeaderboardScope.Global; modSelector.DeselectAll(); - modSelector.FadeTo(api.IsLoggedIn && api.LocalUser.Value.IsSupporter ? 1 : 0); + modSelector.FadeTo(userIsSupporter ? 1 : 0); + getScores(); } private void getScores() @@ -232,6 +232,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; } + if (scope.Value != BeatmapLeaderboardScope.Global && !userIsSupporter) + { + Scores = null; + notSupporterPlaceholder.Show(); + loading.Hide(); + return; + } + else + { + notSupporterPlaceholder.Hide(); + } + content.Show(); loading.Show(); @@ -247,5 +259,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores api.Queue(getScoresRequest); } + + private bool userIsSupporter => api.IsLoggedIn && api.LocalUser.Value.IsSupporter; } } From e3f3b1ab1a1101f86e7b9cdfe6c3d1af7c3c5226 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 20:52:41 +0900 Subject: [PATCH 475/503] Display useful statistics on song bar depending on current ruleset --- osu.Game.Tournament/Components/SongBar.cs | 48 +++++++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 43958aca7a..4a738ae36b 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; using osu.Game.Screens.Menu; using osuTK; using osuTK.Graphics; @@ -23,6 +25,9 @@ namespace osu.Game.Tournament.Components { private BeatmapInfo beatmap; + [Resolved] + private IBindable ruleset { get; set; } + public BeatmapInfo Beatmap { get => beatmap; @@ -165,7 +170,8 @@ namespace osu.Game.Tournament.Components string hardRockExtra = ""; string srExtra = ""; - //var ar = beatmap.BaseDifficulty.ApproachRate; + var ar = beatmap.BaseDifficulty.ApproachRate; + if ((mods & LegacyMods.HardRock) > 0) { hardRockExtra = "*"; @@ -174,12 +180,43 @@ namespace osu.Game.Tournament.Components if ((mods & LegacyMods.DoubleTime) > 0) { - //ar *= 1.5f; + ar *= 1.5f; bpm *= 1.5f; length /= 1.5f; srExtra = "*"; } + (string heading, string content)[] stats; + + switch (ruleset.Value.ID) + { + default: + stats = new (string heading, string content)[] + { + ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), + ("AR", $"{ar:0.#}{srExtra}"), + ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), + }; + break; + + case 1: + case 3: + stats = new (string heading, string content)[] + { + ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), + ("HP", $"{beatmap.BaseDifficulty.DrainRate:0.#}{hardRockExtra}") + }; + break; + + case 2: + stats = new (string heading, string content)[] + { + ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), + ("AR", $"{ar:0.#}{srExtra}"), + }; + break; + } + panelContents.Children = new Drawable[] { new DiffPiece(("Length", TimeSpan.FromMilliseconds(length).ToString(@"mm\:ss"))) @@ -192,12 +229,7 @@ namespace osu.Game.Tournament.Components Anchor = Anchor.CentreLeft, Origin = Anchor.TopLeft }, - new DiffPiece( - //("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), - //("AR", $"{ar:0.#}{srExtra}"), - ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), - ("HP", $"{beatmap.BaseDifficulty.DrainRate:0.#}{hardRockExtra}") - ) + new DiffPiece(stats) { Anchor = Anchor.CentreRight, Origin = Anchor.BottomRight From eb81d15463721c4e3abaf9a89fbef8a9a5eca562 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 20:52:55 +0900 Subject: [PATCH 476/503] Don't attempt to repopulate already populated users on startup --- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index f2a158971b..ec696c818d 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -202,7 +202,8 @@ namespace osu.Game.Tournament { foreach (var p in t.Players) { - PopulateUser(p); + if (p.Username == null || p.Statistics == null) + PopulateUser(p); addedInfo = true; } } @@ -243,7 +244,6 @@ namespace osu.Game.Tournament { user.Username = res.Username; user.Statistics = res.Statistics; - user.Username = res.Username; user.Country = res.Country; user.Cover = res.Cover; From 65d71b94424ab46a3fa307784a8637334d75f172 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 20:54:01 +0900 Subject: [PATCH 477/503] Fix beatmap lookups failing for beatmaps with no local path Turns out the underlying EscapeUriString doesn't like nulls --- osu.Game/Online/API/Requests/GetBeatmapRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index 8e92cf0611..87925b94c6 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -15,6 +15,6 @@ namespace osu.Game.Online.API.Requests this.beatmap = beatmap; } - protected override string Target => $@"beatmaps/lookup?id={beatmap.OnlineBeatmapID}&checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path)}"; + protected override string Target => $@"beatmaps/lookup?id={beatmap.OnlineBeatmapID}&checksum={beatmap.MD5Hash}&filename={System.Uri.EscapeUriString(beatmap.Path ?? string.Empty)}"; } } From 1bd9fa413e76c4f65300cf1005ba8231e9548be3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Nov 2019 23:29:34 +0900 Subject: [PATCH 478/503] Fix incorrect NativeLibs version reference --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 871a9238e3..ff6839f5ca 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -86,6 +86,6 @@ - + From 326a8f62eb49da63a172a4a6eb8aadbfeb35570a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Nov 2019 00:21:34 +0900 Subject: [PATCH 479/503] Calculate more correct AR locally for now --- osu.Game.Tournament/Components/SongBar.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 4a738ae36b..23dc4bb22c 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -180,7 +180,10 @@ namespace osu.Game.Tournament.Components if ((mods & LegacyMods.DoubleTime) > 0) { - ar *= 1.5f; + // temporary local calculation (taken from OsuDifficultyCalculator) + double preempt = (int)BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / 1.5; + ar = (float)(preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5); + bpm *= 1.5f; length /= 1.5f; srExtra = "*"; From 244177880e3ce004a11942e469cbdbe91f2eca1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Nov 2019 01:45:21 +0900 Subject: [PATCH 480/503] Only show star on HR --- osu.Game.Tournament/Components/SongBar.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index 23dc4bb22c..727dddeb7b 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -197,7 +197,7 @@ namespace osu.Game.Tournament.Components stats = new (string heading, string content)[] { ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), - ("AR", $"{ar:0.#}{srExtra}"), + ("AR", $"{ar:0.#}{hardRockExtra}"), ("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"), }; break; @@ -215,7 +215,7 @@ namespace osu.Game.Tournament.Components stats = new (string heading, string content)[] { ("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"), - ("AR", $"{ar:0.#}{srExtra}"), + ("AR", $"{ar:0.#}"), }; break; } From 29b05e293913c75490242416786c9a537b307041 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 24 Nov 2019 00:01:49 +0300 Subject: [PATCH 481/503] Fix getScores can be fired twice on user change --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index e91d12b9fc..d65a03acad 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -213,9 +213,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private void onUserChanged(ValueChangedEvent user) { - modSelector.DeselectAll(); + if (modSelector.SelectedMods.Any()) + modSelector.DeselectAll(); + else + getScores(); + modSelector.FadeTo(userIsSupporter ? 1 : 0); - getScores(); } private void getScores() From 96533631fc546046a2b75f94d10324a0145aa446 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 24 Nov 2019 01:29:11 +0300 Subject: [PATCH 482/503] Simplify if/else statement --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index d65a03acad..112903b0f3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -242,10 +242,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores loading.Hide(); return; } - else - { - notSupporterPlaceholder.Hide(); - } + + notSupporterPlaceholder.Hide(); content.Show(); loading.Show(); From 20a8a653c2f7f9fd8e64e6ef30c5116bb4c4be50 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 04:10:04 +0300 Subject: [PATCH 483/503] Change LegacySkin.Configuration accessibility --- osu.Game/Skinning/LegacySkin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 7ffed18d7b..868e3921bb 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -26,7 +26,7 @@ namespace osu.Game.Skinning [CanBeNull] protected IResourceStore Samples; - protected new LegacySkinConfiguration Configuration + public new LegacySkinConfiguration Configuration { get => base.Configuration as LegacySkinConfiguration; set => base.Configuration = value; From 2437cfd28c008e9f9af01c7ca10ebca41246971d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 04:36:16 +0300 Subject: [PATCH 484/503] Add test ensuring correct version lookup --- osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index 578030748b..8b9c648442 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -116,6 +116,14 @@ namespace osu.Game.Tests.Skins }); } + [Test] + public void TestLegacyVersionLookup() + { + AddStep("Set source1 version 2.3", () => source1.Configuration.LegacyVersion = 2.3m); + AddStep("Set source2 version null", () => source2.Configuration.LegacyVersion = null); + AddAssert("Check legacy version lookup", () => requester.GetConfig(LegacySkinConfiguration.LegacySetting.Version)?.Value == 2.3m); + } + public enum LookupType { Test From b58afa3eb693c29d74d5aac93f7160f5f35dc639 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Sun, 24 Nov 2019 04:36:34 +0300 Subject: [PATCH 485/503] Remove unnecessary mentioning in xmldoc --- osu.Game/Skinning/LegacySkinConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkinConfiguration.cs b/osu.Game/Skinning/LegacySkinConfiguration.cs index 6a667e69f4..b1679bd464 100644 --- a/osu.Game/Skinning/LegacySkinConfiguration.cs +++ b/osu.Game/Skinning/LegacySkinConfiguration.cs @@ -8,7 +8,7 @@ namespace osu.Game.Skinning public const decimal LATEST_VERSION = 2.7m; /// - /// Legacy version of this skin. Null if no version was set to allow fallback to a parent skin version. + /// Legacy version of this skin. /// public decimal? LegacyVersion { get; internal set; } From 6126fd9a6b573a422aae719d240b31f80fea4950 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sun, 24 Nov 2019 10:42:05 +0900 Subject: [PATCH 486/503] ApplyToDrawableHitObjects should be able to get all the hitobject in nasted Playfield --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index e0aeff8330..5ed1e5a368 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -224,7 +224,7 @@ namespace osu.Game.Rulesets.UI Playfield.PostProcess(); foreach (var mod in mods.OfType()) - mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); + mod.ApplyToDrawableHitObjects(Playfield.AllHitObjects); } public override void RequestResume(Action continueResume) From fccdbffa9370d23cc606d4d3ced16a702801ca07 Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Mon, 25 Nov 2019 00:45:42 +0100 Subject: [PATCH 487/503] Use MathF instead of Math- functions when possible MathF-functions are faster than the Math-counterpart and it looks cleaner, so use MathF when we cast to float or int anyway. --- .../Difficulty/CatchPerformanceCalculator.cs | 2 +- .../Objects/Drawable/DrawableFruit.cs | 4 ++-- .../Beatmaps/ManiaBeatmapConverter.cs | 2 +- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/Pieces/SpinnerTicks.cs | 10 +++++----- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 10 +++++----- .../Screens/Drawings/Components/GroupContainer.cs | 2 +- .../Screens/Gameplay/Components/MatchScoreDisplay.cs | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- osu.Game/Overlays/NowPlayingOverlay.cs | 2 +- .../Overlays/Profile/Header/Components/RankGraph.cs | 4 ++-- .../Edit/Compose/Components/BeatDivisorControl.cs | 2 +- .../Compose/Components/CircularDistanceSnapGrid.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 4 ++-- osu.Game/Screens/Select/BeatmapCarousel.cs | 4 ++-- osu.Game/Screens/Select/Details/AdvancedStats.cs | 2 +- 18 files changed, 31 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index a7f0d358ed..b876c774b2 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty // Longer maps are worth more float lengthBonus = 0.95f + 0.4f * Math.Min(1.0f, numTotalHits / 3000.0f) + - (numTotalHits > 3000 ? (float)Math.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f); + (numTotalHits > 3000 ? MathF.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f); // Longer maps are worth more value *= lengthBonus; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index eae652573b..2c97e5083d 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -99,8 +99,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable const float small_pulp = large_pulp_3 / 2; Vector2 positionAt(float angle, float distance) => new Vector2( - distance * (float)Math.Sin(angle * Math.PI / 180), - distance * (float)Math.Cos(angle * Math.PI / 180)); + distance * MathF.Sin(angle * MathF.PI / 180), + distance * MathF.Cos(angle * MathF.PI / 180)); switch (representation) { diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 6c5bb304bf..5fa1e31c78 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps { BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; - int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); + int seed = (int)MathF.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)MathF.Round(difficulty.ApproachRate); Random = new FastRandom(seed); return base.ConvertBeatmap(original); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index b9984a8b90..a249c6f0f3 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -53,11 +53,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; - return Math.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; + return Math.Clamp((int)MathF.Floor(position / local_x_divisor), 0, 6) + 1; } float localXDivisor = 512f / TotalColumns; - return Math.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); + return Math.Clamp((int)MathF.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 9b079895fa..a9475af638 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods float appearDistance = (float)(hitObject.TimePreempt - hitObject.TimeFadeIn) / 2; Vector2 originalPosition = drawable.Position; - Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance; + Vector2 appearOffset = new Vector2(MathF.Cos(theta), MathF.Sin(theta)) * appearDistance; //the - 1 and + 1 prevents the hit objects to appear in the wrong position. double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 122975d55e..71cb9a9691 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; } - float aimRotation = MathHelper.RadiansToDegrees((float)Math.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); + float aimRotation = MathHelper.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); while (Math.Abs(aimRotation - Rotation) > 180) aimRotation += aimRotation < Rotation ? 360 : -360; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index 9219fab830..676cefb236 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -20,9 +20,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; RelativeSizeAxes = Axes.Both; - const int count = 18; + const float count = 18; - for (int i = 0; i < count; i++) + for (float i = 0; i < count; i++) { Add(new Container { @@ -40,10 +40,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Size = new Vector2(60, 10), Origin = Anchor.Centre, Position = new Vector2( - 0.5f + (float)Math.Sin((float)i / count * 2 * MathHelper.Pi) / 2 * 0.86f, - 0.5f + (float)Math.Cos((float)i / count * 2 * MathHelper.Pi) / 2 * 0.86f + 0.5f + MathF.Sin(i / count * 2 * MathF.PI) / 2 * 0.86f, + 0.5f + MathF.Cos(i / count * 2 * MathF.PI) / 2 * 0.86f ), - Rotation = -(float)i / count * 360 + 90, + Rotation = -i / count * 360 + 90, Children = new[] { new Box diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index 24320b6579..d50b2098d6 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -185,14 +185,14 @@ namespace osu.Game.Rulesets.Osu.Replays { Vector2 spinCentreOffset = SPINNER_CENTRE - prevPos; float distFromCentre = spinCentreOffset.Length; - float distToTangentPoint = (float)Math.Sqrt(distFromCentre * distFromCentre - SPIN_RADIUS * SPIN_RADIUS); + float distToTangentPoint = MathF.Sqrt(distFromCentre * distFromCentre - SPIN_RADIUS * SPIN_RADIUS); if (distFromCentre > SPIN_RADIUS) { // Previous cursor position was outside spin circle, set startPosition to the tangent point. // Angle between centre offset and tangent point offset. - float angle = (float)Math.Asin(SPIN_RADIUS / distFromCentre); + float angle = MathF.Asin(SPIN_RADIUS / distFromCentre); if (angle > 0) { @@ -204,8 +204,8 @@ namespace osu.Game.Rulesets.Osu.Replays } // Rotate by angle so it's parallel to tangent line - spinCentreOffset.X = spinCentreOffset.X * (float)Math.Cos(angle) - spinCentreOffset.Y * (float)Math.Sin(angle); - spinCentreOffset.Y = spinCentreOffset.X * (float)Math.Sin(angle) + spinCentreOffset.Y * (float)Math.Cos(angle); + spinCentreOffset.X = spinCentreOffset.X * MathF.Cos(angle) - spinCentreOffset.Y * MathF.Sin(angle); + spinCentreOffset.Y = spinCentreOffset.X * MathF.Sin(angle) + spinCentreOffset.Y * MathF.Cos(angle); // Set length to distToTangentPoint spinCentreOffset.Normalize(); @@ -331,7 +331,7 @@ namespace osu.Game.Rulesets.Osu.Replays Vector2 difference = startPosition - SPINNER_CENTRE; float radius = difference.Length; - float angle = radius == 0 ? 0 : (float)Math.Atan2(difference.Y, difference.X); + float angle = radius == 0 ? 0 : MathF.Atan2(difference.Y, difference.X); double t; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index 8a66ca7bf6..b9a19090df 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components groups.Add(g); nextGroupName++; - if (i < (int)Math.Ceiling(numGroups / 2f)) + if (i < (int)MathF.Ceiling(numGroups / 2f)) topGroups.Add(g); else bottomGroups.Add(g); diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs index 78455c8bb7..cc7903f2fa 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs @@ -100,7 +100,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value); losingBar.ResizeWidthTo(0, 400, Easing.OutQuint); - winningBar.ResizeWidthTo(Math.Min(0.4f, (float)Math.Pow(diff / 1500000f, 0.5) / 2), 400, Easing.OutQuint); + winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint); } protected override void Update() diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index dffa0c4fd5..6d88808150 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -111,7 +111,7 @@ namespace osu.Game.Graphics.Backgrounds float adjustedAlpha = HideAlphaDiscrepancies // Cubically scale alpha to make it drop off more sharply. - ? (float)Math.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) + ? MathF.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) : 1; float elapsedSeconds = (float)Time.Elapsed / 1000; diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 4f73cbfacd..de30e1a754 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -390,7 +390,7 @@ namespace osu.Game.Overlays Vector2 change = e.MousePosition - e.MouseDownPosition; // Diminish the drag distance as we go further to simulate "rubber band" feeling. - change *= change.Length <= 0 ? 0 : (float)Math.Pow(change.Length, 0.7f) / change.Length; + change *= change.Length <= 0 ? 0 : MathF.Pow(change.Length, 0.7f) / change.Length; this.MoveTo(change); return true; diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index c6d96c5917..250b345db7 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Profile.Header.Components placeholder.FadeOut(fade_duration, Easing.Out); graph.DefaultValueCount = ranks.Length; - graph.Values = ranks.Select(x => -(float)Math.Log(x.Value)); + graph.Values = ranks.Select(x => -MathF.Log(x.Value)); } graph.FadeTo(ranks.Length > 1 ? 1 : 0, fade_duration, Easing.Out); @@ -187,7 +187,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public void HideBar() => bar.FadeOut(fade_duration); - private int calculateIndex(float mouseXPosition) => (int)Math.Round(mouseXPosition / DrawWidth * (DefaultValueCount - 1)); + private int calculateIndex(float mouseXPosition) => (int)MathF.Round(mouseXPosition / DrawWidth * (DefaultValueCount - 1)); private Vector2 calculateBallPosition(int index) { diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 9e4691e4dd..42773ef687 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -289,7 +289,7 @@ namespace osu.Game.Screens.Edit.Compose.Components OnUserChange(Current.Value); } - private float getMappedPosition(float divisor) => (float)Math.Pow((divisor - 1) / (availableDivisors.Last() - 1), 0.90f); + private float getMappedPosition(float divisor) => MathF.Pow((divisor - 1) / (availableDivisors.Last() - 1), 0.90f); private class Tick : CompositeDrawable { diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index fc7d51db4b..91e19f9cc0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Edit.Compose.Components float distance = direction.Length; float radius = DistanceSpacing; - int radialCount = Math.Clamp((int)Math.Round(distance / radius), 1, MaxIntervals); + int radialCount = Math.Clamp((int)MathF.Round(distance / radius), 1, MaxIntervals); Vector2 normalisedDirection = direction * new Vector2(1f / distance); Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 59ab6ad265..1a625f8d83 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -206,8 +206,8 @@ namespace osu.Game.Screens.Menu continue; float rotation = MathHelper.DegreesToRadians(i / (float)bars_per_visualiser * 360 + j * 360 / visualiser_rounds); - float rotationCos = (float)Math.Cos(rotation); - float rotationSin = (float)Math.Sin(rotation); + float rotationCos = MathF.Cos(rotation); + float rotationSin = MathF.Sin(rotation); //taking the cos and sin to the 0..1 range var barPosition = new Vector2(rotationCos / 2 + 0.5f, rotationSin / 2 + 0.5f) * size; diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 17736e7819..838ca5322c 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -670,8 +670,8 @@ namespace osu.Game.Screens.Select { // The radius of the circle the carousel moves on. const float circle_radius = 3; - double discriminant = Math.Max(0, circle_radius * circle_radius - dist * dist); - float x = (circle_radius - (float)Math.Sqrt(discriminant)) * halfHeight; + float discriminant = MathF.Max(0, circle_radius * circle_radius - dist * dist); + float x = (circle_radius - MathF.Sqrt(discriminant)) * halfHeight; return 125 + x; } diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 52a57dd506..c5bdc230d0 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Select.Details if ((Beatmap?.Ruleset?.ID ?? 0) == 3) { firstValue.Title = "Key Amount"; - firstValue.Value = (int)Math.Round(Beatmap?.BaseDifficulty?.CircleSize ?? 0); + firstValue.Value = (int)MathF.Round(Beatmap?.BaseDifficulty?.CircleSize ?? 0); } else { From 45514ff660a403a41e2c284c6e6be5ef81406331 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 11:30:55 +0900 Subject: [PATCH 488/503] Apply fixes --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs | 4 ++-- osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs | 3 ++- .../Visual/Gameplay/TestSceneBarHitErrorMeter.cs | 8 ++++---- .../Visual/Online/TestSceneLeaderboardModSelector.cs | 3 ++- .../Visual/Online/TestSceneRankingsDismissableFlag.cs | 3 ++- osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs | 6 +++--- osu.Game.Tournament/TournamentGameBase.cs | 4 ++-- osu.Game/Online/API/APIRequest.cs | 2 +- osu.Game/Overlays/Chat/DrawableChannel.cs | 3 ++- osu.Game/Overlays/Comments/CommentsHeader.cs | 5 +++-- .../Overlays/Comments/DeletedChildrenPlaceholder.cs | 3 ++- osu.Game/Overlays/Comments/DrawableComment.cs | 11 ++++++----- osu.Game/Overlays/Comments/SortTabControl.cs | 3 ++- osu.Game/Overlays/Comments/TotalCommentsCounter.cs | 5 +++-- osu.Game/Overlays/Comments/VotePill.cs | 2 +- .../Profile/Header/Components/PreviousUsernames.cs | 3 ++- osu.Game/Overlays/Rankings/HeaderTitle.cs | 5 +++-- 17 files changed, 42 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 720ef1db42..9b529a2e4c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -11,12 +11,12 @@ using System; using System.Collections.Generic; using osu.Game.Skinning; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Game.Audio; +using osu.Game.Graphics.Sprites; namespace osu.Game.Rulesets.Catch.Tests { @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Tests RelativeSizeAxes = Axes.Both, Colour = Color4.Blue }, - new SpriteText + new OsuSpriteText { Text = "custom" } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 7ca311118e..4da1b1dae0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -16,6 +16,7 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Screens.Play; using osu.Game.Skinning; @@ -125,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Tests { if (!enabled) return null; - return new SpriteText + return new OsuSpriteText { Text = identifier, Font = OsuFont.Default.With(size: 30), diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs index a934d22b5d..e3688c276f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Judgements; using osu.Framework.MathUtils; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Osu.Scoring; @@ -85,9 +85,9 @@ namespace osu.Game.Tests.Visual.Gameplay AutoSizeAxes = Axes.Both, Children = new[] { - new SpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" }, - new SpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" }, - new SpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" }, + new OsuSpriteText { Text = $@"Great: {hitWindows?.WindowFor(HitResult.Great)}" }, + new OsuSpriteText { Text = $@"Good: {hitWindows?.WindowFor(HitResult.Good)}" }, + new OsuSpriteText { Text = $@"Meh: {hitWindows?.WindowFor(HitResult.Meh)}" }, } }); diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index ebe233a5f4..e0e5a088ce 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Bindables; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; namespace osu.Game.Tests.Visual.Online @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online modSelector.SelectedMods.ItemsAdded += mods => { - mods.ForEach(mod => selectedMods.Add(new SpriteText + mods.ForEach(mod => selectedMods.Add(new OsuSpriteText { Text = mod.Acronym, })); diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs index db6afa9bf3..cd954cd6bd 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Rankings; using osu.Game.Users; using osuTK; @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.Online Size = new Vector2(30, 20), Country = countryA, }, - text = new SpriteText + text = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs index 18d6028cb8..0f41247571 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mania; using osu.Game.Users; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Taiko; using osu.Game.Graphics.UserInterface; @@ -94,11 +94,11 @@ namespace osu.Game.Tests.Visual.Online AddRange(new Drawable[] { - new SpriteText + new OsuSpriteText { Text = $@"Username: {user.NewValue?.Username}" }, - new SpriteText + new OsuSpriteText { Text = $@"RankedScore: {user.NewValue?.Statistics.RankedScore}" }, diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index f2a158971b..9e3dfa3ea6 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -12,13 +12,13 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -104,7 +104,7 @@ namespace osu.Game.Tournament Colour = Color4.Red, RelativeSizeAxes = Axes.Both, }, - new SpriteText + new OsuSpriteText { Text = "Please make the window wider", Font = OsuFont.Default.With(weight: "bold"), diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 53b23f5922..b424e0f086 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -150,7 +150,7 @@ namespace osu.Game.Online.API private class DisplayableError { [JsonProperty("error")] - public string ErrorMessage; + public string ErrorMessage { get; set; } } } diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 427bd8dcde..443f2b7bf7 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Chat { @@ -202,7 +203,7 @@ namespace osu.Game.Overlays.Chat RelativeSizeAxes = Axes.X, Height = lineHeight, }, - text = new SpriteText + text = new OsuSpriteText { Margin = new MarginPadding { Horizontal = 10 }, Text = time.ToLocalTime().ToString("dd MMM yyyy"), diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index 66fe7ff3fa..6a7a678cc7 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -10,6 +10,7 @@ using osu.Game.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Input.Events; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -48,7 +49,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.CentreLeft, Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -101,7 +102,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.CentreLeft, Size = new Vector2(10), }, - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs index e849691597..6b41453b91 100644 --- a/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs +++ b/osu.Game/Overlays/Comments/DeletedChildrenPlaceholder.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Bindables; using Humanizer; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -31,7 +32,7 @@ namespace osu.Game.Overlays.Comments Icon = FontAwesome.Solid.Trash, Size = new Vector2(14), }, - countText = new SpriteText + countText = new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), } diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3fb9867f0e..9a11e85a7b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using System.Linq; +using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; namespace osu.Game.Overlays.Comments @@ -122,7 +123,7 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both, }, new ParentUsername(comment), - new SpriteText + new OsuSpriteText { Alpha = comment.IsDeleted ? 1 : 0, Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), @@ -144,7 +145,7 @@ namespace osu.Game.Overlays.Comments Colour = OsuColour.Gray(0.7f), Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -195,7 +196,7 @@ namespace osu.Game.Overlays.Comments if (comment.EditedAt.HasValue) { - info.Add(new SpriteText + info.Add(new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -290,7 +291,7 @@ namespace osu.Game.Overlays.Comments this.count = count; Alpha = count == 0 ? 0 : 1; - Child = text = new SpriteText + Child = text = new OsuSpriteText { Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), }; @@ -323,7 +324,7 @@ namespace osu.Game.Overlays.Comments Icon = FontAwesome.Solid.Reply, Size = new Vector2(14), }, - new SpriteText + new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), Text = parentComment?.User?.Username ?? parentComment?.LegacyName diff --git a/osu.Game/Overlays/Comments/SortTabControl.cs b/osu.Game/Overlays/Comments/SortTabControl.cs index f5423e692f..a114197b8d 100644 --- a/osu.Game/Overlays/Comments/SortTabControl.cs +++ b/osu.Game/Overlays/Comments/SortTabControl.cs @@ -11,6 +11,7 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Bindables; using osu.Framework.Allocation; +using osu.Game.Graphics.Sprites; using osuTK.Graphics; namespace osu.Game.Overlays.Comments @@ -61,7 +62,7 @@ namespace osu.Game.Overlays.Comments public TabButton(CommentsSortCriteria value) { - Add(text = new SpriteText + Add(text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14), Text = value.ToString() diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs index c71ca762e1..376853c1de 100644 --- a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Sprites; using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Comments { @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(5, 0), Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -52,7 +53,7 @@ namespace osu.Game.Overlays.Comments RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.05f) }, - counter = new SpriteText + counter = new OsuSpriteText { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index ab35a477aa..978846549e 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Comments } } }, - sideNumber = new SpriteText + sideNumber = new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, diff --git a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs index f18f319e27..e4c0fe3a5a 100644 --- a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs +++ b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; @@ -63,7 +64,7 @@ namespace osu.Game.Overlays.Profile.Header.Components new Drawable[] { hoverIcon = new HoverIconContainer(), - header = new SpriteText + header = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index cba407ecf7..a1a893fa6b 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osuTK; using osu.Game.Graphics; using osu.Framework.Allocation; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Rankings { @@ -41,13 +42,13 @@ namespace osu.Game.Overlays.Rankings Margin = new MarginPadding { Bottom = flag_margin }, Size = new Vector2(30, 20), }, - scopeText = new SpriteText + scopeText = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light) }, - new SpriteText + new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, From 4904346814feeb39dd95a5879abd6eb0120be701 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 11:31:03 +0900 Subject: [PATCH 489/503] Fix false warnings --- CodeAnalysis/BannedSymbols.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index 3ad8d5db5b..c54c639b4f 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -2,4 +2,4 @@ M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use obj M:System.Object.Equals(System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. M:System.ValueType.Equals(System.Object)~System.Boolean;Don't use object.Equals(Fallbacks to ValueType). Use IEquatable or EqualityComparer.Default instead. T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. -T:osu.Framework.Graphics.Sprites.SpriteText;Use OsuSpriteText. +T:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText. From 36cabe72cf854cbfd05f01fb0d03dc91e9717078 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 11:49:54 +0900 Subject: [PATCH 490/503] Make DimmedLoadingLayer block input when active --- osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs index f7138827cc..f2f6dd429b 100644 --- a/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/DimmedLoadingLayer.cs @@ -10,7 +10,7 @@ using osuTK; namespace osu.Game.Graphics.UserInterface { - public class DimmedLoadingLayer : VisibilityContainer + public class DimmedLoadingLayer : OverlayContainer { private const float transition_duration = 250; From 94e6bfeed33e9c3f1f3acf2ce0fc256d7fca30eb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2019 07:30:17 +0000 Subject: [PATCH 491/503] Bump Microsoft.Build.Traversal from 2.0.19 to 2.0.24 Bumps [Microsoft.Build.Traversal](https://github.com/Microsoft/MSBuildSdks) from 2.0.19 to 2.0.24. - [Release notes](https://github.com/Microsoft/MSBuildSdks/releases) - [Changelog](https://github.com/microsoft/MSBuildSdks/blob/master/RELEASE.md) - [Commits](https://github.com/Microsoft/MSBuildSdks/compare/Microsoft.Build.Traversal.2.0.19...Microsoft.Build.Traversal.2.0.24) Signed-off-by: dependabot-preview[bot] --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index d8b8d14c36..43bb34912a 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Microsoft.Build.Traversal": "2.0.19" + "Microsoft.Build.Traversal": "2.0.24" } } \ No newline at end of file From 719f0d5947e4d92db11682259a8033c361a6d2b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 25 Nov 2019 18:28:43 +0900 Subject: [PATCH 492/503] Fix stutters when changing beatmap difficulties --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 3de0ab191c..7b68460e6b 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Backgrounds Schedule(() => { - if ((Background as BeatmapBackground)?.Beatmap == beatmap) + if ((Background as BeatmapBackground)?.Beatmap.BeatmapInfo.BackgroundEquals(beatmap?.BeatmapInfo) ?? false) return; cancellationSource?.Cancel(); From 6b8983b489a095c6aa43d7346d9b9d47e1af826e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 18:48:58 +0900 Subject: [PATCH 493/503] Consider intro and outro time as "break" time --- osu.Game/Screens/Play/BreakOverlay.cs | 12 +++++++++--- osu.Game/Screens/Play/Player.cs | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 6fdee85f45..28691c0d09 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; @@ -16,6 +16,8 @@ namespace osu.Game.Screens.Play { public class BreakOverlay : Container { + private readonly ScoreProcessor scoreProcessor; + /// /// The duration of the break overlay fading. /// @@ -60,9 +62,12 @@ namespace osu.Game.Screens.Play private readonly RemainingTimeCounter remainingTimeCounter; private readonly BreakInfo info; private readonly BreakArrows breakArrows; + private readonly double gameplayStartTime; - public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor = null) + public BreakOverlay(bool letterboxing, double gameplayStartTime = 0, ScoreProcessor scoreProcessor = null) { + this.gameplayStartTime = gameplayStartTime; + this.scoreProcessor = scoreProcessor; RelativeSizeAxes = Axes.Both; Child = fadeContainer = new Container { @@ -154,7 +159,8 @@ namespace osu.Game.Screens.Play } var currentBreak = breaks[CurrentBreakIndex]; - isBreakTime.Value = currentBreak.HasEffect && currentBreak.Contains(time); + + isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor.HasCompleted); } private void initializeBreaks() diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d6488dc209..7f32db2ebf 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -179,7 +179,7 @@ namespace osu.Game.Screens.Play { target.AddRange(new[] { - breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) + breakOverlay = new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, DrawableRuleset.GameplayStartTime, ScoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -468,7 +468,7 @@ namespace osu.Game.Screens.Play PauseOverlay.Hide(); // breaks and time-based conditions may allow instant resume. - if (breakOverlay.IsBreakTime.Value || GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) + if (breakOverlay.IsBreakTime.Value) completeResume(); else DrawableRuleset.RequestResume(completeResume); From 709ec1404f650cb368a56f88593ceed9f265f303 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 19:01:24 +0900 Subject: [PATCH 494/503] Centralise End/StartTime retrieval to extension method --- .../Objects/Drawable/DrawableCatchHitObject.cs | 4 ++-- .../ManiaBeatmapConversionTest.cs | 3 +-- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- .../Replays/ManiaAutoGenerator.cs | 3 +-- .../OsuBeatmapConversionTest.cs | 3 +-- .../Beatmaps/OsuBeatmapProcessor.cs | 12 ++++++------ osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 4 ++-- .../Drawables/Connections/FollowPointConnection.cs | 4 ++-- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 6 +++--- .../TaikoBeatmapConversionTest.cs | 3 +-- osu.Game/Beatmaps/BeatmapManager.cs | 5 +++-- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 3 +-- osu.Game/Rulesets/Objects/BarLineGenerator.cs | 3 +-- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 +++--- osu.Game/Rulesets/Objects/HitObject.cs | 13 +++++++++++++ .../UI/Scrolling/DrawableScrollingRuleset.cs | 3 +-- .../Edit/Compose/Components/DistanceSnapGrid.cs | 3 +-- osu.Game/Screens/Play/SongProgress.cs | 4 ++-- osu.Game/Screens/Play/SongProgressGraph.cs | 5 ++--- 19 files changed, 47 insertions(+), 42 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index dd4a58a5ef..b7c05392f3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -4,8 +4,8 @@ using System; using osuTK; using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Objects.Drawable @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected override void UpdateStateTransforms(ArmedState state) { - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); using (BeginAbsoluteSequence(endTime, true)) { diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 6f10540973..12865385b6 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Tests.Beatmaps; namespace osu.Game.Rulesets.Mania.Tests @@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Tests yield return new ConvertValue { StartTime = hitObject.StartTime, - EndTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime, + EndTime = hitObject.GetEndTime(), Column = ((ManiaHitObject)hitObject).Column }; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 6297a68e08..5404cf2d23 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy foreach (var obj in originalPattern.HitObjects) { - if (!Precision.AlmostEquals(EndTime, (obj as IHasEndTime)?.EndTime ?? obj.StartTime)) + if (!Precision.AlmostEquals(EndTime, obj.GetEndTime())) intermediatePattern.Add(obj); else endTimePattern.Add(obj); diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 2b336ca16d..483327d5b3 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Mania.Replays @@ -84,7 +83,7 @@ namespace osu.Game.Rulesets.Mania.Replays var currentObject = Beatmap.HitObjects[i]; var nextObjectInColumn = GetNextObject(i); // Get the next object that requires pressing the same button - double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime; + double endTime = currentObject.GetEndTime(); bool canDelayKeyUp = nextObjectInColumn == null || nextObjectInColumn.StartTime > endTime + RELEASE_DELAY; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index e9fdf924c3..1a36bb37d5 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Tests.Beatmaps; @@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests ConvertValue createConvertValue(OsuHitObject obj) => new ConvertValue { StartTime = obj.StartTime, - EndTime = (obj as IHasEndTime)?.EndTime ?? obj.StartTime, + EndTime = obj.GetEndTime(), X = obj.StackedPosition.X, Y = obj.StackedPosition.Y }; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index bb19b783aa..3a829f72fa 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -4,7 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osuTK; @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (objectN is Spinner) continue; - double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime; + double endTime = stackBaseObject.GetEndTime(); double stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo.StackLeniency; if (objectN.StartTime - endTime > stackThreshold) @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; - double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime; + double endTime = objectN.GetEndTime(); if (objectI.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the previous object. @@ -199,7 +199,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (currHitObject.StackHeight != 0 && !(currHitObject is Slider)) continue; - double startTime = (currHitObject as IHasEndTime)?.EndTime ?? currHitObject.StartTime; + double startTime = currHitObject.GetEndTime(); int sliderStack = 0; for (int j = i + 1; j < beatmap.HitObjects.Count; j++) @@ -217,14 +217,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, currHitObject.Position) < stack_distance) { currHitObject.StackHeight++; - startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[j].StartTime; + startTime = beatmap.HitObjects[j].GetEndTime(); } else if (Vector2Extensions.Distance(beatmap.HitObjects[j].Position, position2) < stack_distance) { //Case for sliders - bump notes down and right, rather than up and left. sliderStack++; beatmap.HitObjects[j].StackHeight -= sliderStack; - startTime = (beatmap.HitObjects[j] as IHasEndTime)?.EndTime ?? beatmap.HitObjects[j].StartTime; + startTime = beatmap.HitObjects[j].GetEndTime(); } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 32c9e913c6..9f384ea2e8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Mods @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Mods var fadeOutDuration = h.TimePreempt * fade_out_duration_multiplier; // new duration from completed fade in to end (before fading out) - var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime; + var longFadeDuration = h.GetEndTime() - fadeOutStartTime; switch (drawable) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 1e032eb977..6c4fbbac17 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -6,7 +6,7 @@ using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Vector2 startPosition = osuStart.EndPosition; Vector2 endPosition = osuEnd.Position; - double startTime = (osuStart as IHasEndTime)?.EndTime ?? osuStart.StartTime; + double startTime = osuStart.GetEndTime(); double endTime = osuEnd.StartTime; Vector2 distanceVector = endPosition - startPosition; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index d50b2098d6..bd59e8a03f 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -10,7 +10,7 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; using osu.Game.Replays; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.Replays private void addDelayedMovements(OsuHitObject h, OsuHitObject prev) { - double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime; + double endTime = prev.GetEndTime(); HitWindows hitWindows = null; @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Osu.Replays var startFrame = new OsuReplayFrame(h.StartTime, new Vector2(startPosition.X, startPosition.Y), action); // TODO: Why do we delay 1 ms if the object is a spinner? There already is KEY_UP_DELAY from hEndTime. - double hEndTime = ((h as IHasEndTime)?.EndTime ?? h.StartTime) + KEY_UP_DELAY; + double hEndTime = h.GetEndTime() + KEY_UP_DELAY; int endDelay = h is Spinner ? 1 : 0; var endFrame = new OsuReplayFrame(hEndTime + endDelay, new Vector2(h.StackedEndPosition.X, h.StackedEndPosition.Y)); diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 6c1882b4e2..28f5d4d301 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Tests.Beatmaps; @@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Tests yield return new ConvertValue { StartTime = hitObject.StartTime, - EndTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime, + EndTime = hitObject.GetEndTime(), IsRim = hitObject is RimHit, IsCentre = hitObject is CentreHit, IsDrumRoll = hitObject is DrumRoll, diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e6783ec828..bc78e50f5d 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -25,7 +25,7 @@ using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; -using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; namespace osu.Game.Beatmaps { @@ -334,7 +334,8 @@ namespace osu.Game.Beatmaps var lastObject = b.HitObjects.Last(); - double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime; + //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). + double endTime = lastObject.GetEndTime(); double startTime = b.HitObjects.First().StartTime; return endTime - startTime; diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index f217512965..e231225e3c 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -8,7 +8,6 @@ using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Mods { @@ -42,7 +41,7 @@ namespace osu.Game.Rulesets.Mods HitObject lastObject = beatmap.HitObjects.LastOrDefault(); beginRampTime = beatmap.HitObjects.FirstOrDefault()?.StartTime ?? 0; - finalRateTime = final_rate_progress * ((lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0); + finalRateTime = final_rate_progress * (lastObject?.GetEndTime() ?? 0); } public virtual void Update(Playfield playfield) diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index 4f9395435e..07f0595015 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects { @@ -28,7 +27,7 @@ namespace osu.Game.Rulesets.Objects return; HitObject lastObject = beatmap.HitObjects.Last(); - double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); + double lastHitTime = 1 + (lastObject.GetEndTime()); var timingPoints = beatmap.ControlPointInfo.TimingPoints; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 35228e9ad1..ed48ddbc2f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -382,7 +382,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Result != null && Result.HasResult) { - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); if (Result.TimeOffset + endTime > Time.Current) { @@ -460,7 +460,7 @@ namespace osu.Game.Rulesets.Objects.Drawables throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}."); // Ensure that the judgement is given a valid time offset, because this may not get set by the caller - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); Result.TimeOffset = Math.Min(HitObject.HitWindows.WindowFor(HitResult.Miss), Time.Current - endTime); @@ -495,7 +495,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Judged) return false; - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + var endTime = HitObject.GetEndTime(); CheckForResult(userTriggered, Time.Current - endTime); return Judged; diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index ee0705ec5a..1179efaa6e 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -158,4 +158,17 @@ namespace osu.Game.Rulesets.Objects [NotNull] protected virtual HitWindows CreateHitWindows() => new HitWindows(); } + + public static class HitObjectExtensions + { + /// + /// Returns the end time of this object. + /// + /// + /// This returns the where available, falling back to otherwise. + /// + /// The object. + /// The end time of this object. + public static double GetEndTime(this HitObject hitObject) => (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime; + } } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index f178c01fd6..cfec5d3f49 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -15,7 +15,6 @@ using osu.Game.Configuration; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI.Scrolling.Algorithms; @@ -112,7 +111,7 @@ namespace osu.Game.Rulesets.UI.Scrolling [BackgroundDependencyLoader] private void load() { - double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; + double lastObjectTime = Objects.LastOrDefault()?.GetEndTime() ?? double.MaxValue; double baseBeatLength = TimingControlPoint.DEFAULT_BEAT_LENGTH; if (RelativeScaleBeatLengths) diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 475b6e7274..9508a2cdf0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components @@ -70,7 +69,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - StartTime = (hitObject as IHasEndTime)?.EndTime ?? hitObject.StartTime; + StartTime = hitObject.GetEndTime(); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 3df06ebfa8..713d27bd16 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -12,7 +12,6 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Timing; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Play @@ -34,7 +33,8 @@ namespace osu.Game.Screens.Play public override bool HandleNonPositionalInput => AllowSeeking; public override bool HandlePositionalInput => AllowSeeking; - private double lastHitTime => ((objects.Last() as IHasEndTime)?.EndTime ?? objects.Last().StartTime) + 1; + //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). + private double lastHitTime => objects.Last().GetEndTime() + 1; private double firstHitTime => objects.First().StartTime; diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index e480c5b502..e182a1a53d 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Collections.Generic; using System.Diagnostics; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play @@ -26,7 +25,7 @@ namespace osu.Game.Screens.Play return; var firstHit = objects.First().StartTime; - var lastHit = objects.Max(o => (o as IHasEndTime)?.EndTime ?? o.StartTime); + var lastHit = objects.Max(o => (o.GetEndTime())); if (lastHit == 0) lastHit = objects.Last().StartTime; @@ -35,7 +34,7 @@ namespace osu.Game.Screens.Play foreach (var h in objects) { - var endTime = (h as IHasEndTime)?.EndTime ?? h.StartTime; + var endTime = h.GetEndTime(); Debug.Assert(endTime >= h.StartTime); From 1fd5ed3c0f88f284a2155a379fff07275d9e6a7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 21:35:25 +0900 Subject: [PATCH 495/503] Change login placeholder text to ask for username --- osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index a8bbccb168..d8833ee2f4 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -225,7 +225,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { username = new OsuTextBox { - PlaceholderText = "email address", + PlaceholderText = "username", RelativeSizeAxes = Axes.X, Text = api?.ProvidedUsername ?? string.Empty, TabbableContentContainer = this @@ -239,7 +239,7 @@ namespace osu.Game.Overlays.Settings.Sections.General }, new SettingsCheckbox { - LabelText = "Remember email address", + LabelText = "Remember username", Bindable = config.GetBindable(OsuSetting.SaveUsername), }, new SettingsCheckbox From fbebbab5dbb4db0faaf633accc82e99f29982c5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Nov 2019 22:37:07 +0900 Subject: [PATCH 496/503] Remove excess parenthesis --- osu.Game/Rulesets/Objects/BarLineGenerator.cs | 2 +- osu.Game/Screens/Play/SongProgressGraph.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index 07f0595015..99672240e2 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Objects return; HitObject lastObject = beatmap.HitObjects.Last(); - double lastHitTime = 1 + (lastObject.GetEndTime()); + double lastHitTime = 1 + lastObject.GetEndTime(); var timingPoints = beatmap.ControlPointInfo.TimingPoints; diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index e182a1a53d..78eb456bb5 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play return; var firstHit = objects.First().StartTime; - var lastHit = objects.Max(o => (o.GetEndTime())); + var lastHit = objects.Max(o => o.GetEndTime()); if (lastHit == 0) lastHit = objects.Last().StartTime; From 41fd3f67494c1131affda5c9e9c62da994e4cde1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Nov 2019 23:42:59 +0800 Subject: [PATCH 497/503] Correct BannedSymbols.txt. --- CodeAnalysis/BannedSymbols.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index c54c639b4f..5d86b99fd7 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -2,4 +2,4 @@ M:System.Object.Equals(System.Object,System.Object)~System.Boolean;Don't use obj M:System.Object.Equals(System.Object)~System.Boolean;Don't use object.Equals. Use IEquatable or EqualityComparer.Default instead. M:System.ValueType.Equals(System.Object)~System.Boolean;Don't use object.Equals(Fallbacks to ValueType). Use IEquatable or EqualityComparer.Default instead. T:System.IComparable;Don't use non-generic IComparable. Use generic version instead. -T:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText. +M:osu.Framework.Graphics.Sprites.SpriteText.#ctor;Use OsuSpriteText. From 8e25214eeea21dca5ea24727a968ba6b91223e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Nov 2019 21:21:56 +0100 Subject: [PATCH 498/503] Revert Android to using native network components This reverts commit 9acfc2587aa6a8dcd34a2535f3fc4bcf928bac1b ("Switch android to using managed network components") due to it causing crashes on every online call. The managed legacy TLS provider is slated for removal in later mono releases as it stands anyway. --- osu.Android.props | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 0da3e66236..f2d2af5678 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -16,8 +16,6 @@ armeabi-v7a;x86;arm64-v8a true cjk,mideast,other,rare,west - System.Net.Http.HttpClientHandler - legacy SdkOnly prompt From a453129d448ae718973248cd3eed11727425f7b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Nov 2019 15:13:50 +0900 Subject: [PATCH 499/503] Fix nullref in tests --- osu.Game/Screens/Play/BreakOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 28691c0d09..9ba18224ce 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -160,7 +160,7 @@ namespace osu.Game.Screens.Play var currentBreak = breaks[CurrentBreakIndex]; - isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor.HasCompleted); + isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor?.HasCompleted == true); } private void initializeBreaks() From 77ce9642ba616cb668ca8d9259c3b5a4a4792bfe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Nov 2019 15:21:43 +0900 Subject: [PATCH 500/503] Add test coverage and simplify break time updating --- .../Visual/Gameplay/TestSceneBreakOverlay.cs | 13 ++++++ osu.Game/Screens/Play/BreakOverlay.cs | 41 +++++++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs index 879e15c548..19dce303ea 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakOverlay.cs @@ -95,6 +95,19 @@ namespace osu.Game.Tests.Visual.Gameplay seekAndAssertBreak("seek to break after end", testBreaks[1].EndTime + 500, false); } + [TestCase(true)] + [TestCase(false)] + public void TestBeforeGameplayStart(bool withBreaks) + { + setClock(true); + + if (withBreaks) + loadBreaksStep("multiple breaks", testBreaks); + + seekAndAssertBreak("seek to break intro time", -100, true); + seekAndAssertBreak("seek to break intro time", 0, false); + } + private void addShowBreakStep(double seconds) { AddStep($"show '{seconds}s' break", () => breakOverlay.Breaks = new List diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 9ba18224ce..ee8be87352 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -140,27 +140,34 @@ namespace osu.Game.Screens.Play updateBreakTimeBindable(); } - private void updateBreakTimeBindable() + private void updateBreakTimeBindable() => + isBreakTime.Value = getCurrentBreak()?.HasEffect == true + || Clock.CurrentTime < gameplayStartTime + || scoreProcessor?.HasCompleted == true; + + private BreakPeriod getCurrentBreak() { - if (breaks == null || breaks.Count == 0) - return; - - var time = Clock.CurrentTime; - - if (time > breaks[CurrentBreakIndex].EndTime) + if (breaks?.Count > 0) { - while (time > breaks[CurrentBreakIndex].EndTime && CurrentBreakIndex < breaks.Count - 1) - CurrentBreakIndex++; - } - else - { - while (time < breaks[CurrentBreakIndex].StartTime && CurrentBreakIndex > 0) - CurrentBreakIndex--; + var time = Clock.CurrentTime; + + if (time > breaks[CurrentBreakIndex].EndTime) + { + while (time > breaks[CurrentBreakIndex].EndTime && CurrentBreakIndex < breaks.Count - 1) + CurrentBreakIndex++; + } + else + { + while (time < breaks[CurrentBreakIndex].StartTime && CurrentBreakIndex > 0) + CurrentBreakIndex--; + } + + var closest = breaks[CurrentBreakIndex]; + + return closest.Contains(time) ? closest : null; } - var currentBreak = breaks[CurrentBreakIndex]; - - isBreakTime.Value = (currentBreak.HasEffect && currentBreak.Contains(time)) || (time < gameplayStartTime || scoreProcessor?.HasCompleted == true); + return null; } private void initializeBreaks() From ab017ee648df15b51fe635e6c5cec70d96f1635e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Nov 2019 15:37:13 +0900 Subject: [PATCH 501/503] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f2d2af5678..b80881e2f6 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,6 +53,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 449b4dc4e3..2f633bdbc1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,7 +21,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index ff6839f5ca..38134074f2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + From 9425e80a5d23f29c45b91a6ef9e009cf61a17faf Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 18:34:23 +0800 Subject: [PATCH 502/503] Unify to use double in performance calculators. --- .../Difficulty/CatchPerformanceCalculator.cs | 36 +++++---- .../Difficulty/OsuPerformanceCalculator.cs | 76 +++++++++---------- .../Difficulty/TaikoPerformanceCalculator.cs | 2 +- 3 files changed, 56 insertions(+), 58 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index b876c774b2..3c237c86be 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -47,55 +47,53 @@ namespace osu.Game.Rulesets.Catch.Difficulty return 0; // We are heavily relying on aim in catch the beat - double value = Math.Pow(5.0f * Math.Max(1.0f, Attributes.StarRating / 0.0049f) - 4.0f, 2.0f) / 100000.0f; + double value = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0049) - 4.0, 2.0) / 100000.0; // Longer maps are worth more. "Longer" means how many hits there are which can contribute to combo int numTotalHits = totalComboHits(); // Longer maps are worth more - float lengthBonus = - 0.95f + 0.4f * Math.Min(1.0f, numTotalHits / 3000.0f) + - (numTotalHits > 3000 ? MathF.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f); + double lengthBonus = + 0.95 + 0.4 * Math.Min(1.0, numTotalHits / 3000.0) + + (numTotalHits > 3000 ? Math.Log10(numTotalHits / 3000.0) * 0.5 : 0.0); // Longer maps are worth more value *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available - value *= Math.Pow(0.97f, misses); + value *= Math.Pow(0.97, misses); // Combo scaling - float beatmapMaxCombo = Attributes.MaxCombo; - if (beatmapMaxCombo > 0) - value *= Math.Min(Math.Pow(Attributes.MaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + if (Attributes.MaxCombo > 0) + value *= Math.Min(Math.Pow(Attributes.MaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0); - float approachRate = (float)Attributes.ApproachRate; - float approachRateFactor = 1.0f; - if (approachRate > 9.0f) - approachRateFactor += 0.1f * (approachRate - 9.0f); // 10% for each AR above 9 - else if (approachRate < 8.0f) - approachRateFactor += 0.025f * (8.0f - approachRate); // 2.5% for each AR below 8 + double approachRateFactor = 1.0; + if (Attributes.ApproachRate > 9.0) + approachRateFactor += 0.1 * (Attributes.ApproachRate - 9.0); // 10% for each AR above 9 + else if (Attributes.ApproachRate < 8.0) + approachRateFactor += 0.025 * (8.0 - Attributes.ApproachRate); // 2.5% for each AR below 8 value *= approachRateFactor; if (mods.Any(m => m is ModHidden)) // Hiddens gives nothing on max approach rate, and more the lower it is - value *= 1.05f + 0.075f * (10.0f - Math.Min(10.0f, approachRate)); // 7.5% for each AR below 10 + value *= 1.05 + 0.075 * (10.0 - Math.Min(10.0, Attributes.ApproachRate)); // 7.5% for each AR below 10 if (mods.Any(m => m is ModFlashlight)) // Apply length bonus again if flashlight is on simply because it becomes a lot harder on longer maps. - value *= 1.35f * lengthBonus; + value *= 1.35 * lengthBonus; // Scale the aim value with accuracy _slightly_ - value *= Math.Pow(accuracy(), 5.5f); + value *= Math.Pow(accuracy(), 5.5); // Custom multipliers for NoFail. SpunOut is not applicable. if (mods.Any(m => m is ModNoFail)) - value *= 0.90f; + value *= 0.90; return value; } - private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f); + private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0, 1); private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed; private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit; private int totalComboHits() => misses + ticksHit + fruitsHit; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 093081b6a1..05c78cbc95 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -55,22 +55,22 @@ namespace osu.Game.Rulesets.Osu.Difficulty return 0; // Custom multipliers for NoFail and SpunOut. - double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things + double multiplier = 1.12; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things if (mods.Any(m => m is OsuModNoFail)) - multiplier *= 0.90f; + multiplier *= 0.90; if (mods.Any(m => m is OsuModSpunOut)) - multiplier *= 0.95f; + multiplier *= 0.95; double aimValue = computeAimValue(); double speedValue = computeSpeedValue(); double accuracyValue = computeAccuracyValue(); double totalValue = Math.Pow( - Math.Pow(aimValue, 1.1f) + - Math.Pow(speedValue, 1.1f) + - Math.Pow(accuracyValue, 1.1f), 1.0f / 1.1f + Math.Pow(aimValue, 1.1) + + Math.Pow(speedValue, 1.1) + + Math.Pow(accuracyValue, 1.1), 1.0 / 1.1 ) * multiplier; if (categoryRatings != null) @@ -93,82 +93,82 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (mods.Any(m => m is OsuModTouchDevice)) rawAim = Math.Pow(rawAim, 0.8); - double aimValue = Math.Pow(5.0f * Math.Max(1.0f, rawAim / 0.0675f) - 4.0f, 3.0f) / 100000.0f; + double aimValue = Math.Pow(5.0 * Math.Max(1.0, rawAim / 0.0675) - 4.0, 3.0) / 100000.0; // Longer maps are worth more - double lengthBonus = 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + - (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); + double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) + + (totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0); aimValue *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available - aimValue *= Math.Pow(0.97f, countMiss); + aimValue *= Math.Pow(0.97, countMiss); // Combo scaling if (beatmapMaxCombo > 0) - aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(beatmapMaxCombo, 0.8), 1.0); - double approachRateFactor = 1.0f; + double approachRateFactor = 1.0; - if (Attributes.ApproachRate > 10.33f) - approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f); - else if (Attributes.ApproachRate < 8.0f) + if (Attributes.ApproachRate > 10.33) + approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33); + else if (Attributes.ApproachRate < 8.0) { - approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate); + approachRateFactor += 0.01 * (8.0 - Attributes.ApproachRate); } aimValue *= approachRateFactor; // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) - aimValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate); + aimValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate); if (mods.Any(h => h is OsuModFlashlight)) { // Apply object-based bonus for flashlight. - aimValue *= 1.0f + 0.35f * Math.Min(1.0f, totalHits / 200.0f) + + aimValue *= 1.0 + 0.35 * Math.Min(1.0, totalHits / 200.0) + (totalHits > 200 - ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + - (totalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f) - : 0.0f); + ? 0.3 * Math.Min(1.0, (totalHits - 200) / 300.0) + + (totalHits > 500 ? (totalHits - 500) / 1200.0 : 0.0) + : 0.0); } // Scale the aim value with accuracy _slightly_ - aimValue *= 0.5f + accuracy / 2.0f; + aimValue *= 0.5 + accuracy / 2.0; // It is important to also consider accuracy difficulty when doing that - aimValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; + aimValue *= 0.98 + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; return aimValue; } private double computeSpeedValue() { - double speedValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes.SpeedStrain / 0.0675f) - 4.0f, 3.0f) / 100000.0f; + double speedValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.SpeedStrain / 0.0675) - 4.0, 3.0) / 100000.0; // Longer maps are worth more - speedValue *= 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + - (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); + speedValue *= 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) + + (totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0); // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available - speedValue *= Math.Pow(0.97f, countMiss); + speedValue *= Math.Pow(0.97, countMiss); // Combo scaling if (beatmapMaxCombo > 0) - speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(beatmapMaxCombo, 0.8), 1.0); - double approachRateFactor = 1.0f; - if (Attributes.ApproachRate > 10.33f) - approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f); + double approachRateFactor = 1.0; + if (Attributes.ApproachRate > 10.33) + approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33); speedValue *= approachRateFactor; if (mods.Any(m => m is OsuModHidden)) - speedValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate); + speedValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate); // Scale the speed value with accuracy _slightly_ - speedValue *= 0.02f + accuracy; + speedValue *= 0.02 + accuracy; // It is important to also consider accuracy difficulty when doing that - speedValue *= 0.96f + Math.Pow(Attributes.OverallDifficulty, 2) / 1600; + speedValue *= 0.96 + Math.Pow(Attributes.OverallDifficulty, 2) / 1600; return speedValue; } @@ -190,15 +190,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Pow(1.52163f, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f; + double accuracyValue = Math.Pow(1.52163, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83; // Bonus for many hitcircles - it's harder to keep good accuracy up for longer - accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f)); + accuracyValue *= Math.Min(1.15, Math.Pow(amountHitObjectsWithAccuracy / 1000.0, 0.3)); if (mods.Any(m => m is OsuModHidden)) - accuracyValue *= 1.08f; + accuracyValue *= 1.08; if (mods.Any(m => m is OsuModFlashlight)) - accuracyValue *= 1.02f; + accuracyValue *= 1.02; return accuracyValue; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 70249db0f6..c3638253e4 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty double strainValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0075) - 4.0, 2.0) / 100000.0; // Longer maps are worth more - double lengthBonus = 1 + 0.1f * Math.Min(1.0, totalHits / 1500.0); + double lengthBonus = 1 + 0.1 * Math.Min(1.0, totalHits / 1500.0); strainValue *= lengthBonus; // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available From eba8657d38b6cd26256b3fc461c87eaca3bc5bdd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 26 Nov 2019 18:41:19 +0800 Subject: [PATCH 503/503] Remove newly introduced redundant `this`. --- osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 0b8bab3ffc..ff78d85bf0 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Play this.beatmap = beatmap; this.mods = mods; this.gameplayStartTime = gameplayStartTime; - this.firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime; + firstHitObjectTime = beatmap.Beatmap.HitObjects.First().StartTime; RelativeSizeAxes = Axes.Both;