mirror of
https://github.com/ppy/osu.git
synced 2025-03-16 22:17:19 +08:00
Merge branch 'ppy:master' into gameplay-leaderboard-fix
This commit is contained in:
commit
9ad484a0f4
osu.Game.Tests/Visual/Settings
osu.Game
Overlays/Settings/Sections/Input
Screens/Edit/Compose/Components/Timeline
@ -40,6 +40,43 @@ namespace osu.Game.Tests.Visual.Settings
|
|||||||
AddWaitStep("wait for scroll", 5);
|
AddWaitStep("wait for scroll", 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBindingTwoNonModifiers()
|
||||||
|
{
|
||||||
|
AddStep("press j", () => InputManager.PressKey(Key.J));
|
||||||
|
scrollToAndStartBinding("Increase volume");
|
||||||
|
AddStep("press k", () => InputManager.Key(Key.K));
|
||||||
|
AddStep("release j", () => InputManager.ReleaseKey(Key.J));
|
||||||
|
checkBinding("Increase volume", "K");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBindingSingleKey()
|
||||||
|
{
|
||||||
|
scrollToAndStartBinding("Increase volume");
|
||||||
|
AddStep("press k", () => InputManager.Key(Key.K));
|
||||||
|
checkBinding("Increase volume", "K");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBindingSingleModifier()
|
||||||
|
{
|
||||||
|
scrollToAndStartBinding("Increase volume");
|
||||||
|
AddStep("press shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||||
|
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||||
|
checkBinding("Increase volume", "LShift");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBindingSingleKeyWithModifier()
|
||||||
|
{
|
||||||
|
scrollToAndStartBinding("Increase volume");
|
||||||
|
AddStep("press shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||||
|
AddStep("press k", () => InputManager.Key(Key.K));
|
||||||
|
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||||
|
checkBinding("Increase volume", "LShift-K");
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestBindingMouseWheelToNonGameplay()
|
public void TestBindingMouseWheelToNonGameplay()
|
||||||
{
|
{
|
||||||
@ -169,7 +206,8 @@ namespace osu.Game.Tests.Visual.Settings
|
|||||||
|
|
||||||
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha == 0);
|
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha == 0);
|
||||||
|
|
||||||
AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));
|
AddAssert("binding cleared",
|
||||||
|
() => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -198,7 +236,8 @@ namespace osu.Game.Tests.Visual.Settings
|
|||||||
|
|
||||||
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha == 0);
|
AddUntilStep("restore button hidden", () => settingsKeyBindingRow.ChildrenOfType<RestoreDefaultValueButton<bool>>().First().Alpha == 0);
|
||||||
|
|
||||||
AddAssert("binding cleared", () => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));
|
AddAssert("binding cleared",
|
||||||
|
() => settingsKeyBindingRow.ChildrenOfType<KeyBindingRow.KeyButton>().ElementAt(0).KeyBinding.KeyCombination.Equals(settingsKeyBindingRow.Defaults.ElementAt(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -256,8 +295,8 @@ namespace osu.Game.Tests.Visual.Settings
|
|||||||
var firstRow = panel.ChildrenOfType<KeyBindingRow>().First(r => r.ChildrenOfType<OsuSpriteText>().Any(s => s.Text.ToString() == name));
|
var firstRow = panel.ChildrenOfType<KeyBindingRow>().First(r => r.ChildrenOfType<OsuSpriteText>().Any(s => s.Text.ToString() == name));
|
||||||
var firstButton = firstRow.ChildrenOfType<KeyBindingRow.KeyButton>().First();
|
var firstButton = firstRow.ChildrenOfType<KeyBindingRow.KeyButton>().First();
|
||||||
|
|
||||||
return firstButton.Text.Text == keyName;
|
return firstButton.Text.Text.ToString();
|
||||||
});
|
}, () => Is.EqualTo(keyName));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scrollToAndStartBinding(string name)
|
private void scrollToAndStartBinding(string name)
|
||||||
|
@ -33,6 +33,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
public class KeyBindingRow : Container, IFilterable
|
public class KeyBindingRow : Container, IFilterable
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Invoked when the binding of this row is updated with a change being written.
|
||||||
|
/// </summary>
|
||||||
|
public Action<KeyBindingRow> BindingUpdated { get; set; }
|
||||||
|
|
||||||
private readonly object action;
|
private readonly object action;
|
||||||
private readonly IEnumerable<RealmKeyBinding> bindings;
|
private readonly IEnumerable<RealmKeyBinding> bindings;
|
||||||
|
|
||||||
@ -153,7 +158,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
Spacing = new Vector2(5),
|
Spacing = new Vector2(5),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new CancelButton { Action = finalise },
|
new CancelButton { Action = () => finalise(false) },
|
||||||
new ClearButton { Action = clear },
|
new ClearButton { Action = clear },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -226,7 +231,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromMouseButton(e.Button));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +245,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bindTarget.IsHovered)
|
if (bindTarget.IsHovered)
|
||||||
finalise();
|
finalise(false);
|
||||||
// prevent updating bind target before clear button's action
|
// prevent updating bind target before clear button's action
|
||||||
else if (!cancelAndClearButtons.Any(b => b.IsHovered))
|
else if (!cancelAndClearButtons.Any(b => b.IsHovered))
|
||||||
updateBindTarget();
|
updateBindTarget();
|
||||||
@ -252,7 +257,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
if (bindTarget.IsHovered)
|
if (bindTarget.IsHovered)
|
||||||
{
|
{
|
||||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState, e.ScrollDelta));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState, e.ScrollDelta), KeyCombination.FromScrollDelta(e.ScrollDelta).First());
|
||||||
finalise();
|
finalise();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -263,10 +268,10 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
|
|
||||||
protected override bool OnKeyDown(KeyDownEvent e)
|
protected override bool OnKeyDown(KeyDownEvent e)
|
||||||
{
|
{
|
||||||
if (!HasFocus)
|
if (!HasFocus || e.Repeat)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromKey(e.Key));
|
||||||
if (!isModifier(e.Key)) finalise();
|
if (!isModifier(e.Key)) finalise();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -288,7 +293,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
if (!HasFocus)
|
if (!HasFocus)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromJoystickButton(e.Button));
|
||||||
finalise();
|
finalise();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -310,7 +315,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
if (!HasFocus)
|
if (!HasFocus)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromMidiKey(e.Key));
|
||||||
finalise();
|
finalise();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -332,7 +337,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
if (!HasFocus)
|
if (!HasFocus)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromTabletAuxiliaryButton(e.Button));
|
||||||
finalise();
|
finalise();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -354,7 +359,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
if (!HasFocus)
|
if (!HasFocus)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState));
|
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState), KeyCombination.FromTabletPenButton(e.Button));
|
||||||
finalise();
|
finalise();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -377,10 +382,10 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bindTarget.UpdateKeyCombination(InputKey.None);
|
bindTarget.UpdateKeyCombination(InputKey.None);
|
||||||
finalise();
|
finalise(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finalise()
|
private void finalise(bool hasChanged = true)
|
||||||
{
|
{
|
||||||
if (bindTarget != null)
|
if (bindTarget != null)
|
||||||
{
|
{
|
||||||
@ -393,6 +398,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
// schedule to ensure we don't instantly get focus back on next OnMouseClick (see AcceptFocus impl.)
|
// schedule to ensure we don't instantly get focus back on next OnMouseClick (see AcceptFocus impl.)
|
||||||
bindTarget = null;
|
bindTarget = null;
|
||||||
|
if (hasChanged)
|
||||||
|
BindingUpdated?.Invoke(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +424,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
|
|
||||||
protected override void OnFocusLost(FocusLostEvent e)
|
protected override void OnFocusLost(FocusLostEvent e)
|
||||||
{
|
{
|
||||||
finalise();
|
finalise(false);
|
||||||
base.OnFocusLost(e);
|
base.OnFocusLost(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,6 +570,14 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update from a key combination, only allowing a single non-modifier key to be specified.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullState">A <see cref="KeyCombination"/> generated from the full input state.</param>
|
||||||
|
/// <param name="triggerKey">The key which triggered this update, and should be used as the binding.</param>
|
||||||
|
public void UpdateKeyCombination(KeyCombination fullState, InputKey triggerKey) =>
|
||||||
|
UpdateKeyCombination(new KeyCombination(fullState.Keys.Where(KeyCombination.IsModifierKey).Append(triggerKey)));
|
||||||
|
|
||||||
public void UpdateKeyCombination(KeyCombination newCombination)
|
public void UpdateKeyCombination(KeyCombination newCombination)
|
||||||
{
|
{
|
||||||
if (KeyBinding.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination))
|
if (KeyBinding.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination))
|
||||||
|
@ -19,6 +19,12 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
public abstract class KeyBindingsSubsection : SettingsSubsection
|
public abstract class KeyBindingsSubsection : SettingsSubsection
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// After a successful binding, automatically select the next binding row to make quickly
|
||||||
|
/// binding a large set of keys easier on the user.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual bool AutoAdvanceTarget => false;
|
||||||
|
|
||||||
protected IEnumerable<Framework.Input.Bindings.KeyBinding> Defaults;
|
protected IEnumerable<Framework.Input.Bindings.KeyBinding> Defaults;
|
||||||
|
|
||||||
public RulesetInfo Ruleset { get; protected set; }
|
public RulesetInfo Ruleset { get; protected set; }
|
||||||
@ -49,7 +55,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
Add(new KeyBindingRow(defaultGroup.Key, bindings.Where(b => b.ActionInt.Equals(intKey)).ToList())
|
Add(new KeyBindingRow(defaultGroup.Key, bindings.Where(b => b.ActionInt.Equals(intKey)).ToList())
|
||||||
{
|
{
|
||||||
AllowMainMouseButtons = Ruleset != null,
|
AllowMainMouseButtons = Ruleset != null,
|
||||||
Defaults = defaultGroup.Select(d => d.KeyCombination)
|
Defaults = defaultGroup.Select(d => d.KeyCombination),
|
||||||
|
BindingUpdated = onBindingUpdated
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +65,16 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
Action = () => Children.OfType<KeyBindingRow>().ForEach(k => k.RestoreDefaults())
|
Action = () => Children.OfType<KeyBindingRow>().ForEach(k => k.RestoreDefaults())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onBindingUpdated(KeyBindingRow sender)
|
||||||
|
{
|
||||||
|
if (AutoAdvanceTarget)
|
||||||
|
{
|
||||||
|
var next = Children.SkipWhile(c => c != sender).Skip(1).FirstOrDefault();
|
||||||
|
if (next != null)
|
||||||
|
GetContainingInputManager().ChangeFocus(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ResetButton : DangerousSettingsButton
|
public class ResetButton : DangerousSettingsButton
|
||||||
|
@ -8,6 +8,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
public class VariantBindingsSubsection : KeyBindingsSubsection
|
public class VariantBindingsSubsection : KeyBindingsSubsection
|
||||||
{
|
{
|
||||||
|
protected override bool AutoAdvanceTarget => true;
|
||||||
|
|
||||||
protected override LocalisableString Header { get; }
|
protected override LocalisableString Header { get; }
|
||||||
|
|
||||||
public VariantBindingsSubsection(RulesetInfo ruleset, int variant)
|
public VariantBindingsSubsection(RulesetInfo ruleset, int variant)
|
||||||
|
@ -436,8 +436,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
{
|
{
|
||||||
base.OnDragEnd(e);
|
base.OnDragEnd(e);
|
||||||
|
|
||||||
OnDragHandled?.Invoke(null);
|
dragOperation?.Cancel();
|
||||||
|
dragOperation = null;
|
||||||
|
|
||||||
changeHandler?.EndChange();
|
changeHandler?.EndChange();
|
||||||
|
OnDragHandled?.Invoke(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user