1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 20:07:25 +08:00

Merge pull request #24199 from peppy/revert-to-default-design-change

Update design of "revert to default" button
This commit is contained in:
Bartłomiej Dach 2023-07-13 23:44:24 +02:00 committed by GitHub
commit cdbb6f90be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 122 additions and 138 deletions

View File

@ -195,16 +195,16 @@ namespace osu.Game.Tests.Visual.Settings
InputManager.ReleaseKey(Key.P); InputManager.ReleaseKey(Key.P);
}); });
AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha > 0); AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha > 0);
AddStep("click reset button for bindings", () => AddStep("click reset button for bindings", () =>
{ {
var resetButton = settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First(); var resetButton = settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First();
resetButton.TriggerClick(); resetButton.TriggerClick();
}); });
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha == 0); AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha == 0);
AddAssert("binding cleared", AddAssert("binding cleared",
() => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0))); () => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));
@ -225,7 +225,7 @@ namespace osu.Game.Tests.Visual.Settings
InputManager.ReleaseKey(Key.P); InputManager.ReleaseKey(Key.P);
}); });
AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha > 0); AddUntilStep("restore button shown", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha > 0);
AddStep("click reset button for bindings", () => AddStep("click reset button for bindings", () =>
{ {
@ -234,7 +234,7 @@ namespace osu.Game.Tests.Visual.Settings
resetButton.TriggerClick(); resetButton.TriggerClick();
}); });
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha == 0); AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RevertToDefaultButton<bool>>().First().Alpha == 0);
AddAssert("binding cleared", AddAssert("binding cleared",
() => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0))); () => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));

View File

@ -1,65 +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.
#nullable disable
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Tests.Visual.Settings
{
public partial class TestSceneRestoreDefaultValueButton : OsuTestScene
{
[Resolved]
private OsuColour colours { get; set; }
private float scale = 1;
private readonly Bindable<float> current = new Bindable<float>
{
Default = default,
Value = 1,
};
[Test]
public void TestBasic()
{
RestoreDefaultValueButton<float> restoreDefaultValueButton = null;
AddStep("create button", () => Child = new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colours.GreySeaFoam
},
restoreDefaultValueButton = new RestoreDefaultValueButton<float>
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(scale),
Current = current,
}
}
});
AddSliderStep("set scale", 1, 4, 1, scale =>
{
this.scale = scale;
if (restoreDefaultValueButton != null)
restoreDefaultValueButton.Scale = new Vector2(scale);
});
AddToggleStep("toggle default state", state => current.Value = state ? default : 1);
AddToggleStep("toggle disabled state", state => current.Disabled = state);
}
}
}

View File

@ -0,0 +1,53 @@
// 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.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Overlays;
using osu.Game.Tests.Visual.UserInterface;
using osuTK;
namespace osu.Game.Tests.Visual.Settings
{
public partial class TestSceneRevertToDefaultButton : ThemeComparisonTestScene
{
private float scale = 1;
private readonly Bindable<float> current = new Bindable<float>
{
Default = default,
Value = 1,
};
protected override Drawable CreateContent() => new Container
{
AutoSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Child = new RevertToDefaultButton<float>
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Scale = new Vector2(scale),
Current = current,
}
};
[Test]
public void TestStates()
{
AddStep("create content", () => CreateThemedContent(OverlayColourScheme.Purple));
AddSliderStep("set scale", 1, 4, 1, scale =>
{
this.scale = scale;
foreach (var revertToDefaultButton in this.ChildrenOfType<RevertToDefaultButton<float>>())
revertToDefaultButton.Parent!.Scale = new Vector2(scale);
});
AddToggleStep("toggle default state", state => current.Value = state ? default : 1);
AddToggleStep("toggle disabled state", state => current.Disabled = state);
}
}
}

View File

@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Settings
public void TestRestoreDefaultValueButtonVisibility() public void TestRestoreDefaultValueButtonVisibility()
{ {
SettingsTextBox textBox = null; SettingsTextBox textBox = null;
RestoreDefaultValueButton<string> restoreDefaultValueButton = null; RevertToDefaultButton<string> revertToDefaultButton = null;
AddStep("create settings item", () => AddStep("create settings item", () =>
{ {
@ -33,22 +33,22 @@ namespace osu.Game.Tests.Visual.Settings
}; };
}); });
AddUntilStep("wait for loaded", () => textBox.IsLoaded); AddUntilStep("wait for loaded", () => textBox.IsLoaded);
AddStep("retrieve restore default button", () => restoreDefaultValueButton = textBox.ChildrenOfType<RestoreDefaultValueButton<string>>().Single()); AddStep("retrieve restore default button", () => revertToDefaultButton = textBox.ChildrenOfType<RevertToDefaultButton<string>>().Single());
AddAssert("restore button hidden", () => restoreDefaultValueButton.Alpha == 0); AddAssert("restore button hidden", () => revertToDefaultButton.Alpha == 0);
AddStep("change value from default", () => textBox.Current.Value = "non-default"); AddStep("change value from default", () => textBox.Current.Value = "non-default");
AddUntilStep("restore button shown", () => restoreDefaultValueButton.Alpha > 0); AddUntilStep("restore button shown", () => revertToDefaultButton.Alpha > 0);
AddStep("restore default", () => textBox.Current.SetDefault()); AddStep("restore default", () => textBox.Current.SetDefault());
AddUntilStep("restore button hidden", () => restoreDefaultValueButton.Alpha == 0); AddUntilStep("restore button hidden", () => revertToDefaultButton.Alpha == 0);
} }
[Test] [Test]
public void TestSetAndClearLabelText() public void TestSetAndClearLabelText()
{ {
SettingsTextBox textBox = null; SettingsTextBox textBox = null;
RestoreDefaultValueButton<string> restoreDefaultValueButton = null; RevertToDefaultButton<string> revertToDefaultButton = null;
OsuTextBox control = null; OsuTextBox control = null;
AddStep("create settings item", () => AddStep("create settings item", () =>
@ -61,25 +61,25 @@ namespace osu.Game.Tests.Visual.Settings
AddUntilStep("wait for loaded", () => textBox.IsLoaded); AddUntilStep("wait for loaded", () => textBox.IsLoaded);
AddStep("retrieve components", () => AddStep("retrieve components", () =>
{ {
restoreDefaultValueButton = textBox.ChildrenOfType<RestoreDefaultValueButton<string>>().Single(); revertToDefaultButton = textBox.ChildrenOfType<RevertToDefaultButton<string>>().Single();
control = textBox.ChildrenOfType<OsuTextBox>().Single(); control = textBox.ChildrenOfType<OsuTextBox>().Single();
}); });
AddStep("set non-default value", () => restoreDefaultValueButton.Current.Value = "non-default"); AddStep("set non-default value", () => revertToDefaultButton.Current.Value = "non-default");
AddAssert("default value button centre aligned to control size", () => Precision.AlmostEquals(restoreDefaultValueButton.Parent.DrawHeight, control.DrawHeight, 1)); AddAssert("default value button centre aligned to control size", () => Precision.AlmostEquals(revertToDefaultButton.Parent.DrawHeight, control.DrawHeight, 1));
AddStep("set label", () => textBox.LabelText = "label text"); AddStep("set label", () => textBox.LabelText = "label text");
AddAssert("default value button centre aligned to label size", () => AddAssert("default value button centre aligned to label size", () =>
{ {
var label = textBox.ChildrenOfType<OsuSpriteText>().Single(spriteText => spriteText.Text == "label text"); var label = textBox.ChildrenOfType<OsuSpriteText>().Single(spriteText => spriteText.Text == "label text");
return Precision.AlmostEquals(restoreDefaultValueButton.Parent.DrawHeight, label.DrawHeight, 1); return Precision.AlmostEquals(revertToDefaultButton.Parent.DrawHeight, label.DrawHeight, 1);
}); });
AddStep("clear label", () => textBox.LabelText = default); AddStep("clear label", () => textBox.LabelText = default);
AddAssert("default value button centre aligned to control size", () => Precision.AlmostEquals(restoreDefaultValueButton.Parent.DrawHeight, control.DrawHeight, 1)); AddAssert("default value button centre aligned to control size", () => Precision.AlmostEquals(revertToDefaultButton.Parent.DrawHeight, control.DrawHeight, 1));
AddStep("set warning text", () => textBox.SetNoticeText("This is some very important warning text! Hopefully it doesn't break the alignment of the default value indicator...", true)); AddStep("set warning text", () => textBox.SetNoticeText("This is some very important warning text! Hopefully it doesn't break the alignment of the default value indicator...", true));
AddAssert("default value button centre aligned to control size", () => Precision.AlmostEquals(restoreDefaultValueButton.Parent.DrawHeight, control.DrawHeight, 1)); AddAssert("default value button centre aligned to control size", () => Precision.AlmostEquals(revertToDefaultButton.Parent.DrawHeight, control.DrawHeight, 1));
} }
/// <summary> /// <summary>
@ -92,7 +92,7 @@ namespace osu.Game.Tests.Visual.Settings
{ {
BindableFloat current = null; BindableFloat current = null;
SettingsSlider<float> sliderBar = null; SettingsSlider<float> sliderBar = null;
RestoreDefaultValueButton<float> restoreDefaultValueButton = null; RevertToDefaultButton<float> revertToDefaultButton = null;
AddStep("create settings item", () => AddStep("create settings item", () =>
{ {
@ -107,15 +107,15 @@ namespace osu.Game.Tests.Visual.Settings
}; };
}); });
AddUntilStep("wait for loaded", () => sliderBar.IsLoaded); AddUntilStep("wait for loaded", () => sliderBar.IsLoaded);
AddStep("retrieve restore default button", () => restoreDefaultValueButton = sliderBar.ChildrenOfType<RestoreDefaultValueButton<float>>().Single()); AddStep("retrieve restore default button", () => revertToDefaultButton = sliderBar.ChildrenOfType<RevertToDefaultButton<float>>().Single());
AddAssert("restore button hidden", () => restoreDefaultValueButton.Alpha == 0); AddAssert("restore button hidden", () => revertToDefaultButton.Alpha == 0);
AddStep("change value to next closest", () => sliderBar.Current.Value += current.Precision * 0.6f); AddStep("change value to next closest", () => sliderBar.Current.Value += current.Precision * 0.6f);
AddUntilStep("restore button shown", () => restoreDefaultValueButton.Alpha > 0); AddUntilStep("restore button shown", () => revertToDefaultButton.Alpha > 0);
AddStep("restore default", () => sliderBar.Current.SetDefault()); AddStep("restore default", () => sliderBar.Current.SetDefault());
AddUntilStep("restore button hidden", () => restoreDefaultValueButton.Alpha == 0); AddUntilStep("restore button hidden", () => revertToDefaultButton.Alpha == 0);
} }
[Test] [Test]

View File

@ -793,7 +793,7 @@ namespace osu.Game.Tests.Visual.UserInterface
AddStep("open customisation area", () => modSelectOverlay.CustomisationButton!.TriggerClick()); AddStep("open customisation area", () => modSelectOverlay.CustomisationButton!.TriggerClick());
AddStep("reset half time speed to default", () => modSelectOverlay.ChildrenOfType<ModSettingsArea>().Single() AddStep("reset half time speed to default", () => modSelectOverlay.ChildrenOfType<ModSettingsArea>().Single()
.ChildrenOfType<RestoreDefaultValueButton<double>>().Single().TriggerClick()); .ChildrenOfType<RevertToDefaultButton<double>>().Single().TriggerClick());
AddUntilStep("difficulty multiplier display shows correct value", () => modSelectOverlay.ChildrenOfType<DifficultyMultiplierDisplay>().Single().Current.Value, () => Is.EqualTo(0.7)); AddUntilStep("difficulty multiplier display shows correct value", () => modSelectOverlay.ChildrenOfType<DifficultyMultiplierDisplay>().Single().Current.Value, () => Is.EqualTo(0.7));
} }

View File

@ -1,28 +1,25 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osuTK;
using osu.Game.Localisation; using osu.Game.Localisation;
using osuTK;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
public partial class RestoreDefaultValueButton<T> : OsuClickableContainer, IHasCurrentValue<T> public partial class RevertToDefaultButton<T> : OsuClickableContainer, IHasCurrentValue<T>
{ {
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
@ -31,11 +28,20 @@ namespace osu.Game.Overlays
// this is intentionally not using BindableWithCurrent, as it can use the wrong IsDefault implementation when passed a BindableNumber. // this is intentionally not using BindableWithCurrent, as it can use the wrong IsDefault implementation when passed a BindableNumber.
// using GetBoundCopy() ensures that the received bindable is of the exact same type as the source bindable and uses the proper IsDefault implementation. // using GetBoundCopy() ensures that the received bindable is of the exact same type as the source bindable and uses the proper IsDefault implementation.
private Bindable<T> current; private Bindable<T>? current;
private SpriteIcon icon = null!;
private Circle circle = null!;
[Resolved]
private OsuColour colours { get; set; } = null!;
[Resolved]
private OverlayColourProvider? colourProvider { get; set; }
public Bindable<T> Current public Bindable<T> Current
{ {
get => current; get => current.AsNonNull();
set set
{ {
current?.UnbindAll(); current?.UnbindAll();
@ -50,43 +56,36 @@ namespace osu.Game.Overlays
} }
} }
[Resolved] public RevertToDefaultButton()
private OsuColour colours { get; set; }
private const float size = 4;
private CircularContainer circle = null!;
private Box background = null!;
public RestoreDefaultValueButton()
: base(HoverSampleSet.Button) : base(HoverSampleSet.Button)
{ {
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colour) private void load()
{ {
// size intentionally much larger than actual drawn content, so that the button is easier to click. Size = new Vector2(14);
Size = new Vector2(3 * size);
Add(circle = new CircularContainer AddRange(new Drawable[]
{ {
Anchor = Anchor.Centre, circle = new Circle
Origin = Anchor.Centre,
Size = new Vector2(size),
Masking = true,
Child = background = new Box
{ {
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = colour.Lime1 },
icon = new SpriteIcon
{
Icon = FontAwesome.Solid.Undo,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(8),
} }
}); });
Alpha = 0f;
Action += () => Action += () =>
{ {
if (!current.Disabled) if (current?.Disabled == false)
current.SetDefault(); current.SetDefault();
}; };
} }
@ -120,28 +119,25 @@ namespace osu.Game.Overlays
if (current == null) if (current == null)
return; return;
Enabled.Value = !Current.Disabled; Enabled.Value = !current.Disabled;
if (!Current.Disabled) this.FadeTo(current.Disabled ? 0.2f : (current.IsDefault ? 0 : 1), fade_duration, Easing.OutQuint);
if (IsHovered && Enabled.Value)
{ {
this.FadeTo(Current.IsDefault ? 0 : 1, fade_duration, Easing.OutQuint); icon.RotateTo(-40, 500, Easing.OutQuint);
background.FadeColour(IsHovered ? colours.Lime0 : colours.Lime1, fade_duration, Easing.OutQuint);
circle.TweenEdgeEffectTo(new EdgeEffectParameters icon.FadeColour(colourProvider?.Light1 ?? colours.YellowLight, 300, Easing.OutQuint);
{ circle.FadeColour(colourProvider?.Background2 ?? colours.Gray6, 300, Easing.OutQuint);
Colour = (IsHovered ? colours.Lime1 : colours.Lime3).Opacity(0.4f), this.ScaleTo(1.2f, 300, Easing.OutQuint);
Radius = IsHovered ? 8 : 4,
Type = EdgeEffectType.Glow
}, fade_duration, Easing.OutQuint);
} }
else else
{ {
background.FadeColour(colours.Lime3, fade_duration, Easing.OutQuint); icon.RotateTo(0, 100, Easing.OutQuint);
circle.TweenEdgeEffectTo(new EdgeEffectParameters
{ icon.FadeColour(colourProvider?.Colour0 ?? colours.Yellow, 100, Easing.OutQuint);
Colour = colours.Lime3.Opacity(0.1f), circle.FadeColour(colourProvider?.Background3 ?? colours.Gray3, 100, Easing.OutQuint);
Radius = 2, this.ScaleTo(1f, 100, Easing.OutQuint);
Type = EdgeEffectType.Glow
}, fade_duration, Easing.OutQuint);
} }
} }
} }

View File

@ -103,7 +103,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Width = SettingsPanel.CONTENT_MARGINS, Width = SettingsPanel.CONTENT_MARGINS,
Child = new RestoreDefaultValueButton<bool> Child = new RevertToDefaultButton<bool>
{ {
Current = isDefault, Current = isDefault,
Action = RestoreDefaults, Action = RestoreDefaults,

View File

@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Settings
// intentionally done before LoadComplete to avoid overhead. // intentionally done before LoadComplete to avoid overhead.
if (ShowsDefaultIndicator) if (ShowsDefaultIndicator)
{ {
defaultValueIndicatorContainer.Add(new RestoreDefaultValueButton<T> defaultValueIndicatorContainer.Add(new RevertToDefaultButton<T>
{ {
Current = controlWithCurrent.Current, Current = controlWithCurrent.Current,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,