From 1de28ed77bbd27400a916f548800d66a388e98ab Mon Sep 17 00:00:00 2001 From: eyhn Date: Wed, 30 Jul 2025 12:43:56 +0800 Subject: [PATCH 1/4] Add display range to SliderBar --- .../UserInterface/TestSceneSliderBar.cs | 15 +++ .../Graphics/UserInterface/SliderBar.cs | 91 ++++++++++++++++--- 2 files changed, 94 insertions(+), 12 deletions(-) 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/SliderBar.cs b/osu.Framework/Graphics/UserInterface/SliderBar.cs index 89f4306e33..0043d91631 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,10 +133,30 @@ 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. + /// + /// The normalized value representing the position between and . + /// protected abstract void UpdateValue(float value); 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); } From 8b1180e39979d302179de7bf2e018bb893729149 Mon Sep 17 00:00:00 2001 From: eyhn Date: Wed, 30 Jul 2025 14:13:33 +0800 Subject: [PATCH 2/4] Fix compile error --- osu.Framework/Graphics/UserInterface/SliderBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Framework/Graphics/UserInterface/SliderBar.cs b/osu.Framework/Graphics/UserInterface/SliderBar.cs index 0043d91631..1f05e8f843 100644 --- a/osu.Framework/Graphics/UserInterface/SliderBar.cs +++ b/osu.Framework/Graphics/UserInterface/SliderBar.cs @@ -28,7 +28,7 @@ public abstract partial class SliderBar : Container, IHasCurrentValue /// /// The maximum value to display on the slider bar. - /// By default, the slider bar will display values between and of . + /// By default, the slider bar will display values between and of . /// To display a different range, you can set and . /// public T MaxDisplayRange From e4d25ce721368cd23dab938f8b751afe8bdab03a Mon Sep 17 00:00:00 2001 From: eyhn Date: Wed, 30 Jul 2025 14:22:35 +0800 Subject: [PATCH 3/4] Fix remaining compile errors --- osu.Framework/Graphics/UserInterface/SliderBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Framework/Graphics/UserInterface/SliderBar.cs b/osu.Framework/Graphics/UserInterface/SliderBar.cs index 1f05e8f843..5e91e876ac 100644 --- a/osu.Framework/Graphics/UserInterface/SliderBar.cs +++ b/osu.Framework/Graphics/UserInterface/SliderBar.cs @@ -45,7 +45,7 @@ public T MaxDisplayRange /// /// The minimum value to display on the slider bar. - /// By default, the slider bar will display values between and of . + /// By default, the slider bar will display values between and of . /// To display a different range, you can set and . /// public T MinDisplayRange From d34f3a9c881966d8fc822786f774195803fed301 Mon Sep 17 00:00:00 2001 From: eyhn Date: Wed, 30 Jul 2025 16:50:00 +0800 Subject: [PATCH 4/4] Adjust parameter naming --- osu.Framework/Graphics/UserInterface/BasicSliderBar.cs | 4 ++-- osu.Framework/Graphics/UserInterface/SliderBar.cs | 4 ++-- osu.Framework/Testing/Drawables/Steps/StepSlider.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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 5e91e876ac..debe595570 100644 --- a/osu.Framework/Graphics/UserInterface/SliderBar.cs +++ b/osu.Framework/Graphics/UserInterface/SliderBar.cs @@ -154,10 +154,10 @@ protected float NormalizedPosition /// /// Triggered when the value has changed. Used to update the displayed value. /// - /// + /// /// The normalized value representing the position between and . /// - protected abstract void UpdateValue(float value); + protected abstract void UpdateValue(float position); protected override void LoadComplete() { 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()