1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 01:27:29 +08:00

Well it works, just pretty ugly looking.

This commit is contained in:
Swords 2021-05-15 01:01:17 +10:00
parent 1a465c60ca
commit 0725088fde
7 changed files with 299 additions and 156 deletions

View File

@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Input.Bindings;
using osu.Framework.Testing;
using osu.Framework.Threading;
using osu.Game.Overlays;
@ -31,13 +32,16 @@ namespace osu.Game.Tests.Visual.Settings
[Test]
public void TestClickTwiceOnClearButton()
{
SettingsKeyBindingRow firstSettingRow = null;
KeyBindingRow firstRow = null;
AddStep("click first row", () =>
{
firstRow = panel.ChildrenOfType<KeyBindingRow>().First();
InputManager.MoveMouseTo(firstRow);
firstSettingRow = panel.ChildrenOfType<SettingsKeyBindingRow>().First();
InputManager.MoveMouseTo(firstSettingRow);
InputManager.Click(MouseButton.Left);
firstRow = firstSettingRow.KeyBindingRow;
});
AddStep("schedule button clicks", () =>
@ -71,7 +75,7 @@ namespace osu.Game.Tests.Visual.Settings
AddStep("click first row with two bindings", () =>
{
multiBindingRow = panel.ChildrenOfType<KeyBindingRow>().First(row => row.Defaults.Count() > 1);
multiBindingRow = panel.ChildrenOfType<SettingsKeyBindingRow>().First(row => row.KeyBindingRow.Defaults.Count() > 1).KeyBindingRow;
InputManager.MoveMouseTo(multiBindingRow);
InputManager.Click(MouseButton.Left);
});
@ -105,38 +109,67 @@ namespace osu.Game.Tests.Visual.Settings
}
[Test]
public void TestResetButtonOnBindings()
public void TestSingleBindResetButton()
{
SettingsKeyBindingRow multiSettingsBindingRow = null;
KeyBindingRow multiBindingRow = null;
AddStep("click first row with two bindings", () =>
{
multiSettingsBindingRow = panel.ChildrenOfType<SettingsKeyBindingRow>().First(row => row.KeyBindingRow.Defaults.Count() > 1);
multiBindingRow = panel.ChildrenOfType<KeyBindingRow>().First(row => row.Defaults.Count() > 1);
InputManager.MoveMouseTo(multiBindingRow);
InputManager.Click(MouseButton.Left);
InputManager.PressKey(Key.P);
InputManager.ReleaseKey(Key.P);
});
AddUntilStep("restore button shown", () => multiSettingsBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha > 0);
clickSingleBindResetButton();
AddAssert("first binding cleared", () => multiBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(multiBindingRow.Defaults.ElementAt(0)));
AddStep("click second binding", () =>
{
var target = multiBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(1);
InputManager.MoveMouseTo(target);
InputManager.Click(MouseButton.Left);
});
clickSingleBindResetButton();
AddAssert("second binding cleared", () => multiBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(1).KeyBinding.KeyCombination.Equals(multiBindingRow.Defaults.ElementAt(1)));
AddUntilStep("restore button hidden", () => multiSettingsBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha == 0);
void clickSingleBindResetButton()
{
AddStep("click reset button for single binding", () =>
AddStep("click reset button for bindings", () =>
{
var clearButton = multiBindingRow.ChildrenOfType<KeyBindingRow.SingleBindResetButton>().Single();
var clearButton = multiSettingsBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().Single();
InputManager.MoveMouseTo(clearButton);
InputManager.Click(MouseButton.Left);
});
}
}
[Test]
public void TestResetAllBindingsButton()
{
SettingsKeyBindingRow multiSettingsBindingRow = null;
KeyBindingRow multiBindingRow = null;
AddStep("click first row and press p", () =>
{
multiSettingsBindingRow = panel.ChildrenOfType<SettingsKeyBindingRow>().First(row => row.KeyBindingRow.Defaults.Count() > 1);
multiBindingRow = panel.ChildrenOfType<KeyBindingRow>().First();
InputManager.MoveMouseTo(multiBindingRow);
InputManager.Click(MouseButton.Left);
InputManager.PressKey(Key.P);
InputManager.ReleaseKey(Key.P);
});
clickResetAllBindingsButton();
AddAssert("bindings cleared", () => multiBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(multiBindingRow.Defaults.ElementAt(0)));
void clickResetAllBindingsButton()
{
AddStep("click reset button for all bindings", () =>
{
var clearButton = panel.ChildrenOfType<ResetButton>().First();
InputManager.MoveMouseTo(clearButton);
InputManager.Click(MouseButton.Left);
@ -176,4 +209,4 @@ namespace osu.Game.Tests.Visual.Settings
AddAssert("first binding selected", () => multiBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().First().IsBinding);
}
}
}
}

View File

@ -7,6 +7,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Overlays.Settings;
using osu.Game.Overlays;
namespace osu.Game.Tests.Visual.Settings
{
@ -37,7 +38,7 @@ namespace osu.Game.Tests.Visual.Settings
private class TestSettingsTextBox : SettingsTextBox
{
public new Drawable RestoreDefaultValueButton => this.ChildrenOfType<RestoreDefaultValueButton>().Single();
public Drawable RestoreDefaultValueButton => this.ChildrenOfType<RestoreDefaultValueButton<string>>().Single();
}
}
}
}

View File

@ -4,12 +4,14 @@
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
@ -22,7 +24,7 @@ using osuTK.Input;
namespace osu.Game.Overlays.KeyBinding
{
public class KeyBindingRow : Container, IFilterable
public class KeyBindingRow : Container, IFilterable, IHasCurrentValue<bool>
{
private readonly object action;
private readonly IEnumerable<Framework.Input.Bindings.KeyBinding> bindings;
@ -51,6 +53,13 @@ namespace osu.Game.Overlays.KeyBinding
private FillFlowContainer cancelAndClearButtons;
private FillFlowContainer<KeyButton> buttons;
private BindableWithCurrent<bool> isKeysDefaultValue;
public Bindable<bool> Current
{
get => isKeysDefaultValue.Current;
set => isKeysDefaultValue.Current = value;
}
public IEnumerable<string> FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend(text.Text.ToString());
public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings)
@ -58,6 +67,11 @@ namespace osu.Game.Overlays.KeyBinding
this.action = action;
this.bindings = bindings;
isKeysDefaultValue = new BindableWithCurrent<bool>()
{
Default = true
};
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
@ -71,6 +85,17 @@ namespace osu.Game.Overlays.KeyBinding
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
isKeysDefaultValue.Value = bindings.Select(b => b.KeyCombination).SequenceEqual(Defaults);
isKeysDefaultValue.BindValueChanged(resetButtons =>
{
if (resetButtons.NewValue != resetButtons.OldValue && resetButtons.NewValue && !bindings.Select(b => b.KeyCombination).SequenceEqual(Defaults))
{
RestoreDefaults();
finalise();
}
});
EdgeEffect = new EdgeEffectParameters
{
Radius = 2,
@ -109,7 +134,6 @@ namespace osu.Game.Overlays.KeyBinding
Children = new Drawable[]
{
new CancelButton { Action = finalise },
new SingleBindResetButton { Action = singleBindReset },
new ClearButton { Action = clear },
},
}
@ -129,6 +153,8 @@ namespace osu.Game.Overlays.KeyBinding
button.UpdateKeyCombination(d);
store.Update(button.KeyBinding);
}
isKeysDefaultValue.Value = true;
}
protected override bool OnHover(HoverEvent e)
@ -282,21 +308,29 @@ namespace osu.Game.Overlays.KeyBinding
finalise();
}
private void singleBindReset()
{
if (bindTarget == null)
return;
bindTarget.UpdateKeyCombination(Defaults.ElementAt(buttons.IndexOf(bindTarget)));
finalise();
}
private void finalise()
{
if (bindTarget != null)
{
store.Update(bindTarget.KeyBinding);
KeyCombination keyDefault = Defaults.ElementAt(buttons.IndexOf(bindTarget));
if (isKeysDefaultValue.Value)
{
if (!keyDefault.Equals(bindTarget.KeyBinding.KeyCombination))
{
isKeysDefaultValue.Value = false;
}
}
else
{
if (keyDefault.Equals(bindTarget.KeyBinding.KeyCombination) &&
buttons.Select(b => b.KeyBinding.KeyCombination).SequenceEqual(Defaults))
{
isKeysDefaultValue.Value = true;
}
}
bindTarget.IsBinding = false;
Schedule(() =>
{
@ -349,24 +383,6 @@ namespace osu.Game.Overlays.KeyBinding
}
}
public class SingleBindResetButton : TriangleButton
{
public SingleBindResetButton()
{
Text = "Reset";
Size = new Vector2(80, 20);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
BackgroundColour = colours.Green;
Triangles.ColourDark = colours.GreenDark;
Triangles.ColourLight = colours.GreenLight;
}
}
public class ClearButton : TriangleButton
{
public ClearButton()
@ -487,4 +503,4 @@ namespace osu.Game.Overlays.KeyBinding
}
}
}
}
}

View File

@ -1,17 +1,20 @@
// 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 System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input;
using osu.Game.Overlays.Settings;
using osu.Game.Rulesets;
using osuTK;
using osu.Game.Graphics;
using osu.Framework.Input.Bindings;
namespace osu.Game.Overlays.KeyBinding
{
@ -41,16 +44,12 @@ namespace osu.Game.Overlays.KeyBinding
int intKey = (int)defaultGroup.Key;
// one row per valid action.
Add(new KeyBindingRow(defaultGroup.Key, bindings.Where(b => ((int)b.Action).Equals(intKey)))
{
AllowMainMouseButtons = Ruleset != null,
Defaults = defaultGroup.Select(d => d.KeyCombination)
});
Add(new SettingsKeyBindingRow(defaultGroup, bindings, Ruleset));
}
Add(new ResetButton
{
Action = () => Children.OfType<KeyBindingRow>().ForEach(k => k.RestoreDefaults())
Action = () => Children.OfType<SettingsKeyBindingRow>().ForEach(k => k.KeyBindingRow.RestoreDefaults())
});
}
}
@ -72,4 +71,4 @@ namespace osu.Game.Overlays.KeyBinding
Triangles.ColourLight = colours.Pink;
}
}
}
}

View File

@ -0,0 +1,70 @@
// 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.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets;
namespace osu.Game.Overlays.KeyBinding
{
public class SettingsKeyBindingRow : Container, IFilterable
{
private readonly IGrouping<object, Framework.Input.Bindings.KeyBinding> defaultGroup;
private readonly IEnumerable<Framework.Input.Bindings.KeyBinding> bindings;
public readonly KeyBindingRow KeyBindingRow;
private bool matchingFilter;
public bool MatchingFilter
{
get => matchingFilter;
set
{
matchingFilter = value;
this.FadeTo(!matchingFilter ? 0 : 1);
}
}
public bool FilteringActive { get; set; }
public IEnumerable<string> FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend(defaultGroup.Key.ToString());
public SettingsKeyBindingRow(
IGrouping<object, Framework.Input.Bindings.KeyBinding> defaultGroup,
IEnumerable<Framework.Input.Bindings.KeyBinding> bindings,
RulesetInfo ruleset)
{
this.defaultGroup = defaultGroup;
this.bindings = bindings;
KeyBindingRow = new KeyBindingRow(defaultGroup.Key, bindings.Where(b => ((int)b.Action).Equals((int)defaultGroup.Key)))
{
AllowMainMouseButtons = ruleset != null,
Defaults = defaultGroup.Select(d => d.KeyCombination)
};
RestoreDefaultValueButton<bool> restoreDefaultButton;
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Padding = new MarginPadding { Right = SettingsPanel.CONTENT_MARGINS };
InternalChildren = new Drawable[]
{
restoreDefaultButton = new RestoreDefaultValueButton<bool>(),
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS },
Child = KeyBindingRow
},
};
restoreDefaultButton.Bindable = KeyBindingRow.Current;
}
}
}

View File

@ -0,0 +1,119 @@
// 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 osuTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Overlays
{
public class RestoreDefaultValueButton<T> : Container, IHasTooltip
{
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
private Bindable<T> bindable;
public Bindable<T> Bindable
{
get => bindable;
set
{
bindable = value;
bindable.ValueChanged += _ => UpdateState();
bindable.DisabledChanged += _ => UpdateState();
bindable.DefaultChanged += _ => UpdateState();
UpdateState();
}
}
private Color4 buttonColour;
private bool hovering;
public RestoreDefaultValueButton()
{
RelativeSizeAxes = Axes.Y;
Width = SettingsPanel.CONTENT_MARGINS;
Alpha = 0f;
}
[BackgroundDependencyLoader]
private void load(OsuColour colour)
{
buttonColour = colour.Yellow;
Child = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
CornerRadius = 3,
Masking = true,
Colour = buttonColour,
EdgeEffect = new EdgeEffectParameters
{
Colour = buttonColour.Opacity(0.1f),
Type = EdgeEffectType.Glow,
Radius = 2,
},
Size = new Vector2(0.33f, 0.8f),
Child = new Box { RelativeSizeAxes = Axes.Both },
};
}
protected override void LoadComplete()
{
base.LoadComplete();
UpdateState();
}
public string TooltipText => "revert to default";
protected override bool OnClick(ClickEvent e)
{
if (bindable != null && !bindable.Disabled)
bindable.SetDefault();
return true;
}
protected override bool OnHover(HoverEvent e)
{
hovering = true;
UpdateState();
return false;
}
protected override void OnHoverLost(HoverLostEvent e)
{
hovering = false;
UpdateState();
}
public void SetButtonColour(Color4 buttonColour)
{
this.buttonColour = buttonColour;
UpdateState();
}
public void UpdateState() => Scheduler.AddOnce(updateState);
private void updateState()
{
if (bindable == null)
return;
this.FadeTo(bindable.IsDefault ? 0f :
hovering && !bindable.Disabled ? 1f : 0.65f, 200, Easing.OutQuint);
this.FadeColour(bindable.Disabled ? Color4.Gray : buttonColour, 200, Easing.OutQuint);
}
}
}

View File

@ -108,7 +108,8 @@ namespace osu.Game.Overlays.Settings
protected SettingsItem()
{
RestoreDefaultValueButton restoreDefaultButton;
RestoreDefaultValueButton<T> restoreDefaultButton;
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
@ -116,7 +117,7 @@ namespace osu.Game.Overlays.Settings
InternalChildren = new Drawable[]
{
restoreDefaultButton = new RestoreDefaultValueButton(),
restoreDefaultButton = new RestoreDefaultValueButton<T>(),
FlowContent = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
@ -146,101 +147,5 @@ namespace osu.Game.Overlays.Settings
if (labelText != null)
labelText.Alpha = controlWithCurrent.Current.Disabled ? 0.3f : 1;
}
protected internal class RestoreDefaultValueButton : Container, IHasTooltip
{
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
private Bindable<T> bindable;
public Bindable<T> Bindable
{
get => bindable;
set
{
bindable = value;
bindable.ValueChanged += _ => UpdateState();
bindable.DisabledChanged += _ => UpdateState();
bindable.DefaultChanged += _ => UpdateState();
UpdateState();
}
}
private Color4 buttonColour;
private bool hovering;
public RestoreDefaultValueButton()
{
RelativeSizeAxes = Axes.Y;
Width = SettingsPanel.CONTENT_MARGINS;
Padding = new MarginPadding { Vertical = 1.5f };
Alpha = 0f;
}
[BackgroundDependencyLoader]
private void load(OsuColour colour)
{
buttonColour = colour.Yellow;
Child = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
CornerRadius = 3,
Masking = true,
Colour = buttonColour,
EdgeEffect = new EdgeEffectParameters
{
Colour = buttonColour.Opacity(0.1f),
Type = EdgeEffectType.Glow,
Radius = 2,
},
Width = 0.33f,
Child = new Box { RelativeSizeAxes = Axes.Both },
};
}
protected override void LoadComplete()
{
base.LoadComplete();
UpdateState();
}
public string TooltipText => "revert to default";
protected override bool OnClick(ClickEvent e)
{
if (bindable != null && !bindable.Disabled)
bindable.SetDefault();
return true;
}
protected override bool OnHover(HoverEvent e)
{
hovering = true;
UpdateState();
return false;
}
protected override void OnHoverLost(HoverLostEvent e)
{
hovering = false;
UpdateState();
}
public void UpdateState() => Scheduler.AddOnce(updateState);
private void updateState()
{
if (bindable == null)
return;
this.FadeTo(bindable.IsDefault ? 0f :
hovering && !bindable.Disabled ? 1f : 0.65f, 200, Easing.OutQuint);
this.FadeColour(bindable.Disabled ? Color4.Gray : buttonColour, 200, Easing.OutQuint);
}
}
}
}
}