mirror of
https://github.com/ppy/osu.git
synced 2026-05-20 02:39:53 +08:00
Merge pull request #36116 from frenzibyte/new-settings/form-visuals
Prepare form controls for use in settings
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Edit.Setup;
|
||||
using osuTK;
|
||||
|
||||
@@ -25,109 +28,199 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
protected override Drawable CreateContent() => new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new PopoverContainer
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new OsuScrollContainer
|
||||
new BackgroundBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new FillFlowContainer
|
||||
},
|
||||
new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new OsuScrollContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 400,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(5),
|
||||
Padding = new MarginPadding(10),
|
||||
Children = new Drawable[]
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
new FormTextBox
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Width = 400,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(5),
|
||||
Padding = new MarginPadding(10),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Caption = "Artist",
|
||||
HintText = "Poot artist here!",
|
||||
PlaceholderText = "Here is an artist",
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormTextBox
|
||||
{
|
||||
Caption = "Artist",
|
||||
HintText = "Poot artist here!",
|
||||
PlaceholderText = "Here is an artist",
|
||||
Current = { Disabled = true },
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormNumberBox(allowDecimals: true)
|
||||
{
|
||||
Caption = "Number",
|
||||
HintText = "Insert your favourite number",
|
||||
PlaceholderText = "Mine is 42!",
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormCheckBox
|
||||
{
|
||||
Caption = EditorSetupStrings.LetterboxDuringBreaks,
|
||||
HintText = EditorSetupStrings.LetterboxDuringBreaksDescription,
|
||||
},
|
||||
new FormCheckBox
|
||||
{
|
||||
Caption = EditorSetupStrings.LetterboxDuringBreaks,
|
||||
HintText = EditorSetupStrings.LetterboxDuringBreaksDescription,
|
||||
Current = { Disabled = true },
|
||||
},
|
||||
new FormSliderBar<float>
|
||||
{
|
||||
Caption = "Slider",
|
||||
Current = new BindableFloat
|
||||
new FormTextBox
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
Value = 5,
|
||||
Precision = 0.1f,
|
||||
Caption = "Artist",
|
||||
HintText = "Poot artist here!",
|
||||
PlaceholderText = "Here is an artist",
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormEnumDropdown<CountdownType>
|
||||
{
|
||||
Caption = EditorSetupStrings.EnableCountdown,
|
||||
HintText = EditorSetupStrings.CountdownDescription,
|
||||
},
|
||||
new FormFileSelector
|
||||
{
|
||||
Caption = "File selector",
|
||||
PlaceholderText = "Select a file",
|
||||
},
|
||||
new FormBeatmapFileSelector(true)
|
||||
{
|
||||
Caption = "File selector with intermediate choice dialog",
|
||||
PlaceholderText = "Select a file",
|
||||
},
|
||||
new FormColourPalette
|
||||
{
|
||||
Caption = "Combo colours",
|
||||
Colours =
|
||||
new FormTextBox
|
||||
{
|
||||
Colour4.Red,
|
||||
Colour4.Green,
|
||||
Colour4.Blue,
|
||||
Colour4.Yellow,
|
||||
}
|
||||
},
|
||||
new FormButton
|
||||
{
|
||||
Caption = "No text in button",
|
||||
Action = () => { },
|
||||
},
|
||||
new FormButton
|
||||
{
|
||||
Caption = "Text in button which is pretty long and is very likely to wrap",
|
||||
ButtonText = "Foo the bar",
|
||||
Action = () => { },
|
||||
Caption = "Artist",
|
||||
HintText = "Poot artist here!",
|
||||
PlaceholderText = "Here is an artist",
|
||||
Current = { Disabled = true },
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormNumberBox(allowDecimals: true)
|
||||
{
|
||||
Caption = "Number",
|
||||
HintText = "Insert your favourite number",
|
||||
PlaceholderText = "Mine is 42!",
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormCheckBox
|
||||
{
|
||||
Caption = EditorSetupStrings.LetterboxDuringBreaks,
|
||||
HintText = EditorSetupStrings.LetterboxDuringBreaksDescription,
|
||||
},
|
||||
new FormCheckBox
|
||||
{
|
||||
Caption = EditorSetupStrings.LetterboxDuringBreaks,
|
||||
HintText = EditorSetupStrings.LetterboxDuringBreaksDescription,
|
||||
Current = { Disabled = true },
|
||||
},
|
||||
new FormCheckBox
|
||||
{
|
||||
Caption = EditorSetupStrings.LetterboxDuringBreaks,
|
||||
HintText = EditorSetupStrings.LetterboxDuringBreaksDescription,
|
||||
Current = { Value = true, Disabled = true },
|
||||
},
|
||||
new FormSliderBar<float>
|
||||
{
|
||||
Caption = "Slider",
|
||||
HintText = "Slider hint",
|
||||
Current = new BindableFloat
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
Value = 5,
|
||||
Precision = 0.1f,
|
||||
},
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormSliderBar<float>
|
||||
{
|
||||
Caption = "Slider",
|
||||
HintText = "Slider hint",
|
||||
Current = new BindableFloat
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
Value = 5,
|
||||
Precision = 0.1f,
|
||||
Disabled = true,
|
||||
},
|
||||
TransferValueOnCommit = true,
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormSliderBar<float>
|
||||
{
|
||||
Caption = "Slider (percentage)",
|
||||
HintText = "Percentage slider hint",
|
||||
Current = new BindableFloat
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 1,
|
||||
Value = 0.2f,
|
||||
Precision = 0.0001f,
|
||||
},
|
||||
DisplayAsPercentage = true,
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormSliderBar<float>
|
||||
{
|
||||
Caption = "Slider (custom)",
|
||||
HintText = "Custom slider hint",
|
||||
Current = new BindableFloat
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 1,
|
||||
Value = 0.2f,
|
||||
Precision = 0.0001f,
|
||||
},
|
||||
LabelFormat = v => $"{v * 100:0.00} funometer",
|
||||
TooltipFormat = v => $"This setting has the value set to {v * 100:0.00} funometer.",
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormSliderBar<float>
|
||||
{
|
||||
Caption = "Slider (custom)",
|
||||
HintText = "Custom slider hint",
|
||||
Current = new BindableFloat
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 1,
|
||||
Value = 0.2f,
|
||||
Precision = 0.0001f,
|
||||
Disabled = true,
|
||||
},
|
||||
TransferValueOnCommit = true,
|
||||
LabelFormat = v => $"{v * 100:0.00} funometer",
|
||||
TooltipFormat = v => $"This setting has the value set to {v * 100:0.00} funometer.",
|
||||
TabbableContentContainer = this,
|
||||
},
|
||||
new FormEnumDropdown<CountdownType>
|
||||
{
|
||||
Caption = EditorSetupStrings.EnableCountdown,
|
||||
HintText = EditorSetupStrings.CountdownDescription,
|
||||
},
|
||||
new FormEnumDropdown<CountdownType>
|
||||
{
|
||||
Caption = EditorSetupStrings.EnableCountdown,
|
||||
HintText = EditorSetupStrings.CountdownDescription,
|
||||
Current = { Disabled = true },
|
||||
},
|
||||
new FormFileSelector
|
||||
{
|
||||
Caption = "File selector",
|
||||
PlaceholderText = "Select a file",
|
||||
},
|
||||
new FormBeatmapFileSelector(true)
|
||||
{
|
||||
Caption = "File selector with intermediate choice dialog",
|
||||
PlaceholderText = "Select a file",
|
||||
},
|
||||
new FormColourPalette
|
||||
{
|
||||
Caption = "Combo colours",
|
||||
Colours =
|
||||
{
|
||||
Colour4.Red,
|
||||
Colour4.Green,
|
||||
Colour4.Blue,
|
||||
Colour4.Yellow,
|
||||
}
|
||||
},
|
||||
new FormButton
|
||||
{
|
||||
Caption = "No text in button",
|
||||
Action = () => { },
|
||||
},
|
||||
new FormButton
|
||||
{
|
||||
Caption = "Text in button which is pretty long and is very likely to wrap",
|
||||
ButtonText = "Foo the bar",
|
||||
Action = () => { },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private partial class BackgroundBox : Box
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
Colour = colourProvider.Background4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,19 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public partial class TestSceneLabelledSwitchButton : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestSwitchButton(bool hasDescription) => createSwitchButton(hasDescription);
|
||||
|
||||
@@ -4,15 +4,21 @@
|
||||
#nullable disable
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public partial class TestSceneSwitchButton : OsuManualInputManagerTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
|
||||
|
||||
private SwitchButton switchButton;
|
||||
|
||||
[SetUp]
|
||||
@@ -42,5 +48,15 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("toggle bindable", () => bindable.Toggle());
|
||||
AddStep("toggle bindable", () => bindable.Toggle());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDisabledState()
|
||||
{
|
||||
AddToggleStep("toggle disabled", v =>
|
||||
{
|
||||
if (switchButton.IsNotNull())
|
||||
switchButton.Current.Disabled = v;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Online.API;
|
||||
@@ -56,7 +55,7 @@ namespace osu.Game.Tournament.Screens.Setup
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.2f),
|
||||
Colour = ColourProvider.Background5,
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Screens
|
||||
@@ -15,6 +16,9 @@ namespace osu.Game.Tournament.Screens
|
||||
[Resolved]
|
||||
protected LadderInfo LadderInfo { get; private set; } = null!;
|
||||
|
||||
[Cached]
|
||||
protected readonly OverlayColourProvider ColourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
protected TournamentScreen()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
@@ -25,12 +25,12 @@ namespace osu.Game.Graphics.UserInterface
|
||||
/// </summary>
|
||||
public bool DisplayAsPercentage { get; set; }
|
||||
|
||||
public virtual LocalisableString TooltipText { get; private set; }
|
||||
public virtual LocalisableString TooltipText { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of decimal digits to be displayed in the tooltip.
|
||||
/// </summary>
|
||||
private const int max_decimal_digits = 5;
|
||||
public const int MAX_DECIMAL_DIGITS = 5;
|
||||
|
||||
private Sample sample = null!;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
CurrentNumber.BindValueChanged(current => TooltipText = GetDisplayableValue(current.NewValue), true);
|
||||
CurrentNumber.BindValueChanged(current => TooltipText = GetTooltipText(current.NewValue), true);
|
||||
}
|
||||
|
||||
protected override void OnUserChange(T value)
|
||||
@@ -55,7 +55,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
playSample(value);
|
||||
|
||||
TooltipText = GetDisplayableValue(value);
|
||||
TooltipText = GetTooltipText(value);
|
||||
}
|
||||
|
||||
private void playSample(T value)
|
||||
@@ -83,6 +83,6 @@ namespace osu.Game.Graphics.UserInterface
|
||||
channel.Play();
|
||||
}
|
||||
|
||||
public LocalisableString GetDisplayableValue(T value) => value.ToStandardFormattedString(max_decimal_digits, DisplayAsPercentage);
|
||||
protected virtual LocalisableString GetTooltipText(T value) => value.ToStandardFormattedString(MAX_DECIMAL_DIGITS, DisplayAsPercentage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
@@ -45,10 +44,10 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
private Box background = null!;
|
||||
private FormFieldCaption caption = null!;
|
||||
private OsuSpriteText text = null!;
|
||||
private Nub checkbox = null!;
|
||||
|
||||
private Sample? sampleChecked;
|
||||
private Sample? sampleUnchecked;
|
||||
private Sample? sampleDisabled;
|
||||
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||
@@ -89,7 +88,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
},
|
||||
checkbox = new Nub
|
||||
new SwitchButton
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
@@ -101,6 +100,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
|
||||
sampleChecked = audio.Samples.Get(@"UI/check-on");
|
||||
sampleUnchecked = audio.Samples.Get(@"UI/check-off");
|
||||
sampleDisabled = audio.Samples.Get(@"UI/default-select-disabled");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -142,25 +142,26 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
if (!Current.Disabled)
|
||||
Current.Value = !Current.Value;
|
||||
else
|
||||
sampleDisabled?.Play();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
background.Colour = Current.Disabled ? colourProvider.Background4 : colourProvider.Background5;
|
||||
caption.Colour = Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content2;
|
||||
checkbox.Colour = Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||
text.Colour = Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||
caption.Colour = Current.Disabled ? colourProvider.Background1 : colourProvider.Content2;
|
||||
text.Colour = Current.Disabled ? colourProvider.Background1 : colourProvider.Content1;
|
||||
|
||||
text.Text = Current.Value ? CommonStrings.Enabled : CommonStrings.Disabled;
|
||||
|
||||
if (!Current.Disabled)
|
||||
{
|
||||
BorderThickness = IsHovered ? 2 : 0;
|
||||
// use FadeColour to override any existing colour transform (i.e. FlashColour on click).
|
||||
background.FadeColour(IsHovered
|
||||
? ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark4)
|
||||
: colourProvider.Background5);
|
||||
|
||||
if (IsHovered)
|
||||
BorderColour = colourProvider.Light4;
|
||||
}
|
||||
BorderThickness = IsHovered ? 2 : 0;
|
||||
BorderColour = Current.Disabled ? colourProvider.Dark1 : colourProvider.Light4;
|
||||
}
|
||||
|
||||
public IEnumerable<LocalisableString> FilterTerms => Caption.Yield();
|
||||
|
||||
@@ -171,10 +171,14 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Size = new Vector2(16),
|
||||
Margin = new MarginPadding { Right = 5 },
|
||||
},
|
||||
};
|
||||
|
||||
AddInternal(new HoverClickSounds());
|
||||
AddInternal(new HoverClickSounds
|
||||
{
|
||||
Enabled = { BindTarget = Enabled },
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -210,29 +214,26 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
label.Alpha = string.IsNullOrEmpty(SearchBar.SearchTerm.Value) ? 1 : 0;
|
||||
|
||||
caption.Colour = Dropdown.Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content2;
|
||||
label.Colour = Dropdown.Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||
chevron.Colour = Dropdown.Current.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||
caption.Colour = Dropdown.Current.Disabled ? colourProvider.Background1 : colourProvider.Content2;
|
||||
label.Colour = Dropdown.Current.Disabled ? colourProvider.Background1 : colourProvider.Content1;
|
||||
chevron.Colour = Dropdown.Current.Disabled ? colourProvider.Background1 : colourProvider.Content1;
|
||||
DisabledColour = Colour4.White;
|
||||
|
||||
bool dropdownOpen = Dropdown.Menu.State == MenuState.Open;
|
||||
|
||||
if (!Dropdown.Current.Disabled)
|
||||
{
|
||||
BorderThickness = IsHovered || dropdownOpen ? 2 : 0;
|
||||
BorderThickness = IsHovered || dropdownOpen ? 2 : 0;
|
||||
|
||||
if (Dropdown.Current.Disabled)
|
||||
BorderColour = colourProvider.Dark1;
|
||||
else
|
||||
BorderColour = dropdownOpen ? colourProvider.Highlight1 : colourProvider.Light4;
|
||||
|
||||
if (dropdownOpen)
|
||||
Background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark3);
|
||||
else if (IsHovered)
|
||||
Background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark4);
|
||||
else
|
||||
Background.Colour = colourProvider.Background5;
|
||||
}
|
||||
if (dropdownOpen)
|
||||
Background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark3);
|
||||
else if (IsHovered)
|
||||
Background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark4);
|
||||
else
|
||||
{
|
||||
Background.Colour = colourProvider.Background4;
|
||||
}
|
||||
Background.Colour = colourProvider.Background5;
|
||||
}
|
||||
|
||||
private void updateChevron()
|
||||
|
||||
@@ -17,6 +17,8 @@ using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays;
|
||||
@@ -97,9 +99,31 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether to format the tooltip as a percentage or the actual value.
|
||||
/// </summary>
|
||||
public bool DisplayAsPercentage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether sound effects should play when adjusting this slider.
|
||||
/// </summary>
|
||||
public bool PlaySamplesOnAdjust { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The string formatting function to use for the value label.
|
||||
/// </summary>
|
||||
public Func<T, LocalisableString> LabelFormat { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The string formatting function to use for the slider's tooltip text.
|
||||
/// If not provided, <see cref="LabelFormat"/> is used.
|
||||
/// </summary>
|
||||
public Func<T, LocalisableString> TooltipFormat { get; init; }
|
||||
|
||||
private Box background = null!;
|
||||
private Box flashLayer = null!;
|
||||
private FormTextBox.InnerTextBox textBox = null!;
|
||||
private OsuSpriteText valueLabel = null!;
|
||||
private InnerSlider slider = null!;
|
||||
private FormFieldCaption captionText = null!;
|
||||
private IFocusManager focusManager = null!;
|
||||
@@ -109,6 +133,12 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
|
||||
private readonly Bindable<Language> currentLanguage = new Bindable<Language>();
|
||||
|
||||
public FormSliderBar()
|
||||
{
|
||||
LabelFormat ??= defaultLabelFormat;
|
||||
TooltipFormat ??= v => LabelFormat(v);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, OsuGame? game)
|
||||
{
|
||||
@@ -153,6 +183,10 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0.5f,
|
||||
// the textbox is hidden when the control is unfocused,
|
||||
// but clicking on the label should reach the textbox,
|
||||
// therefore make it always present.
|
||||
AlwaysPresent = true,
|
||||
CommitOnFocusLost = true,
|
||||
SelectAllOnFocus = true,
|
||||
OnInputError = () =>
|
||||
@@ -162,6 +196,14 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
},
|
||||
TabbableContentContainer = tabbableContentContainer,
|
||||
},
|
||||
valueLabel = new TruncatingSpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0.5f,
|
||||
Padding = new MarginPadding { Right = 5 },
|
||||
},
|
||||
slider = new InnerSlider
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
@@ -170,6 +212,9 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
Width = 0.5f,
|
||||
Current = currentNumberInstantaneous,
|
||||
OnCommit = () => current.Value = currentNumberInstantaneous.Value,
|
||||
TooltipFormat = TooltipFormat,
|
||||
DisplayAsPercentage = DisplayAsPercentage,
|
||||
PlaySamplesOnAdjust = PlaySamplesOnAdjust,
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -218,6 +263,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
|
||||
current.CopyTo(currentNumberInstantaneous);
|
||||
currentLanguage.BindValueChanged(_ => Schedule(updateValueDisplay));
|
||||
currentNumberInstantaneous.BindDisabledChanged(_ => updateState());
|
||||
currentNumberInstantaneous.BindValueChanged(e =>
|
||||
{
|
||||
if (!TransferValueOnCommit)
|
||||
@@ -299,15 +345,20 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
bool childHasFocus = slider.Focused.Value || textBox.Focused.Value;
|
||||
|
||||
textBox.Alpha = 1;
|
||||
textBox.ReadOnly = Current.Disabled;
|
||||
textBox.ReadOnly = currentNumberInstantaneous.Disabled;
|
||||
textBox.Alpha = textBox.Focused.Value ? 1 : 0;
|
||||
valueLabel.Alpha = textBox.Focused.Value ? 0 : 1;
|
||||
|
||||
background.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Background4 : colourProvider.Background5;
|
||||
captionText.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Foreground1 : colourProvider.Content2;
|
||||
textBox.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||
captionText.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Background1 : colourProvider.Content2;
|
||||
textBox.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Background1 : colourProvider.Content1;
|
||||
valueLabel.Colour = currentNumberInstantaneous.Disabled ? colourProvider.Background1 : colourProvider.Content1;
|
||||
|
||||
BorderThickness = childHasFocus || IsHovered || slider.IsDragging.Value ? 2 : 0;
|
||||
BorderColour = childHasFocus ? colourProvider.Highlight1 : colourProvider.Light4;
|
||||
|
||||
if (Current.Disabled)
|
||||
BorderColour = colourProvider.Dark1;
|
||||
else
|
||||
BorderColour = childHasFocus ? colourProvider.Highlight1 : colourProvider.Light4;
|
||||
|
||||
if (childHasFocus)
|
||||
background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark3);
|
||||
@@ -321,19 +372,28 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
if (updatingFromTextBox) return;
|
||||
|
||||
textBox.Text = slider.GetDisplayableValue(currentNumberInstantaneous.Value).ToString();
|
||||
textBox.Text = currentNumberInstantaneous.Value.ToStandardFormattedString(OsuSliderBar<T>.MAX_DECIMAL_DIGITS);
|
||||
valueLabel.Text = LabelFormat(currentNumberInstantaneous.Value);
|
||||
}
|
||||
|
||||
private LocalisableString defaultLabelFormat(T value) => currentNumberInstantaneous.Value.ToStandardFormattedString(OsuSliderBar<T>.MAX_DECIMAL_DIGITS, DisplayAsPercentage);
|
||||
|
||||
private partial class InnerSlider : OsuSliderBar<T>
|
||||
{
|
||||
public BindableBool Focused { get; } = new BindableBool();
|
||||
|
||||
public BindableBool IsDragging { get; set; } = new BindableBool();
|
||||
|
||||
public Action? OnCommit { get; set; }
|
||||
|
||||
public sealed override LocalisableString TooltipText => base.TooltipText;
|
||||
|
||||
public required Func<T, LocalisableString> TooltipFormat { get; init; }
|
||||
|
||||
private Box leftBox = null!;
|
||||
private Box rightBox = null!;
|
||||
private InnerSliderNub nub = null!;
|
||||
private HoverClickSounds sounds = null!;
|
||||
public const float NUB_WIDTH = 10;
|
||||
|
||||
[Resolved]
|
||||
@@ -382,7 +442,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
}
|
||||
}
|
||||
},
|
||||
new HoverClickSounds()
|
||||
sounds = new HoverClickSounds()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -442,6 +502,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
sounds.Enabled.Value = !Current.Disabled;
|
||||
rightBox.Colour = colourProvider.Background6;
|
||||
|
||||
if (Current.Disabled)
|
||||
@@ -470,6 +531,8 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected sealed override LocalisableString GetTooltipText(T value) => TooltipFormat(value);
|
||||
}
|
||||
|
||||
private partial class InnerSliderNub : Circle
|
||||
|
||||
@@ -189,26 +189,22 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
textBox.ReadOnly = disabled;
|
||||
textBox.Alpha = 1;
|
||||
|
||||
caption.Colour = disabled ? colourProvider.Foreground1 : colourProvider.Content2;
|
||||
caption.Colour = disabled ? colourProvider.Background1 : colourProvider.Content2;
|
||||
textBox.Colour = disabled ? colourProvider.Foreground1 : colourProvider.Content1;
|
||||
|
||||
if (!disabled)
|
||||
{
|
||||
BorderThickness = IsHovered || textBox.Focused.Value ? 2 : 0;
|
||||
BorderThickness = IsHovered || textBox.Focused.Value ? 2 : 0;
|
||||
|
||||
if (disabled)
|
||||
BorderColour = colourProvider.Dark1;
|
||||
else
|
||||
BorderColour = textBox.Focused.Value ? colourProvider.Highlight1 : colourProvider.Light4;
|
||||
|
||||
if (textBox.Focused.Value)
|
||||
background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark3);
|
||||
else if (IsHovered)
|
||||
background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark4);
|
||||
else
|
||||
background.Colour = colourProvider.Background5;
|
||||
}
|
||||
if (textBox.Focused.Value)
|
||||
background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark3);
|
||||
else if (IsHovered)
|
||||
background.Colour = ColourInfo.GradientVertical(colourProvider.Background5, colourProvider.Dark4);
|
||||
else
|
||||
{
|
||||
BorderThickness = 0;
|
||||
background.Colour = colourProvider.Background4;
|
||||
}
|
||||
background.Colour = colourProvider.Background5;
|
||||
}
|
||||
|
||||
internal partial class InnerTextBox : OsuTextBox
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
@@ -24,12 +23,12 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
private const float padding = 1.25f;
|
||||
|
||||
private readonly Box fill;
|
||||
private readonly Container switchContainer;
|
||||
private readonly Drawable switchCircle;
|
||||
private readonly CircularBorderContainer circularContainer;
|
||||
private readonly Container nubContainer;
|
||||
private readonly Drawable nub;
|
||||
private readonly CircularContainer content;
|
||||
|
||||
private Color4 enabledColour;
|
||||
private Color4 disabledColour;
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||
|
||||
private Sample? sampleChecked;
|
||||
private Sample? sampleUnchecked;
|
||||
@@ -38,7 +37,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
Size = new Vector2(45, 20);
|
||||
|
||||
InternalChild = circularContainer = new CircularBorderContainer
|
||||
InternalChild = content = new CircularContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BorderColour = Color4.White,
|
||||
@@ -56,15 +55,14 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(border_thickness + padding),
|
||||
Child = switchContainer = new Container
|
||||
Child = nubContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = switchCircle = new CircularContainer
|
||||
Child = nub = new Circle
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
Masking = true,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,14 +71,8 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OverlayColourProvider? colourProvider, OsuColour colours, AudioManager audio)
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
enabledColour = colourProvider?.Highlight1 ?? colours.BlueDark;
|
||||
disabledColour = colourProvider?.Background3 ?? colours.Gray3;
|
||||
|
||||
switchContainer.Colour = enabledColour;
|
||||
fill.Colour = disabledColour;
|
||||
|
||||
sampleChecked = audio.Samples.Get(@"UI/check-on");
|
||||
sampleUnchecked = audio.Samples.Get(@"UI/check-off");
|
||||
}
|
||||
@@ -89,27 +81,29 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Current.BindValueChanged(updateState, true);
|
||||
Current.BindDisabledChanged(_ => updateColours());
|
||||
Current.BindValueChanged(_ => updateState(), true);
|
||||
|
||||
FinishTransforms(true);
|
||||
}
|
||||
|
||||
private void updateState(ValueChangedEvent<bool> state)
|
||||
private void updateState()
|
||||
{
|
||||
switchCircle.MoveToX(state.NewValue ? switchContainer.DrawWidth - switchCircle.DrawWidth : 0, 200, Easing.OutQuint);
|
||||
fill.FadeTo(state.NewValue ? 1 : 0, 250, Easing.OutQuint);
|
||||
nub.MoveToX(Current.Value ? nubContainer.DrawWidth - nub.DrawWidth : 0, 200, Easing.OutQuint);
|
||||
fill.FadeTo(Current.Value ? 1 : 0, 250, Easing.OutQuint);
|
||||
|
||||
updateBorder();
|
||||
updateColours();
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
updateBorder();
|
||||
updateColours();
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateBorder();
|
||||
updateColours();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
@@ -123,15 +117,35 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
sampleUnchecked?.Play();
|
||||
}
|
||||
|
||||
private void updateBorder()
|
||||
private void updateColours()
|
||||
{
|
||||
circularContainer.TransformBorderTo((Current.Value ? enabledColour : disabledColour).Lighten(IsHovered ? 0.3f : 0));
|
||||
}
|
||||
ColourInfo borderColour;
|
||||
ColourInfo switchColour;
|
||||
|
||||
private partial class CircularBorderContainer : CircularContainer
|
||||
{
|
||||
public void TransformBorderTo(ColourInfo colour)
|
||||
=> this.TransformTo(nameof(BorderColour), colour, 250, Easing.OutQuint);
|
||||
if (Current.Disabled)
|
||||
{
|
||||
borderColour = colourProvider.Dark2;
|
||||
switchColour = colourProvider.Dark1;
|
||||
fill.Colour = colourProvider.Dark5;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hover = IsHovered && !Current.Disabled;
|
||||
|
||||
borderColour = hover ? colourProvider.Highlight1.Opacity(0.5f) : colourProvider.Highlight1.Opacity(0.3f);
|
||||
switchColour = hover ? colourProvider.Highlight1 : colourProvider.Light4;
|
||||
|
||||
if (!Current.Value)
|
||||
{
|
||||
borderColour = borderColour.MultiplyAlpha(0.8f);
|
||||
switchColour = switchColour.MultiplyAlpha(0.8f);
|
||||
}
|
||||
|
||||
fill.Colour = colourProvider.Background6;
|
||||
}
|
||||
|
||||
nubContainer.FadeColour(switchColour, 250, Easing.OutQuint);
|
||||
content.TransformTo(nameof(BorderColour), borderColour, 250, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user