mirror of
https://github.com/ppy/osu.git
synced 2026-05-21 05:09:57 +08:00
Use new sliders-with-text-input in editor toolboxes
Addresses https://github.com/ppy/osu/discussions/35732. And yes, I renamed "perfect curve threshold" to "bias" so that the text can fit. Sue me.
This commit is contained in:
@@ -68,15 +68,18 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
toleranceSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayTolerance
|
||||
Current = displayTolerance,
|
||||
ExpandedLabelText = "Control point spacing",
|
||||
},
|
||||
cornerThresholdSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayCornerThreshold
|
||||
Current = displayCornerThreshold,
|
||||
ExpandedLabelText = "Corner bias",
|
||||
},
|
||||
circleThresholdSlider = new ExpandableSlider<int>
|
||||
{
|
||||
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);
|
||||
|
||||
|
||||
@@ -127,21 +127,25 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
Current = StartPositionX,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "X offset",
|
||||
},
|
||||
startPositionYSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = StartPositionY,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Y offset",
|
||||
},
|
||||
spacingSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = Spacing,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Spacing",
|
||||
},
|
||||
gridLinesRotationSlider = new ExpandableSlider<float>
|
||||
{
|
||||
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 =>
|
||||
|
||||
@@ -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<float, SizeSlider<float>> slider1;
|
||||
private ExpandableSlider<float> slider1;
|
||||
private ExpandableSlider<double> slider2;
|
||||
|
||||
[SetUp]
|
||||
@@ -36,7 +35,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
Width = 1,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
slider1 = new ExpandableSlider<float, SizeSlider<float>>
|
||||
slider1 = new ExpandableSlider<float>
|
||||
{
|
||||
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);
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
/// </summary>
|
||||
public partial class ExpandableSlider<T, TSlider> : CompositeDrawable, IExpandable, IHasCurrentValue<T>
|
||||
where T : struct, INumber<T>, IMinMaxValue<T>
|
||||
where TSlider : RoundedSliderBar<T>, new()
|
||||
where TSlider : FormSliderBar<T>, new()
|
||||
{
|
||||
private readonly OsuSpriteText label;
|
||||
private readonly OsuSpriteText contractedLabel;
|
||||
private readonly TSlider slider;
|
||||
|
||||
private LocalisableString contractedLabelText;
|
||||
|
||||
/// <summary>
|
||||
/// The label text to display when this slider is in a contracted state.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// The label text to display when this slider is in an expanded state.
|
||||
/// </summary>
|
||||
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<T> 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
|
||||
/// <summary>
|
||||
/// An <see cref="IExpandable"/> implementation for the UI slider bar control.
|
||||
/// </summary>
|
||||
public partial class ExpandableSlider<T> : ExpandableSlider<T, RoundedSliderBar<T>>
|
||||
public partial class ExpandableSlider<T> : ExpandableSlider<T, FormSliderBar<T>>
|
||||
where T : struct, INumber<T>, IMinMaxValue<T>
|
||||
{
|
||||
}
|
||||
|
||||
@@ -58,26 +58,49 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
}
|
||||
}
|
||||
|
||||
private LocalisableString caption;
|
||||
|
||||
/// <summary>
|
||||
/// Caption describing this slider bar, displayed on top of the controls.
|
||||
/// </summary>
|
||||
public LocalisableString Caption { get; init; }
|
||||
public LocalisableString Caption
|
||||
{
|
||||
get => caption;
|
||||
set
|
||||
{
|
||||
caption = value;
|
||||
|
||||
if (IsLoaded)
|
||||
captionText.Caption = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hint text containing an extended description of this slider bar, displayed in a tooltip when hovering the caption.
|
||||
/// </summary>
|
||||
public LocalisableString HintText { get; init; }
|
||||
|
||||
private float keyboardStep;
|
||||
|
||||
/// <summary>
|
||||
/// A custom step value for each key press which actuates a change on this control.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
@@ -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<double> IDistanceSnapProvider.DistanceSpacingMultiplier => DistanceSpacingMultiplier;
|
||||
|
||||
private ExpandableSlider<double, SizeSlider<double>> distanceSpacingSlider = null!;
|
||||
private ExpandableSlider<double> 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<double, SizeSlider<double>>
|
||||
distanceSpacingSlider = new ExpandableSlider<double>
|
||||
{
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user