diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs index b333e16dbb..b536ecf10a 100644 --- a/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs +++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs @@ -104,6 +104,21 @@ public TestSceneSliderBar() KeyboardStep = 1, Current = sliderBarValue }, + new SpriteText + { + Text = "w/ WithDisplayRange:", + }, + new BasicSliderBar + { + Size = new Vector2(200, 10), + BackgroundColour = Color4.White, + SelectionColour = Color4.Pink, + FocusColour = Color4.OrangeRed, + KeyboardStep = 1, + Current = sliderBarValue, + MaxDisplayRange = 20, + MinDisplayRange = 0 + } } }); } diff --git a/osu.Framework/Graphics/UserInterface/BasicSliderBar.cs b/osu.Framework/Graphics/UserInterface/BasicSliderBar.cs index 9b6697d13d..81a772d926 100644 --- a/osu.Framework/Graphics/UserInterface/BasicSliderBar.cs +++ b/osu.Framework/Graphics/UserInterface/BasicSliderBar.cs @@ -83,9 +83,9 @@ private void updateFocus() } } - protected override void UpdateValue(float value) + protected override void UpdateValue(float position) { - SelectionBox.ScaleTo(new Vector2(value, 1), 300, Easing.OutQuint); + SelectionBox.ScaleTo(new Vector2(position, 1), 300, Easing.OutQuint); } } } diff --git a/osu.Framework/Graphics/UserInterface/SliderBar.cs b/osu.Framework/Graphics/UserInterface/SliderBar.cs index 89f4306e33..debe595570 100644 --- a/osu.Framework/Graphics/UserInterface/SliderBar.cs +++ b/osu.Framework/Graphics/UserInterface/SliderBar.cs @@ -22,6 +22,44 @@ public abstract partial class SliderBar : Container, IHasCurrentValue /// public float RangePadding; + private T maxDisplayRange = T.MaxValue; + + private T minDisplayRange = T.MinValue; + + /// + /// The maximum value to display on the slider bar. + /// By default, the slider bar will display values between and of . + /// To display a different range, you can set and . + /// + public T MaxDisplayRange + { + get + { + if (maxDisplayRange == T.MaxValue) + return currentNumberInstantaneous.MaxValue; + + return maxDisplayRange; + } + set => maxDisplayRange = value; + } + + /// + /// The minimum value to display on the slider bar. + /// By default, the slider bar will display values between and of . + /// To display a different range, you can set and . + /// + public T MinDisplayRange + { + get + { + if (minDisplayRange == T.MinValue) + return currentNumberInstantaneous.MinValue; + + return minDisplayRange; + } + set => minDisplayRange = value; + } + public float UsableWidth => DrawWidth - 2 * RangePadding; /// @@ -95,11 +133,31 @@ protected float NormalizedValue } } + /// + /// The normalized value representing the position between and . + /// + protected float NormalizedPosition + { + get + { + float min = float.CreateTruncating(MinDisplayRange); + float max = float.CreateTruncating(MaxDisplayRange); + + if (max - min == 0) + return 1; + + float val = float.CreateTruncating(currentNumberInstantaneous.Value); + return (val - min) / (max - min); + } + } + /// /// Triggered when the value has changed. Used to update the displayed value. /// - /// The normalized value. - protected abstract void UpdateValue(float value); + /// + /// The normalized value representing the position between and . + /// + protected abstract void UpdateValue(float position); protected override void LoadComplete() { @@ -112,10 +170,10 @@ protected override void LoadComplete() Scheduler.AddOnce(updateValue); } - private void updateValue() => UpdateValue(NormalizedValue); + private void updateValue() => UpdateValue(NormalizedPosition); private bool handleClick; - private float? relativeValueAtMouseDown; + private float? normalizedPositionAtMouseDown; protected override bool OnMouseDown(MouseDownEvent e) { @@ -125,11 +183,14 @@ protected override bool OnMouseDown(MouseDownEvent e) if (ShouldHandleAsRelativeDrag(e)) { - float min = float.CreateTruncating(currentNumberInstantaneous.MinValue); - float max = float.CreateTruncating(currentNumberInstantaneous.MaxValue); + float min = float.CreateTruncating(MinDisplayRange); + float max = float.CreateTruncating(MaxDisplayRange); float val = float.CreateTruncating(currentNumberInstantaneous.Value); - relativeValueAtMouseDown = (val - min) / (max - min); + if (max - min == 0) + normalizedPositionAtMouseDown = 1; + + normalizedPositionAtMouseDown = (val - min) / (max - min); // Click shouldn't be handled if relative dragging is happening (i.e. while holding a nub). // This is generally an expectation by most OSes and UIs. @@ -138,7 +199,7 @@ protected override bool OnMouseDown(MouseDownEvent e) else { handleClick = true; - relativeValueAtMouseDown = null; + normalizedPositionAtMouseDown = null; } return base.OnMouseDown(e); @@ -246,18 +307,24 @@ private void handleMouseInput(MouseButtonEvent e) float localX = ToLocalSpace(e.ScreenSpaceMousePosition).X; - float newValue; + float normalizedPosition; - if (relativeValueAtMouseDown != null && e is DragEvent drag) + if (normalizedPositionAtMouseDown != null && e is DragEvent drag) { - newValue = relativeValueAtMouseDown.Value + (localX - ToLocalSpace(drag.ScreenSpaceMouseDownPosition).X) / UsableWidth; + normalizedPosition = normalizedPositionAtMouseDown.Value + (localX - ToLocalSpace(drag.ScreenSpaceMouseDownPosition).X) / UsableWidth; } else { - newValue = (localX - RangePadding) / UsableWidth; + normalizedPosition = (localX - RangePadding) / UsableWidth; } - currentNumberInstantaneous.SetProportional(newValue, e.ShiftPressed ? KeyboardStep : 0); + double min = double.CreateTruncating(MinDisplayRange); + double max = double.CreateTruncating(MaxDisplayRange); + double value = min + (max - min) * normalizedPosition; + if (e.ShiftPressed) // if shift is pressed, snap the final value to the closest multiple of KeyboardStep + value = Math.Round(value / KeyboardStep) * KeyboardStep; + + currentNumberInstantaneous.Set(value); onUserChange(currentNumberInstantaneous.Value); } diff --git a/osu.Framework/Testing/Drawables/Steps/StepSlider.cs b/osu.Framework/Testing/Drawables/Steps/StepSlider.cs index c8931db818..9bf6dac447 100644 --- a/osu.Framework/Testing/Drawables/Steps/StepSlider.cs +++ b/osu.Framework/Testing/Drawables/Steps/StepSlider.cs @@ -88,13 +88,13 @@ protected override void OnDragEnd(DragEndEvent e) base.OnDragEnd(e); } - protected override void UpdateValue(float normalizedValue) + protected override void UpdateValue(float position) { var value = Current.Value; ValueChanged?.Invoke(value); spriteText.Text = $"{text}: {Convert.ToDouble(value):#,0.##}"; - selection.ResizeWidthTo(normalizedValue); + selection.ResizeWidthTo(position); } protected void Flash()