2020-06-12 17:09:35 +02:00
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.
2022-03-26 12:51:14 +01:00
/// For creating and extracting inputs from a generic input, the implicit operators and <see cref="Type"/> can additionally be used.
2020-06-12 17:09:35 +02:00
/// Note that this type is serializable using <see cref="DataContractAttribute"/>.
/// </summary>
[DataContract]
2021-12-21 11:39:29 +01:00
public readonly struct GenericInput : IEquatable < GenericInput > {
2020-06-12 17:09:35 +02:00
/// <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 ;
2022-03-26 12:51:14 +01:00
/// <summary>
/// Returns this generic input's <see cref="Keys"/>.
/// </summary>
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Keyboard"/> or <see cref="InputType.None"/>.</exception>
2022-06-15 11:44:28 +02:00
public Keys Key = > this . Type = = InputType . None ? 0 : this . Type = = InputType . Keyboard ? ( Keys ) this . value : throw new InvalidOperationException ( ) ;
2022-03-26 12:51:14 +01:00
/// <summary>
/// Returns this generic input's <see cref="MouseButton"/>.
/// </summary>
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Mouse"/>.</exception>
public MouseButton MouseButton = > this . Type = = InputType . Mouse ? ( MouseButton ) this . value : throw new InvalidOperationException ( ) ;
/// <summary>
/// Returns this generic input's <see cref="Buttons"/>.
/// </summary>
2022-06-15 11:44:28 +02:00
/// <exception cref="InvalidOperationException">If this generic input's <see cref="Type"/> is not <see cref="InputType.Gamepad"/> or <see cref="InputType.None"/>.</exception>
public Buttons Button = > this . Type = = InputType . None ? 0 : this . Type = = InputType . Gamepad ? ( Buttons ) this . value : throw new InvalidOperationException ( ) ;
2022-03-26 12:51:14 +01:00
/// <summary>
/// Creates a new generic input from the given keyboard <see cref="Keys"/>.
/// </summary>
/// <param name="key">The key to convert.</param>
public GenericInput ( Keys key ) : this ( InputType . Keyboard , ( int ) key ) { }
/// <summary>
/// Creates a new generic input from the given <see cref="MouseButton"/>.
/// </summary>
/// <param name="button">The button to convert.</param>
public GenericInput ( MouseButton button ) : this ( InputType . Mouse , ( int ) button ) { }
/// <summary>
/// Creates a new generic input from the given gamepad <see cref="Buttons"/>.
/// </summary>
/// <param name="button">The button to convert.</param>
public GenericInput ( Buttons button ) : this ( InputType . Gamepad , ( int ) button ) { }
2022-05-18 21:45:38 +02:00
/// <summary>
/// Creates a new generic input from the given <see cref="Enum"/> value.
/// If the value is a <see cref="MouseButton"/>, <see cref="Keys"/> or <see cref="Buttons"/>, the appropriate <see cref="Type"/> and value will be set. Otherwise, the <see cref="Type"/> will be set to <see cref="InputType.None"/>.
/// </summary>
/// <param name="value">The value to convert.</param>
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 ) ;
}
2020-06-12 17:09:35 +02:00
private GenericInput ( InputType type , int value ) {
this . Type = type ;
this . value = value ;
}
2021-11-22 19:25:18 +01:00
/// <summary>Returns this generic input, converted to a string.</summary>
/// <returns>This generic input, converted to a string.</returns>
2021-06-20 23:05:02 +02:00
public override string ToString ( ) {
switch ( this . Type ) {
case InputType . Mouse :
2021-07-13 15:41:42 +02:00
return $"Mouse{(MouseButton) this}" ;
2021-06-20 23:05:02 +02:00
case InputType . Keyboard :
2021-07-13 15:41:42 +02:00
return ( ( Keys ) this ) . ToString ( ) ;
2021-06-20 23:05:02 +02:00
case InputType . Gamepad :
2021-07-13 15:41:42 +02:00
return $"Gamepad{(Buttons) this}" ;
default :
return this . Type . ToString ( ) ;
2021-06-20 23:05:02 +02:00
}
}
2021-12-21 11:39:29 +01:00
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the <paramref name="other">other</paramref> parameter; otherwise, false.</returns>
public bool Equals ( GenericInput other ) {
return this . Type = = other . Type & & this . value = = other . value ;
}
2021-11-22 19:25:18 +01:00
/// <summary>Indicates whether this instance and a specified object are equal.</summary>
/// <param name="obj">The object to compare with the current instance.</param>
2021-12-21 11:39:29 +01:00
/// <returns>true if <paramref name="obj">obj</paramref> and this instance are the same type and represent the same value; otherwise, false.</returns>
2021-06-20 23:17:39 +02:00
public override bool Equals ( object obj ) {
2021-12-21 11:39:29 +01:00
return obj is GenericInput other & & this . Equals ( other ) ;
2021-06-20 23:17:39 +02:00
}
2021-11-22 19:25:18 +01:00
/// <summary>Returns the hash code for this instance.</summary>
/// <returns>A 32-bit signed integer that is the hash code for this instance.</returns>
2021-06-20 23:17:39 +02:00
public override int GetHashCode ( ) {
2022-06-15 11:38:11 +02:00
return ( int ) this . Type * 397 ^ this . value ;
2021-06-20 23:17:39 +02:00
}
/// <summary>
2021-12-21 11:39:29 +01:00
/// Compares the two generic input instances for equality using <see cref="Equals(GenericInput)"/>
2021-06-20 23:17:39 +02:00
/// </summary>
/// <param name="left">The left input</param>
/// <param name="right">The right input</param>
/// <returns>Whether the two generic inputs are equal</returns>
public static bool operator = = ( GenericInput left , GenericInput right ) {
return left . Equals ( right ) ;
}
/// <summary>
2021-12-21 11:39:29 +01:00
/// Compares the two generic input instances for inequality using <see cref="Equals(GenericInput)"/>
2021-06-20 23:17:39 +02:00
/// </summary>
/// <param name="left">The left input</param>
/// <param name="right">The right input</param>
/// <returns>Whether the two generic inputs are not equal</returns>
public static bool operator ! = ( GenericInput left , GenericInput right ) {
return ! left . Equals ( right ) ;
}
2020-06-12 17:09:35 +02:00
/// <summary>
/// Converts a <see cref="Keys"/> to a generic input.
/// </summary>
2022-03-26 12:51:14 +01:00
/// <param name="key">The keys to convert</param>
2020-06-12 17:09:35 +02:00
/// <returns>The resulting generic input</returns>
2022-03-26 12:51:14 +01:00
public static implicit operator GenericInput ( Keys key ) {
return new GenericInput ( key ) ;
2020-06-12 17:09:35 +02:00
}
/// <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 ) {
2022-03-26 12:51:14 +01:00
return new GenericInput ( button ) ;
2020-06-12 17:09:35 +02:00
}
/// <summary>
/// Converts a <see cref="Buttons"/> to a generic input.
/// </summary>
2022-03-26 12:51:14 +01:00
/// <param name="button">The buttons to convert</param>
2020-06-12 17:09:35 +02:00
/// <returns>The resulting generic input</returns>
2022-03-26 12:51:14 +01:00
public static implicit operator GenericInput ( Buttons button ) {
return new GenericInput ( button ) ;
2020-06-12 17:09:35 +02:00
}
/// <summary>
/// Converts a generic input to a <see cref="Keys"/>.
/// </summary>
/// <param name="input">The input to convert</param>
/// <returns>The resulting keys</returns>
2022-03-26 12:51:14 +01:00
/// <exception cref="InvalidOperationException">If the given generic input's <see cref="Type"/> is not <see cref="InputType.Keyboard"/> or <see cref="InputType.None"/></exception>
2020-06-12 17:09:35 +02:00
public static implicit operator Keys ( GenericInput input ) {
2022-03-26 12:51:14 +01:00
return input . Key ;
2020-06-12 17:09:35 +02:00
}
/// <summary>
/// Converts a generic input to a <see cref="MouseButton"/>.
/// </summary>
/// <param name="input">The input to convert</param>
/// <returns>The resulting button</returns>
2022-03-26 12:51:14 +01:00
/// <exception cref="InvalidOperationException">If the given generic input's <see cref="Type"/> is not <see cref="InputType.Mouse"/></exception>
2020-06-12 17:09:35 +02:00
public static implicit operator MouseButton ( GenericInput input ) {
2022-03-26 12:51:14 +01:00
return input . MouseButton ;
2020-06-12 17:09:35 +02:00
}
/// <summary>
/// Converts a generic input to a <see cref="Buttons"/>.
/// </summary>
/// <param name="input">The input to convert</param>
/// <returns>The resulting buttons</returns>
2022-03-26 12:51:14 +01:00
/// <exception cref="InvalidOperationException">If the given generic input's <see cref="Type"/> is not <see cref="InputType.Gamepad"/></exception>
2020-06-12 17:09:35 +02:00
public static implicit operator Buttons ( GenericInput input ) {
2022-03-26 12:51:14 +01:00
return input . Button ;
2020-06-12 17:09:35 +02:00
}
/// <summary>
/// A type of input button.
/// </summary>
[DataContract]
public enum InputType {
2021-06-21 00:49:09 +02:00
/// <summary>
/// A type representing no value
/// </summary>
[EnumMember]
None ,
2020-06-12 17:09:35 +02:00
/// <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
}
}
2022-06-17 18:23:47 +02:00
}