From 7258a097489655632d89def6cdbac09cd54f3d3a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Apr 2022 18:04:07 +0900 Subject: [PATCH 01/15] Allow `SettingsSection`s to exit without a parent `SettingsPanel` --- osu.Game/Overlays/Settings/SettingsSection.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 28c42a0e47..dc3af9104f 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -44,7 +45,7 @@ namespace osu.Game.Overlays.Settings public bool FilteringActive { get; set; } - [Resolved] + [Resolved(canBeNull: true)] private SettingsPanel settingsPanel { get; set; } protected SettingsSection() @@ -117,7 +118,7 @@ namespace osu.Game.Overlays.Settings }, }); - selectedSection = settingsPanel.CurrentSection.GetBoundCopy(); + selectedSection = settingsPanel?.CurrentSection.GetBoundCopy() ?? new Bindable(this); selectedSection.BindValueChanged(_ => updateContentFade(), true); } @@ -138,7 +139,10 @@ namespace osu.Game.Overlays.Settings protected override bool OnClick(ClickEvent e) { if (!isCurrentSection) + { + Debug.Assert(settingsPanel != null); settingsPanel.SectionsContainer.ScrollTo(this); + } return base.OnClick(e); } From 2a043aa6de7ae64990a6069e7cb0402d4e8f06fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Apr 2022 18:04:43 +0900 Subject: [PATCH 02/15] Add a method of finding and applying settings with classic default value --- osu.Game/Overlays/Settings/ISettingsItem.cs | 6 ++++ osu.Game/Overlays/Settings/SettingsItem.cs | 36 ++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/ISettingsItem.cs b/osu.Game/Overlays/Settings/ISettingsItem.cs index e7afa48502..e6b1e68741 100644 --- a/osu.Game/Overlays/Settings/ISettingsItem.cs +++ b/osu.Game/Overlays/Settings/ISettingsItem.cs @@ -9,5 +9,11 @@ namespace osu.Game.Overlays.Settings public interface ISettingsItem : IDrawable, IDisposable { event Action SettingChanged; + + /// + /// Apply the default values of a setting item, if the setting item specifies a "classic" default via . + /// + /// Whether to apply the classic value. If false, the standard default is applied. + void ApplyClassicDefault(bool useClassicDefault); } } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 1c5668479f..845a7f5cdf 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -30,6 +30,8 @@ namespace osu.Game.Overlays.Settings /// public object SettingSourceObject { get; internal set; } + public const string CLASSIC_DEFAULT_SEARCH_TERM = @"has-classic-default"; + private IHasCurrentValue controlWithCurrent => Control as IHasCurrentValue; protected override Container Content => FlowContent; @@ -96,7 +98,23 @@ namespace osu.Game.Overlays.Settings set => controlWithCurrent.Current = value; } - public virtual IEnumerable FilterTerms => Keywords == null ? new[] { LabelText.ToString() } : new List(Keywords) { LabelText.ToString() }.ToArray(); + public virtual IEnumerable FilterTerms + { + get + { + var keywords = new List(Keywords ?? Array.Empty()) + { + LabelText.ToString() + }; + + if (GetClassicDefault != null) + { + keywords.Add(CLASSIC_DEFAULT_SEARCH_TERM); + } + + return keywords; + } + } public IEnumerable Keywords { get; set; } @@ -108,6 +126,22 @@ namespace osu.Game.Overlays.Settings public event Action SettingChanged; + /// + /// An action which when invoked will apply a classic default value to this setting. + /// + public Func GetClassicDefault { get; set; } + + public void ApplyClassicDefault(bool useClassicDefault) + { + if (GetClassicDefault != null) + { + if (useClassicDefault) + Current.Value = GetClassicDefault(); + else + Current.SetDefault(); + } + } + protected SettingsItem() { RelativeSizeAxes = Axes.X; From e0b9ab022de2f610b294a53c065ae07d4e81f999 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Apr 2022 18:05:24 +0900 Subject: [PATCH 03/15] Add classic default values against setting controls --- osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs | 1 + osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs | 1 + .../Overlays/Settings/Sections/UserInterface/GeneralSettings.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index a4c0381d16..33db74c530 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -33,6 +33,7 @@ namespace osu.Game.Rulesets.Osu.UI }, new SettingsCheckbox { + GetClassicDefault = () => false, LabelText = "Snaking out sliders", Current = config.GetBindable(OsuRulesetSetting.SnakingOutSliders) }, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index d4e4fd571d..3ca677ef7b 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -21,6 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsEnumDropdown { + GetClassicDefault = () => ScoringMode.Classic, LabelText = GameplaySettingsStrings.ScoreDisplayMode, Current = config.GetBindable(OsuSetting.ScoreDisplayMode), Keywords = new[] { "scoring" } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index 6e1558f7d7..06f2c9794c 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -37,6 +37,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface }, new SettingsSlider { + GetClassicDefault = () => 0, LabelText = UserInterfaceStrings.HoldToConfirmActivationTime, Current = config.GetBindable(OsuSetting.UIHoldActivationDelay), Keywords = new[] { @"delay" }, From 1caee3876802ca5ac8aa81c9bb932f8a558192ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 Apr 2022 18:05:52 +0900 Subject: [PATCH 04/15] Add first-run "behaviour" screen to allow users a choice of more familiar UX --- .../TestSceneFirstRunScreenBehaviour.cs | 19 ++++ .../FirstRunSetupOverlayStrings.cs | 28 ++++- .../Overlays/FirstRunSetup/ScreenBehaviour.cs | 104 ++++++++++++++++++ osu.Game/Overlays/FirstRunSetupOverlay.cs | 1 + 4 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs create mode 100644 osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs new file mode 100644 index 0000000000..d7f0c5ba03 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs @@ -0,0 +1,19 @@ +// 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.Screens; +using osu.Game.Overlays.FirstRunSetup; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneFirstRunScreenBehaviour : OsuManualInputManagerTestScene + { + public TestSceneFirstRunScreenBehaviour() + { + AddStep("load screen", () => + { + Child = new ScreenStack(new ScreenBehaviour()); + }); + } + } +} diff --git a/osu.Game/Localisation/FirstRunSetupOverlayStrings.cs b/osu.Game/Localisation/FirstRunSetupOverlayStrings.cs index 001de93c16..15b8d0ba67 100644 --- a/osu.Game/Localisation/FirstRunSetupOverlayStrings.cs +++ b/osu.Game/Localisation/FirstRunSetupOverlayStrings.cs @@ -17,7 +17,8 @@ namespace osu.Game.Localisation /// /// "Click to resume first-run setup at any point" /// - public static LocalisableString ClickToResumeFirstRunSetupAtAnyPoint => new TranslatableString(getKey(@"click_to_resume_first_run_setup_at_any_point"), @"Click to resume first-run setup at any point"); + public static LocalisableString ClickToResumeFirstRunSetupAtAnyPoint => + new TranslatableString(getKey(@"click_to_resume_first_run_setup_at_any_point"), @"Click to resume first-run setup at any point"); /// /// "First-run setup" @@ -53,6 +54,31 @@ osu! is a very configurable game, and diving straight into the settings can some /// public static LocalisableString Next(LocalisableString nextStepDescription) => new TranslatableString(getKey(@"next"), @"Next ({0})", nextStepDescription); + /// + /// "Behaviour" + /// + public static LocalisableString Behaviour => new TranslatableString(getKey(@"behaviour"), @"Behaviour"); + + /// + /// "Some new defaults for game behaviours have been implemented, with the aim of improving the game experience and making it more accessible to everyone. + /// + /// We recommend you give the new defaults a try, but if you'd like to have things feel more like classic versions of osu!, you can easily apply some sane defaults below." + /// + public static LocalisableString BehaviourDescription => new TranslatableString(getKey(@"behaviour_description"), + @"Some new defaults for game behaviours have been implemented, with the aim of improving the game experience and making it more accessible to everyone. + +We recommend you give the new defaults a try, but if you'd like to have things feel more like classic versions of osu!, you can easily apply some sane defaults below."); + + /// + /// "New defaults" + /// + public static LocalisableString NewDefaults => new TranslatableString(getKey(@"new_defaults"), @"New defaults"); + + /// + /// "Classic defaults" + /// + public static LocalisableString ClassicDefaults => new TranslatableString(getKey(@"classic_defaults"), @"Classic defaults"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs new file mode 100644 index 0000000000..61177c821b --- /dev/null +++ b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs @@ -0,0 +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.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; +using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections; + +namespace osu.Game.Overlays.FirstRunSetup +{ + public class ScreenBehaviour : FirstRunSetupScreen + { + private SearchContainer searchContainer; + + [BackgroundDependencyLoader] + private void load() + { + Content.Children = new Drawable[] + { + new OsuTextFlowContainer(cp => cp.Font = OsuFont.Default.With(size: 24)) + { + Text = FirstRunSetupOverlayStrings.BehaviourDescription, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Absolute, 10), + new Dimension(), + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new[] + { + new TriangleButton + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Text = FirstRunSetupOverlayStrings.NewDefaults, + RelativeSizeAxes = Axes.X, + Action = applyStandard, + }, + Empty(), + new DangerousTriangleButton + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Text = FirstRunSetupOverlayStrings.ClassicDefaults, + RelativeSizeAxes = Axes.X, + Action = applyClassic + } + }, + }, + }, + searchContainer = new SearchContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new SettingsSection[] + { + new GeneralSection(), + new SkinSection(), + new UserInterfaceSection(), + new GameplaySection(), + new RulesetSection(), + new AudioSection(), + new GraphicsSection(), + new OnlineSection(), + new MaintenanceSection(), + new DebugSection(), + }, + SearchTerm = SettingsItem.CLASSIC_DEFAULT_SEARCH_TERM, + } + }; + } + + private void applyClassic() + { + foreach (var i in searchContainer.ChildrenOfType()) + i.ApplyClassicDefault(true); + } + + private void applyStandard() + { + foreach (var i in searchContainer.ChildrenOfType()) + i.ApplyClassicDefault(false); + } + } +} diff --git a/osu.Game/Overlays/FirstRunSetupOverlay.cs b/osu.Game/Overlays/FirstRunSetupOverlay.cs index a12fec4507..26b1eb2d45 100644 --- a/osu.Game/Overlays/FirstRunSetupOverlay.cs +++ b/osu.Game/Overlays/FirstRunSetupOverlay.cs @@ -70,6 +70,7 @@ namespace osu.Game.Overlays { new FirstRunStep(typeof(ScreenWelcome), FirstRunSetupOverlayStrings.WelcomeTitle), new FirstRunStep(typeof(ScreenUIScale), GraphicsSettingsStrings.UIScaling), + new FirstRunStep(typeof(ScreenBehaviour), FirstRunSetupOverlayStrings.Behaviour), }; private Container stackContainer = null!; From d97dc22e79021f94249a99cae827d1d25003bac7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Apr 2022 21:23:41 +0900 Subject: [PATCH 05/15] Add missing dependencies for behaviour screen test --- .../Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs index d7f0c5ba03..9747b5cc53 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs @@ -1,13 +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 osu.Framework.Allocation; using osu.Framework.Screens; +using osu.Game.Overlays; using osu.Game.Overlays.FirstRunSetup; namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneFirstRunScreenBehaviour : OsuManualInputManagerTestScene { + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + public TestSceneFirstRunScreenBehaviour() { AddStep("load screen", () => From 5d0842ac447f2912872e6e37d029305baf69b0b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 23 Apr 2022 21:53:47 +0900 Subject: [PATCH 06/15] Add a few more classic defaults to missed settings --- osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs | 1 + osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs | 1 + .../Settings/Sections/UserInterface/SongSelectSettings.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs index 5029c6a617..6978c77aad 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs @@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { + GetClassicDefault = () => false, LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak, Current = config.GetBindable(OsuSetting.AlwaysPlayFirstComboBreak) } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs index ba9779d650..285cdfa3f8 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs @@ -30,6 +30,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { + GetClassicDefault = () => false, LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail, Current = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), Keywords = new[] { "hp", "bar" } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index 6290046987..213234db4f 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -32,6 +32,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { + GetClassicDefault = () => true, LabelText = UserInterfaceStrings.RightMouseScroll, Current = config.GetBindable(OsuSetting.SongSelectRightMouseScroll), }, From b41e273086df007bb12b1521df7e31cd6bc53a04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Apr 2022 15:06:27 +0900 Subject: [PATCH 07/15] Convert function weirdness to property + bool --- .../UI/OsuSettingsSubsection.cs | 2 +- .../Sections/Gameplay/AudioSettings.cs | 2 +- .../Sections/Gameplay/GeneralSettings.cs | 2 +- .../Settings/Sections/Gameplay/HUDSettings.cs | 2 +- .../Sections/UserInterface/GeneralSettings.cs | 2 +- .../UserInterface/SongSelectSettings.cs | 2 +- osu.Game/Overlays/Settings/SettingsItem.cs | 29 +++++++++++-------- 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 33db74c530..a638019e69 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.UI }, new SettingsCheckbox { - GetClassicDefault = () => false, + ClassicDefault = false, LabelText = "Snaking out sliders", Current = config.GetBindable(OsuRulesetSetting.SnakingOutSliders) }, diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs index 6978c77aad..e2e00813bd 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - GetClassicDefault = () => false, + ClassicDefault = false, LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak, Current = config.GetBindable(OsuSetting.AlwaysPlayFirstComboBreak) } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 3ca677ef7b..5231ce1211 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { new SettingsEnumDropdown { - GetClassicDefault = () => ScoringMode.Classic, + ClassicDefault = ScoringMode.Classic, LabelText = GameplaySettingsStrings.ScoreDisplayMode, Current = config.GetBindable(OsuSetting.ScoreDisplayMode), Keywords = new[] { "scoring" } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs index 285cdfa3f8..829977e9b6 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay }, new SettingsCheckbox { - GetClassicDefault = () => false, + ClassicDefault = false, LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail, Current = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), Keywords = new[] { "hp", "bar" } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index 06f2c9794c..7fc049915e 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface }, new SettingsSlider { - GetClassicDefault = () => 0, + ClassicDefault = 0, LabelText = UserInterfaceStrings.HoldToConfirmActivationTime, Current = config.GetBindable(OsuSetting.UIHoldActivationDelay), Keywords = new[] { @"delay" }, diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index 213234db4f..b91b5c5243 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { new SettingsCheckbox { - GetClassicDefault = () => true, + ClassicDefault = true, LabelText = UserInterfaceStrings.RightMouseScroll, Current = config.GetBindable(OsuSetting.SongSelectRightMouseScroll), }, diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 845a7f5cdf..0b9a553c2c 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -107,10 +107,8 @@ namespace osu.Game.Overlays.Settings LabelText.ToString() }; - if (GetClassicDefault != null) - { + if (hasClassicDefault) keywords.Add(CLASSIC_DEFAULT_SEARCH_TERM); - } return keywords; } @@ -126,20 +124,27 @@ namespace osu.Game.Overlays.Settings public event Action SettingChanged; + private T classicDefault; + private bool hasClassicDefault; + /// - /// An action which when invoked will apply a classic default value to this setting. + /// A "classic" default value for this setting. /// - public Func GetClassicDefault { get; set; } + public T ClassicDefault + { + set + { + classicDefault = value; + hasClassicDefault = true; + } + } public void ApplyClassicDefault(bool useClassicDefault) { - if (GetClassicDefault != null) - { - if (useClassicDefault) - Current.Value = GetClassicDefault(); - else - Current.SetDefault(); - } + if (hasClassicDefault && useClassicDefault) + Current.Value = classicDefault; + else + Current.SetDefault(); } protected SettingsItem() From 71aa7c813e24fe7636b7c938cd2e9ada83038240 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Apr 2022 15:33:39 +0900 Subject: [PATCH 08/15] Fix regressed logic for applying classic defaults --- osu.Game/Overlays/Settings/SettingsItem.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 0b9a553c2c..db9fbfcbb4 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -141,7 +141,10 @@ namespace osu.Game.Overlays.Settings public void ApplyClassicDefault(bool useClassicDefault) { - if (hasClassicDefault && useClassicDefault) + if (!hasClassicDefault) + return; + + if (useClassicDefault) Current.Value = classicDefault; else Current.SetDefault(); From 2c836e2d6312fc0a162f322163385c484cb19a94 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Apr 2022 15:55:32 +0900 Subject: [PATCH 09/15] Fix scrollbar overlapping content --- osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs index eb4b97069c..8fcfdbf689 100644 --- a/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs +++ b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs @@ -22,6 +22,7 @@ namespace osu.Game.Overlays.FirstRunSetup new OsuScrollContainer(Direction.Vertical) { RelativeSizeAxes = Axes.Both, + ScrollbarOverlapsContent = false, Child = Content = new FillFlowContainer { Spacing = new Vector2(20), From 0343687b85fd00349056b06da0ef3fda63317e4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Apr 2022 15:59:39 +0900 Subject: [PATCH 10/15] Make apply default methods more explicit in behaviour --- .../Overlays/FirstRunSetup/ScreenBehaviour.cs | 9 +++++---- osu.Game/Overlays/Settings/ISettingsItem.cs | 15 +++++++++++--- osu.Game/Overlays/Settings/SettingsItem.cs | 20 +++++++++---------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs index 61177c821b..1316d14302 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.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.Graphics; using osu.Framework.Graphics.Containers; @@ -91,14 +92,14 @@ namespace osu.Game.Overlays.FirstRunSetup private void applyClassic() { - foreach (var i in searchContainer.ChildrenOfType()) - i.ApplyClassicDefault(true); + foreach (var i in searchContainer.ChildrenOfType().Where(s => s.HasClassicDefault)) + i.ApplyClassicDefault(); } private void applyStandard() { - foreach (var i in searchContainer.ChildrenOfType()) - i.ApplyClassicDefault(false); + foreach (var i in searchContainer.ChildrenOfType().Where(s => s.HasClassicDefault)) + i.ApplyDefault(); } } } diff --git a/osu.Game/Overlays/Settings/ISettingsItem.cs b/osu.Game/Overlays/Settings/ISettingsItem.cs index e6b1e68741..61191dcacf 100644 --- a/osu.Game/Overlays/Settings/ISettingsItem.cs +++ b/osu.Game/Overlays/Settings/ISettingsItem.cs @@ -11,9 +11,18 @@ namespace osu.Game.Overlays.Settings event Action SettingChanged; /// - /// Apply the default values of a setting item, if the setting item specifies a "classic" default via . + /// Whether this setting has a classic default (ie. a different default which better aligns with osu-stable expectations). /// - /// Whether to apply the classic value. If false, the standard default is applied. - void ApplyClassicDefault(bool useClassicDefault); + bool HasClassicDefault { get; } + + /// + /// Apply the classic default value of the associated setting. Will throw if is false. + /// + void ApplyClassicDefault(); + + /// + /// Apply the default value of the associated setting. + /// + void ApplyDefault(); } } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 3c755ab570..afcd41af22 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Settings LabelText.ToString() }; - if (hasClassicDefault) + if (HasClassicDefault) keywords.Add(CLASSIC_DEFAULT_SEARCH_TERM); return keywords; @@ -139,7 +139,8 @@ namespace osu.Game.Overlays.Settings public event Action SettingChanged; private T classicDefault; - private bool hasClassicDefault; + + public bool HasClassicDefault { get; private set; } /// /// A "classic" default value for this setting. @@ -149,21 +150,20 @@ namespace osu.Game.Overlays.Settings set { classicDefault = value; - hasClassicDefault = true; + HasClassicDefault = true; } } - public void ApplyClassicDefault(bool useClassicDefault) + public void ApplyClassicDefault() { - if (!hasClassicDefault) - return; + if (!HasClassicDefault) + throw new InvalidOperationException($"Cannot apply a classic default to a setting which doesn't have one defined via {nameof(ClassicDefault)}."); - if (useClassicDefault) - Current.Value = classicDefault; - else - Current.SetDefault(); + Current.Value = classicDefault; } + public void ApplyDefault() => Current.SetDefault(); + protected SettingsItem() { RelativeSizeAxes = Axes.X; From 0354dd5ce623830c0061e5414f59ba0372fe270e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Apr 2022 16:02:39 +0900 Subject: [PATCH 11/15] Add comment regarding section initialisation in `ScreenBehaviour` --- osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs | 2 ++ osu.Game/Overlays/SettingsOverlay.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs index 1316d14302..db7659e87a 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs @@ -74,8 +74,10 @@ namespace osu.Game.Overlays.FirstRunSetup AutoSizeAxes = Axes.Y, Children = new SettingsSection[] { + // This list should be kept in sync with SettingsOverlay. new GeneralSection(), new SkinSection(), + // InputSection is intentionally omitted for now due to its sub-panel being a pain to set up. new UserInterfaceSection(), new GameplaySection(), new RulesetSection(), diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index c84cba8189..7cd8fc6d66 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -23,6 +23,7 @@ namespace osu.Game.Overlays protected override IEnumerable CreateSections() => new SettingsSection[] { + // This list should be kept in sync with ScreenBehaviour. new GeneralSection(), new SkinSection(), new InputSection(createSubPanel(new KeyBindingPanel())), From 92cac0b74e67616aec5845d11c9adb7deb3d6b2a Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Thu, 28 Apr 2022 17:30:24 +0900 Subject: [PATCH 12/15] Fix TabControls using the wrong sample --- .../BeatmapListing/BeatmapListingCardSizeTabControl.cs | 3 ++- osu.Game/Overlays/OverlaySortTabControl.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs index e4fda9d9c3..1f9a63e3b9 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs @@ -72,7 +72,8 @@ namespace osu.Game.Overlays.BeatmapListing Size = new Vector2(12), Icon = getIconForCardSize(Value) } - } + }, + new HoverClickSounds(HoverSampleSet.TabSelect) }; } diff --git a/osu.Game/Overlays/OverlaySortTabControl.cs b/osu.Game/Overlays/OverlaySortTabControl.cs index d4dde0db3f..5f5cfce344 100644 --- a/osu.Game/Overlays/OverlaySortTabControl.cs +++ b/osu.Game/Overlays/OverlaySortTabControl.cs @@ -149,7 +149,7 @@ namespace osu.Game.Overlays } }); - AddInternal(new HoverClickSounds()); + AddInternal(new HoverClickSounds(HoverSampleSet.TabSelect)); } protected override void LoadComplete() From 37816ebc41abc2679c667a848865382872aa01b2 Mon Sep 17 00:00:00 2001 From: Jamie Taylor Date: Thu, 28 Apr 2022 17:33:51 +0900 Subject: [PATCH 13/15] Add audio feedback to `SwitchButton` checkbox --- .../Graphics/UserInterfaceV2/SwitchButton.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs index c6477d1781..f483e67b27 100644 --- a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs @@ -4,6 +4,8 @@ #nullable enable using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -31,6 +33,9 @@ namespace osu.Game.Graphics.UserInterfaceV2 private Color4 enabledColour; private Color4 disabledColour; + private Sample? sampleChecked; + private Sample? sampleUnchecked; + public SwitchButton() { Size = new Vector2(45, 20); @@ -70,13 +75,16 @@ namespace osu.Game.Graphics.UserInterfaceV2 } [BackgroundDependencyLoader(true)] - private void load(OverlayColourProvider? colourProvider, OsuColour colours) + private void load(OverlayColourProvider? colourProvider, OsuColour colours, AudioManager audio) { enabledColour = colourProvider?.Highlight1 ?? colours.BlueDark; disabledColour = colourProvider?.Background3 ?? colours.Gray3; switchContainer.Colour = enabledColour; fill.Colour = disabledColour; + + sampleChecked = audio.Samples.Get(@"UI/check-on"); + sampleUnchecked = audio.Samples.Get(@"UI/check-off"); } protected override void LoadComplete() @@ -107,6 +115,16 @@ namespace osu.Game.Graphics.UserInterfaceV2 base.OnHoverLost(e); } + protected override void OnUserChange(bool value) + { + base.OnUserChange(value); + + if (value) + sampleChecked?.Play(); + else + sampleUnchecked?.Play(); + } + private void updateBorder() { circularContainer.TransformBorderTo((Current.Value ? enabledColour : disabledColour).Lighten(IsHovered ? 0.3f : 0)); From 93db6c6bb0a82b85cf1a4429bcf8e7ff165bc75f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Apr 2022 17:46:00 +0900 Subject: [PATCH 14/15] Move `FastRandom` to `LegacyRandom` in `osu.Game` project --- .../Beatmaps/CatchBeatmapProcessor.cs | 8 +- .../Beatmaps/ManiaBeatmapConverter.cs | 8 +- .../Legacy/DistanceObjectPatternGenerator.cs | 4 +- .../Legacy/EndTimeObjectPatternGenerator.cs | 4 +- .../Legacy/HitObjectPatternGenerator.cs | 4 +- .../Patterns/Legacy/PatternGenerator.cs | 6 +- .../MathUtils/FastRandom.cs | 95 ------------------- .../Utils/LegacyRandom.cs | 37 +++++--- 8 files changed, 40 insertions(+), 126 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs rename osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs => osu.Game/Utils/LegacyRandom.cs (79%) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 346a09cac8..ab61b14ac4 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -5,10 +5,10 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Catch.MathUtils; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Utils; namespace osu.Game.Rulesets.Catch.Beatmaps { @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps public void ApplyPositionOffsets(IBeatmap beatmap) { - var rng = new FastRandom(RNG_SEED); + var rng = new LegacyRandom(RNG_SEED); float? lastPosition = null; double lastStartTime = 0; @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps initialiseHyperDash(beatmap); } - private static void applyHardRockOffset(CatchHitObject hitObject, ref float? lastPosition, ref double lastStartTime, FastRandom rng) + private static void applyHardRockOffset(CatchHitObject hitObject, ref float? lastPosition, ref double lastStartTime, LegacyRandom rng) { float offsetPosition = hitObject.OriginalX; double startTime = hitObject.StartTime; @@ -146,7 +146,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps /// The position which the offset should be applied to. /// The maximum offset, cannot exceed 20px. /// The random number generator. - private static void applyRandomOffset(ref float position, double maxOffset, FastRandom rng) + private static void applyRandomOffset(ref float position, double maxOffset, LegacyRandom rng) { bool right = rng.NextBool(); float rand = Math.Min(20, (float)rng.Next(0, Math.Max(0, maxOffset))); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 47e0e6d7b1..207c6907c8 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -11,8 +11,8 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Mania.Beatmaps.Patterns; -using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy; +using osu.Game.Utils; using osuTK; namespace osu.Game.Rulesets.Mania.Beatmaps @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private readonly int originalTargetColumns; // Internal for testing purposes - internal FastRandom Random { get; private set; } + internal LegacyRandom Random { get; private set; } private Pattern lastPattern = new Pattern(); @@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps IBeatmapDifficultyInfo difficulty = original.Difficulty; int seed = (int)MathF.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)MathF.Round(difficulty.ApproachRate); - Random = new FastRandom(seed); + Random = new LegacyRandom(seed); return base.ConvertBeatmap(original, cancellationToken); } @@ -227,7 +227,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator { - public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) + public SpecificBeatmapPatternGenerator(LegacyRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 5f8b58d94d..dafe65f415 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -8,12 +8,12 @@ using System.Linq; using osu.Framework.Extensions.EnumExtensions; using osu.Game.Audio; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; +using osu.Game.Utils; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private PatternType convertType; - public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) + public DistanceObjectPatternGenerator(LegacyRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { convertType = PatternType.None; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index f816a70ab3..2265d3d347 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -2,13 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using System.Linq; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Utils; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private readonly int endTime; private readonly PatternType convertType; - public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) + public EndTimeObjectPatternGenerator(LegacyRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { endTime = (int)((HitObject as IHasDuration)?.EndTime ?? 0); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 53b059b4e2..41d4c9322b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -9,11 +9,11 @@ using osuTK; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -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; +using osu.Game.Utils; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private readonly PatternType convertType; - public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, + public HitObjectPatternGenerator(LegacyRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index eaf0ea0f2b..d5689c047a 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -5,8 +5,8 @@ using System; using System.Linq; using JetBrains.Annotations; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; +using osu.Game.Utils; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { @@ -23,14 +23,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// /// The random number generator to use. /// - protected readonly FastRandom Random; + protected readonly LegacyRandom Random; /// /// The beatmap which is being converted from. /// protected readonly IBeatmap OriginalBeatmap; - protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) + protected PatternGenerator(LegacyRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap) : base(hitObject, beatmap, previousPattern) { if (random == null) throw new ArgumentNullException(nameof(random)); diff --git a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs deleted file mode 100644 index a9cd7f2476..0000000000 --- a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs +++ /dev/null @@ -1,95 +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; - -namespace osu.Game.Rulesets.Mania.MathUtils -{ - /// - /// A PRNG specified in http://heliosphan.org/fastrandom.html. - /// - internal class FastRandom - { - private const double int_to_real = 1.0 / (int.MaxValue + 1.0); - private const uint int_mask = 0x7FFFFFFF; - private const uint y = 842502087; - private const uint z = 3579807591; - private const uint w = 273326509; - - internal uint X { get; private set; } - internal uint Y { get; private set; } = y; - internal uint Z { get; private set; } = z; - internal uint W { get; private set; } = w; - - public FastRandom(int seed) - { - X = (uint)seed; - } - - public FastRandom() - : this(Environment.TickCount) - { - } - - /// - /// Generates a random unsigned integer within the range [, ). - /// - /// The random value. - public uint NextUInt() - { - uint t = X ^ (X << 11); - X = Y; - Y = Z; - Z = W; - return W = W ^ (W >> 19) ^ t ^ (t >> 8); - } - - /// - /// Generates a random integer value within the range [0, ). - /// - /// The random value. - public int Next() => (int)(int_mask & NextUInt()); - - /// - /// Generates a random integer value within the range [0, ). - /// - /// The upper bound. - /// The random value. - public int Next(int upperBound) => (int)(NextDouble() * upperBound); - - /// - /// Generates a random integer value within the range [, ). - /// - /// The lower bound of the range. - /// The upper bound of the range. - /// The random value. - public int Next(int lowerBound, int upperBound) => (int)(lowerBound + NextDouble() * (upperBound - lowerBound)); - - /// - /// Generates a random double value within the range [0, 1). - /// - /// The random value. - public double NextDouble() => int_to_real * Next(); - - private uint bitBuffer; - private int bitIndex = 32; - - /// - /// Generates a reandom boolean value. Cached such that a random value is only generated once in every 32 calls. - /// - /// The random value. - public bool NextBool() - { - if (bitIndex == 32) - { - bitBuffer = NextUInt(); - bitIndex = 1; - - return (bitBuffer & 1) == 1; - } - - bitIndex++; - return ((bitBuffer >>= 1) & 1) == 1; - } - } -} diff --git a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs b/osu.Game/Utils/LegacyRandom.cs similarity index 79% rename from osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs rename to osu.Game/Utils/LegacyRandom.cs index 46e427e1b7..cf731aa91f 100644 --- a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs +++ b/osu.Game/Utils/LegacyRandom.cs @@ -2,27 +2,36 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Utils; -namespace osu.Game.Rulesets.Catch.MathUtils +namespace osu.Game.Utils { /// /// A PRNG specified in http://heliosphan.org/fastrandom.html. + /// Should only be used to match legacy behaviour. See for a newer alternative. /// - public class FastRandom + /// + /// Known in osu-stable code as `FastRandom`. + /// + public class LegacyRandom { private const double int_to_real = 1.0 / (int.MaxValue + 1.0); private const uint int_mask = 0x7FFFFFFF; - private const uint y_initial = 842502087; - private const uint z_initial = 3579807591; - private const uint w_initial = 273326509; - private uint x, y = y_initial, z = z_initial, w = w_initial; + private const uint y = 842502087; + private const uint z = 3579807591; + private const uint w = 273326509; - public FastRandom(int seed) + public uint X { get; private set; } + public uint Y { get; private set; } = y; + public uint Z { get; private set; } = z; + public uint W { get; private set; } = w; + + public LegacyRandom(int seed) { - x = (uint)seed; + X = (uint)seed; } - public FastRandom() + public LegacyRandom() : this(Environment.TickCount) { } @@ -33,11 +42,11 @@ namespace osu.Game.Rulesets.Catch.MathUtils /// The random value. public uint NextUInt() { - uint t = x ^ (x << 11); - x = y; - y = z; - z = w; - return w = w ^ (w >> 19) ^ t ^ (t >> 8); + uint t = X ^ (X << 11); + X = Y; + Y = Z; + Z = W; + return W = W ^ (W >> 19) ^ t ^ (t >> 8); } /// From 32ad2166698528574947aca2c17fe28eb35d2757 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Apr 2022 22:58:32 +0900 Subject: [PATCH 15/15] Allow dragging the osu! logo Logic borrowed from `NowPlayingOverlay`. --- osu.Game/Screens/Menu/OsuLogo.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 1d3aef0653..1217a28fe7 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Menu AutoSizeAxes = Axes.Both, Children = new Drawable[] { - logoBounceContainer = new Container + logoBounceContainer = new DragContainer { AutoSizeAxes = Axes.Both, Children = new Drawable[] @@ -402,5 +402,26 @@ namespace osu.Game.Screens.Menu impactContainer.ScaleTo(0.96f); impactContainer.ScaleTo(1.12f, 250); } + + private class DragContainer : Container + { + protected override bool OnDragStart(DragStartEvent e) => true; + + protected override void OnDrag(DragEvent e) + { + Vector2 change = e.MousePosition - e.MouseDownPosition; + + // Diminish the drag distance as we go further to simulate "rubber band" feeling. + change *= change.Length <= 0 ? 0 : MathF.Pow(change.Length, 0.6f) / change.Length; + + this.MoveTo(change); + } + + protected override void OnDragEnd(DragEndEvent e) + { + this.MoveTo(Vector2.Zero, 800, Easing.OutElastic); + base.OnDragEnd(e); + } + } } }