using System; using System.Linq; using System.Runtime.Serialization; using Microsoft.Xna.Framework.Input; namespace MLEM.Input { /// /// A generic input represents any kind of input key. /// This includes for keyboard keys, for mouse buttons and for gamepad buttons. /// For creating and extracting inputs from a generic input, the implicit operators and can additionally be used. /// Note that this type is serializable using . /// [DataContract] public readonly struct GenericInput : IEquatable { /// /// All values created from all values of the enum. /// public static readonly GenericInput[] AllKeys = InputHandler.AllKeys.Select(k => (GenericInput) k).ToArray(); /// /// All values created from all values of the enum. /// public static readonly GenericInput[] AllMouseButtons = MouseExtensions.MouseButtons.Select(k => (GenericInput) k).ToArray(); /// /// All values created from all values of the enum. /// public static readonly GenericInput[] AllButtons = InputHandler.AllButtons.Select(k => (GenericInput) k).ToArray(); /// /// All values created from all values of the , and enums. /// This collection represents all possible valid, non-default values. /// public static readonly GenericInput[] AllInputs = GenericInput.AllKeys.Concat(GenericInput.AllMouseButtons).Concat(GenericInput.AllButtons).ToArray(); /// /// The of this generic input's current . /// [DataMember] public readonly InputType Type; [DataMember] private readonly int value; /// /// Returns this generic input's . /// /// If this generic input's is not or . public Keys Key => this.Type == InputType.None ? 0 : this.Type == InputType.Keyboard ? (Keys) this.value : throw new InvalidOperationException(); /// /// Returns this generic input's . /// /// If this generic input's is not . public MouseButton MouseButton => this.Type == InputType.Mouse ? (MouseButton) this.value : throw new InvalidOperationException(); /// /// Returns this generic input's . /// /// If this generic input's is not or . public Buttons Button => this.Type == InputType.None ? 0 : this.Type == InputType.Gamepad ? (Buttons) this.value : throw new InvalidOperationException(); /// /// Creates a new generic input from the given keyboard . /// /// The key to convert. public GenericInput(Keys key) : this(InputType.Keyboard, (int) key) {} /// /// Creates a new generic input from the given . /// /// The button to convert. public GenericInput(MouseButton button) : this(InputType.Mouse, (int) button) {} /// /// Creates a new generic input from the given gamepad . /// /// The button to convert. public GenericInput(Buttons button) : this(InputType.Gamepad, (int) button) {} /// /// Creates a new generic input from the given value. /// If the value is a , or , the appropriate and value will be set. Otherwise, the will be set to . /// /// The value to convert. public GenericInput(Enum value) { this.Type = value is MouseButton ? InputType.Mouse : value is Keys ? InputType.Keyboard : value is Buttons ? InputType.Gamepad : InputType.None; this.value = Convert.ToInt32(value); } private GenericInput(InputType type, int value) { this.Type = type; this.value = value; } /// Returns this generic input, converted to a string. /// This generic input, converted to a string. public override string ToString() { switch (this.Type) { case InputType.Mouse: return $"Mouse{(MouseButton) this}"; case InputType.Keyboard: return ((Keys) this).ToString(); case InputType.Gamepad: return $"Gamepad{(Buttons) this}"; default: return this.Type.ToString(); } } /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the other parameter; otherwise, false. public bool Equals(GenericInput other) { return this.Type == other.Type && this.value == other.value; } /// Indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// true if obj and this instance are the same type and represent the same value; otherwise, false. public override bool Equals(object obj) { return obj is GenericInput other && this.Equals(other); } /// Returns the hash code for this instance. /// A 32-bit signed integer that is the hash code for this instance. public override int GetHashCode() { return (int) this.Type * 397 ^ this.value; } /// /// Compares the two generic input instances for equality using /// /// The left input /// The right input /// Whether the two generic inputs are equal public static bool operator ==(GenericInput left, GenericInput right) { return left.Equals(right); } /// /// Compares the two generic input instances for inequality using /// /// The left input /// The right input /// Whether the two generic inputs are not equal public static bool operator !=(GenericInput left, GenericInput right) { return !left.Equals(right); } /// /// Converts a to a generic input. /// /// The keys to convert /// The resulting generic input public static implicit operator GenericInput(Keys key) { return new GenericInput(key); } /// /// Converts a to a generic input. /// /// The button to convert /// The resulting generic input public static implicit operator GenericInput(MouseButton button) { return new GenericInput(button); } /// /// Converts a to a generic input. /// /// The buttons to convert /// The resulting generic input public static implicit operator GenericInput(Buttons button) { return new GenericInput(button); } /// /// Converts a generic input to a . /// /// The input to convert /// The resulting keys /// If the given generic input's is not or public static implicit operator Keys(GenericInput input) { return input.Key; } /// /// Converts a generic input to a . /// /// The input to convert /// The resulting button /// If the given generic input's is not public static implicit operator MouseButton(GenericInput input) { return input.MouseButton; } /// /// Converts a generic input to a . /// /// The input to convert /// The resulting buttons /// If the given generic input's is not public static implicit operator Buttons(GenericInput input) { return input.Button; } /// /// A type of input button. /// [DataContract] public enum InputType { /// /// A type representing no value /// [EnumMember] None, /// /// A type representing /// [EnumMember] Mouse, /// /// A type representing /// [EnumMember] Keyboard, /// /// A type representing /// [EnumMember] Gamepad } } }