diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index 791f46d407..b1884aab6f 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -7,7 +7,7 @@ using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mania.Configuration; @@ -31,47 +31,45 @@ namespace osu.Game.Rulesets.Mania Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = RulesetSettingsStrings.ScrollingDirection, + Caption = RulesetSettingsStrings.ScrollingDirection, Current = config.GetBindable(ManiaRulesetSetting.ScrollDirection) - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { - LabelText = RulesetSettingsStrings.ScrollSpeed, + Caption = RulesetSettingsStrings.ScrollSpeed, Current = config.GetBindable(ManiaRulesetSetting.ScrollSpeed), - KeyboardStep = 1 - }, - new SettingsCheckbox + KeyboardStep = 1, + LabelFormat = v => RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(v), v), + }), + new SettingsItemV2(new FormCheckBox + { + Caption = RulesetSettingsStrings.TimingBasedColouring, + Current = config.GetBindable(ManiaRulesetSetting.TimingBasedNoteColouring), + }) { Keywords = new[] { "color" }, - LabelText = RulesetSettingsStrings.TimingBasedColouring, - Current = config.GetBindable(ManiaRulesetSetting.TimingBasedNoteColouring), }, }; - Add(new SettingsCheckbox + Add(new SettingsItemV2(new FormCheckBox { - LabelText = RulesetSettingsStrings.TouchOverlay, + Caption = RulesetSettingsStrings.TouchOverlay, Current = config.GetBindable(ManiaRulesetSetting.TouchOverlay) - }); + })); if (RuntimeInfo.IsMobile) { - Add(new SettingsEnumDropdown + Add(new SettingsItemV2(new FormEnumDropdown { - LabelText = RulesetSettingsStrings.MobileLayout, + Caption = RulesetSettingsStrings.MobileLayout, Current = config.GetBindable(ManiaRulesetSetting.MobileLayout), #pragma warning disable CS0618 // Type or member is obsolete Items = Enum.GetValues().Where(l => l != ManiaMobileLayout.LandscapeWithOverlay), #pragma warning restore CS0618 // Type or member is obsolete - }); + })); } } - - private partial class ManiaScrollSlider : RoundedSliderBar - { - public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(Current.Value), Current.Value); - } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 0e410dbf57..2382fe6d95 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -3,7 +3,9 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Osu.Configuration; @@ -27,32 +29,34 @@ namespace osu.Game.Rulesets.Osu.UI Children = new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = RulesetSettingsStrings.SnakingInSliders, + Caption = RulesetSettingsStrings.SnakingInSliders, Current = config.GetBindable(OsuRulesetSetting.SnakingInSliders) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - ClassicDefault = false, - LabelText = RulesetSettingsStrings.SnakingOutSliders, + Caption = RulesetSettingsStrings.SnakingOutSliders, Current = config.GetBindable(OsuRulesetSetting.SnakingOutSliders) - }, - new SettingsCheckbox + }) { - LabelText = RulesetSettingsStrings.CursorTrail, + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = false, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = RulesetSettingsStrings.CursorTrail, Current = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = RulesetSettingsStrings.CursorRipples, + Caption = RulesetSettingsStrings.CursorRipples, Current = config.GetBindable(OsuRulesetSetting.ShowCursorRipples) - }, - new SettingsEnumDropdown + }), + new SettingsItemV2(new FormEnumDropdown { - LabelText = RulesetSettingsStrings.PlayfieldBorderStyle, + Caption = RulesetSettingsStrings.PlayfieldBorderStyle, Current = config.GetBindable(OsuRulesetSetting.PlayfieldBorderStyle), - }, + }), }; } } diff --git a/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs b/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs index 84dea474c5..58fb6a0246 100644 --- a/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs +++ b/osu.Game.Rulesets.Taiko/TaikoSettingsSubsection.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Taiko.Configuration; @@ -26,11 +27,11 @@ namespace osu.Game.Rulesets.Taiko Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = RulesetSettingsStrings.TouchControlScheme, + Caption = RulesetSettingsStrings.TouchControlScheme, Current = config.GetBindable(TaikoRulesetSetting.TouchControlScheme) - } + }) }; } } diff --git a/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs b/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs index 2fc5378ba1..ceca59dccf 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneAudioOffsetAdjustControl.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Configuration; +using osu.Game.Overlays; using osu.Game.Overlays.Settings.Sections.Audio; using osu.Game.Scoring; using osu.Game.Tests.Visual.Ranking; @@ -25,6 +26,9 @@ namespace osu.Game.Tests.Visual.Settings [Cached] private SessionAverageHitErrorTracker tracker = new SessionAverageHitErrorTracker(); + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + private Container content = null!; protected override Container Content => content; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index 287b678b07..ac413fe306 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Overlays; +using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections.Input; using osu.Game.Rulesets.Taiko; using osuTK.Input; @@ -202,16 +203,16 @@ namespace osu.Game.Tests.Visual.Settings InputManager.ReleaseKey(Key.P); }); - AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha > 0); + AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType().First().Alpha > 0); AddStep("click reset button for bindings", () => { - var resetButton = settingsKeyBindingRow.ChildrenOfType>().First(); + var resetButton = settingsKeyBindingRow.ChildrenOfType().First(); resetButton.TriggerClick(); }); - AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha == 0); + AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType().First().Alpha == 0); AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType().ElementAt(0).KeyBinding.Value.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0))); @@ -232,7 +233,7 @@ namespace osu.Game.Tests.Visual.Settings InputManager.ReleaseKey(Key.P); }); - AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha > 0); + AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType().First().Alpha > 0); AddStep("click reset button for bindings", () => { @@ -241,7 +242,7 @@ namespace osu.Game.Tests.Visual.Settings resetButton.TriggerClick(); }); - AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType>().First().Alpha == 0); + AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType().First().Alpha == 0); AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType().ElementAt(0).KeyBinding.Value.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0))); @@ -394,7 +395,7 @@ namespace osu.Game.Tests.Visual.Settings AddStep("reset Left (centre) to default", () => { var row = panel.ChildrenOfType().First(r => r.ChildrenOfType().Any(s => s.Text.ToString() == "Left (centre)")); - row.ChildrenOfType>().Single().TriggerClick(); + row.ChildrenOfType().Single().TriggerClick(); }); KeyBindingConflictPopover popover = null; @@ -450,7 +451,7 @@ namespace osu.Game.Tests.Visual.Settings AddStep("revert row to default", () => { var row = panel.ChildrenOfType().First(r => r.ChildrenOfType().Any(s => s.Text.ToString() == "Left (centre)")); - InputManager.MoveMouseTo(row.ChildrenOfType>().Single()); + InputManager.MoveMouseTo(row.ChildrenOfType().Single()); InputManager.Click(MouseButton.Left); }); AddWaitStep("wait a bit", 3); diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingRow.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingRow.cs index ff996a9ca1..09a46ba88c 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingRow.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingRow.cs @@ -10,6 +10,7 @@ using osu.Framework.Input.Bindings; using osu.Framework.Testing; using osu.Game.Input.Bindings; using osu.Game.Overlays; +using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections.Input; namespace osu.Game.Tests.Visual.Settings @@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual.Settings row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.Escape))); row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.ExtraMouseButton1))); }); - AddUntilStep("revert to default button not shown", () => row.ChildrenOfType>().Single().Alpha, () => Is.Zero); + AddUntilStep("revert to default button not shown", () => row.ChildrenOfType().Single().Alpha, () => Is.Zero); AddStep("change key bindings", () => { @@ -54,7 +55,7 @@ namespace osu.Game.Tests.Visual.Settings row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.Z))); row.KeyBindings.Add(new RealmKeyBinding(GlobalAction.Back, new KeyCombination(InputKey.I))); }); - AddUntilStep("revert to default button not shown", () => row.ChildrenOfType>().Single().Alpha, () => Is.Not.Zero); + AddUntilStep("revert to default button not shown", () => row.ChildrenOfType().Single().Alpha, () => Is.Not.Zero); } } } diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItemV2.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItemV2.cs index 043eadf370..d460ea0078 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItemV2.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItemV2.cs @@ -10,6 +10,7 @@ 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.Testing; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; @@ -31,7 +32,6 @@ namespace osu.Game.Tests.Visual.Settings private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); private FormSliderBar sliderBar = null!; - private FormSliderBar classicSliderBar = null!; private SearchContainer searchContainer = null!; @@ -173,7 +173,7 @@ namespace osu.Game.Tests.Visual.Settings { ShowRevertToDefaultButton = false }, - new SettingsItemV2(classicSliderBar = new FormSliderBar + new SettingsItemV2(new FormSliderBar { Caption = "Slider with classic default", Current = new BindableFloat @@ -185,7 +185,7 @@ namespace osu.Game.Tests.Visual.Settings }, }) { - ApplyClassicDefault = () => classicSliderBar.Current.Value = 2, + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = 2, }, }, }, diff --git a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs index e9f70180e1..194e4301c2 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Input.Handlers; using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Testing; using osu.Framework.Utils; @@ -69,7 +70,7 @@ namespace osu.Game.Tests.Visual.Settings { AddStep("Test with wide tablet", () => tabletHandler.SetTabletSize(new Vector2(160, 100))); - AddStep("Reset to full area", () => settings.ChildrenOfType().First().TriggerClick()); + AddStep("Reset to full area", () => settings.ChildrenOfType().First().TriggerClick()); ensureValid(); AddStep("rotate 10", () => tabletHandler.Rotation.Value = 10); @@ -129,7 +130,7 @@ namespace osu.Game.Tests.Visual.Settings private void ensureInvalid() => AddAssert("area invalid", () => !settings.AreaSelection.IsWithinBounds); - public class TestTabletHandler : ITabletHandler + public class TestTabletHandler : InputHandler, ITabletHandler { public Bindable AreaOffset { get; } = new Bindable(); public Bindable AreaSize { get; } = new Bindable(); @@ -149,7 +150,7 @@ namespace osu.Game.Tests.Visual.Settings private readonly Bindable tablet = new Bindable(); - public BindableBool Enabled { get; } = new BindableBool(true); + public override bool IsActive => true; public void SetTabletSize(Vector2 size) { diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs index 3eb97cf2dd..0737d0fc94 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs @@ -389,6 +389,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2 SortBy(SortMode.Artist); checkMatchedBeatmaps(6); + AddUntilStep("wait for spread indicator", () => this.ChildrenOfType().Any(d => d.Enabled.Value)); AddStep("click spread indicator", () => this.ChildrenOfType().Single(d => d.Enabled.Value).TriggerClick()); WaitForFiltering(); checkMatchedBeatmaps(3); @@ -412,6 +413,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2 WaitForFiltering(); checkMatchedBeatmaps(3); + AddUntilStep("wait for spread indicator", () => this.ChildrenOfType().Any(d => d.Enabled.Value)); AddStep("click spread indicator", () => this.ChildrenOfType().Single(d => d.Enabled.Value).TriggerClick()); WaitForFiltering(); checkMatchedBeatmaps(3); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonsInput.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonsInput.cs index 985f613b63..f30b82d618 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonsInput.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonsInput.cs @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("Move cursor to button", () => InputManager.MoveMouseTo(settingsButton)); AddAssert("Button is hovered", () => settingsButton.IsHovered); - AddStep("Move cursor to padded area", () => InputManager.MoveMouseTo(settingsButton.ScreenSpaceDrawQuad.TopLeft + new Vector2(SettingsPanel.CONTENT_MARGINS / 2f, 10))); + AddStep("Move cursor to padded area", () => InputManager.MoveMouseTo(settingsButton.ScreenSpaceDrawQuad.TopLeft + new Vector2(SettingsPanel.CONTENT_PADDING.Left / 2f, 10))); AddAssert("Cursor within a button", () => settingsButton.ScreenSpaceDrawQuad.Contains(InputManager.CurrentState.Mouse.Position)); AddAssert("Button is not hovered", () => !settingsButton.IsHovered); } diff --git a/osu.Game/Graphics/UserInterfaceV2/FormDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/FormDropdown.cs index 9482f1f831..60b8700dc8 100644 --- a/osu.Game/Graphics/UserInterfaceV2/FormDropdown.cs +++ b/osu.Game/Graphics/UserInterfaceV2/FormDropdown.cs @@ -30,7 +30,11 @@ namespace osu.Game.Graphics.UserInterfaceV2 /// /// Hint text containing an extended description of this slider bar, displayed in a tooltip when hovering the caption. /// - public LocalisableString HintText { get; init; } + public LocalisableString HintText + { + get => header.HintText; + set => header.HintText = value; + } /// /// The maximum height of the dropdown's menu. diff --git a/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs b/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs index e228491880..14d8213d25 100644 --- a/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs +++ b/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs @@ -108,7 +108,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 /// /// Whether sound effects should play when adjusting this slider. /// - public bool PlaySamplesOnAdjust { get; init; } + public bool PlaySamplesOnAdjust { get; init; } = true; /// /// The string formatting function to use for the value label. @@ -418,7 +418,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 private LocalisableString defaultLabelFormat(T value) => currentNumberInstantaneous.Value.ToStandardFormattedString(OsuSliderBar.MAX_DECIMAL_DIGITS, DisplayAsPercentage); - private partial class InnerSlider : OsuSliderBar + public partial class InnerSlider : OsuSliderBar { public BindableBool Focused { get; } = new BindableBool(); diff --git a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs index 5bb6aca7f4..ce4b1e93c7 100644 --- a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs @@ -51,7 +51,6 @@ namespace osu.Game.Graphics.UserInterfaceV2 { RelativeSizeAxes = Axes.Both, AlwaysPresent = true, - Alpha = 0 }, new Container { @@ -92,7 +91,6 @@ namespace osu.Game.Graphics.UserInterfaceV2 private void updateState() { nub.MoveToX(Current.Value ? nubContainer.DrawWidth - nub.DrawWidth : 0, 200, Easing.OutQuint); - fill.FadeTo(Current.Value ? 1 : 0, 250, Easing.OutQuint); updateColours(); } @@ -112,7 +110,11 @@ namespace osu.Game.Graphics.UserInterfaceV2 protected override void OnUserChange(bool value) { base.OnUserChange(value); + PlaySample(value); + } + public void PlaySample(bool value) + { if (value) sampleChecked?.Play(); else @@ -135,7 +137,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 bool hover = IsHovered && !Current.Disabled; borderColour = hover ? colourProvider.Highlight1.Opacity(0.5f) : colourProvider.Highlight1.Opacity(0.3f); - switchColour = hover ? colourProvider.Highlight1 : colourProvider.Light4; + switchColour = hover || Current.Value ? colourProvider.Highlight1 : colourProvider.Light4; if (!Current.Value) { @@ -143,7 +145,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 switchColour = switchColour.MultiplyAlpha(0.8f); } - fill.Colour = colourProvider.Background6; + fill.Colour = Current.Value ? colourProvider.Colour4.Darken(0.2f) : colourProvider.Background6; } nubContainer.FadeColour(switchColour, 250, Easing.OutQuint); diff --git a/osu.Game/Localisation/GameplaySettingsStrings.cs b/osu.Game/Localisation/GameplaySettingsStrings.cs index 2715f0b8cf..6c4ccfb572 100644 --- a/osu.Game/Localisation/GameplaySettingsStrings.cs +++ b/osu.Game/Localisation/GameplaySettingsStrings.cs @@ -120,9 +120,9 @@ namespace osu.Game.Localisation public static LocalisableString ModsHeader => new TranslatableString(getKey(@"mods_header"), @"Mods"); /// - /// "Increase visibility of first object when visual impairment mods are enabled" + /// "Increase first object visibility on visual impairment mods" /// - public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase visibility of first object when visual impairment mods are enabled"); + public static LocalisableString IncreaseFirstObjectVisibility => new TranslatableString(getKey(@"increase_first_object_visibility"), @"Increase first object visibility on visual impairment mods"); /// /// "Hide during gameplay" diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 370ba838dc..f6fa1147ea 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -625,7 +625,7 @@ namespace osu.Game return new TouchSettings(th); case MidiHandler: - return new InputSection.HandlerSection(handler); + return new InputSubsection(handler); // return null for handlers that shouldn't have settings. default: diff --git a/osu.Game/Overlays/Settings/DangerousSettingsButtonV2.cs b/osu.Game/Overlays/Settings/DangerousSettingsButtonV2.cs new file mode 100644 index 0000000000..9c2c739444 --- /dev/null +++ b/osu.Game/Overlays/Settings/DangerousSettingsButtonV2.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. + +using osu.Framework.Allocation; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Settings +{ + /// + /// A with pink colours to mark dangerous/destructive actions. + /// + public partial class DangerousSettingsButtonV2 : SettingsButtonV2 + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + BackgroundColour = colours.DangerousButtonColour; + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 811f6b606a..5742272e96 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -7,9 +7,10 @@ using osu.Framework.Graphics; using System.Collections.Generic; using System.Linq; using osu.Framework; +using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Localisation; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio @@ -21,30 +22,37 @@ namespace osu.Game.Overlays.Settings.Sections.Audio [Resolved] private AudioManager audio { get; set; } = null!; - private SettingsDropdown dropdown = null!; + private AudioDeviceDropdown dropdown = null!; - private SettingsCheckbox? wasapiExperimental; + private FormCheckBox? wasapiExperimental; + + private readonly Bindable wasapiExperimentalNote = new Bindable(); [BackgroundDependencyLoader] private void load() { Children = new Drawable[] { - dropdown = new AudioDeviceSettingsDropdown + new SettingsItemV2(dropdown = new AudioDeviceDropdown + { + Caption = AudioSettingsStrings.OutputDevice, + }) { - LabelText = AudioSettingsStrings.OutputDevice, Keywords = new[] { "speaker", "headphone", "output" } }, }; if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) { - Add(wasapiExperimental = new SettingsCheckbox + Add(new SettingsItemV2(wasapiExperimental = new FormCheckBox { - LabelText = AudioSettingsStrings.WasapiLabel, - TooltipText = AudioSettingsStrings.WasapiTooltip, + Caption = AudioSettingsStrings.WasapiLabel, + HintText = AudioSettingsStrings.WasapiTooltip, Current = audio.UseExperimentalWasapi, - Keywords = new[] { "wasapi", "latency", "exclusive" } + }) + { + Keywords = new[] { "wasapi", "latency", "exclusive" }, + Note = { BindTarget = wasapiExperimentalNote }, }); wasapiExperimental.Current.ValueChanged += _ => onDeviceChanged(string.Empty); @@ -64,9 +72,9 @@ namespace osu.Game.Overlays.Settings.Sections.Audio if (wasapiExperimental != null) { if (wasapiExperimental.Current.Value) - wasapiExperimental.SetNoticeText(AudioSettingsStrings.WasapiNotice, true); + wasapiExperimentalNote.Value = new SettingsNote.Data(AudioSettingsStrings.WasapiNotice, SettingsNote.Type.Warning); else - wasapiExperimental.ClearNoticeText(); + wasapiExperimentalNote.Value = null; } } @@ -103,15 +111,10 @@ namespace osu.Game.Overlays.Settings.Sections.Audio } } - private partial class AudioDeviceSettingsDropdown : SettingsDropdown + private partial class AudioDeviceDropdown : FormDropdown { - protected override OsuDropdown CreateDropdown() => new AudioDeviceDropdownControl(); - - private partial class AudioDeviceDropdownControl : DropdownControl - { - protected override LocalisableString GenerateItemText(string item) - => string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item); - } + protected override LocalisableString GenerateItemText(string item) + => string.IsNullOrEmpty(item) ? CommonStrings.Default : base.GenerateItemText(item); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs index 6e5e010518..f815cf82e6 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioOffsetAdjustControl.cs @@ -11,171 +11,173 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; -using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Extensions; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Screens.Play.PlayerSettings; -using osuTK; namespace osu.Game.Overlays.Settings.Sections.Audio { - public partial class AudioOffsetAdjustControl : SettingsItem + public partial class AudioOffsetAdjustControl : CompositeDrawable { - public IBindable SuggestedOffset => ((AudioOffsetPreview)Control).SuggestedOffset; - - [BackgroundDependencyLoader] - private void load() + public Bindable Current { - LabelText = AudioSettingsStrings.AudioOffset; + get => current.Current; + set => current.Current = value; } - protected override Drawable CreateControl() => new AudioOffsetPreview(); + private readonly BindableNumberWithCurrent current = new BindableNumberWithCurrent(); - private partial class AudioOffsetPreview : CompositeDrawable, IHasCurrentValue + private readonly IBindableList averageHitErrorHistory = new BindableList(); + + public readonly Bindable SuggestedOffset = new Bindable(); + + private Container notchContainer = null!; + private SettingsNote hintNote = null!; + private RoundedButton applySuggestion = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load(SessionAverageHitErrorTracker hitErrorTracker) { - public Bindable Current + averageHitErrorHistory.BindTo(hitErrorTracker.AverageHitErrorHistory); + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + InternalChild = new FillFlowContainer { - get => current.Current; - set => current.Current = value; - } - - private readonly BindableNumberWithCurrent current = new BindableNumberWithCurrent(); - - private readonly IBindableList averageHitErrorHistory = new BindableList(); - - public readonly Bindable SuggestedOffset = new Bindable(); - - private Container notchContainer = null!; - private TextFlowContainer hintText = null!; - private RoundedButton applySuggestion = null!; - - [BackgroundDependencyLoader] - private void load(SessionAverageHitErrorTracker hitErrorTracker) - { - averageHitErrorHistory.BindTo(hitErrorTracker.AverageHitErrorHistory); - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - InternalChild = new FillFlowContainer + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(10), - Direction = FillDirection.Vertical, - Children = new Drawable[] + new SettingsItemV2(new FormSliderBar { - new OffsetSliderBar + Caption = AudioSettingsStrings.AudioOffset, + RelativeSizeAxes = Axes.X, + Current = { BindTarget = Current }, + KeyboardStep = 1, + LabelFormat = v => $"{v:N0} ms", + TooltipFormat = BeatmapOffsetControl.GetOffsetExplanatoryText, + }), + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { - RelativeSizeAxes = Axes.X, - Current = { BindTarget = Current }, - KeyboardStep = 1, + Left = SettingsPanel.CONTENT_PADDING.Left + 9, + Right = SettingsPanel.CONTENT_PADDING.Right + 5 }, - notchContainer = new Container + Child = notchContainer = new Container { RelativeSizeAxes = Axes.X, + Width = 0.5f, Height = 10, - Padding = new MarginPadding { Horizontal = Nub.DEFAULT_EXPANDED_SIZE / 2 }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }, - hintText = new OsuTextFlowContainer(t => t.Font = OsuFont.Default.With(size: 16)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, - applySuggestion = new RoundedButton - { - RelativeSizeAxes = Axes.X, - Text = AudioSettingsStrings.ApplySuggestedOffset, - Action = () => + Margin = new MarginPadding { Top = 2 }, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Padding = new MarginPadding { - if (SuggestedOffset.Value.HasValue) - current.Value = SuggestedOffset.Value.Value; - hitErrorTracker.ClearHistory(); - } + Horizontal = FormSliderBar.InnerSlider.NUB_WIDTH / 2 + }, + }, + }, + hintNote = new SettingsNote + { + RelativeSizeAxes = Axes.X, + Padding = SettingsPanel.CONTENT_PADDING, + TextAnchor = Anchor.TopCentre, + }, + applySuggestion = new RoundedButton + { + RelativeSizeAxes = Axes.X, + Text = AudioSettingsStrings.ApplySuggestedOffset, + Padding = SettingsPanel.CONTENT_PADDING, + Action = () => + { + if (SuggestedOffset.Value.HasValue) + current.Value = SuggestedOffset.Value.Value; + hitErrorTracker.ClearHistory(); } } - }; - } + } + }; + } - protected override void LoadComplete() + protected override void LoadComplete() + { + base.LoadComplete(); + + averageHitErrorHistory.BindCollectionChanged(updateDisplay, true); + current.BindValueChanged(_ => updateHintText()); + SuggestedOffset.BindValueChanged(_ => updateHintText(), true); + } + + private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) { - base.LoadComplete(); - - averageHitErrorHistory.BindCollectionChanged(updateDisplay, true); - current.BindValueChanged(_ => updateHintText()); - SuggestedOffset.BindValueChanged(_ => updateHintText(), true); - } - - private void updateDisplay(object? _, NotifyCollectionChangedEventArgs e) - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - foreach (SessionAverageHitErrorTracker.DataPoint dataPoint in e.NewItems!) + case NotifyCollectionChangedAction.Add: + foreach (SessionAverageHitErrorTracker.DataPoint dataPoint in e.NewItems!) + { + notchContainer.ForEach(n => n.Alpha *= 0.95f); + notchContainer.Add(new Circle { - notchContainer.ForEach(n => n.Alpha *= 0.95f); - notchContainer.Add(new Box - { - RelativeSizeAxes = Axes.Y, - Width = 2, - RelativePositionAxes = Axes.X, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - X = getXPositionForOffset(dataPoint.SuggestedGlobalAudioOffset) - }); - } + RelativeSizeAxes = Axes.Y, + Width = 2, + RelativePositionAxes = Axes.X, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = colourProvider.Light1, + X = getXPositionForOffset(dataPoint.SuggestedGlobalAudioOffset) + }); + } - break; + break; - case NotifyCollectionChangedAction.Remove: - foreach (SessionAverageHitErrorTracker.DataPoint dataPoint in e.OldItems!) - { - var notch = notchContainer.FirstOrDefault(n => n.X == getXPositionForOffset(dataPoint.SuggestedGlobalAudioOffset)); - Debug.Assert(notch != null); - notchContainer.Remove(notch, true); - } + case NotifyCollectionChangedAction.Remove: + foreach (SessionAverageHitErrorTracker.DataPoint dataPoint in e.OldItems!) + { + var notch = notchContainer.FirstOrDefault(n => n.X == getXPositionForOffset(dataPoint.SuggestedGlobalAudioOffset)); + Debug.Assert(notch != null); + notchContainer.Remove(notch, true); + } - break; + break; - case NotifyCollectionChangedAction.Reset: - notchContainer.Clear(); - break; - } - - SuggestedOffset.Value = averageHitErrorHistory.Any() ? Math.Round(averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset)) : null; + case NotifyCollectionChangedAction.Reset: + notchContainer.Clear(); + break; } - private float getXPositionForOffset(double offset) => (float)(Math.Clamp(offset, current.MinValue, current.MaxValue) / (2 * current.MaxValue)); + SuggestedOffset.Value = averageHitErrorHistory.Any() ? Math.Round(averageHitErrorHistory.Average(dataPoint => dataPoint.SuggestedGlobalAudioOffset)) : null; + } - private void updateHintText() + private float getXPositionForOffset(double offset) => (float)(Math.Clamp(offset, current.MinValue, current.MaxValue) / (2 * current.MaxValue)); + + private void updateHintText() + { + if (SuggestedOffset.Value == null) { - if (SuggestedOffset.Value == null) - { - applySuggestion.Enabled.Value = false; - hintText.Text = AudioSettingsStrings.SuggestedOffsetNote; - } - else if (Math.Abs(SuggestedOffset.Value.Value - current.Value) < 1) - { - applySuggestion.Enabled.Value = false; - hintText.Text = AudioSettingsStrings.SuggestedOffsetCorrect(averageHitErrorHistory.Count); - } - else - { - applySuggestion.Enabled.Value = true; - hintText.Text = AudioSettingsStrings.SuggestedOffsetValueReceived(averageHitErrorHistory.Count, SuggestedOffset.Value.Value.ToStandardFormattedString(0)); - } + applySuggestion.Enabled.Value = false; + notchContainer.Hide(); + hintNote.Current.Value = new SettingsNote.Data(AudioSettingsStrings.SuggestedOffsetNote, SettingsNote.Type.Informational); } - - private partial class OffsetSliderBar : RoundedSliderBar + else if (Math.Abs(SuggestedOffset.Value.Value - current.Value) < 1) { - public override LocalisableString TooltipText => BeatmapOffsetControl.GetOffsetExplanatoryText(Current.Value); + applySuggestion.Enabled.Value = false; + notchContainer.Show(); + hintNote.Current.Value = new SettingsNote.Data(AudioSettingsStrings.SuggestedOffsetCorrect(averageHitErrorHistory.Count), SettingsNote.Type.Informational); + } + else + { + applySuggestion.Enabled.Value = true; + notchContainer.Show(); + hintNote.Current.Value = new SettingsNote.Data(AudioSettingsStrings.SuggestedOffsetValueReceived(averageHitErrorHistory.Count, SuggestedOffset.Value.Value.ToStandardFormattedString(0)), SettingsNote.Type.Informational); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index b839c98f9f..1cfba9632f 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio @@ -25,13 +26,14 @@ namespace osu.Game.Overlays.Settings.Sections.Audio new AudioOffsetAdjustControl { Current = config.GetBindable(OsuSetting.AudioOffset), + Margin = new MarginPadding { Bottom = 5 }, }, - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = AudioSettingsStrings.AdjustBeatmapOffsetAutomatically, - TooltipText = AudioSettingsStrings.AdjustBeatmapOffsetAutomaticallyTooltip, + Caption = AudioSettingsStrings.AdjustBeatmapOffsetAutomatically, + HintText = AudioSettingsStrings.AdjustBeatmapOffsetAutomaticallyTooltip, Current = config.GetBindable(OsuSetting.AutomaticallyAdjustBeatmapOffset), - } + }) }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 2bb5fa983f..c0d38e50c1 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -6,7 +6,7 @@ using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Audio @@ -20,46 +20,38 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { Children = new Drawable[] { - new VolumeAdjustSlider + new SettingsItemV2(new FormSliderBar { - LabelText = AudioSettingsStrings.MasterVolume, + Caption = AudioSettingsStrings.MasterVolume, Current = audio.Volume, KeyboardStep = 0.01f, - DisplayAsPercentage = true - }, - new SettingsSlider + DisplayAsPercentage = true, + PlaySamplesOnAdjust = false, + }), + new SettingsItemV2(new FormSliderBar { - LabelText = AudioSettingsStrings.MasterVolumeInactive, + Caption = AudioSettingsStrings.MasterVolumeInactive, Current = config.GetBindable(OsuSetting.VolumeInactive), KeyboardStep = 0.01f, DisplayAsPercentage = true - }, - new VolumeAdjustSlider + }), + new SettingsItemV2(new FormSliderBar { - LabelText = AudioSettingsStrings.EffectVolume, + Caption = AudioSettingsStrings.EffectVolume, Current = audio.VolumeSample, KeyboardStep = 0.01f, - DisplayAsPercentage = true - }, - - new VolumeAdjustSlider + DisplayAsPercentage = true, + PlaySamplesOnAdjust = false, + }), + new SettingsItemV2(new FormSliderBar { - LabelText = AudioSettingsStrings.MusicVolume, + Caption = AudioSettingsStrings.MusicVolume, Current = audio.VolumeTrack, KeyboardStep = 0.01f, - DisplayAsPercentage = true - }, + DisplayAsPercentage = true, + PlaySamplesOnAdjust = false, + }), }; } - - private partial class VolumeAdjustSlider : SettingsSlider - { - protected override Drawable CreateControl() - { - var sliderBar = (RoundedSliderBar)base.CreateControl(); - sliderBar.PlaySamplesOnAdjust = false; - return sliderBar; - } - } } } diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/BatchImportSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/BatchImportSettings.cs index 1c17356313..86455c4585 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/BatchImportSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/BatchImportSettings.cs @@ -11,10 +11,10 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings { protected override LocalisableString Header => @"Batch Import"; - private SettingsButton importBeatmapsButton = null!; - private SettingsButton importCollectionsButton = null!; - private SettingsButton importScoresButton = null!; - private SettingsButton importSkinsButton = null!; + private SettingsButtonV2 importBeatmapsButton = null!; + private SettingsButtonV2 importCollectionsButton = null!; + private SettingsButtonV2 importScoresButton = null!; + private SettingsButtonV2 importSkinsButton = null!; [BackgroundDependencyLoader] private void load(LegacyImportManager? legacyImportManager) @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings AddRange(new[] { - importBeatmapsButton = new SettingsButton + importBeatmapsButton = new SettingsButtonV2 { Text = @"Import beatmaps from stable", Action = () => @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings legacyImportManager.ImportFromStableAsync(StableContent.Beatmaps).ContinueWith(_ => Schedule(() => importBeatmapsButton.Enabled.Value = true)); } }, - importSkinsButton = new SettingsButton + importSkinsButton = new SettingsButtonV2 { Text = @"Import skins from stable", Action = () => @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings legacyImportManager.ImportFromStableAsync(StableContent.Skins).ContinueWith(_ => Schedule(() => importSkinsButton.Enabled.Value = true)); } }, - importCollectionsButton = new SettingsButton + importCollectionsButton = new SettingsButtonV2 { Text = @"Import collections from stable", Action = () => @@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings legacyImportManager.ImportFromStableAsync(StableContent.Collections).ContinueWith(_ => Schedule(() => importCollectionsButton.Enabled.Value = true)); } }, - importScoresButton = new SettingsButton + importScoresButton = new SettingsButtonV2 { Text = @"Import scores from stable", Action = () => diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs index 914fc9d141..04b63ccb84 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Overlays.Settings.Sections.DebugSettings { @@ -14,17 +15,17 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings [BackgroundDependencyLoader] private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig) { - Add(new SettingsCheckbox + Add(new SettingsItemV2(new FormCheckBox { - LabelText = @"Show log overlay", + Caption = @"Show log overlay", Current = frameworkConfig.GetBindable(FrameworkSetting.ShowLogOverlay) - }); + })); - Add(new SettingsCheckbox + Add(new SettingsItemV2(new FormCheckBox { - LabelText = @"Bypass front-to-back render pass", + Caption = @"Bypass front-to-back render pass", Current = config.GetBindable(DebugSetting.BypassFrontToBackPass) - }); + })); } } } diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs index 7b9b88a213..63b09872b7 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs @@ -13,6 +13,7 @@ using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Database; +using osu.Game.Graphics.UserInterfaceV2; namespace osu.Game.Overlays.Settings.Sections.DebugSettings { @@ -23,10 +24,10 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings [BackgroundDependencyLoader] private void load(GameHost host, RealmAccess realm) { - SettingsButton blockAction; - SettingsButton unblockAction; + SettingsButtonV2 blockAction; + SettingsButtonV2 unblockAction; - Add(new SettingsButton + Add(new SettingsButtonV2 { Text = @"Clear all caches", Action = () => @@ -38,11 +39,11 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings } }); - SettingsEnumDropdown latencyModeDropdown; - Add(latencyModeDropdown = new SettingsEnumDropdown + FormEnumDropdown latencyModeDropdown; + Add(new SettingsItemV2(latencyModeDropdown = new FormEnumDropdown { - LabelText = "GC mode", - }); + Caption = "GC mode", + })); latencyModeDropdown.Current.BindValueChanged(mode => { @@ -65,7 +66,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings { AddRange(new Drawable[] { - new SettingsButton + new SettingsButtonV2 { Text = @"Compact realm", Action = () => @@ -76,11 +77,11 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings } } }, - blockAction = new SettingsButton + blockAction = new SettingsButtonV2 { Text = @"Block realm", }, - unblockAction = new SettingsButton + unblockAction = new SettingsButtonV2 { Text = @"Unblock realm", } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs index 467c988020..e4c64612f5 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs @@ -3,8 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay @@ -18,19 +20,23 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new Drawable[] { - new SettingsSlider + new SettingsItemV2(new FormSliderBar { - LabelText = AudioSettingsStrings.PositionalLevel, - Keywords = new[] { @"positional", @"balance" }, + Caption = AudioSettingsStrings.PositionalLevel, Current = osuConfig.GetBindable(OsuSetting.PositionalHitsoundsLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true - }, - new SettingsCheckbox + }) { - ClassicDefault = false, - LabelText = GameplaySettingsStrings.AlwaysPlayFirstComboBreak, + Keywords = new[] { @"positional", @"balance" }, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = GameplaySettingsStrings.AlwaysPlayFirstComboBreak, Current = config.GetBindable(OsuSetting.AlwaysPlayFirstComboBreak) + }) + { + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = false, } }; } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs index 830ccec279..23478fe954 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay @@ -18,31 +19,33 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new Drawable[] { - new SettingsSlider + new SettingsItemV2(new FormSliderBar { - LabelText = GameplaySettingsStrings.BackgroundDim, + Caption = GameplaySettingsStrings.BackgroundDim, Current = config.GetBindable(OsuSetting.DimLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { - LabelText = GameplaySettingsStrings.BackgroundBlur, + Caption = GameplaySettingsStrings.BackgroundBlur, Current = config.GetBindable(OsuSetting.BlurLevel), KeyboardStep = 0.01f, DisplayAsPercentage = true - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.LightenDuringBreaks, + Caption = GameplaySettingsStrings.LightenDuringBreaks, Current = config.GetBindable(OsuSetting.LightenDuringBreaks), + }) + { Keywords = new[] { "dim", "level" } }, - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.FadePlayfieldWhenHealthLow, + Caption = GameplaySettingsStrings.FadePlayfieldWhenHealthLow, Current = config.GetBindable(OsuSetting.FadePlayfieldWhenHealthLow), - }, + }), }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs index 69566d85f4..32e79809e5 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay @@ -23,35 +24,41 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay Children = new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = SkinSettingsStrings.BeatmapSkins, + Caption = SkinSettingsStrings.BeatmapSkins, Current = config.GetBindable(OsuSetting.BeatmapSkins) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox + { + Caption = SkinSettingsStrings.BeatmapColours, + Current = config.GetBindable(OsuSetting.BeatmapColours) + }) { Keywords = new[] { "combo", "override", "color" }, - LabelText = SkinSettingsStrings.BeatmapColours, - Current = config.GetBindable(OsuSetting.BeatmapColours) }, - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox + { + Caption = SkinSettingsStrings.BeatmapHitsounds, + Current = config.GetBindable(OsuSetting.BeatmapHitsounds) + }) { Keywords = new[] { "samples", "override" }, - LabelText = SkinSettingsStrings.BeatmapHitsounds, - Current = config.GetBindable(OsuSetting.BeatmapHitsounds) }, - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = GraphicsSettingsStrings.StoryboardVideo, + Caption = GraphicsSettingsStrings.StoryboardVideo, Current = config.GetBindable(OsuSetting.ShowStoryboard) - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { - Keywords = new[] { "color" }, - LabelText = GraphicsSettingsStrings.ComboColourNormalisation, + Caption = GraphicsSettingsStrings.ComboColourNormalisation, Current = comboColourNormalisation, DisplayAsPercentage = true, - } + }) + { + Keywords = new[] { "color" }, + }, }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 779d5cdf00..4f402c1cb7 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -3,8 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Rulesets.Scoring; @@ -19,23 +21,25 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - ClassicDefault = ScoringMode.Classic, - LabelText = GameplaySettingsStrings.ScoreDisplayMode, + Caption = GameplaySettingsStrings.ScoreDisplayMode, Current = config.GetBindable(OsuSetting.ScoreDisplayMode), - Keywords = new[] { "scoring" } - }, - new SettingsCheckbox + }) { - LabelText = GraphicsSettingsStrings.HitLighting, + Keywords = new[] { "scoring" }, + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = ScoringMode.Classic, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = GraphicsSettingsStrings.HitLighting, Current = config.GetBindable(OsuSetting.HitLighting) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.StarFountains, + Caption = GameplaySettingsStrings.StarFountains, Current = config.GetBindable(OsuSetting.StarFountains) - }, + }), }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs index b4caaf7983..711e10da47 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs @@ -3,8 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay @@ -18,44 +20,50 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = GameplaySettingsStrings.HUDVisibilityMode, + Caption = GameplaySettingsStrings.HUDVisibilityMode, Current = config.GetBindable(OsuSetting.HUDVisibilityMode) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.ShowReplaySettingsOverlay, + Caption = GameplaySettingsStrings.ShowReplaySettingsOverlay, Current = config.GetBindable(OsuSetting.ReplaySettingsOverlay), + }) + { Keywords = new[] { "hide" }, }, - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.AlwaysShowKeyOverlay, + Caption = GameplaySettingsStrings.AlwaysShowKeyOverlay, Current = config.GetBindable(OsuSetting.KeyOverlay), + }) + { Keywords = new[] { "counter" }, }, - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.AlwaysShowGameplayLeaderboard, + Caption = GameplaySettingsStrings.AlwaysShowGameplayLeaderboard, Current = config.GetBindable(OsuSetting.GameplayLeaderboard), - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.AlwaysRequireHoldForMenu, + Caption = GameplaySettingsStrings.AlwaysRequireHoldForMenu, Current = config.GetBindable(OsuSetting.AlwaysRequireHoldingForPause), - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.AlwaysShowHoldForMenuButton, + Caption = GameplaySettingsStrings.AlwaysShowHoldForMenuButton, Current = config.GetBindable(OsuSetting.AlwaysShowHoldForMenuButton), - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - ClassicDefault = false, - LabelText = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail, + Caption = GameplaySettingsStrings.ShowHealthDisplayWhenCantFail, Current = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail), - Keywords = new[] { "hp", "bar" } + }) + { + Keywords = new[] { "hp", "bar" }, + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = false, }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs index c245a1a9ea..bed050fac5 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay @@ -19,32 +20,35 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new Drawable[] { - new SettingsSlider> + new SettingsItemV2(new FormSliderBar { - LabelText = SkinSettingsStrings.GameplayCursorSize, + Caption = SkinSettingsStrings.GameplayCursorSize, Current = config.GetBindable(OsuSetting.GameplayCursorSize), - KeyboardStep = 0.01f - }, - new SettingsCheckbox + KeyboardStep = 0.01f, + LabelFormat = v => $"{v:0.##}x" + }), + new SettingsItemV2(new FormCheckBox { - LabelText = SkinSettingsStrings.AutoCursorSize, + Caption = SkinSettingsStrings.AutoCursorSize, Current = config.GetBindable(OsuSetting.AutoCursorSize) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = SkinSettingsStrings.GameplayCursorDuringTouch, - Keywords = new[] { @"touchscreen" }, + Caption = SkinSettingsStrings.GameplayCursorDuringTouch, Current = config.GetBindable(OsuSetting.GameplayCursorDuringTouch) + }) + { + Keywords = new[] { @"touchscreen" }, }, }; if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) { - Add(new SettingsCheckbox + Add(new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.DisableWinKey, + Caption = GameplaySettingsStrings.DisableWinKey, Current = config.GetBindable(OsuSetting.GameplayDisableWinKey) - }); + })); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index 79a971510f..136108e0ab 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Gameplay @@ -21,10 +22,12 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = GameplaySettingsStrings.IncreaseFirstObjectVisibility, + Caption = GameplaySettingsStrings.IncreaseFirstObjectVisibility, Current = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility), + }) + { Keywords = new[] { @"approach", @"circle", @"hidden" }, }, }; diff --git a/osu.Game/Overlays/Settings/Sections/General/InstallationSettings.cs b/osu.Game/Overlays/Settings/Sections/General/InstallationSettings.cs index 68f3ba9b17..99d04398df 100644 --- a/osu.Game/Overlays/Settings/Sections/General/InstallationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/InstallationSettings.cs @@ -20,14 +20,14 @@ namespace osu.Game.Overlays.Settings.Sections.General [BackgroundDependencyLoader] private void load(Storage storage) { - Add(new SettingsButton + Add(new SettingsButtonV2 { Text = GeneralSettingsStrings.OpenOsuFolder, Keywords = new[] { @"logs", @"files", @"access", "directory" }, Action = () => storage.PresentExternally(), }); - Add(new DangerousSettingsButton + Add(new DangerousSettingsButtonV2 { Text = GeneralSettingsStrings.ChangeFolderLocation, Action = () => game?.PerformFromScreen(menu => menu.Push(new MigrationSelectScreen())) diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index 2af6e36b7f..515302239b 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -6,6 +6,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.General @@ -19,22 +20,22 @@ namespace osu.Game.Overlays.Settings.Sections.General { Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = GeneralSettingsStrings.LanguageDropdown, + Caption = GeneralSettingsStrings.LanguageDropdown, Current = game.CurrentLanguage, AlwaysShowSearchBar = true, - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GeneralSettingsStrings.PreferOriginalMetadataLanguage, + Caption = GeneralSettingsStrings.PreferOriginalMetadataLanguage, Current = frameworkConfig.GetBindable(FrameworkSetting.ShowUnicode) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GeneralSettingsStrings.Prefer24HourTimeDisplay, + Caption = GeneralSettingsStrings.Prefer24HourTimeDisplay, Current = config.GetBindable(OsuSetting.Prefer24HourTime) - }, + }), }; } } diff --git a/osu.Game/Overlays/Settings/Sections/General/QuickActionSettings.cs b/osu.Game/Overlays/Settings/Sections/General/QuickActionSettings.cs index d01a63f87a..3293242418 100644 --- a/osu.Game/Overlays/Settings/Sections/General/QuickActionSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/QuickActionSettings.cs @@ -35,21 +35,21 @@ namespace osu.Game.Overlays.Settings.Sections.General { AddRange(new Drawable[] { - new SettingsButton + new SettingsButtonV2 { Text = GeneralSettingsStrings.RunSetupWizard, Keywords = new[] { @"first run", @"initial", @"getting started", @"import", @"tutorial", @"recommended beatmaps" }, TooltipText = FirstRunSetupOverlayStrings.FirstRunSetupDescription, Action = () => firstRunSetupOverlay?.Show(), }, - new SettingsButton + new SettingsButtonV2 { Text = GeneralSettingsStrings.LearnMoreAboutLazer, TooltipText = GeneralSettingsStrings.LearnMoreAboutLazerTooltip, BackgroundColour = colours.YellowDark, Action = () => game?.ShowWiki(@"Help_centre/Upgrading_to_lazer") }, - new SettingsButton + new SettingsButtonV2 { Text = GeneralSettingsStrings.ReportIssue, TooltipText = GeneralSettingsStrings.ReportIssueTooltip, @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Settings.Sections.General if (supportsExport) { - Add(new SettingsButton + Add(new SettingsButtonV2 { Text = GeneralSettingsStrings.ExportLogs, BackgroundColour = colours.YellowDarker.Darken(0.5f), diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 87b1acc23a..c8efb50acc 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.Dialog; @@ -20,8 +21,10 @@ namespace osu.Game.Overlays.Settings.Sections.General { protected override LocalisableString Header => GeneralSettingsStrings.UpdateHeader; - private SettingsButton checkForUpdatesButton = null!; - private SettingsEnumDropdown releaseStreamDropdown = null!; + private SettingsButtonV2 checkForUpdatesButton = null!; + private FormEnumDropdown releaseStreamDropdown = null!; + + private readonly Bindable releaseStreamDropdownNote = new Bindable(); private readonly Bindable configReleaseStream = new Bindable(); @@ -47,26 +50,28 @@ namespace osu.Game.Overlays.Settings.Sections.General // For simplicity, hide the concept of release streams from mobile users. if (isDesktop) { - Add(releaseStreamDropdown = new SettingsEnumDropdown + Add(new SettingsItemV2(releaseStreamDropdown = new FormEnumDropdown { - LabelText = GeneralSettingsStrings.ReleaseStream, + Caption = GeneralSettingsStrings.ReleaseStream, Current = { Value = configReleaseStream.Value }, + }) + { Keywords = new[] { @"version" }, + ShowRevertToDefaultButton = updateManager!.FixedReleaseStream == null }); if (updateManager!.FixedReleaseStream != null) { configReleaseStream.Value = updateManager.FixedReleaseStream.Value; - releaseStreamDropdown.ShowsDefaultIndicator = false; releaseStreamDropdown.Items = [updateManager.FixedReleaseStream.Value]; - releaseStreamDropdown.SetNoticeText(GeneralSettingsStrings.ChangeReleaseStreamPackageManagerWarning); + releaseStreamDropdownNote.Value = new SettingsNote.Data(GeneralSettingsStrings.ChangeReleaseStreamPackageManagerWarning, SettingsNote.Type.Warning); } releaseStreamDropdown.Current.BindValueChanged(releaseStreamChanged); } - Add(checkForUpdatesButton = new SettingsButton + Add(checkForUpdatesButton = new SettingsButtonV2 { Text = GeneralSettingsStrings.CheckUpdate, Action = () => checkForUpdates().FireAndForget() diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index cdc4f328c3..cc1105c579 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -9,7 +9,6 @@ using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -18,7 +17,7 @@ using osu.Framework.Platform; using osu.Framework.Platform.Windows; using osu.Game.Configuration; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osuTK; using osuTK.Graphics; @@ -29,8 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader; - private FillFlowContainer> scalingSettings = null!; - private SettingsSlider dimSlider = null!; + private FillFlowContainer scalingSettings = null!; private readonly Bindable currentDisplay = new Bindable(); @@ -51,12 +49,19 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private IWindow? window; - private SettingsDropdown resolutionFullscreenDropdown = null!; - private SettingsDropdown resolutionWindowedDropdown = null!; - private SettingsDropdown displayDropdown = null!; - private SettingsDropdown windowModeDropdown = null!; - private SettingsCheckbox minimiseOnFocusLossCheckbox = null!; - private SettingsCheckbox safeAreaConsiderationsCheckbox = null!; + private readonly BindableBool resolutionFullscreenCanBeShown = new BindableBool(true); + private readonly BindableBool resolutionWindowedCanBeShown = new BindableBool(true); + private readonly BindableBool displayDropdownCanBeShown = new BindableBool(true); + private readonly BindableBool minimiseOnFocusLossCanBeShown = new BindableBool(true); + private readonly BindableBool safeAreaConsiderationsCanBeShown = new BindableBool(true); + + private FormDropdown resolutionWindowedDropdown = null!; + private FormDropdown displayDropdown = null!; + private FormDropdown windowModeDropdown = null!; + + private FormSliderBar dimSlider = null!; + + private readonly Bindable windowModeDropdownNote = new Bindable(); private Bindable windowedPositionX = null!; private Bindable windowedPositionY = null!; @@ -98,105 +103,137 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Children = new Drawable[] { - windowModeDropdown = new SettingsDropdown + new SettingsItemV2(windowModeDropdown = new FormDropdown { - LabelText = GraphicsSettingsStrings.ScreenMode, + Caption = GraphicsSettingsStrings.ScreenMode, Items = window?.SupportedWindowModes, - CanBeShown = { Value = window?.SupportedWindowModes.Count() > 1 }, Current = config.GetBindable(FrameworkSetting.WindowMode), - }, - displayDropdown = new DisplaySettingsDropdown + }) { - LabelText = GraphicsSettingsStrings.Display, + CanBeShown = { Value = window?.SupportedWindowModes.Count() > 1 }, + Note = { BindTarget = windowModeDropdownNote }, + }, + new SettingsItemV2(displayDropdown = new DisplayDropdown + { + Caption = GraphicsSettingsStrings.Display, Items = window?.Displays, Current = currentDisplay, - }, - resolutionFullscreenDropdown = new ResolutionSettingsDropdown + }) { - LabelText = GraphicsSettingsStrings.Resolution, - ShowsDefaultIndicator = false, + CanBeShown = { BindTarget = displayDropdownCanBeShown } + }, + new SettingsItemV2(new ResolutionDropdown + { + Caption = GraphicsSettingsStrings.Resolution, ItemSource = resolutionsFullscreen, Current = sizeFullscreen - }, - resolutionWindowedDropdown = new ResolutionSettingsDropdown + }) { - LabelText = GraphicsSettingsStrings.Resolution, - ShowsDefaultIndicator = false, + CanBeShown = { BindTarget = resolutionFullscreenCanBeShown }, + ShowRevertToDefaultButton = false, + }, + new SettingsItemV2(resolutionWindowedDropdown = new ResolutionDropdown + { + Caption = GraphicsSettingsStrings.Resolution, ItemSource = resolutionsWindowed, Current = windowedResolution - }, - minimiseOnFocusLossCheckbox = new SettingsCheckbox + }) { - LabelText = GraphicsSettingsStrings.MinimiseOnFocusLoss, + CanBeShown = { BindTarget = resolutionWindowedCanBeShown }, + ShowRevertToDefaultButton = false, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = GraphicsSettingsStrings.MinimiseOnFocusLoss, Current = config.GetBindable(FrameworkSetting.MinimiseOnFocusLossInFullscreen), + }) + { + CanBeShown = { BindTarget = minimiseOnFocusLossCanBeShown }, Keywords = new[] { "alt-tab", "minimize", "focus", "hide" }, }, - safeAreaConsiderationsCheckbox = new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = GraphicsSettingsStrings.ShrinkGameToSafeArea, + Caption = GraphicsSettingsStrings.ShrinkGameToSafeArea, Current = osuConfig.GetBindable(OsuSetting.SafeAreaConsiderations), - }, - new SettingsSlider + }) { - LabelText = GraphicsSettingsStrings.UIScaling, + CanBeShown = { BindTarget = safeAreaConsiderationsCanBeShown }, + }, + new SettingsItemV2(new FormSliderBar + { + Caption = GraphicsSettingsStrings.UIScaling, TransferValueOnCommit = true, Current = osuConfig.GetBindable(OsuSetting.UIScale), KeyboardStep = 0.01f, - Keywords = new[] { "scale", "letterbox" }, - }, - new SettingsEnumDropdown + LabelFormat = v => $@"{v:0.##}x", + }) { - LabelText = GraphicsSettingsStrings.ScreenScaling, - Current = osuConfig.GetBindable(OsuSetting.Scaling), Keywords = new[] { "scale", "letterbox" }, }, - scalingSettings = new FillFlowContainer> + new SettingsItemV2(new FormEnumDropdown + { + Caption = GraphicsSettingsStrings.ScreenScaling, + Current = osuConfig.GetBindable(OsuSetting.Scaling), + }) + { + Keywords = new[] { "scale", "letterbox" }, + }, + scalingSettings = new FillFlowContainer { Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Masking = true, + Spacing = new Vector2(0, SettingsSection.ITEM_SPACING_V2), Children = new[] { - new SettingsSlider + new SettingsItemV2(new FormSliderBar { - LabelText = GraphicsSettingsStrings.HorizontalPosition, - Keywords = new[] { "screen", "scaling" }, + Caption = GraphicsSettingsStrings.HorizontalPosition, Current = scalingPositionX, KeyboardStep = 0.01f, - DisplayAsPercentage = true - }, - new SettingsSlider + DisplayAsPercentage = true, + }.With(bindPreviewEvent)) { - LabelText = GraphicsSettingsStrings.VerticalPosition, Keywords = new[] { "screen", "scaling" }, + }, + new SettingsItemV2(new FormSliderBar + { + Caption = GraphicsSettingsStrings.VerticalPosition, Current = scalingPositionY, KeyboardStep = 0.01f, - DisplayAsPercentage = true - }, - new SettingsSlider + DisplayAsPercentage = true, + }.With(bindPreviewEvent)) { - LabelText = GraphicsSettingsStrings.HorizontalScale, Keywords = new[] { "screen", "scaling" }, + }, + new SettingsItemV2(new FormSliderBar + { + Caption = GraphicsSettingsStrings.HorizontalScale, Current = scalingSizeX, KeyboardStep = 0.01f, - DisplayAsPercentage = true - }, - new SettingsSlider + DisplayAsPercentage = true, + }.With(bindPreviewEvent)) { - LabelText = GraphicsSettingsStrings.VerticalScale, Keywords = new[] { "screen", "scaling" }, + }, + new SettingsItemV2(new FormSliderBar + { + Caption = GraphicsSettingsStrings.VerticalScale, Current = scalingSizeY, KeyboardStep = 0.01f, - DisplayAsPercentage = true - }, - dimSlider = new SettingsSlider + DisplayAsPercentage = true, + }.With(bindPreviewEvent)) { - LabelText = GameplaySettingsStrings.BackgroundDim, + Keywords = new[] { "screen", "scaling" }, + }, + new SettingsItemV2(dimSlider = new FormSliderBar + { + Caption = GameplaySettingsStrings.BackgroundDim, Current = scalingBackgroundDim, KeyboardStep = 0.01f, DisplayAsPercentage = true, - }, + }.With(bindPreviewEvent)), } }, }; @@ -208,8 +245,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { base.LoadComplete(); - scalingSettings.ForEach(s => bindPreviewEvent(s.Current)); - windowModeDropdown.Current.BindValueChanged(_ => { updateDisplaySettingsVisibility(); @@ -298,18 +333,19 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); scalingSettings.AutoSizeAxes = scalingMode.Value != ScalingMode.Off ? Axes.Y : Axes.None; - scalingSettings.ForEach(s => + + foreach (SettingsItemV2 item in scalingSettings) { - if (s == dimSlider) - { - s.CanBeShown.Value = scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays; - } + FormSliderBar slider = (FormSliderBar)item.Control; + + if (slider == dimSlider) + item.CanBeShown.Value = scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays; else { - s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything; - s.CanBeShown.Value = scalingMode.Value != ScalingMode.Off; + slider.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything; + item.CanBeShown.Value = scalingMode.Value != ScalingMode.Off; } - }); + } } } @@ -325,12 +361,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private void updateDisplaySettingsVisibility() { - resolutionFullscreenDropdown.CanBeShown.Value = windowModeDropdown.Current.Value == WindowMode.Fullscreen && resolutionsFullscreen.Count > 1; - resolutionWindowedDropdown.CanBeShown.Value = windowModeDropdown.Current.Value == WindowMode.Windowed && resolutionsWindowed.Count > 1; + resolutionFullscreenCanBeShown.Value = windowModeDropdown.Current.Value == WindowMode.Fullscreen && resolutionsFullscreen.Count > 1; + resolutionWindowedCanBeShown.Value = windowModeDropdown.Current.Value == WindowMode.Windowed && resolutionsWindowed.Count > 1; - displayDropdown.CanBeShown.Value = displayDropdown.Items.Count() > 1; - minimiseOnFocusLossCheckbox.CanBeShown.Value = RuntimeInfo.IsDesktop && windowModeDropdown.Current.Value == WindowMode.Fullscreen; - safeAreaConsiderationsCheckbox.CanBeShown.Value = host.Window?.SafeAreaPadding.Value.Total != Vector2.Zero; + displayDropdownCanBeShown.Value = displayDropdown.Items.Count() > 1; + minimiseOnFocusLossCanBeShown.Value = RuntimeInfo.IsDesktop && windowModeDropdown.Current.Value == WindowMode.Fullscreen; + safeAreaConsiderationsCanBeShown.Value = host.Window?.SafeAreaPadding.Value.Total != Vector2.Zero; } private void updateScreenModeWarning() @@ -339,16 +375,16 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (RuntimeInfo.OS == RuntimeInfo.Platform.macOS && !FrameworkEnvironment.UseSDL3) { if (windowModeDropdown.Current.Value == WindowMode.Fullscreen) - windowModeDropdown.SetNoticeText(LayoutSettingsStrings.FullscreenMacOSNote, true); + windowModeDropdownNote.Value = new SettingsNote.Data(LayoutSettingsStrings.FullscreenMacOSNote, SettingsNote.Type.Critical); else - windowModeDropdown.ClearNoticeText(); + windowModeDropdownNote.Value = null; return; } if (windowModeDropdown.Current.Value != WindowMode.Fullscreen) { - windowModeDropdown.SetNoticeText(GraphicsSettingsStrings.NotFullscreenNote, true); + windowModeDropdownNote.Value = new SettingsNote.Data(GraphicsSettingsStrings.NotFullscreenNote, SettingsNote.Type.Warning); return; } @@ -357,28 +393,28 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics switch (fullscreenCapability.Value) { case FullscreenCapability.Unknown: - windowModeDropdown.SetNoticeText(LayoutSettingsStrings.CheckingForFullscreenCapabilities, true); + windowModeDropdownNote.Value = new SettingsNote.Data(LayoutSettingsStrings.CheckingForFullscreenCapabilities, SettingsNote.Type.Informational); break; case FullscreenCapability.Capable: - windowModeDropdown.SetNoticeText(LayoutSettingsStrings.OsuIsRunningExclusiveFullscreen); + windowModeDropdownNote.Value = new SettingsNote.Data(LayoutSettingsStrings.OsuIsRunningExclusiveFullscreen, SettingsNote.Type.Informational); break; case FullscreenCapability.Incapable: - windowModeDropdown.SetNoticeText(LayoutSettingsStrings.UnableToRunExclusiveFullscreen, true); + windowModeDropdownNote.Value = new SettingsNote.Data(LayoutSettingsStrings.UnableToRunExclusiveFullscreen, SettingsNote.Type.Warning); break; } } else { // We can only detect exclusive fullscreen status on windows currently. - windowModeDropdown.ClearNoticeText(); + windowModeDropdownNote.Value = null; } } - private void bindPreviewEvent(Bindable bindable) + private void bindPreviewEvent(FormSliderBar slider) { - bindable.ValueChanged += _ => + slider.Current.ValueChanged += _ => { switch (scalingMode.Value) { @@ -421,37 +457,22 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } - private partial class UIScaleSlider : RoundedSliderBar + private partial class DisplayDropdown : FormDropdown { - public override LocalisableString TooltipText => base.TooltipText + "x"; - } - - private partial class DisplaySettingsDropdown : SettingsDropdown - { - protected override OsuDropdown CreateDropdown() => new DisplaySettingsDropdownControl(); - - private partial class DisplaySettingsDropdownControl : DropdownControl + protected override LocalisableString GenerateItemText(Display item) { - protected override LocalisableString GenerateItemText(Display item) - { - return $"{item.Index}: {item.Name} ({item.Bounds.Width}x{item.Bounds.Height})"; - } + return $"{item.Index}: {item.Name} ({item.Bounds.Width}x{item.Bounds.Height})"; } } - private partial class ResolutionSettingsDropdown : SettingsDropdown + private partial class ResolutionDropdown : FormDropdown { - protected override OsuDropdown CreateDropdown() => new ResolutionDropdownControl(); - - private partial class ResolutionDropdownControl : DropdownControl + protected override LocalisableString GenerateItemText(Size item) { - protected override LocalisableString GenerateItemText(Size item) - { - if (item == new Size(9999, 9999)) - return CommonStrings.Default; + if (item == new Size(9999, 9999)) + return CommonStrings.Default; - return $"{item.Width}x{item.Height}"; - } + return $"{item.Width}x{item.Height}"; } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 69697bd9a3..f1cec99f38 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Configuration; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Overlays.Dialog; @@ -29,32 +29,38 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Children = new Drawable[] { - new RendererSettingsDropdown + new SettingsItemV2(new RendererDropdown { - LabelText = GraphicsSettingsStrings.Renderer, + Caption = GraphicsSettingsStrings.Renderer, Current = renderer, Items = host.GetPreferredRenderersForCurrentPlatform().Order() #pragma warning disable CS0612 // Type or member is obsolete .Where(t => t != RendererType.Vulkan && t != RendererType.OpenGLLegacy), #pragma warning restore CS0612 // Type or member is obsolete + }) + { Keywords = new[] { @"compatibility", @"directx" }, }, // TODO: this needs to be a custom dropdown at some point - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = GraphicsSettingsStrings.FrameLimiter, + Caption = GraphicsSettingsStrings.FrameLimiter, Current = config.GetBindable(FrameworkSetting.FrameSync), + }) + { Keywords = new[] { @"fps", @"framerate" }, }, - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = GraphicsSettingsStrings.ThreadingMode, + Caption = GraphicsSettingsStrings.ThreadingMode, Current = config.GetBindable(FrameworkSetting.ExecutionMode) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GraphicsSettingsStrings.ShowFPS, + Caption = GraphicsSettingsStrings.ShowFPS, Current = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay), + }) + { Keywords = new[] { @"framerate", @"counter" }, }, }; @@ -82,30 +88,25 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }); } - private partial class RendererSettingsDropdown : SettingsEnumDropdown + private partial class RendererDropdown : FormEnumDropdown { - protected override OsuDropdown CreateDropdown() => new RendererDropdown(); + private RendererType hostResolvedRenderer; + private bool automaticRendererInUse; - protected partial class RendererDropdown : DropdownControl + [BackgroundDependencyLoader] + private void load(FrameworkConfigManager config, GameHost host) { - private RendererType hostResolvedRenderer; - private bool automaticRendererInUse; + var renderer = config.GetBindable(FrameworkSetting.Renderer); + automaticRendererInUse = renderer.Value == RendererType.Automatic; + hostResolvedRenderer = host.ResolvedRenderer; + } - [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, GameHost host) - { - var renderer = config.GetBindable(FrameworkSetting.Renderer); - automaticRendererInUse = renderer.Value == RendererType.Automatic; - hostResolvedRenderer = host.ResolvedRenderer; - } + protected override LocalisableString GenerateItemText(RendererType item) + { + if (item == RendererType.Automatic && automaticRendererInUse) + return LocalisableString.Interpolate($"{base.GenerateItemText(item)} ({hostResolvedRenderer.GetDescription()})"); - protected override LocalisableString GenerateItemText(RendererType item) - { - if (item == RendererType.Automatic && automaticRendererInUse) - return LocalisableString.Interpolate($"{base.GenerateItemText(item)} ({hostResolvedRenderer.GetDescription()})"); - - return base.GenerateItemText(item); - } + return base.GenerateItemText(item); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs index c7180ec51b..f5dd19dc99 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics @@ -18,16 +19,16 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = GraphicsSettingsStrings.ScreenshotFormat, + Caption = GraphicsSettingsStrings.ScreenshotFormat, Current = config.GetBindable(OsuSetting.ScreenshotFormat) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = GraphicsSettingsStrings.ShowCursorInScreenshots, + Caption = GraphicsSettingsStrings.ShowCursorInScreenshots, Current = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor) - } + }) }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs index 2e0bbe3c16..0481b45037 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs @@ -9,6 +9,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Video; using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Graphics @@ -18,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics protected override LocalisableString Header => GraphicsSettingsStrings.VideoHeader; private Bindable hardwareVideoDecoder; - private SettingsCheckbox hwAccelCheckbox; + private FormCheckBox hwAccelCheckbox; [BackgroundDependencyLoader] private void load(FrameworkConfigManager config) @@ -27,10 +28,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Children = new Drawable[] { - hwAccelCheckbox = new SettingsCheckbox + new SettingsItemV2(hwAccelCheckbox = new FormCheckBox { - LabelText = GraphicsSettingsStrings.UseHardwareAcceleration, - }, + Caption = GraphicsSettingsStrings.UseHardwareAcceleration, + }), }; hwAccelCheckbox.Current.Default = hardwareVideoDecoder.Default != HardwareVideoDecoder.None; diff --git a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs index 704fa6e907..c892e8fa21 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { Children = new Drawable[] { - new SettingsButton + new SettingsButtonV2 { Text = BindingSettingsStrings.Configure, TooltipText = BindingSettingsStrings.ChangeBindingsButton, diff --git a/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs index 8455c09633..d5d7540f79 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs @@ -8,25 +8,23 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Handlers.Joystick; using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { - public partial class JoystickSettings : SettingsSubsection + public partial class JoystickSettings : InputSubsection { protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad; private readonly JoystickHandler joystickHandler; - private readonly Bindable enabled = new BindableBool(true); - - private SettingsSlider deadzoneSlider; - private Bindable handlerDeadzone; private Bindable localDeadzone; public JoystickSettings(JoystickHandler joystickHandler) + : base(joystickHandler) { this.joystickHandler = joystickHandler; } @@ -38,30 +36,22 @@ namespace osu.Game.Overlays.Settings.Sections.Input handlerDeadzone = joystickHandler.DeadzoneThreshold.GetBoundCopy(); localDeadzone = handlerDeadzone.GetUnboundCopy(); - Children = new Drawable[] + AddRange(new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormSliderBar { - LabelText = CommonStrings.Enabled, - Current = enabled - }, - deadzoneSlider = new SettingsSlider - { - LabelText = JoystickSettingsStrings.DeadzoneThreshold, + Caption = JoystickSettingsStrings.DeadzoneThreshold, KeyboardStep = 0.01f, DisplayAsPercentage = true, Current = localDeadzone, - }, - }; + }) + }); } protected override void LoadComplete() { base.LoadComplete(); - enabled.BindTo(joystickHandler.Enabled); - enabled.BindValueChanged(e => deadzoneSlider.Current.Disabled = !e.NewValue, true); - handlerDeadzone.BindValueChanged(val => { bool disabled = localDeadzone.Disabled; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index c9ef6ef891..98a6d2600f 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -94,6 +94,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input private Container content = null!; private OsuSpriteText text = null!; + private SettingsRevertToDefaultButton revertButton = null!; private FillFlowContainer cancelAndClearButtons = null!; private FillFlowContainer buttons = null!; @@ -127,27 +128,24 @@ namespace osu.Game.Overlays.Settings.Sections.Input { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Right = SettingsPanel.CONTENT_MARGINS }; + Padding = new MarginPadding { Right = SettingsPanel.CONTENT_PADDING.Right }; InternalChildren = new Drawable[] { - new Container + revertButton = new SettingsRevertToDefaultButton { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Height = 1, RelativeSizeAxes = Axes.Y, - Width = SettingsPanel.CONTENT_MARGINS, - Child = new RevertToDefaultButton - { - Current = isDefault, - Action = RestoreDefaults, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } + IconSize = 12, + Action = RestoreDefaults, }, new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, + Padding = new MarginPadding { Left = SettingsPanel.CONTENT_PADDING.Left }, Children = new Drawable[] { content = new Container @@ -179,7 +177,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input { AutoSizeAxes = Axes.Both, Anchor = Anchor.TopRight, - Origin = Anchor.TopRight + Origin = Anchor.TopRight, + Spacing = new Vector2(-6, 0), }, cancelAndClearButtons = new FillFlowContainer { @@ -223,6 +222,19 @@ namespace osu.Game.Overlays.Settings.Sections.Input keypressSamples[i] = audioManager.Samples.Get($@"Keyboard/key-press-{1 + i}"); } + protected override void LoadComplete() + { + base.LoadComplete(); + + isDefault.BindValueChanged(d => + { + if (d.NewValue) + revertButton.Hide(); + else + revertButton.Show(); + }, true); + } + public void RestoreDefaults() { int i = 0; @@ -483,7 +495,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input protected override void OnFocus(FocusEvent e) { - content.AutoSizeDuration = 500; + content.AutoSizeDuration = 250; content.AutoSizeEasing = Easing.OutQuint; cancelAndClearButtons.FadeIn(300, Easing.OutQuint); diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index cde9f10549..873ecc3f47 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -111,7 +111,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - public partial class ResetButton : DangerousSettingsButton + public partial class ResetButton : DangerousSettingsButtonV2 { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 3fb4016498..1d4538baef 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.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. -#nullable disable - using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -11,30 +9,33 @@ using osu.Framework.Graphics; using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Localisation; using osu.Game.Configuration; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Input; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input { - public partial class MouseSettings : SettingsSubsection + public partial class MouseSettings : InputSubsection { private readonly MouseHandler mouseHandler; protected override LocalisableString Header => MouseSettingsStrings.Mouse; - private Bindable handlerSensitivity; + private Bindable handlerSensitivity = null!; + private Bindable localSensitivity = null!; + private Bindable windowMode = null!; + private Bindable minimiseOnFocusLoss = null!; + private FormEnumDropdown confineMouseModeSetting = null!; + private Bindable relativeMode = null!; - private Bindable localSensitivity; + private FormCheckBox highPrecisionMouse = null!; - private Bindable windowMode; - private Bindable minimiseOnFocusLoss; - private SettingsEnumDropdown confineMouseModeSetting; - private Bindable relativeMode; + private readonly Bindable highPrecisionMouseNote = new Bindable(); - private SettingsCheckbox highPrecisionMouse; + protected override bool IsToggleable => false; public MouseSettings(MouseHandler mouseHandler) + : base(mouseHandler) { this.mouseHandler = mouseHandler; } @@ -50,38 +51,47 @@ namespace osu.Game.Overlays.Settings.Sections.Input windowMode = config.GetBindable(FrameworkSetting.WindowMode); minimiseOnFocusLoss = config.GetBindable(FrameworkSetting.MinimiseOnFocusLossInFullscreen); - Children = new Drawable[] + AddRange(new Drawable[] { - highPrecisionMouse = new SettingsCheckbox + new SettingsItemV2(highPrecisionMouse = new FormCheckBox { - LabelText = MouseSettingsStrings.HighPrecisionMouse, - TooltipText = MouseSettingsStrings.HighPrecisionMouseTooltip, + Caption = MouseSettingsStrings.HighPrecisionMouse, + HintText = MouseSettingsStrings.HighPrecisionMouseTooltip, Current = relativeMode, + }) + { Keywords = new[] { @"raw", @"input", @"relative", @"cursor", "sensitivity", "speed", "velocity" }, + Note = { BindTarget = highPrecisionMouseNote }, }, - new SensitivitySetting + new SettingsItemV2(new FormSliderBar + { + Caption = MouseSettingsStrings.CursorSensitivity, + Current = localSensitivity, + KeyboardStep = 0.01f, + TransferValueOnCommit = true, + LabelFormat = v => $@"{v:0.##}x", + TooltipFormat = v => localSensitivity.Disabled ? MouseSettingsStrings.EnableHighPrecisionForSensitivityAdjust : $@"{v:0.##}x", + }) { Keywords = new[] { "speed", "velocity" }, - LabelText = MouseSettingsStrings.CursorSensitivity, - Current = localSensitivity }, - confineMouseModeSetting = new SettingsEnumDropdown + new SettingsItemV2(confineMouseModeSetting = new FormEnumDropdown { - LabelText = MouseSettingsStrings.ConfineMouseMode, + Caption = MouseSettingsStrings.ConfineMouseMode, Current = osuConfig.GetBindable(OsuSetting.ConfineMouseMode) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust, - TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip, + Caption = MouseSettingsStrings.DisableMouseWheelVolumeAdjust, + HintText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip, Current = osuConfig.GetBindable(OsuSetting.MouseDisableWheel) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = MouseSettingsStrings.DisableClicksDuringGameplay, + Caption = MouseSettingsStrings.DisableClicksDuringGameplay, Current = osuConfig.GetBindable(OsuSetting.MouseDisableButtons) - }, - }; + }), + }); } protected override void LoadComplete() @@ -112,9 +122,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input case RuntimeInfo.Platform.macOS: case RuntimeInfo.Platform.iOS: if (highPrecision.NewValue) - highPrecisionMouse.SetNoticeText(MouseSettingsStrings.HighPrecisionPlatformWarning, true); + highPrecisionMouseNote.Value = new SettingsNote.Data(MouseSettingsStrings.HighPrecisionPlatformWarning, SettingsNote.Type.Warning); else - highPrecisionMouse.ClearNoticeText(); + highPrecisionMouseNote.Value = null; break; } @@ -131,27 +141,13 @@ namespace osu.Game.Overlays.Settings.Sections.Input if (confineModeOverriden) { confineMouseModeSetting.Current.Disabled = true; - confineMouseModeSetting.TooltipText = MouseSettingsStrings.NotApplicableFullscreen; + confineMouseModeSetting.HintText = MouseSettingsStrings.NotApplicableFullscreen; } else { confineMouseModeSetting.Current.Disabled = false; - confineMouseModeSetting.TooltipText = string.Empty; + confineMouseModeSetting.HintText = default; } } - - public partial class SensitivitySetting : SettingsSlider - { - public SensitivitySetting() - { - KeyboardStep = 0.01f; - TransferValueOnCommit = true; - } - } - - public partial class SensitivitySlider : RoundedSliderBar - { - public override LocalisableString TooltipText => Current.Disabled ? MouseSettingsStrings.EnableHighPrecisionForSensitivityAdjust : $"{base.TooltipText}x"; - } } } diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs index b3fdd53466..5cd0926550 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs @@ -41,71 +41,92 @@ namespace osu.Game.Overlays.Settings.Sections.Input private Box usableFill; private OsuSpriteText usableAreaText; + [Resolved] + private OsuColour colour { get; set; } + public TabletAreaSelection(ITabletHandler handler) { this.handler = handler; - Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }; + Padding = SettingsPanel.CONTENT_PADDING; } [BackgroundDependencyLoader] - private void load() + private void load(OverlayColourProvider colourProvider) { - InternalChild = tabletContainer = new Container + InternalChildren = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - CornerRadius = 5, - BorderThickness = 2, - BorderColour = colour.Gray3, - Children = new Drawable[] + new Container { - new Box + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 5, + CornerExponent = 2.5f, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = colour.Gray1, - }, - usableAreaContainer = new UsableAreaContainer(handler) - { - Origin = Anchor.Centre, - Children = new Drawable[] + new Box { - usableFill = new Box + Colour = colourProvider.Background5, + RelativeSizeAxes = Axes.Both, + }, + tabletContainer = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + CornerRadius = 5, + BorderThickness = 2, + BorderColour = colourProvider.Background3, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Alpha = 0.6f, - }, - new Box - { - Colour = Color4.White, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Height = 5, - }, - new Box - { - Colour = Color4.White, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 5, - }, - usableAreaText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = Color4.White, - Font = OsuFont.Default.With(size: 12), - Y = 10 + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background4, + }, + usableAreaContainer = new UsableAreaContainer(handler) + { + Origin = Anchor.Centre, + Children = new Drawable[] + { + usableFill = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.6f, + }, + new Box + { + Colour = Color4.White, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = 5, + }, + new Box + { + Colour = Color4.White, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 5, + }, + usableAreaText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.White, + Font = OsuFont.Default.With(size: 12), + Y = 10 + } + } + }, + tabletName = new OsuSpriteText + { + Padding = new MarginPadding(3), + Font = OsuFont.Default.With(size: 8) + }, } } - }, - tabletName = new OsuSpriteText - { - Padding = new MarginPadding(3), - Font = OsuFont.Default.With(size: 8) - }, - } + } + }, }; } @@ -169,9 +190,6 @@ namespace osu.Game.Overlays.Settings.Sections.Input return a; } - [Resolved] - private OsuColour colour { get; set; } - private void checkBounds() { if (tablet.Value == null) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 2a3710c67b..b5e9e2ee4e 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -9,6 +9,8 @@ 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.Input.Handlers; using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Platform; @@ -17,13 +19,14 @@ using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; using osuTK; using osu.Game.Localisation; using osu.Game.Online.Chat; namespace osu.Game.Overlays.Settings.Sections.Input { - public partial class TabletSettings : SettingsSubsection + public partial class TabletSettings : InputSubsection { public override IEnumerable FilterTerms => base.FilterTerms.Concat(new LocalisableString[] { "area" }); @@ -74,70 +77,92 @@ namespace osu.Game.Overlays.Settings.Sections.Input private FillFlowContainer mainSettings; - private FillFlowContainer noTabletMessage; + private Container noTabletMessage; protected override LocalisableString Header => TabletSettingsStrings.Tablet; public TabletSettings(ITabletHandler tabletHandler) + : base((InputHandler)tabletHandler) { this.tabletHandler = tabletHandler; } [BackgroundDependencyLoader] - private void load(OsuColour colours, LocalisationManager localisation, OsuConfigManager osuConfig) + private void load(OsuColour colours, LocalisationManager localisation, OsuConfigManager osuConfig, OverlayColourProvider colourProvider) { scalingMode = osuConfig.GetBindable(OsuSetting.Scaling); scalingSizeX = osuConfig.GetBindable(OsuSetting.ScalingSizeX); scalingSizeY = osuConfig.GetBindable(OsuSetting.ScalingSizeY); - Children = new Drawable[] + AddRange(new Drawable[] { - new SettingsCheckbox - { - LabelText = CommonStrings.Enabled, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Current = enabled, - }, - noTabletMessage = new FillFlowContainer + noTabletMessage = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, - Spacing = new Vector2(5f), - Children = new Drawable[] + Padding = SettingsPanel.CONTENT_PADDING, + Child = new Container { - new OsuSpriteText + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Masking = true, + CornerRadius = 5, + CornerExponent = 2.5f, + Children = new Drawable[] { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = TabletSettingsStrings.NoTabletDetected, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Dark2, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(5f), + Padding = new MarginPadding { Horizontal = 8, Vertical = 10 }, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = TabletSettingsStrings.NoTabletDetected, + Font = OsuFont.Style.Caption1.With(weight: FontWeight.SemiBold), + Colour = colourProvider.Content2, + }, + new LinkFlowContainer(cp => + { + cp.Colour = colours.Orange1; + cp.Font = OsuFont.Style.Caption1.With(weight: FontWeight.SemiBold); + }) + { + TextAnchor = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }.With(t => + { + t.NewLine(); + + const string url = @"https://opentabletdriver.net/Wiki/FAQ/General"; + var formattedSource = MessageFormatter.FormatText(localisation.GetLocalisedString(TabletSettingsStrings.NoTabletDetectedDescription(url))); + + t.AddLinks(formattedSource.Text, formattedSource.Links); + }), + } + }, }, - new LinkFlowContainer(cp => cp.Colour = colours.Yellow) - { - TextAnchor = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }.With(t => - { - t.NewLine(); - - const string url = @"https://opentabletdriver.net/Wiki/FAQ/General"; - var formattedSource = MessageFormatter.FormatText(localisation.GetLocalisedString(TabletSettingsStrings.NoTabletDetectedDescription(url))); - - t.AddLinks(formattedSource.Text, formattedSource.Links); - }), - } + }, }, mainSettings = new FillFlowContainer { Alpha = 0, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0, SettingsSection.ITEM_SPACING), + Spacing = new Vector2(0, SettingsSection.ITEM_SPACING_V2), Direction = FillDirection.Vertical, Children = new Drawable[] { @@ -146,7 +171,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input RelativeSizeAxes = Axes.X, Height = 300, }, - new DangerousSettingsButton + new DangerousSettingsButtonV2 { Text = TabletSettingsStrings.ResetToFullArea, Action = () => @@ -156,9 +181,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input areaOffset.SetDefault(); areaSize.SetDefault(); }, - CanBeShown = { BindTarget = enabled } }, - new SettingsButton + new SettingsButtonV2 { Text = TabletSettingsStrings.ConformToCurrentGameAspectRatio, Action = () => @@ -174,73 +198,62 @@ namespace osu.Game.Overlays.Settings.Sections.Input forceAspectRatio(gameplayWidth / gameplayHeight); }, - CanBeShown = { BindTarget = enabled } }, - new SettingsSlider + new SettingsItemV2(new FormSliderBar { TransferValueOnCommit = true, - LabelText = TabletSettingsStrings.XOffset, + Caption = TabletSettingsStrings.XOffset, Current = offsetX, - CanBeShown = { BindTarget = enabled } - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { TransferValueOnCommit = true, - LabelText = TabletSettingsStrings.YOffset, + Caption = TabletSettingsStrings.YOffset, Current = offsetY, - CanBeShown = { BindTarget = enabled } - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { TransferValueOnCommit = true, - LabelText = TabletSettingsStrings.Rotation, + Caption = TabletSettingsStrings.Rotation, Current = rotation, - CanBeShown = { BindTarget = enabled } - }, + }), new RotationPresetButtons(tabletHandler) { - Padding = new MarginPadding - { - Horizontal = SettingsPanel.CONTENT_MARGINS - } + Padding = SettingsPanel.CONTENT_PADDING, }, - new SettingsSlider + new SettingsItemV2(new FormSliderBar { TransferValueOnCommit = true, - LabelText = TabletSettingsStrings.AspectRatio, + Caption = TabletSettingsStrings.AspectRatio, Current = aspectRatio, - CanBeShown = { BindTarget = enabled } - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = TabletSettingsStrings.LockAspectRatio, + Caption = TabletSettingsStrings.LockAspectRatio, Current = aspectLock, - CanBeShown = { BindTarget = enabled } - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { TransferValueOnCommit = true, - LabelText = CommonStrings.Width, + Caption = CommonStrings.Width, Current = sizeX, - CanBeShown = { BindTarget = enabled } - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { TransferValueOnCommit = true, - LabelText = CommonStrings.Height, + Caption = CommonStrings.Height, Current = sizeY, - CanBeShown = { BindTarget = enabled } - }, - new SettingsPercentageSlider + }), + new SettingsItemV2(new FormSliderBar { TransferValueOnCommit = true, - LabelText = TabletSettingsStrings.TipPressureForClick, + Caption = TabletSettingsStrings.TipPressureForClick, Current = pressureThreshold, - CanBeShown = { BindTarget = enabled } - }, + DisplayAsPercentage = true, + }), } }, - }; + }); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Settings/Sections/Input/TouchSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TouchSettings.cs index 0056de6674..5499d49648 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TouchSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TouchSettings.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Input.Handlers; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Input @@ -15,34 +16,25 @@ namespace osu.Game.Overlays.Settings.Sections.Input /// /// Touch input settings subsection common to all touch handlers (even on different platforms). /// - public partial class TouchSettings : SettingsSubsection + public partial class TouchSettings : InputSubsection { - private readonly InputHandler handler; - protected override LocalisableString Header => TouchSettingsStrings.Touch; + protected override bool IsToggleable => !RuntimeInfo.IsMobile; + public TouchSettings(InputHandler handler) + : base(handler) { - this.handler = handler; } [BackgroundDependencyLoader] private void load(OsuConfigManager osuConfig) { - if (!RuntimeInfo.IsMobile) // don't allow disabling the only input method (touch) on mobile. + Add(new SettingsItemV2(new FormCheckBox { - Add(new SettingsCheckbox - { - LabelText = CommonStrings.Enabled, - Current = handler.Enabled - }); - } - - Add(new SettingsCheckbox - { - LabelText = TouchSettingsStrings.DisableTapsDuringGameplay, + Caption = TouchSettingsStrings.DisableTapsDuringGameplay, Current = osuConfig.GetBindable(OsuSetting.TouchDisableGameplayTaps) - }); + })); } public override IEnumerable FilterTerms => base.FilterTerms.Concat(new LocalisableString[] { @"touchscreen" }); diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 0204aa5e64..0b22022362 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Handlers; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Graphics; @@ -45,30 +44,5 @@ namespace osu.Game.Overlays.Settings.Sections Add(handlerSection); } } - - public partial class HandlerSection : SettingsSubsection - { - private readonly InputHandler handler; - - public HandlerSection(InputHandler handler) - { - this.handler = handler; - } - - [BackgroundDependencyLoader] - private void load() - { - Children = new Drawable[] - { - new SettingsCheckbox - { - LabelText = CommonStrings.Enabled, - Current = handler.Enabled - }, - }; - } - - protected override LocalisableString Header => handler.Description; - } } } diff --git a/osu.Game/Overlays/Settings/Sections/InputSubsection.cs b/osu.Game/Overlays/Settings/Sections/InputSubsection.cs new file mode 100644 index 0000000000..50fb688707 --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/InputSubsection.cs @@ -0,0 +1,183 @@ +// 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.Input.Events; +using osu.Framework.Input.Handlers; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Settings.Sections +{ + public partial class InputSubsection : SettingsSubsection + { + private readonly InputHandler handler; + + protected override LocalisableString Header => handler.Description; + + /// + /// Whether the input handler can be toggled on/off by the user. + /// + protected virtual bool IsToggleable => true; + + private readonly BindableBool handlerEnabled = new BindableBool(); + + public InputSubsection(InputHandler handler) + { + this.handler = handler; + + FlowContent.AlwaysPresent = true; + } + + [BackgroundDependencyLoader] + private void load() + { + HeaderContainer.Child = new ToggleableHeader(Header, IsToggleable) + { + Current = { BindTarget = handlerEnabled }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + handlerEnabled.BindTo(handler.Enabled); + handlerEnabled.BindValueChanged(v => updateEnabledState(), true); + } + + private void updateEnabledState() + { + // set negative bottom margin to not have too much vertical gap between disabled input subsections. + bool negativeBottomMargin = !handlerEnabled.Value || FlowContent.Count == 0; + HeaderContainer.TransformTo(nameof(Margin), new MarginPadding { Bottom = negativeBottomMargin ? -15 : 0 }, 300, Easing.OutQuint); + + FlowContent.ClearTransforms(); + + if (!handlerEnabled.Value) + { + FlowContent.AutoSizeAxes = Axes.None; + FlowContent.ResizeHeightTo(0, 300, Easing.OutQuint); + + FlowContent.FadeOut(200, Easing.OutQuint); + } + else + { + // enable auto size transform momentarily for smooth pop in animation, and disable it right after the transform is added. + // we don't want this specification to apply when a dropdown in the input settings is being open, it causes too slow animation. + // (try removing the schedule below then watch a settings dropdown menu opening animation). + FlowContent.AutoSizeDuration = 300; + FlowContent.AutoSizeEasing = Easing.OutQuint; + FlowContent.AutoSizeAxes = Axes.Y; + ScheduleAfterChildren(() => FlowContent.AutoSizeDuration = 0); + + FlowContent.FadeIn(300, Easing.OutQuint); + } + } + + private partial class ToggleableHeader : CompositeDrawable + { + private readonly LocalisableString header; + private readonly bool toggleable; + + public readonly BindableBool Current = new BindableBool(true); + + public ToggleableHeader(LocalisableString header, bool toggleable) + { + this.header = header; + this.toggleable = toggleable; + } + + private SwitchButton switchButton = null!; + private OsuSpriteText headerText = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Both; + + InternalChildren = new Drawable[] + { + switchButton = new SwitchButton + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + Scale = new Vector2(0.6f), + Position = new Vector2(12, 8), + Rotation = 90, + }, + headerText = new OsuSpriteText + { + Text = header, + Font = OsuFont.GetFont(size: 20), + Margin = new MarginPadding { Vertical = 12 }, + X = 20, + }, + new HoverSounds(), + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + switchButton.Current.ValueChanged += v => Current.Value = v.NewValue; + + Current.BindValueChanged(v => + { + switchButton.Current.Disabled = false; + switchButton.Current.Value = v.NewValue; + switchButton.Current.Disabled = !toggleable; + + updateDisplay(); + }, true); + } + + protected override bool OnHover(HoverEvent e) + { + updateDisplay(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateDisplay(); + base.OnHoverLost(e); + } + + protected override bool OnClick(ClickEvent e) + { + if (toggleable) + { + Current.Toggle(); + switchButton.PlaySample(Current.Value); + } + + updateDisplay(); + return true; + } + + private void updateDisplay() + { + // default, toggled on (or not toggleable) + Color4 col = colourProvider.Content1; + + if (toggleable && !Current.Value) + col = IsHovered ? colourProvider.Light1 : colourProvider.Foreground1; + + headerText.FadeColour(col, 300, Easing.OutQuint); + } + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs index 597e03fab2..a4d20fb459 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs @@ -14,16 +14,16 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { protected override LocalisableString Header => CommonStrings.Beatmaps; - private SettingsButton deleteBeatmapsButton = null!; - private SettingsButton deleteBeatmapVideosButton = null!; - private SettingsButton resetOffsetsButton = null!; - private SettingsButton restoreButton = null!; - private SettingsButton undeleteButton = null!; + private SettingsButtonV2 deleteBeatmapsButton = null!; + private SettingsButtonV2 deleteBeatmapVideosButton = null!; + private SettingsButtonV2 resetOffsetsButton = null!; + private SettingsButtonV2 restoreButton = null!; + private SettingsButtonV2 undeleteButton = null!; [BackgroundDependencyLoader] private void load(BeatmapManager beatmaps, IDialogOverlay? dialogOverlay) { - Add(deleteBeatmapsButton = new DangerousSettingsButton + Add(deleteBeatmapsButton = new DangerousSettingsButtonV2 { Text = MaintenanceSettingsStrings.DeleteAllBeatmaps, Action = () => @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance } }); - Add(deleteBeatmapVideosButton = new DangerousSettingsButton + Add(deleteBeatmapVideosButton = new DangerousSettingsButtonV2 { Text = MaintenanceSettingsStrings.DeleteAllBeatmapVideos, Action = () => @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance } }); - Add(resetOffsetsButton = new DangerousSettingsButton + Add(resetOffsetsButton = new DangerousSettingsButtonV2 { Text = MaintenanceSettingsStrings.ResetAllOffsets, Action = () => @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance AddRange(new Drawable[] { - restoreButton = new SettingsButton + restoreButton = new SettingsButtonV2 { Text = MaintenanceSettingsStrings.RestoreAllHiddenDifficulties, Action = () => @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Task.Run(beatmaps.RestoreAll).ContinueWith(_ => Schedule(() => restoreButton.Enabled.Value = true)); } }, - undeleteButton = new SettingsButton + undeleteButton = new SettingsButtonV2 { Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedBeatmaps, Action = () => diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs index b1c44aa93c..922969035d 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance [BackgroundDependencyLoader] private void load(IDialogOverlay? dialogOverlay) { - Add(new DangerousSettingsButton + Add(new DangerousSettingsButtonV2 { Text = MaintenanceSettingsStrings.DeleteAllCollections, Action = () => diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index 47314dcafe..2c79daffb6 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance AddRange(new Drawable[] { - new SettingsButton + new SettingsButtonV2 { Text = DebugSettingsStrings.ImportFiles, Action = () => @@ -40,7 +40,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance performer?.PerformFromScreen(menu => menu.Push(new FileImportScreen())); }, }, - new SettingsButton + new SettingsButtonV2 { Text = DebugSettingsStrings.RunLatencyCertifier, Action = () => performer?.PerformFromScreen(menu => menu.Push(new LatencyCertifierScreen())) diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs index 9c55308abe..17101c6526 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/ModPresetSettings.cs @@ -25,15 +25,15 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance [Resolved] private INotificationOverlay? notificationOverlay { get; set; } - private SettingsButton undeleteButton = null!; - private SettingsButton deleteAllButton = null!; + private SettingsButtonV2 undeleteButton = null!; + private SettingsButtonV2 deleteAllButton = null!; [BackgroundDependencyLoader] private void load(IDialogOverlay? dialogOverlay) { AddRange(new Drawable[] { - deleteAllButton = new DangerousSettingsButton + deleteAllButton = new DangerousSettingsButtonV2 { Text = MaintenanceSettingsStrings.DeleteAllModPresets, Action = () => @@ -45,7 +45,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance }, DeleteConfirmationContentStrings.ModPresets)); } }, - undeleteButton = new SettingsButton + undeleteButton = new SettingsButtonV2 { Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedModPresets, Action = () => Task.Run(undeleteModPresets).ContinueWith(t => Schedule(onModPresetsUndeleted, t)) diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs index 235f239c7c..b4a1d449ed 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs @@ -13,12 +13,12 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { protected override LocalisableString Header => CommonStrings.Scores; - private SettingsButton deleteScoresButton = null!; + private SettingsButtonV2 deleteScoresButton = null!; [BackgroundDependencyLoader] private void load(ScoreManager scores, IDialogOverlay? dialogOverlay) { - Add(deleteScoresButton = new DangerousSettingsButton + Add(deleteScoresButton = new DangerousSettingsButtonV2 { Text = MaintenanceSettingsStrings.DeleteAllScores, Action = () => diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs index e962118a36..85b4898e05 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs @@ -13,12 +13,12 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { protected override LocalisableString Header => CommonStrings.Skins; - private SettingsButton deleteSkinsButton = null!; + private SettingsButtonV2 deleteSkinsButton = null!; [BackgroundDependencyLoader] private void load(SkinManager skins, IDialogOverlay? dialogOverlay) { - Add(deleteSkinsButton = new DangerousSettingsButton + Add(deleteSkinsButton = new DangerousSettingsButtonV2 { Text = MaintenanceSettingsStrings.DeleteAllSkins, Action = () => diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index 608c6ef1b2..227d3feeaf 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online @@ -18,27 +19,27 @@ namespace osu.Game.Overlays.Settings.Sections.Online { Children = new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = OnlineSettingsStrings.NotifyOnMentioned, + Caption = OnlineSettingsStrings.NotifyOnMentioned, Current = config.GetBindable(OsuSetting.NotifyOnUsernameMentioned) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = OnlineSettingsStrings.NotifyOnPrivateMessage, + Caption = OnlineSettingsStrings.NotifyOnPrivateMessage, Current = config.GetBindable(OsuSetting.NotifyOnPrivateMessage) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = OnlineSettingsStrings.NotifyOnFriendPresenceChange, - TooltipText = OnlineSettingsStrings.NotifyOnFriendPresenceChangeTooltip, + Caption = OnlineSettingsStrings.NotifyOnFriendPresenceChange, + HintText = OnlineSettingsStrings.NotifyOnFriendPresenceChangeTooltip, Current = config.GetBindable(OsuSetting.NotifyOnFriendPresenceChange), - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = OnlineSettingsStrings.HideCountryFlags, + Caption = OnlineSettingsStrings.HideCountryFlags, Current = config.GetBindable(OsuSetting.HideCountryFlags) - }, + }), }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index 3d0fac32cf..3445c67b95 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online @@ -18,11 +19,11 @@ namespace osu.Game.Overlays.Settings.Sections.Online { Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = OnlineSettingsStrings.DiscordRichPresence, + Caption = OnlineSettingsStrings.DiscordRichPresence, Current = config.GetBindable(OsuSetting.DiscordRichPresence) - } + }), }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index ce5c85bed0..bcb1d91547 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.Online @@ -18,28 +19,34 @@ namespace osu.Game.Overlays.Settings.Sections.Online { Children = new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = OnlineSettingsStrings.ExternalLinkWarning, + Caption = OnlineSettingsStrings.ExternalLinkWarning, Current = config.GetBindable(OsuSetting.ExternalLinkWarning) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - LabelText = OnlineSettingsStrings.PreferNoVideo, - Keywords = new[] { "no-video" }, + Caption = OnlineSettingsStrings.PreferNoVideo, Current = config.GetBindable(OsuSetting.PreferNoVideo) - }, - new SettingsCheckbox + }) { - LabelText = OnlineSettingsStrings.AutomaticallyDownloadMissingBeatmaps, - Keywords = new[] { "spectator", "replay" }, + Keywords = new[] { "no-video" }, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = OnlineSettingsStrings.AutomaticallyDownloadMissingBeatmaps, Current = config.GetBindable(OsuSetting.AutomaticallyDownloadMissingBeatmaps), - }, - new SettingsCheckbox + }) { - LabelText = OnlineSettingsStrings.ShowExplicitContent, - Keywords = new[] { "nsfw", "18+", "offensive" }, + Keywords = new[] { "spectator", "replay" }, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = OnlineSettingsStrings.ShowExplicitContent, Current = config.GetBindable(OsuSetting.ShowOnlineExplicitContent), + }) + { + Keywords = new[] { "nsfw", "18+", "offensive" }, } }; } diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 4d7c0117e2..da0a21382b 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections { public partial class SkinSection : SettingsSection { - private SkinSettingsDropdown skinDropdown; + private SkinDropdown skinDropdown; public override LocalisableString Header => SkinSettingsStrings.SkinSectionHeader; @@ -65,29 +65,28 @@ namespace osu.Game.Overlays.Settings.Sections { Children = new Drawable[] { - skinDropdown = new SkinSettingsDropdown + new SettingsItemV2(skinDropdown = new SkinDropdown { AlwaysShowSearchBar = true, AllowNonContiguousMatching = true, - LabelText = SkinSettingsStrings.CurrentSkin, + Caption = SkinSettingsStrings.CurrentSkin, Current = skins.CurrentSkinInfo, - }, + }), new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS }, + Padding = SettingsPanel.CONTENT_PADDING, Children = new Drawable[] { // This is all super-temporary until we move skin settings to their own panel / overlay. - new RenameSkinButton { Padding = new MarginPadding(), RelativeSizeAxes = Axes.None, Width = 120 }, - new ExportSkinButton { Padding = new MarginPadding(), RelativeSizeAxes = Axes.None, Width = 120 }, - new DeleteSkinButton { Padding = new MarginPadding(), RelativeSizeAxes = Axes.None, Width = 110 }, + new RenameSkinButton { Padding = new MarginPadding { Right = 2.5f }, RelativeSizeAxes = Axes.X, Width = 1 / 3f }, + new ExportSkinButton { Padding = new MarginPadding { Horizontal = 2.5f }, RelativeSizeAxes = Axes.X, Width = 1 / 3f }, + new DeleteSkinButton { Padding = new MarginPadding { Left = 2.5f }, RelativeSizeAxes = Axes.X, Width = 1 / 3f }, } }, - new SettingsButton + new SettingsButtonV2 { Text = SkinSettingsStrings.SkinLayoutEditor, Action = () => skinEditor?.ToggleVisibility(), @@ -148,17 +147,12 @@ namespace osu.Game.Overlays.Settings.Sections realmSubscription?.Dispose(); } - private partial class SkinSettingsDropdown : SettingsDropdown> + private partial class SkinDropdown : FormDropdown> { - protected override OsuDropdown> CreateDropdown() => new SkinDropdownControl(); - - private partial class SkinDropdownControl : DropdownControl - { - protected override LocalisableString GenerateItemText(Live item) => item.ToString(); - } + protected override LocalisableString GenerateItemText(Live item) => item.ToString(); } - public partial class RenameSkinButton : SettingsButton, IHasPopover + public partial class RenameSkinButton : SettingsButtonV2, IHasPopover { [Resolved] private SkinManager skins { get; set; } @@ -189,7 +183,7 @@ namespace osu.Game.Overlays.Settings.Sections } } - public partial class ExportSkinButton : SettingsButton + public partial class ExportSkinButton : SettingsButtonV2 { [Resolved] private SkinManager skins { get; set; } @@ -227,7 +221,7 @@ namespace osu.Game.Overlays.Settings.Sections } } - public partial class DeleteSkinButton : DangerousSettingsButton + public partial class DeleteSkinButton : DangerousSettingsButtonV2 { [Resolved] private SkinManager skins { get; set; } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index 3f39980b43..9a894e89fe 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -3,9 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Configuration; -using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.UserInterface @@ -19,29 +20,33 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { Children = new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = UserInterfaceStrings.CursorRotation, + Caption = UserInterfaceStrings.CursorRotation, Current = config.GetBindable(OsuSetting.CursorRotation) - }, - new SettingsSlider> + }), + new SettingsItemV2(new FormSliderBar { - LabelText = UserInterfaceStrings.MenuCursorSize, + Caption = UserInterfaceStrings.MenuCursorSize, Current = config.GetBindable(OsuSetting.MenuCursorSize), - KeyboardStep = 0.01f - }, - new SettingsCheckbox + KeyboardStep = 0.01f, + LabelFormat = v => $"{v:0.##}x" + }), + new SettingsItemV2(new FormCheckBox { - LabelText = UserInterfaceStrings.Parallax, + Caption = UserInterfaceStrings.Parallax, Current = config.GetBindable(OsuSetting.MenuParallax) - }, - new SettingsSlider + }), + new SettingsItemV2(new FormSliderBar { - ClassicDefault = 0, - LabelText = UserInterfaceStrings.HoldToConfirmActivationTime, + Caption = UserInterfaceStrings.HoldToConfirmActivationTime, Current = config.GetBindable(OsuSetting.UIHoldActivationDelay), + KeyboardStep = 50, + LabelFormat = v => $"{v:N0} ms", + }) + { Keywords = new[] { @"delay" }, - KeyboardStep = 50 + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = 0, }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index c50d56b458..e38dcbc006 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; @@ -18,9 +17,9 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { protected override LocalisableString Header => UserInterfaceStrings.MainMenuHeader; - private IBindable user; + private IBindable user = null!; - private SettingsEnumDropdown backgroundSourceDropdown; + private readonly Bindable backgroundSourceNote = new Bindable(); [BackgroundDependencyLoader] private void load(OsuConfigManager config, IAPIProvider api) @@ -29,38 +28,45 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface Children = new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = UserInterfaceStrings.ShowMenuTips, + Caption = UserInterfaceStrings.ShowMenuTips, Current = config.GetBindable(OsuSetting.MenuTips) - }, - new SettingsCheckbox + }), + new SettingsItemV2(new FormCheckBox { - Keywords = new[] { "intro", "welcome" }, - LabelText = UserInterfaceStrings.InterfaceVoices, + Caption = UserInterfaceStrings.InterfaceVoices, Current = config.GetBindable(OsuSetting.MenuVoice) - }, - new SettingsCheckbox + }) { Keywords = new[] { "intro", "welcome" }, - LabelText = UserInterfaceStrings.OsuMusicTheme, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = UserInterfaceStrings.OsuMusicTheme, Current = config.GetBindable(OsuSetting.MenuMusic) - }, - new SettingsEnumDropdown + }) { - LabelText = UserInterfaceStrings.IntroSequence, + Keywords = new[] { "intro", "welcome" }, + }, + new SettingsItemV2(new FormEnumDropdown + { + Caption = UserInterfaceStrings.IntroSequence, Current = config.GetBindable(OsuSetting.IntroSequence), - }, - backgroundSourceDropdown = new SettingsEnumDropdown + }), + new SettingsItemV2(new FormEnumDropdown { - LabelText = UserInterfaceStrings.BackgroundSource, + Caption = UserInterfaceStrings.BackgroundSource, Current = config.GetBindable(OsuSetting.MenuBackgroundSource), - }, - new SettingsEnumDropdown + }) { - LabelText = UserInterfaceStrings.SeasonalBackgrounds, + Note = { BindTarget = backgroundSourceNote }, + }, + new SettingsItemV2(new FormEnumDropdown + { + Caption = UserInterfaceStrings.SeasonalBackgrounds, Current = config.GetBindable(OsuSetting.SeasonalBackgroundMode), - } + }) }; } @@ -71,9 +77,9 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface user.BindValueChanged(u => { if (u.NewValue?.IsSupporter != true) - backgroundSourceDropdown.SetNoticeText(UserInterfaceStrings.NotSupporterNote, true); + backgroundSourceNote.Value = new SettingsNote.Data(UserInterfaceStrings.NotSupporterNote, SettingsNote.Type.Informational); else - backgroundSourceDropdown.ClearNoticeText(); + backgroundSourceNote.Value = null; }, true); } } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index d15008f858..83ee3eb09a 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -3,8 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; using osu.Game.Overlays.Mods.Input; @@ -19,35 +21,40 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface { Children = new Drawable[] { - new SettingsCheckbox + new SettingsItemV2(new FormCheckBox { - LabelText = UserInterfaceStrings.ShowConvertedBeatmaps, + Caption = UserInterfaceStrings.ShowConvertedBeatmaps, Current = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), + }) + { Keywords = new[] { "converts", "converted" } }, - new SettingsEnumDropdown + new SettingsItemV2(new FormEnumDropdown { - LabelText = UserInterfaceStrings.RandomSelectionAlgorithm, + Caption = UserInterfaceStrings.RandomSelectionAlgorithm, Current = config.GetBindable(OsuSetting.RandomSelectAlgorithm), - }, - new SettingsEnumDropdown + }), + new SettingsItemV2(new FormEnumDropdown { - LabelText = UserInterfaceStrings.ModSelectHotkeyStyle, + Caption = UserInterfaceStrings.ModSelectHotkeyStyle, Current = config.GetBindable(OsuSetting.ModSelectHotkeyStyle), - ClassicDefault = ModSelectHotkeyStyle.Classic - }, - new SettingsCheckbox + }) { - LabelText = UserInterfaceStrings.ModSelectTextSearchStartsActive, + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = ModSelectHotkeyStyle.Classic, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = UserInterfaceStrings.ModSelectTextSearchStartsActive, Current = config.GetBindable(OsuSetting.ModSelectTextSearchStartsActive), - ClassicDefault = false - }, - new SettingsCheckbox + }) { - LabelText = GameplaySettingsStrings.BackgroundBlur, + ApplyClassicDefault = c => ((IHasCurrentValue)c).Current.Value = false, + }, + new SettingsItemV2(new FormCheckBox + { + Caption = GameplaySettingsStrings.BackgroundBlur, Current = config.GetBindable(OsuSetting.SongSelectBackgroundBlur), - ClassicDefault = false, - } + }), }; } } diff --git a/osu.Game/Overlays/Settings/SettingsButtonV2.cs b/osu.Game/Overlays/Settings/SettingsButtonV2.cs new file mode 100644 index 0000000000..4d5e1d5c59 --- /dev/null +++ b/osu.Game/Overlays/Settings/SettingsButtonV2.cs @@ -0,0 +1,43 @@ +// 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.Framework.Graphics.Containers; +using osu.Framework.Localisation; +using osu.Game.Graphics.UserInterfaceV2; + +namespace osu.Game.Overlays.Settings +{ + public partial class SettingsButtonV2 : RoundedButton, IConditionalFilterable + { + public SettingsButtonV2() + { + RelativeSizeAxes = Axes.X; + Margin = new MarginPadding { Vertical = -1.5f }; + Padding = SettingsPanel.CONTENT_PADDING; + } + + public IEnumerable Keywords { get; set; } = Array.Empty(); + + public BindableBool CanBeShown { get; } = new BindableBool(true); + IBindable IConditionalFilterable.CanBeShown => CanBeShown; + + public override IEnumerable FilterTerms + { + get + { + if (TooltipText != default) + yield return TooltipText; + + foreach (string s in Keywords) + yield return s; + + foreach (LocalisableString s in base.FilterTerms) + yield return s; + } + } + } +} diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 825d066b9d..a32dec4ca8 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding { Top = 20, Bottom = 30, Horizontal = SettingsPanel.CONTENT_MARGINS }; + Padding = new MarginPadding { Top = 20, Bottom = 30, Left = SettingsPanel.CONTENT_PADDING.Left, Right = SettingsPanel.CONTENT_PADDING.Right }; FillFlowContainer modes; diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index 8d155fd01e..4e32efc4f4 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -35,7 +35,8 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X, Padding = new MarginPadding { - Horizontal = SettingsPanel.CONTENT_MARGINS, + Left = SettingsPanel.CONTENT_PADDING.Left, + Right = SettingsPanel.CONTENT_PADDING.Right, Top = Toolbar.Toolbar.TOOLTIP_HEIGHT, Bottom = 30 } diff --git a/osu.Game/Overlays/Settings/SettingsItemV2.cs b/osu.Game/Overlays/Settings/SettingsItemV2.cs index 084aa1ad1f..e6eddb4559 100644 --- a/osu.Game/Overlays/Settings/SettingsItemV2.cs +++ b/osu.Game/Overlays/Settings/SettingsItemV2.cs @@ -14,7 +14,8 @@ namespace osu.Game.Overlays.Settings { public sealed partial class SettingsItemV2 : CompositeDrawable, ISettingsItem, IConditionalFilterable { - private readonly IFormControl control; + public readonly IFormControl Control; + private readonly SettingsRevertToDefaultButton revertButton; private readonly BindableBool controlDefault = new BindableBool(true); @@ -32,7 +33,7 @@ namespace osu.Game.Overlays.Settings public SettingsItemV2(IFormControl control) { - this.control = control; + Control = control; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -41,7 +42,7 @@ namespace osu.Game.Overlays.Settings { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS_RIGHT }, + Padding = SettingsPanel.CONTENT_PADDING, Direction = FillDirection.Vertical, Children = new Drawable[] { @@ -78,8 +79,8 @@ namespace osu.Game.Overlays.Settings { base.LoadComplete(); - controlDefault.Value = control.IsDefault; - controlEnabled.Value = !control.IsDisabled; + controlDefault.Value = Control.IsDefault; + controlEnabled.Value = !Control.IsDisabled; controlDefault.BindValueChanged(_ => updateDefaultState()); controlEnabled.BindValueChanged(_ => updateDefaultState(), true); @@ -99,8 +100,8 @@ namespace osu.Game.Overlays.Settings protected override void Update() { base.Update(); - controlDefault.Value = control.IsDefault; - controlEnabled.Value = !control.IsDisabled; + controlDefault.Value = Control.IsDefault; + controlEnabled.Value = !Control.IsDisabled; } #region ISettingsItem @@ -111,20 +112,20 @@ namespace osu.Game.Overlays.Settings /// If set, this setting is considered as having a "classic" default value, /// and this is the function for overwriting the control with that value. /// - public Action? ApplyClassicDefault { get; set; } + public Action? ApplyClassicDefault { get; set; } - void ISettingsItem.ApplyClassicDefault() => ApplyClassicDefault?.Invoke(); + void ISettingsItem.ApplyClassicDefault() => ApplyClassicDefault?.Invoke(Control); public void ApplyDefault() { - if (!control.IsDisabled) - control.SetDefault(); + if (!Control.IsDisabled) + Control.SetDefault(); } public event Action SettingChanged { - add => control.ValueChanged += value; - remove => control.ValueChanged -= value; + add => Control.ValueChanged += value; + remove => Control.ValueChanged -= value; } #endregion @@ -140,7 +141,7 @@ namespace osu.Game.Overlays.Settings get { var filterTerms = new List(Keywords.Select(k => (LocalisableString)k)); - filterTerms.AddRange(control.FilterTerms); + filterTerms.AddRange(Control.FilterTerms); if (HasClassicDefault) filterTerms.Add(CLASSIC_DEFAULT_SEARCH_TERM); diff --git a/osu.Game/Overlays/Settings/SettingsNote.cs b/osu.Game/Overlays/Settings/SettingsNote.cs index 3552e32d4e..dec2694b4f 100644 --- a/osu.Game/Overlays/Settings/SettingsNote.cs +++ b/osu.Game/Overlays/Settings/SettingsNote.cs @@ -26,6 +26,14 @@ namespace osu.Game.Overlays.Settings [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; + public new MarginPadding Padding + { + get => base.Padding; + set => base.Padding = value; + } + + public Anchor TextAnchor { get; init; } = Anchor.TopLeft; + [BackgroundDependencyLoader] private void load() { @@ -53,6 +61,7 @@ namespace osu.Game.Overlays.Settings }, text = new OsuTextFlowContainer(s => s.Font = OsuFont.Style.Caption1.With(weight: FontWeight.SemiBold)) { + TextAnchor = TextAnchor, Padding = new MarginPadding(8), RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 9602e4373f..c3e995b81a 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -35,6 +35,7 @@ namespace osu.Game.Overlays.Settings public virtual IEnumerable FilterTerms => new[] { Header }; public const int ITEM_SPACING = 14; + public const int ITEM_SPACING_V2 = 7; private const int header_size = 24; private const int border_size = 4; @@ -73,7 +74,7 @@ namespace osu.Game.Overlays.Settings { Top = 36 }, - Spacing = new Vector2(0, ITEM_SPACING), + Spacing = new Vector2(0, ITEM_SPACING_V2), Direction = FillDirection.Vertical, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, @@ -114,10 +115,7 @@ namespace osu.Game.Overlays.Settings { Font = OsuFont.TorusAlternate.With(size: header_size), Text = Header, - Margin = new MarginPadding - { - Horizontal = SettingsPanel.CONTENT_MARGINS - } + Margin = SettingsPanel.CONTENT_PADDING, }, FlowContent } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 87772eb18c..669425b667 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -18,6 +18,8 @@ namespace osu.Game.Overlays.Settings protected readonly FillFlowContainer FlowContent; + protected Container HeaderContainer { get; private set; } = null!; + protected abstract LocalisableString Header { get; } public virtual IEnumerable FilterTerms => new[] { Header }; @@ -37,9 +39,9 @@ namespace osu.Game.Overlays.Settings FlowContent = new FillFlowContainer { - Margin = new MarginPadding { Top = SettingsSection.ITEM_SPACING }, + Margin = new MarginPadding { Top = SettingsSection.ITEM_SPACING_V2 }, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, SettingsSection.ITEM_SPACING), + Spacing = new Vector2(0, SettingsSection.ITEM_SPACING_V2), RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }; @@ -53,11 +55,20 @@ namespace osu.Game.Overlays.Settings { AddRangeInternal(new Drawable[] { - new OsuSpriteText + HeaderContainer = new Container { - Text = Header, - Margin = new MarginPadding { Vertical = (header_height - header_font_size) * 0.5f, Horizontal = SettingsPanel.CONTENT_MARGINS }, - Font = OsuFont.GetFont(size: header_font_size), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = SettingsPanel.CONTENT_PADDING, + Children = new[] + { + new OsuSpriteText + { + Text = Header, + Font = OsuFont.GetFont(size: header_font_size), + Margin = new MarginPadding { Vertical = (header_height - header_font_size) * 0.5f }, + }, + }, }, FlowContent }); diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 8fd12e1e13..e35df36646 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -31,8 +31,8 @@ namespace osu.Game.Overlays { public const float CONTENT_MARGINS = 20; - // extra margin to give room to the revert-to-default button in settings controls. - public const float CONTENT_MARGINS_RIGHT = 30; + // extra right padding to give room to the revert-to-default button in settings controls. + public static readonly MarginPadding CONTENT_PADDING = new MarginPadding { Left = 20, Right = 30 }; public const float TRANSITION_LENGTH = 600; @@ -134,7 +134,8 @@ namespace osu.Game.Overlays Padding = new MarginPadding { Vertical = 20, - Horizontal = CONTENT_MARGINS + Left = CONTENT_PADDING.Left, + Right = CONTENT_PADDING.Right, }, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre,