1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 10:18:22 +08:00

Refactor star "DifficultyRangeFilterControl" into generic range slider class

This commit is contained in:
mk56-spn 2022-11-26 12:19:08 +01:00
parent 44a71741e4
commit 92ed2ed4ef
5 changed files with 279 additions and 181 deletions

View File

@ -1,28 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Screens.Select;
using osuTK;
namespace osu.Game.Tests.Visual.SongSelect
{
public class TestSceneDifficultyRangeFilterControl : OsuTestScene
{
[Test]
public void TestBasic()
{
AddStep("create control", () =>
{
Child = new DifficultyRangeFilterControl
{
Width = 200,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(3),
};
});
}
}
}

View File

@ -0,0 +1,60 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneRangeSlider : OsuTestScene
{
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
private readonly BindableNumber<double> customStart = new BindableNumber<double>
{
MinValue = 0,
MaxValue = 100,
Precision = 0.001f
};
private readonly BindableNumber<double> customEnd = new BindableNumber<double>(100)
{
MinValue = 0,
MaxValue = 100,
Precision = 0.1f
};
[Test]
public void TestBasic()
{
AddStep("create Control", () => Child = new RangeSlider
{
Width = 200,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(3),
LowerBound = customStart,
UpperBound = customEnd,
TooltipSuffix = "suffix",
NubWidth = Nub.HEIGHT * 2,
DefaultStringLowerBound = "Start",
DefaultStringUpperBound = "End"
});
AddStep("Test Range", () =>
{
customStart.Value = 50;
customEnd.Value = 75;
});
AddStep("Test nub pushing", () =>
{
customStart.Value = 90;
});
}
}
}

View File

@ -0,0 +1,210 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Graphics.Sprites;
using osu.Game.Overlays;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Graphics.UserInterface
{
public class RangeSlider : CompositeDrawable
{
/// <summary>
/// The lower limiting value
/// </summary>
public Bindable<double> LowerBound
{
set => lowerBound.Current = value;
}
/// <summary>
/// The upper limiting value
/// </summary>
public Bindable<double> UpperBound
{
set => upperBound.Current = value;
}
/// <summary>
/// Text that describes this RangeSlider's functionality
/// </summary>
public string Label
{
set => label.Text = value;
}
public float NubWidth
{
set => lowerBound.NubWidth = upperBound.NubWidth = value;
}
/// <summary>
/// Minimum difference between the lower bound and higher bound
/// </summary>
public float MinRange
{
set => minRange = value;
}
/// <summary>
/// lower bound display for when it is set to its default value
/// </summary>
public string DefaultStringLowerBound
{
set => lowerBound.DefaultString = value;
}
/// <summary>
/// upper bound display for when it is set to its default value
/// </summary>
public string DefaultStringUpperBound
{
set => upperBound.DefaultString = value;
}
public LocalisableString DefaultTooltipLowerBound
{
set => lowerBound.DefaultTooltip = value;
}
public LocalisableString DefaultTooltipUpperBound
{
set => upperBound.DefaultTooltip = value;
}
public string TooltipSuffix
{
set => upperBound.TooltipSuffix = lowerBound.TooltipSuffix = value;
}
private float minRange = 0.1f;
private readonly OsuSpriteText label;
private readonly LowerBoundSlider lowerBound;
private readonly UpperBoundSlider upperBound;
public RangeSlider()
{
const float vertical_offset = 13;
InternalChildren = new Drawable[]
{
label = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 14),
},
upperBound = new UpperBoundSlider
{
KeyboardStep = 0.1f,
RelativeSizeAxes = Axes.X,
Y = vertical_offset,
},
lowerBound = new LowerBoundSlider
{
KeyboardStep = 0.1f,
RelativeSizeAxes = Axes.X,
Y = vertical_offset,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
lowerBound.Current.ValueChanged += min => upperBound.Current.Value = Math.Max(min.NewValue + minRange, upperBound.Current.Value);
upperBound.Current.ValueChanged += max => lowerBound.Current.Value = Math.Min(max.NewValue - minRange, lowerBound.Current.Value);
}
private class LowerBoundSlider : BoundSlider
{
protected override void LoadComplete()
{
base.LoadComplete();
LeftBox.Height = 6; // hide any colour bleeding from overlap
AccentColour = BackgroundColour;
BackgroundColour = Color4.Transparent;
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
base.ReceivePositionalInputAt(screenSpacePos)
&& screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X;
}
private class UpperBoundSlider : BoundSlider
{
protected override void LoadComplete()
{
base.LoadComplete();
RightBox.Height = 6; // just to match the left bar height really
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
base.ReceivePositionalInputAt(screenSpacePos)
&& screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X;
}
protected class BoundSlider : OsuSliderBar<double>
{
public string? DefaultString;
public LocalisableString? DefaultTooltip;
public string? TooltipSuffix;
public float NubWidth { get; set; } = Nub.HEIGHT;
public override LocalisableString TooltipText =>
(Current.IsDefault ? DefaultTooltip : Current.Value.ToString($@"0.## {TooltipSuffix}")) ?? Current.Value.ToString($@"0.## {TooltipSuffix}");
protected override bool OnHover(HoverEvent e)
{
base.OnHover(e);
return true; // Make sure only one nub shows hover effect at once.
}
protected override void LoadComplete()
{
base.LoadComplete();
Nub.Width = NubWidth;
RangePadding = Nub.Width / 2;
OsuSpriteText currentDisplay;
Nub.Add(currentDisplay = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = -0.5f,
Colour = Color4.White,
Font = OsuFont.Torus.With(size: 10),
});
Current.BindValueChanged(current =>
{
currentDisplay.Text = (current.NewValue != Current.Default ? current.NewValue.ToString("N1") : DefaultString) ?? current.NewValue.ToString("N1");
}, true);
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider? colourProvider)
{
if (colourProvider == null) return;
AccentColour = colourProvider.Background2;
Nub.AccentColour = colourProvider.Background2;
Nub.GlowingAccentColour = colourProvider.Background1;
Nub.GlowColour = colourProvider.Background2;
}
}
}
}

View File

@ -1,152 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.Select
{
internal class DifficultyRangeFilterControl : CompositeDrawable
{
private Bindable<double> lowerStars = null!;
private Bindable<double> upperStars = null!;
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
const float vertical_offset = 13;
InternalChildren = new Drawable[]
{
new OsuSpriteText
{
Text = "Difficulty range",
Font = OsuFont.GetFont(size: 14),
},
new MaximumStarsSlider
{
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
KeyboardStep = 0.1f,
RelativeSizeAxes = Axes.X,
Y = vertical_offset,
},
new MinimumStarsSlider
{
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
KeyboardStep = 0.1f,
RelativeSizeAxes = Axes.X,
Y = vertical_offset,
}
};
lowerStars = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum);
upperStars = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum);
}
protected override void LoadComplete()
{
base.LoadComplete();
lowerStars.ValueChanged += min => upperStars.Value = Math.Max(min.NewValue + 0.1, upperStars.Value);
upperStars.ValueChanged += max => lowerStars.Value = Math.Min(max.NewValue - 0.1, lowerStars.Value);
}
private class MinimumStarsSlider : StarsSlider
{
public MinimumStarsSlider()
: base("0")
{
}
public override LocalisableString TooltipText => Current.Value.ToString(@"0.## stars");
protected override void LoadComplete()
{
base.LoadComplete();
LeftBox.Height = 6; // hide any colour bleeding from overlap
AccentColour = BackgroundColour;
BackgroundColour = Color4.Transparent;
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
base.ReceivePositionalInputAt(screenSpacePos)
&& screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X;
}
private class MaximumStarsSlider : StarsSlider
{
public MaximumStarsSlider()
: base("∞")
{
}
protected override void LoadComplete()
{
base.LoadComplete();
RightBox.Height = 6; // just to match the left bar height really
}
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
base.ReceivePositionalInputAt(screenSpacePos)
&& screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X;
}
private class StarsSlider : OsuSliderBar<double>
{
private readonly string defaultString;
public override LocalisableString TooltipText => Current.IsDefault
? UserInterfaceStrings.NoLimit
: Current.Value.ToString(@"0.## stars");
protected StarsSlider(string defaultString)
{
this.defaultString = defaultString;
}
protected override bool OnHover(HoverEvent e)
{
base.OnHover(e);
return true; // Make sure only one nub shows hover effect at once.
}
protected override void LoadComplete()
{
base.LoadComplete();
Nub.Width = Nub.HEIGHT;
RangePadding = Nub.Width / 2;
OsuSpriteText currentDisplay;
Nub.Add(currentDisplay = new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Y = -0.5f,
Colour = Color4.White,
Font = OsuFont.Torus.With(size: 10),
});
Current.BindValueChanged(current =>
{
currentDisplay.Text = current.NewValue != Current.Default ? current.NewValue.ToString("N1") : defaultString;
}, true);
}
}
}
}

View File

@ -16,6 +16,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Localisation;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets;
using osu.Game.Screens.Select.Filter;
@ -172,12 +173,19 @@ namespace osu.Game.Screens.Select
Height = 40,
Children = new Drawable[]
{
new DifficultyRangeFilterControl
new RangeSlider
{
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,
Label = "Difficulty range",
LowerBound = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
UpperBound = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
RelativeSizeAxes = Axes.Both,
Width = 0.48f,
DefaultStringLowerBound = "0",
DefaultStringUpperBound = "∞",
DefaultTooltipUpperBound = UserInterfaceStrings.NoLimit,
TooltipSuffix = "stars"
},
collectionDropdown = new CollectionDropdown
{