diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 145f58fb55..5ee52f32f5 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -109,15 +109,6 @@ namespace osu.Game.Overlays.Mods protected virtual IEnumerable CreateFooterButtons() { - if (AllowCustomisation) - { - yield return CustomisationButton = new ShearedToggleButton(BUTTON_WIDTH) - { - Text = ModSelectOverlayStrings.ModCustomisation, - Active = { BindTarget = customisationVisible } - }; - } - yield return deselectAllModsButton = new DeselectAllModsButton(this); } @@ -125,10 +116,8 @@ namespace osu.Game.Overlays.Mods public IEnumerable AllAvailableMods => AvailableMods.Value.SelectMany(pair => pair.Value); - private readonly BindableBool customisationVisible = new BindableBool(); private Bindable textSearchStartsActive = null!; - private ModSettingsArea modSettingsArea = null!; private ColumnScrollContainer columnScroll = null!; private ColumnFlowContainer columnFlow = null!; private FillFlowContainer footerButtonFlow = null!; @@ -138,9 +127,9 @@ namespace osu.Game.Overlays.Mods private Container aboveColumnsContent = null!; private RankingInformationDisplay? rankingInformationDisplay; private BeatmapAttributesDisplay? beatmapAttributesDisplay; + private ModCustomisationPanel customisationPanel = null!; protected ShearedButton BackButton { get; private set; } = null!; - protected ShearedToggleButton? CustomisationButton { get; private set; } protected SelectAllModsButton? SelectAllModsButton { get; set; } private Sample? columnAppearSample; @@ -173,35 +162,8 @@ namespace osu.Game.Overlays.Mods columnAppearSample = audio.Samples.Get(@"SongSelect/mod-column-pop-in"); - AddRange(new Drawable[] - { - new ClickToReturnContainer - { - RelativeSizeAxes = Axes.Both, - HandleMouse = { BindTarget = customisationVisible }, - OnClicked = () => customisationVisible.Value = false - }, - modSettingsArea = new ModSettingsArea - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Height = 0 - }, - }); - MainAreaContent.AddRange(new Drawable[] { - aboveColumnsContent = new Container - { - RelativeSizeAxes = Axes.X, - Height = RankingInformationDisplay.HEIGHT, - Padding = new MarginPadding { Horizontal = 100 }, - Child = SearchTextBox = new ShearedSearchTextBox - { - HoldFocus = false, - Width = 300 - } - }, new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, @@ -237,7 +199,27 @@ namespace osu.Game.Overlays.Mods } } } - } + }, + aboveColumnsContent = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = 100, Bottom = 15f }, + Children = new Drawable[] + { + SearchTextBox = new ShearedSearchTextBox + { + HoldFocus = false, + Width = 300, + }, + customisationPanel = new ModCustomisationPanel + { + Alpha = 0f, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Width = 400, + } + } + }, }); FooterContent.Add(footerButtonFlow = new FillFlowContainer @@ -320,7 +302,7 @@ namespace osu.Game.Overlays.Mods // This is an optimisation to prevent refreshing the available settings controls when it can be // reasonably assumed that the settings panel is never to be displayed (e.g. FreeModSelectOverlay). if (AllowCustomisation) - ((IBindable>)modSettingsArea.SelectedMods).BindTo(SelectedMods); + ((IBindable>)customisationPanel.SelectedMods).BindTo(SelectedMods); SelectedMods.BindValueChanged(_ => { @@ -347,7 +329,7 @@ namespace osu.Game.Overlays.Mods } }, true); - customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); + customisationPanel.Expanded.BindValueChanged(_ => updateCustomisationVisualState(), true); SearchTextBox.Current.BindValueChanged(query => { @@ -491,7 +473,7 @@ namespace osu.Game.Overlays.Mods private void updateCustomisation() { - if (CustomisationButton == null) + if (!AllowCustomisation) return; bool anyCustomisableModActive = false; @@ -506,38 +488,21 @@ namespace osu.Game.Overlays.Mods if (anyCustomisableModActive) { - customisationVisible.Disabled = false; + customisationPanel.Show(); - if (anyModPendingConfiguration && !customisationVisible.Value) - customisationVisible.Value = true; + if (anyModPendingConfiguration) + customisationPanel.Expanded.Value = true; } else { - if (customisationVisible.Value) - customisationVisible.Value = false; - - customisationVisible.Disabled = true; + customisationPanel.Expanded.Value = false; + customisationPanel.Hide(); } } private void updateCustomisationVisualState() { - const double transition_duration = 300; - - MainAreaContent.FadeColour(customisationVisible.Value ? Colour4.Gray : Colour4.White, transition_duration, Easing.InOutCubic); - - foreach (var button in footerButtonFlow) - { - if (button != CustomisationButton) - button.Enabled.Value = !customisationVisible.Value; - } - - float modAreaHeight = customisationVisible.Value ? ModSettingsArea.HEIGHT : 0; - - modSettingsArea.ResizeHeightTo(modAreaHeight, transition_duration, Easing.InOutCubic); - TopLevelContent.MoveToY(-modAreaHeight, transition_duration, Easing.InOutCubic); - - if (customisationVisible.Value) + if (customisationPanel.Expanded.Value) SearchTextBox.KillFocus(); else setTextBoxFocus(textSearchStartsActive.Value); @@ -693,6 +658,8 @@ namespace osu.Game.Overlays.Mods if (!allFiltered) nonFilteredColumnCount += 1; } + + customisationPanel.Expanded.Value = false; } #endregion @@ -758,10 +725,9 @@ namespace osu.Game.Overlays.Mods void hideOverlay(bool immediate) { - if (customisationVisible.Value) + if (customisationPanel.Expanded.Value) { - Debug.Assert(CustomisationButton != null); - CustomisationButton.TriggerClick(); + customisationPanel.Expanded.Value = false; if (!immediate) return; @@ -967,38 +933,5 @@ namespace osu.Game.Overlays.Mods updateState(); } } - - /// - /// A container which blocks and handles input, managing the "return from customisation" state change. - /// - private partial class ClickToReturnContainer : Container - { - public BindableBool HandleMouse { get; } = new BindableBool(); - - public Action? OnClicked { get; set; } - - public override bool HandlePositionalInput => base.HandlePositionalInput && HandleMouse.Value; - - protected override bool Handle(UIEvent e) - { - if (!HandleMouse.Value) - return base.Handle(e); - - switch (e) - { - case ClickEvent: - OnClicked?.Invoke(); - return true; - - case HoverEvent: - return false; - - case MouseEvent: - return true; - } - - return base.Handle(e); - } - } } } diff --git a/osu.Game/Overlays/Mods/ModSettingsArea.cs b/osu.Game/Overlays/Mods/ModSettingsArea.cs deleted file mode 100644 index d0e0f7e648..0000000000 --- a/osu.Game/Overlays/Mods/ModSettingsArea.cs +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Events; -using osu.Game.Configuration; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; -using osuTK; - -namespace osu.Game.Overlays.Mods -{ - public partial class ModSettingsArea : CompositeDrawable - { - public Bindable> SelectedMods { get; } = new Bindable>(Array.Empty()); - - public const float HEIGHT = 250; - - private readonly Box background; - private readonly FillFlowContainer modSettingsFlow; - - [Resolved] - private OverlayColourProvider colourProvider { get; set; } = null!; - - public override bool AcceptsFocus => true; - - public ModSettingsArea() - { - RelativeSizeAxes = Axes.X; - Height = HEIGHT; - - Anchor = Anchor.BottomRight; - Origin = Anchor.BottomRight; - - InternalChild = new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - background = new Box - { - RelativeSizeAxes = Axes.Both - }, - new OsuScrollContainer(Direction.Horizontal) - { - RelativeSizeAxes = Axes.Both, - ScrollbarOverlapsContent = false, - ClampExtension = 100, - Child = modSettingsFlow = new FillFlowContainer - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Vertical = 7, Horizontal = 70 }, - Spacing = new Vector2(7), - Direction = FillDirection.Horizontal - } - } - } - }; - } - - [BackgroundDependencyLoader] - private void load() - { - background.Colour = colourProvider.Dark3; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - SelectedMods.BindValueChanged(_ => updateMods(), true); - } - - private void updateMods() - { - modSettingsFlow.Clear(); - - // Importantly, the selected mods bindable is already ordered by the mod select overlay (following the order of mod columns and panels). - // Using AsOrdered produces a slightly different order (e.g. DT and NC no longer becoming adjacent), - // which breaks user expectations when interacting with the overlay. - foreach (var mod in SelectedMods.Value) - { - var settings = mod.CreateSettingsControls().ToList(); - - if (settings.Count > 0) - { - if (modSettingsFlow.Any()) - { - modSettingsFlow.Add(new Box - { - RelativeSizeAxes = Axes.Y, - Width = 2, - Colour = colourProvider.Dark4, - }); - } - - modSettingsFlow.Add(new ModSettingsColumn(mod, settings)); - } - } - } - - protected override bool OnMouseDown(MouseDownEvent e) => true; - protected override bool OnHover(HoverEvent e) => true; - - public partial class ModSettingsColumn : CompositeDrawable - { - public readonly Mod Mod; - - public ModSettingsColumn(Mod mod, IEnumerable settingsControls) - { - Mod = mod; - - Width = 250; - RelativeSizeAxes = Axes.Y; - Padding = new MarginPadding { Bottom = 7 }; - - InternalChild = new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, 10), - new Dimension() - }, - Content = new[] - { - new Drawable[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7), - Children = new Drawable[] - { - new ModSwitchTiny(mod) - { - Active = { Value = true }, - Scale = new Vector2(0.6f), - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft - }, - new OsuSpriteText - { - Text = mod.Name, - Font = OsuFont.Default.With(size: 16, weight: FontWeight.SemiBold), - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - Margin = new MarginPadding { Bottom = 2 } - } - } - } - }, - new[] { Empty() }, - new Drawable[] - { - new OsuScrollContainer(Direction.Vertical) - { - RelativeSizeAxes = Axes.Both, - ClampExtension = 100, - Child = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = 7 }, - ChildrenEnumerable = settingsControls, - Spacing = new Vector2(0, 7) - } - } - } - } - }; - } - } - } -}