diff --git a/osu.Game.Rulesets.Osu/Edit/FreehandSliderToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/FreehandSliderToolboxGroup.cs index f17118ba34..43bc4420f3 100644 --- a/osu.Game.Rulesets.Osu/Edit/FreehandSliderToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/FreehandSliderToolboxGroup.cs @@ -68,15 +68,18 @@ namespace osu.Game.Rulesets.Osu.Edit { toleranceSlider = new ExpandableSlider { - Current = displayTolerance + Current = displayTolerance, + ExpandedLabelText = "Control point spacing", }, cornerThresholdSlider = new ExpandableSlider { - Current = displayCornerThreshold + Current = displayCornerThreshold, + ExpandedLabelText = "Corner bias", }, circleThresholdSlider = new ExpandableSlider { - Current = displayCircleThreshold + Current = displayCircleThreshold, + ExpandedLabelText = "Perfect curve bias" } }; } @@ -88,24 +91,18 @@ namespace osu.Game.Rulesets.Osu.Edit displayTolerance.BindValueChanged(tolerance => { toleranceSlider.ContractedLabelText = $"C. P. S.: {tolerance.NewValue:N0}"; - toleranceSlider.ExpandedLabelText = $"Control Point Spacing: {tolerance.NewValue:N0}"; - Tolerance.Value = displayToInternalTolerance(tolerance.NewValue); }, true); displayCornerThreshold.BindValueChanged(threshold => { - cornerThresholdSlider.ContractedLabelText = $"C. T.: {threshold.NewValue:N0}"; - cornerThresholdSlider.ExpandedLabelText = $"Corner Threshold: {threshold.NewValue:N0}"; - + cornerThresholdSlider.ContractedLabelText = $"C. B.: {threshold.NewValue:N0}"; CornerThreshold.Value = displayToInternalCornerThreshold(threshold.NewValue); }, true); displayCircleThreshold.BindValueChanged(threshold => { - circleThresholdSlider.ContractedLabelText = $"P. C. T.: {threshold.NewValue:N0}"; - circleThresholdSlider.ExpandedLabelText = $"Perfect Curve Threshold: {threshold.NewValue:N0}"; - + circleThresholdSlider.ContractedLabelText = $"P. C. B.: {threshold.NewValue:N0}"; CircleThreshold.Value = displayToInternalCircleThreshold(threshold.NewValue); }, true); diff --git a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs index 991d42c7b4..5bd5b54f39 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuGridToolboxGroup.cs @@ -127,21 +127,25 @@ namespace osu.Game.Rulesets.Osu.Edit { Current = StartPositionX, KeyboardStep = 1, + ExpandedLabelText = "X offset", }, startPositionYSlider = new ExpandableSlider { Current = StartPositionY, KeyboardStep = 1, + ExpandedLabelText = "Y offset", }, spacingSlider = new ExpandableSlider { Current = Spacing, KeyboardStep = 1, + ExpandedLabelText = "Spacing", }, gridLinesRotationSlider = new ExpandableSlider { Current = GridLinesRotation, KeyboardStep = 1, + ExpandedLabelText = "Rotation", }, new FillFlowContainer { @@ -182,14 +186,12 @@ namespace osu.Game.Rulesets.Osu.Edit StartPositionX.BindValueChanged(x => { startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:#,0.##}"; - startPositionXSlider.ExpandedLabelText = $"X Offset: {x.NewValue:#,0.##}"; StartPosition.Value = new Vector2(x.NewValue, StartPosition.Value.Y); }, true); StartPositionY.BindValueChanged(y => { startPositionYSlider.ContractedLabelText = $"Y: {y.NewValue:#,0.##}"; - startPositionYSlider.ExpandedLabelText = $"Y Offset: {y.NewValue:#,0.##}"; StartPosition.Value = new Vector2(StartPosition.Value.X, y.NewValue); }, true); @@ -202,7 +204,6 @@ namespace osu.Game.Rulesets.Osu.Edit Spacing.BindValueChanged(spacing => { spacingSlider.ContractedLabelText = $"S: {spacing.NewValue:#,0.##}"; - spacingSlider.ExpandedLabelText = $"Spacing: {spacing.NewValue:#,0.##}"; SpacingVector.Value = new Vector2(spacing.NewValue); editorBeatmap.GridSize = (int)spacing.NewValue; }, true); @@ -210,7 +211,6 @@ namespace osu.Game.Rulesets.Osu.Edit GridLinesRotation.BindValueChanged(rotation => { gridLinesRotationSlider.ContractedLabelText = $"R: {rotation.NewValue:#,0.##}"; - gridLinesRotationSlider.ExpandedLabelText = $"Rotation: {rotation.NewValue:#,0.##}"; }, true); GridType.BindValueChanged(v => diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs index 3f4f86e424..44998e6fa2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; -using osu.Game.Overlays.Settings.Sections; using osuTK; namespace osu.Game.Tests.Visual.UserInterface @@ -19,7 +18,7 @@ namespace osu.Game.Tests.Visual.UserInterface private TestExpandingContainer container; private SettingsToolboxGroup toolboxGroup; - private ExpandableSlider> slider1; + private ExpandableSlider slider1; private ExpandableSlider slider2; [SetUp] @@ -36,7 +35,7 @@ namespace osu.Game.Tests.Visual.UserInterface Width = 1, Children = new Drawable[] { - slider1 = new ExpandableSlider> + slider1 = new ExpandableSlider { Current = new BindableFloat { @@ -62,13 +61,13 @@ namespace osu.Game.Tests.Visual.UserInterface slider1.Current.BindValueChanged(v => { - slider1.ExpandedLabelText = $"Slider One ({v.NewValue:0.##x})"; + slider1.ExpandedLabelText = "Slider One"; slider1.ContractedLabelText = $"S. 1. ({v.NewValue:0.##x})"; }, true); slider2.Current.BindValueChanged(v => { - slider2.ExpandedLabelText = $"Slider Two ({v.NewValue:N2})"; + slider2.ExpandedLabelText = "Slider Two"; slider2.ContractedLabelText = $"S. 2. ({v.NewValue:N2})"; }, true); }); diff --git a/osu.Game/Graphics/Containers/ExpandingContainer.cs b/osu.Game/Graphics/Containers/ExpandingContainer.cs index 65a00b725c..7cce49fb81 100644 --- a/osu.Game/Graphics/Containers/ExpandingContainer.cs +++ b/osu.Game/Graphics/Containers/ExpandingContainer.cs @@ -4,7 +4,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; +using osu.Framework.Input; using osu.Framework.Threading; namespace osu.Game.Graphics.Containers @@ -58,6 +58,8 @@ namespace osu.Game.Graphics.Containers protected virtual OsuScrollContainer CreateScrollContainer() => new OsuScrollContainer(); + private InputManager inputManager = null!; + private bool? lastMouseInBounds; private ScheduledDelegate? hoverExpandEvent; protected override void LoadComplete() @@ -68,37 +70,35 @@ namespace osu.Game.Graphics.Containers { this.ResizeWidthTo(v.NewValue ? expandedWidth : contractedWidth, TRANSITION_DURATION, Easing.OutQuint); }, true); + + inputManager = GetContainingInputManager()!; } - protected override bool OnHover(HoverEvent e) + protected override void Update() { - updateHoverExpansion(); - return true; + base.Update(); + + bool mouseInBounds = Contains(inputManager.CurrentState.Mouse.Position); + + if (lastMouseInBounds != mouseInBounds) + updateExpansionState(mouseInBounds); + + lastMouseInBounds = mouseInBounds; } - protected override void OnHoverLost(HoverLostEvent e) - { - if (hoverExpandEvent != null) - { - hoverExpandEvent?.Cancel(); - hoverExpandEvent = null; - - Expanded.Value = false; - return; - } - - base.OnHoverLost(e); - } - - private void updateHoverExpansion() + private void updateExpansionState(bool mouseInBounds) { if (!ExpandOnHover) return; hoverExpandEvent?.Cancel(); + hoverExpandEvent = null; - if (IsHovered && !Expanded.Value) + if (mouseInBounds && !Expanded.Value) hoverExpandEvent = Scheduler.AddDelayed(() => Expanded.Value = true, HoverExpansionDelay); + + if (!mouseInBounds && Expanded.Value) + Expanded.Value = false; } } } diff --git a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs index 4cc77e218f..addf4c9110 100644 --- a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs +++ b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterfaceV2; using Vector2 = osuTK.Vector2; namespace osu.Game.Graphics.UserInterface @@ -19,49 +20,27 @@ namespace osu.Game.Graphics.UserInterface /// public partial class ExpandableSlider : CompositeDrawable, IExpandable, IHasCurrentValue where T : struct, INumber, IMinMaxValue - where TSlider : RoundedSliderBar, new() + where TSlider : FormSliderBar, new() { - private readonly OsuSpriteText label; + private readonly OsuSpriteText contractedLabel; private readonly TSlider slider; - private LocalisableString contractedLabelText; - /// /// The label text to display when this slider is in a contracted state. /// public LocalisableString ContractedLabelText { - get => contractedLabelText; - set - { - if (value == contractedLabelText) - return; - - contractedLabelText = value; - - if (!Expanded.Value) - label.Text = value; - } + get => contractedLabel.Text; + set => contractedLabel.Text = value; } - private LocalisableString expandedLabelText; - /// /// The label text to display when this slider is in an expanded state. /// public LocalisableString ExpandedLabelText { - get => expandedLabelText; - set - { - if (value == expandedLabelText) - return; - - expandedLabelText = value; - - if (Expanded.Value) - label.Text = value; - } + get => slider.Caption; + set => slider.Caption = value; } public Bindable Current @@ -95,7 +74,7 @@ namespace osu.Game.Graphics.UserInterface Spacing = new Vector2(0f, 10f), Children = new Drawable[] { - label = new OsuSpriteText(), + contractedLabel = new OsuSpriteText(), slider = new TSlider { RelativeSizeAxes = Axes.X, @@ -118,7 +97,8 @@ namespace osu.Game.Graphics.UserInterface Expanded.BindValueChanged(v => { - label.Text = v.NewValue ? expandedLabelText : contractedLabelText; + contractedLabel.FadeTo(v.NewValue ? 0 : 1); + slider.FadeTo(v.NewValue ? Current.Disabled ? 0.3f : 1f : 0f, 500, Easing.OutQuint); slider.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None; }, true); @@ -133,7 +113,7 @@ namespace osu.Game.Graphics.UserInterface /// /// An implementation for the UI slider bar control. /// - public partial class ExpandableSlider : ExpandableSlider> + public partial class ExpandableSlider : ExpandableSlider> where T : struct, INumber, IMinMaxValue { } diff --git a/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs b/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs index 1304c298fb..59217f64ab 100644 --- a/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs +++ b/osu.Game/Graphics/UserInterfaceV2/FormSliderBar.cs @@ -58,26 +58,49 @@ namespace osu.Game.Graphics.UserInterfaceV2 } } + private LocalisableString caption; + /// /// Caption describing this slider bar, displayed on top of the controls. /// - public LocalisableString Caption { get; init; } + public LocalisableString Caption + { + get => caption; + set + { + caption = value; + + if (IsLoaded) + captionText.Caption = value; + } + } /// /// Hint text containing an extended description of this slider bar, displayed in a tooltip when hovering the caption. /// public LocalisableString HintText { get; init; } + private float keyboardStep; + /// /// A custom step value for each key press which actuates a change on this control. /// - public float KeyboardStep { get; init; } + public float KeyboardStep + { + get => keyboardStep; + set + { + keyboardStep = value; + if (IsLoaded) + slider.KeyboardStep = value; + } + } private Box background = null!; private Box flashLayer = null!; private FormTextBox.InnerTextBox textBox = null!; private InnerSlider slider = null!; - private FormFieldCaption caption = null!; + private FormFieldCaption captionText = null!; private IFocusManager focusManager = null!; [Resolved] @@ -117,11 +140,10 @@ namespace osu.Game.Graphics.UserInterfaceV2 }, Children = new Drawable[] { - caption = new FormFieldCaption + captionText = new FormFieldCaption { Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft, - Caption = Caption, TooltipText = HintText, }, textBox = new FormNumberBox.InnerNumberBox(allowDecimals: true) @@ -145,7 +167,6 @@ namespace osu.Game.Graphics.UserInterfaceV2 Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.X, Width = 0.5f, - KeyboardStep = KeyboardStep, Current = currentNumberInstantaneous, OnCommit = () => current.Value = currentNumberInstantaneous.Value, } @@ -161,6 +182,9 @@ namespace osu.Game.Graphics.UserInterfaceV2 { base.LoadComplete(); + slider.KeyboardStep = keyboardStep; + captionText.Caption = caption; + focusManager = GetContainingFocusManager()!; textBox.Focused.BindValueChanged(_ => updateState()); @@ -270,7 +294,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 textBox.Alpha = 1; background.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Background4 : colourProvider.Background5; - caption.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Foreground1 : colourProvider.Content2; + captionText.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Foreground1 : colourProvider.Content2; textBox.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Foreground1 : colourProvider.Content1; BorderThickness = childHasFocus || IsHovered || slider.IsDragging.Value ? 2 : 0; diff --git a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs index 2d6e09b3fd..d2f402a6fa 100644 --- a/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/ComposerDistanceSnapProvider.cs @@ -20,7 +20,6 @@ using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osu.Game.Overlays.OSD; -using osu.Game.Overlays.Settings.Sections; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; @@ -42,7 +41,7 @@ namespace osu.Game.Rulesets.Edit Bindable IDistanceSnapProvider.DistanceSpacingMultiplier => DistanceSpacingMultiplier; - private ExpandableSlider> distanceSpacingSlider = null!; + private ExpandableSlider distanceSpacingSlider = null!; private ExpandableButton currentDistanceSpacingButton = null!; [Resolved] @@ -78,11 +77,12 @@ namespace osu.Game.Rulesets.Edit Alpha = DistanceSpacingMultiplier.Disabled ? 0 : 1, Children = new Drawable[] { - distanceSpacingSlider = new ExpandableSlider> + distanceSpacingSlider = new ExpandableSlider { KeyboardStep = adjust_step, // Manual binding in LoadComplete to handle one-way event flow. Current = DistanceSpacingMultiplier.GetUnboundCopy(), + ExpandedLabelText = "Distance spacing", }, currentDistanceSpacingButton = new ExpandableButton { @@ -104,7 +104,6 @@ namespace osu.Game.Rulesets.Edit DistanceSpacingMultiplier.BindValueChanged(multiplier => { distanceSpacingSlider.ContractedLabelText = $"D. S. ({multiplier.NewValue:0.##x})"; - distanceSpacingSlider.ExpandedLabelText = $"Distance Spacing ({multiplier.NewValue:0.##x})"; if (multiplier.NewValue != multiplier.OldValue) onScreenDisplay?.Display(new DistanceSpacingToast(multiplier.NewValue.ToLocalisableString(@"0.##x"), multiplier));