mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-01 05:10:50 +01:00
added a more generic keybind and input handling system
This commit is contained in:
parent
601423407d
commit
251261f3d7
6 changed files with 268 additions and 67 deletions
|
@ -32,9 +32,9 @@ namespace MLEM.Ui.Elements {
|
||||||
base.Update(time);
|
base.Update(time);
|
||||||
|
|
||||||
if (this.IsSelected) {
|
if (this.IsSelected) {
|
||||||
if (this.Controls.LeftButtons.Any(b => this.Input.IsPressed(b, this.Controls.GamepadIndex))) {
|
if (this.Controls.LeftButtons.IsPressed(this.Input, this.Controls.GamepadIndex)) {
|
||||||
this.CurrentValue -= this.StepPerScroll;
|
this.CurrentValue -= this.StepPerScroll;
|
||||||
} else if (this.Controls.RightButtons.Any(b => this.Input.IsPressed(b, this.Controls.GamepadIndex))) {
|
} else if (this.Controls.RightButtons.IsPressed(this.Input, this.Controls.GamepadIndex)) {
|
||||||
this.CurrentValue += this.StepPerScroll;
|
this.CurrentValue += this.StepPerScroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,39 +54,32 @@ namespace MLEM.Ui {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons on the keyboard which perform the <see cref="Element.OnPressed"/> action.
|
/// A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons on the keyboard which perform the <see cref="Element.OnPressed"/> action.
|
||||||
/// If the <see cref="ModifierKey.Shift"/> is held, these buttons perform <see cref="Element.OnSecondaryPressed"/>.
|
/// If the <see cref="ModifierKey.Shift"/> is held, these buttons perform <see cref="Element.OnSecondaryPressed"/>.
|
||||||
/// To easily add more elements to this list, use <see cref="AddButtons"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object[] KeyboardButtons = {Keys.Space, Keys.Enter};
|
public readonly Keybind KeyboardButtons = new Keybind().Add(Keys.Space).Add(Keys.Enter);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons on a gamepad that perform the <see cref="Element.OnPressed"/> action.
|
/// AA <see cref="Keybind"/> that acts as the buttons on a gamepad that perform the <see cref="Element.OnPressed"/> action.
|
||||||
/// To easily add more elements to this list, use <see cref="AddButtons"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object[] GamepadButtons = {Buttons.A};
|
public readonly Keybind GamepadButtons = new Keybind().Add(Buttons.A);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons on a gamepad that perform the <see cref="Element.OnSecondaryPressed"/> action.
|
/// A <see cref="Keybind"/> that acts as the buttons on a gamepad that perform the <see cref="Element.OnSecondaryPressed"/> action.
|
||||||
/// To easily add more elements to this list, use <see cref="AddButtons"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object[] SecondaryGamepadButtons = {Buttons.X};
|
public readonly Keybind SecondaryGamepadButtons = new Keybind().Add(Buttons.X);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons that select a <see cref="Element"/> that is above the currently selected element.
|
/// A <see cref="Keybind"/> that acts as the buttons that select a <see cref="Element"/> that is above the currently selected element.
|
||||||
/// To easily add more elements to this list, use <see cref="AddButtons"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object[] UpButtons = {Buttons.DPadUp, Buttons.LeftThumbstickUp};
|
public readonly Keybind UpButtons = new Keybind().Add(Buttons.DPadUp).Add(Buttons.LeftThumbstickUp);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons that select a <see cref="Element"/> that is below the currently selected element.
|
/// A <see cref="Keybind"/> that acts as the buttons that select a <see cref="Element"/> that is below the currently selected element.
|
||||||
/// To easily add more elements to this list, use <see cref="AddButtons"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object[] DownButtons = {Buttons.DPadDown, Buttons.LeftThumbstickDown};
|
public readonly Keybind DownButtons = new Keybind().Add(Buttons.DPadDown).Add(Buttons.LeftThumbstickDown);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons that select a <see cref="Element"/> that is to the left of the currently selected element.
|
/// A <see cref="Keybind"/> that acts as the buttons that select a <see cref="Element"/> that is to the left of the currently selected element.
|
||||||
/// To easily add more elements to this list, use <see cref="AddButtons"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object[] LeftButtons = {Buttons.DPadLeft, Buttons.LeftThumbstickLeft};
|
public readonly Keybind LeftButtons = new Keybind().Add(Buttons.DPadLeft).Add(Buttons.LeftThumbstickLeft);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of A list of <see cref="Keys"/>, <see cref="Buttons"/> and/or <see cref="MouseButton"/> that act as the buttons that select a <see cref="Element"/> that is to the right of the currently selected element.
|
/// A <see cref="Keybind"/> that acts as the buttons that select a <see cref="Element"/> that is to the right of the currently selected element.
|
||||||
/// To easily add more elements to this list, use <see cref="AddButtons"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object[] RightButtons = {Buttons.DPadRight, Buttons.LeftThumbstickRight};
|
public readonly Keybind RightButtons = new Keybind().Add(Buttons.DPadRight).Add(Buttons.LeftThumbstickRight);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The zero-based index of the <see cref="GamePad"/> used for gamepad input.
|
/// The zero-based index of the <see cref="GamePad"/> used for gamepad input.
|
||||||
/// If this index is lower than 0, every connected gamepad will trigger input.
|
/// If this index is lower than 0, every connected gamepad will trigger input.
|
||||||
|
@ -162,7 +155,7 @@ namespace MLEM.Ui {
|
||||||
|
|
||||||
// KEYBOARD INPUT
|
// KEYBOARD INPUT
|
||||||
if (this.HandleKeyboard) {
|
if (this.HandleKeyboard) {
|
||||||
if (this.KeyboardButtons.Any(this.IsAnyPressed)) {
|
if (this.KeyboardButtons.IsPressed(this.Input, this.GamepadIndex)) {
|
||||||
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed) {
|
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed) {
|
||||||
if (this.Input.IsModifierKeyDown(ModifierKey.Shift)) {
|
if (this.Input.IsModifierKeyDown(ModifierKey.Shift)) {
|
||||||
// secondary action on element using space or enter
|
// secondary action on element using space or enter
|
||||||
|
@ -215,19 +208,19 @@ namespace MLEM.Ui {
|
||||||
|
|
||||||
// GAMEPAD INPUT
|
// GAMEPAD INPUT
|
||||||
if (this.HandleGamepad) {
|
if (this.HandleGamepad) {
|
||||||
if (this.GamepadButtons.Any(this.IsAnyPressed)) {
|
if (this.GamepadButtons.IsPressed(this.Input, this.GamepadIndex)) {
|
||||||
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed)
|
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed)
|
||||||
this.System.OnElementPressed?.Invoke(this.SelectedElement);
|
this.System.OnElementPressed?.Invoke(this.SelectedElement);
|
||||||
} else if (this.SecondaryGamepadButtons.Any(this.IsAnyPressed)) {
|
} else if (this.SecondaryGamepadButtons.IsPressed(this.Input, this.GamepadIndex)) {
|
||||||
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed)
|
if (this.SelectedElement?.Root != null && this.SelectedElement.CanBePressed)
|
||||||
this.System.OnElementSecondaryPressed?.Invoke(this.SelectedElement);
|
this.System.OnElementSecondaryPressed?.Invoke(this.SelectedElement);
|
||||||
} else if (this.DownButtons.Any(this.IsAnyPressed)) {
|
} else if (this.DownButtons.IsPressed(this.Input, this.GamepadIndex)) {
|
||||||
this.HandleGamepadNextElement(Direction2.Down);
|
this.HandleGamepadNextElement(Direction2.Down);
|
||||||
} else if (this.LeftButtons.Any(this.IsAnyPressed)) {
|
} else if (this.LeftButtons.IsPressed(this.Input, this.GamepadIndex)) {
|
||||||
this.HandleGamepadNextElement(Direction2.Left);
|
this.HandleGamepadNextElement(Direction2.Left);
|
||||||
} else if (this.RightButtons.Any(this.IsAnyPressed)) {
|
} else if (this.RightButtons.IsPressed(this.Input, this.GamepadIndex)) {
|
||||||
this.HandleGamepadNextElement(Direction2.Right);
|
this.HandleGamepadNextElement(Direction2.Right);
|
||||||
} else if (this.UpButtons.Any(this.IsAnyPressed)) {
|
} else if (this.UpButtons.IsPressed(this.Input, this.GamepadIndex)) {
|
||||||
this.HandleGamepadNextElement(Direction2.Up);
|
this.HandleGamepadNextElement(Direction2.Up);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,10 +376,6 @@ namespace MLEM.Ui {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAnyPressed(object button) {
|
|
||||||
return this.Input.IsPressed(button, this.GamepadIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleGamepadNextElement(Direction2 dir) {
|
private void HandleGamepadNextElement(Direction2 dir) {
|
||||||
this.IsAutoNavMode = true;
|
this.IsAutoNavMode = true;
|
||||||
RectangleF searchArea = default;
|
RectangleF searchArea = default;
|
||||||
|
@ -417,14 +406,5 @@ namespace MLEM.Ui {
|
||||||
this.SelectElement(this.ActiveRoot, next);
|
this.SelectElement(this.ActiveRoot, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A helper function to add <see cref="Keys"/>, <see cref="Buttons"/> or <see cref="MouseButton"/> to an array of controls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="controls">The controls to add to</param>
|
|
||||||
/// <param name="additional">The additional controls to add to the controls list</param>
|
|
||||||
public static void AddButtons(ref object[] controls, params object[] additional) {
|
|
||||||
controls = controls.Concat(additional).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
116
MLEM/Input/GenericInput.cs
Normal file
116
MLEM/Input/GenericInput.cs
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
|
namespace MLEM.Input {
|
||||||
|
/// <summary>
|
||||||
|
/// A generic input represents any kind of input key.
|
||||||
|
/// This includes <see cref="Keys"/> for keyboard keys, <see cref="MouseButton"/> for mouse buttons and <see cref="Buttons"/> for gamepad buttons.
|
||||||
|
/// For creating and extracting inputs from a generic input, the implicit operators and <see cref="Type"/> can be used.
|
||||||
|
/// Note that this type is serializable using <see cref="DataContractAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public struct GenericInput {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="InputType"/> of this generic input's current <see cref="value"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataMember]
|
||||||
|
public readonly InputType Type;
|
||||||
|
[DataMember]
|
||||||
|
private readonly int value;
|
||||||
|
|
||||||
|
private GenericInput(InputType type, int value) {
|
||||||
|
this.Type = type;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a <see cref="Keys"/> to a generic input.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="keys">The keys to convert</param>
|
||||||
|
/// <returns>The resulting generic input</returns>
|
||||||
|
public static implicit operator GenericInput(Keys keys) {
|
||||||
|
return new GenericInput(InputType.Keyboard, (int) keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a <see cref="MouseButton"/> to a generic input.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="button">The button to convert</param>
|
||||||
|
/// <returns>The resulting generic input</returns>
|
||||||
|
public static implicit operator GenericInput(MouseButton button) {
|
||||||
|
return new GenericInput(InputType.Mouse, (int) button);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a <see cref="Buttons"/> to a generic input.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buttons">The buttons to convert</param>
|
||||||
|
/// <returns>The resulting generic input</returns>
|
||||||
|
public static implicit operator GenericInput(Buttons buttons) {
|
||||||
|
return new GenericInput(InputType.Gamepad, (int) buttons);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a generic input to a <see cref="Keys"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The input to convert</param>
|
||||||
|
/// <returns>The resulting keys</returns>
|
||||||
|
/// <exception cref="ArgumentException">If the given generic input's <see cref="Type"/> is not <see cref="InputType.Keyboard"/></exception>
|
||||||
|
public static implicit operator Keys(GenericInput input) {
|
||||||
|
if (input.Type != InputType.Keyboard)
|
||||||
|
throw new ArgumentException();
|
||||||
|
return (Keys) input.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a generic input to a <see cref="MouseButton"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The input to convert</param>
|
||||||
|
/// <returns>The resulting button</returns>
|
||||||
|
/// <exception cref="ArgumentException">If the given generic input's <see cref="Type"/> is not <see cref="InputType.Mouse"/></exception>
|
||||||
|
public static implicit operator MouseButton(GenericInput input) {
|
||||||
|
if (input.Type != InputType.Mouse)
|
||||||
|
throw new ArgumentException();
|
||||||
|
return (MouseButton) input.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a generic input to a <see cref="Buttons"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The input to convert</param>
|
||||||
|
/// <returns>The resulting buttons</returns>
|
||||||
|
/// <exception cref="ArgumentException">If the given generic input's <see cref="Type"/> is not <see cref="InputType.Gamepad"/></exception>
|
||||||
|
public static implicit operator Buttons(GenericInput input) {
|
||||||
|
if (input.Type != InputType.Gamepad)
|
||||||
|
throw new ArgumentException();
|
||||||
|
return (Buttons) input.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A type of input button.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public enum InputType {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A type representing <see cref="MouseButton"/>
|
||||||
|
/// </summary>
|
||||||
|
[EnumMember]
|
||||||
|
Mouse,
|
||||||
|
/// <summary>
|
||||||
|
/// A type representing <see cref="Keys"/>
|
||||||
|
/// </summary>
|
||||||
|
[EnumMember]
|
||||||
|
Keyboard,
|
||||||
|
/// <summary>
|
||||||
|
/// A type representing <see cref="Buttons"/>
|
||||||
|
/// </summary>
|
||||||
|
[EnumMember]
|
||||||
|
Gamepad
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -432,13 +432,13 @@ namespace MLEM.Input {
|
||||||
/// <param name="index">The index of the gamepad to query (if applicable), or -1 for any gamepad</param>
|
/// <param name="index">The index of the gamepad to query (if applicable), or -1 for any gamepad</param>
|
||||||
/// <returns>Whether the given control is down</returns>
|
/// <returns>Whether the given control is down</returns>
|
||||||
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
|
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
|
||||||
public bool IsDown(object control, int index = -1) {
|
public bool IsDown(GenericInput control, int index = -1) {
|
||||||
if (control is Keys key)
|
if (control.Type == GenericInput.InputType.Keyboard)
|
||||||
return this.IsKeyDown(key);
|
return this.IsKeyDown(control);
|
||||||
if (control is Buttons button)
|
if (control.Type == GenericInput.InputType.Gamepad)
|
||||||
return this.IsGamepadButtonDown(button, index);
|
return this.IsGamepadButtonDown(control, index);
|
||||||
if (control is MouseButton mouse)
|
if (control.Type == GenericInput.InputType.Mouse)
|
||||||
return this.IsMouseButtonDown(mouse);
|
return this.IsMouseButtonDown(control);
|
||||||
throw new ArgumentException(nameof(control));
|
throw new ArgumentException(nameof(control));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,13 +450,13 @@ namespace MLEM.Input {
|
||||||
/// <param name="index">The index of the gamepad to query (if applicable), or -1 for any gamepad</param>
|
/// <param name="index">The index of the gamepad to query (if applicable), or -1 for any gamepad</param>
|
||||||
/// <returns>Whether the given control is down</returns>
|
/// <returns>Whether the given control is down</returns>
|
||||||
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
|
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
|
||||||
public bool IsUp(object control, int index = -1) {
|
public bool IsUp(GenericInput control, int index = -1) {
|
||||||
if (control is Keys key)
|
if (control.Type == GenericInput.InputType.Keyboard)
|
||||||
return this.IsKeyUp(key);
|
return this.IsKeyUp(control);
|
||||||
if (control is Buttons button)
|
if (control.Type == GenericInput.InputType.Gamepad)
|
||||||
return this.IsGamepadButtonUp(button, index);
|
return this.IsGamepadButtonUp(control, index);
|
||||||
if (control is MouseButton mouse)
|
if (control.Type == GenericInput.InputType.Mouse)
|
||||||
return this.IsMouseButtonUp(mouse);
|
return this.IsMouseButtonUp(control);
|
||||||
throw new ArgumentException(nameof(control));
|
throw new ArgumentException(nameof(control));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,28 +468,28 @@ namespace MLEM.Input {
|
||||||
/// <param name="index">The index of the gamepad to query (if applicable), or -1 for any gamepad</param>
|
/// <param name="index">The index of the gamepad to query (if applicable), or -1 for any gamepad</param>
|
||||||
/// <returns>Whether the given control is down</returns>
|
/// <returns>Whether the given control is down</returns>
|
||||||
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
|
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
|
||||||
public bool IsPressed(object control, int index = -1) {
|
public bool IsPressed(GenericInput control, int index = -1) {
|
||||||
if (control is Keys key)
|
if (control.Type == GenericInput.InputType.Keyboard)
|
||||||
return this.IsKeyPressed(key);
|
return this.IsKeyPressed(control);
|
||||||
if (control is Buttons button)
|
if (control.Type == GenericInput.InputType.Gamepad)
|
||||||
return this.IsGamepadButtonPressed(button, index);
|
return this.IsGamepadButtonPressed(control, index);
|
||||||
if (control is MouseButton mouse)
|
if (control.Type == GenericInput.InputType.Mouse)
|
||||||
return this.IsMouseButtonPressed(mouse);
|
return this.IsMouseButtonPressed(control);
|
||||||
throw new ArgumentException(nameof(control));
|
throw new ArgumentException(nameof(control));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IsDown"/>
|
/// <inheritdoc cref="IsDown"/>
|
||||||
public bool IsAnyDown(params object[] control) {
|
public bool IsAnyDown(params GenericInput[] control) {
|
||||||
return control.Any(c => this.IsDown(c));
|
return control.Any(c => this.IsDown(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IsUp"/>
|
/// <inheritdoc cref="IsUp"/>
|
||||||
public bool IsAnyUp(params object[] control) {
|
public bool IsAnyUp(params GenericInput[] control) {
|
||||||
return control.Any(c => this.IsUp(c));
|
return control.Any(c => this.IsUp(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IsPressed"/>
|
/// <inheritdoc cref="IsPressed"/>
|
||||||
public bool IsAnyPressed(params object[] control) {
|
public bool IsAnyPressed(params GenericInput[] control) {
|
||||||
return control.Any(c => this.IsPressed(c));
|
return control.Any(c => this.IsPressed(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
105
MLEM/Input/Keybind.cs
Normal file
105
MLEM/Input/Keybind.cs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
|
namespace MLEM.Input {
|
||||||
|
/// <summary>
|
||||||
|
/// A keybind represents a generic way to trigger input.
|
||||||
|
/// A keybind is made up of multiple key combinations, one of which has to be pressed for the keybind to be triggered.
|
||||||
|
/// Note that this type is serializable using <see cref="DataContractAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
[DataContract]
|
||||||
|
public class Keybind {
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
private readonly List<Combination> combinations = new List<Combination>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new key combination to this keybind that can optionally be pressed for the keybind to trigger.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key to be pressed.</param>
|
||||||
|
/// <param name="modifiers">The modifier keys that have to be held down.</param>
|
||||||
|
/// <returns>This keybind, for chaining</returns>
|
||||||
|
public Keybind Add(GenericInput key, params GenericInput[] modifiers) {
|
||||||
|
this.combinations.Add(new Combination(key, modifiers));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Add(MLEM.Input.GenericInput,MLEM.Input.GenericInput[])"/>
|
||||||
|
public Keybind Add(GenericInput key, ModifierKey modifier) {
|
||||||
|
return this.Add(key, modifier.GetKeys().Select(m => (GenericInput) m).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears this keybind, removing all active combinations.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>This keybind, for chaining</returns>
|
||||||
|
public Keybind Clear() {
|
||||||
|
this.combinations.Clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies all of the combinations from the given keybind into this keybind.
|
||||||
|
/// Note that this doesn't <see cref="Clear"/> this keybind, so combinations will be merged rather than replaced.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The keybind to copy from</param>
|
||||||
|
/// <returns>This keybind, for chaining</returns>
|
||||||
|
public Keybind CopyFrom(Keybind other) {
|
||||||
|
this.combinations.AddRange(other.combinations);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether this keybind is considered to be down.
|
||||||
|
/// See <see cref="InputHandler.IsDown"/> for more information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handler">The input handler to query the keys with</param>
|
||||||
|
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
|
||||||
|
/// <returns>Whether this keybind is considered to be down</returns>
|
||||||
|
public bool IsDown(InputHandler handler, int gamepadIndex = -1) {
|
||||||
|
return this.combinations.Any(c => c.IsDown(handler, gamepadIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns whether this keybind is considered to be pressed.
|
||||||
|
/// See <see cref="InputHandler.IsPressed"/> for more information.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="handler">The input handler to query the keys with</param>
|
||||||
|
/// <param name="gamepadIndex">The index of the gamepad to query, or -1 to query all gamepads</param>
|
||||||
|
/// <returns>Whether this keybind is considered to be pressed</returns>
|
||||||
|
public bool IsPressed(InputHandler handler, int gamepadIndex = -1) {
|
||||||
|
return this.combinations.Any(c => c.IsPressed(handler, gamepadIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataContract]
|
||||||
|
private class Combination {
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
private readonly GenericInput[] modifiers;
|
||||||
|
[DataMember]
|
||||||
|
private readonly GenericInput key;
|
||||||
|
|
||||||
|
public Combination(GenericInput key, GenericInput[] modifiers) {
|
||||||
|
this.modifiers = modifiers;
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsDown(InputHandler handler, int gamepadIndex = -1) {
|
||||||
|
return this.IsModifierDown(handler, gamepadIndex) && handler.IsDown(this.key, gamepadIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool IsPressed(InputHandler handler, int gamepadIndex = -1) {
|
||||||
|
return this.IsModifierDown(handler, gamepadIndex) && handler.IsPressed(this.key, gamepadIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsModifierDown(InputHandler handler, int gamepadIndex = -1) {
|
||||||
|
return this.modifiers.Length <= 0 || this.modifiers.Any(m => handler.IsDown(m, gamepadIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
#tool docfx.console&version=2.51.0
|
#tool docfx.console&version=2.51.0
|
||||||
|
|
||||||
// this is the upcoming version, for prereleases
|
// this is the upcoming version, for prereleases
|
||||||
var version = Argument("version", "3.3.3");
|
var version = Argument("version", "4.0.0");
|
||||||
var target = Argument("target", "Default");
|
var target = Argument("target", "Default");
|
||||||
var branch = Argument("branch", "master");
|
var branch = Argument("branch", "master");
|
||||||
var config = Argument("configuration", "Release");
|
var config = Argument("configuration", "Release");
|
||||||
|
|
Loading…
Reference in a new issue