2019-08-07 22:25:33 +02:00
using System ;
2019-08-09 22:04:26 +02:00
using System.Collections.Generic ;
2019-08-29 18:12:02 +02:00
using System.Collections.ObjectModel ;
2019-08-09 22:04:26 +02:00
using System.Linq ;
2019-08-07 22:25:33 +02:00
using Microsoft.Xna.Framework ;
using Microsoft.Xna.Framework.Input ;
2019-08-29 18:12:02 +02:00
using Microsoft.Xna.Framework.Input.Touch ;
2019-08-09 22:04:26 +02:00
using MLEM.Misc ;
2019-08-07 22:25:33 +02:00
namespace MLEM.Input {
2020-05-21 17:21:34 +02:00
/// <summary>
/// An input handler is a more advanced wrapper around MonoGame's default input system.
/// It includes keyboard, mouse, gamepad and touch states, as well as a new "pressed" state for keys and the ability for keyboard and gamepad repeat events.
/// </summary>
2019-12-05 17:52:25 +01:00
public class InputHandler : GameComponent {
2019-08-07 22:25:33 +02:00
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the keyboard state from the last update call
/// </summary>
2019-08-07 22:25:33 +02:00
public KeyboardState LastKeyboardState { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the current keyboard state
/// </summary>
2019-08-07 22:25:33 +02:00
public KeyboardState KeyboardState { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the keyboard keys that are currently being pressed
/// </summary>
2019-09-04 18:49:59 +02:00
public Keys [ ] PressedKeys { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Set this property to false to disable keyboard handling for this input handler.
/// </summary>
2019-08-29 18:12:02 +02:00
public bool HandleKeyboard ;
2019-08-07 22:25:33 +02:00
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the mouse state from the last update call
/// </summary>
2019-08-07 22:25:33 +02:00
public MouseState LastMouseState { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the current mouse state
/// </summary>
2019-08-07 22:25:33 +02:00
public MouseState MouseState { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the current position of the mouse, extracted from <see cref="MouseState"/>
/// </summary>
2019-08-07 22:25:33 +02:00
public Point MousePosition = > this . MouseState . Position ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the position of the mouse from the last update call, extracted from <see cref="LastMouseState"/>
/// </summary>
2019-08-07 22:25:33 +02:00
public Point LastMousePosition = > this . LastMouseState . Position ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the current scroll wheel value, in increments of 120
/// </summary>
2019-08-07 22:25:33 +02:00
public int ScrollWheel = > this . MouseState . ScrollWheelValue ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the scroll wheel value from the last update call, in increments of 120
/// </summary>
2019-08-07 22:25:33 +02:00
public int LastScrollWheel = > this . LastMouseState . ScrollWheelValue ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// Set this property to false to disable mouse handling for this input handler.
/// </summary>
2019-08-29 18:12:02 +02:00
public bool HandleMouse ;
2019-08-07 22:25:33 +02:00
private readonly GamePadState [ ] lastGamepads = new GamePadState [ GamePad . MaximumGamePadCount ] ;
private readonly GamePadState [ ] gamepads = new GamePadState [ GamePad . MaximumGamePadCount ] ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the amount of gamepads that are currently connected.
/// This property is automatically updated in <see cref="Update()"/>
/// </summary>
2019-08-29 10:26:18 +02:00
public int ConnectedGamepads { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Set this property to false to disable keyboard handling for this input handler.
/// </summary>
2019-08-29 18:12:02 +02:00
public bool HandleGamepads ;
2019-08-07 22:25:33 +02:00
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the touch state from the last update call
/// </summary>
2019-08-29 18:12:02 +02:00
public TouchCollection LastTouchState { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains the current touch state
/// </summary>
2019-08-29 18:12:02 +02:00
public TouchCollection TouchState { get ; private set ; }
2020-05-21 17:21:34 +02:00
/// <summary>
/// Contains all of the gestures that have finished during the last update call.
/// To easily query these gestures, use <see cref="GetGesture"/>
/// </summary>
2019-08-29 18:12:02 +02:00
public readonly ReadOnlyCollection < GestureSample > Gestures ;
private readonly List < GestureSample > gestures = new List < GestureSample > ( ) ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// Set this property to false to disable touch handling for this input handler.
/// </summary>
2019-08-29 18:12:02 +02:00
public bool HandleTouch ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// This is the amount of time that has to pass before the first keyboard repeat event is triggered.
/// <seealso cref="KeyRepeatRate"/>
/// </summary>
2019-09-04 18:49:59 +02:00
public TimeSpan KeyRepeatDelay = TimeSpan . FromSeconds ( 0.65 ) ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// This is the amount of time that has to pass between keyboard repeat events.
/// <seealso cref="KeyRepeatDelay"/>
/// </summary>
2019-09-04 18:49:59 +02:00
public TimeSpan KeyRepeatRate = TimeSpan . FromSeconds ( 0.05 ) ;
2019-09-09 20:56:10 +02:00
2020-05-21 17:21:34 +02:00
/// <summary>
/// Set this property to false to disable keyboard repeat event handling.
/// </summary>
2019-09-09 20:56:10 +02:00
public bool HandleKeyboardRepeats = true ;
2019-09-04 18:49:59 +02:00
private DateTime heldKeyStart ;
private DateTime lastKeyRepeat ;
2019-09-09 20:56:10 +02:00
private bool triggerKeyRepeat ;
2019-09-04 18:49:59 +02:00
private Keys heldKey ;
2020-05-21 17:21:34 +02:00
/// <summary>
/// Set this property to false to disable gamepad repeat event handling.
/// </summary>
2019-09-09 20:56:10 +02:00
public bool HandleGamepadRepeats = true ;
2019-09-10 11:41:13 +02:00
private readonly DateTime [ ] heldGamepadButtonStarts = new DateTime [ GamePad . MaximumGamePadCount ] ;
private readonly DateTime [ ] lastGamepadButtonRepeats = new DateTime [ GamePad . MaximumGamePadCount ] ;
private readonly bool [ ] triggerGamepadButtonRepeat = new bool [ GamePad . MaximumGamePadCount ] ;
private readonly Buttons ? [ ] heldGamepadButtons = new Buttons ? [ GamePad . MaximumGamePadCount ] ;
2019-09-09 20:56:10 +02:00
2020-05-21 17:21:34 +02:00
/// <summary>
/// Creates a new input handler with optional initial values.
/// </summary>
2021-02-18 18:36:29 +01:00
/// <param name="game">The game instance that this input handler belongs to</param>
2020-05-21 17:21:34 +02:00
/// <param name="handleKeyboard">If keyboard input should be handled</param>
/// <param name="handleMouse">If mouse input should be handled</param>
/// <param name="handleGamepads">If gamepad input should be handled</param>
/// <param name="handleTouch">If touch input should be handled</param>
2021-02-18 18:36:29 +01:00
public InputHandler ( Game game , bool handleKeyboard = true , bool handleMouse = true , bool handleGamepads = true , bool handleTouch = true ) : base ( game ) {
2019-08-29 18:12:02 +02:00
this . HandleKeyboard = handleKeyboard ;
this . HandleMouse = handleMouse ;
this . HandleGamepads = handleGamepads ;
this . HandleTouch = handleTouch ;
this . Gestures = this . gestures . AsReadOnly ( ) ;
2019-08-07 22:25:33 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Updates this input handler, querying pressed and released keys and calculating repeat events.
/// Call this in your <see cref="Game.Update"/> method.
/// </summary>
2019-08-07 22:25:33 +02:00
public void Update ( ) {
2021-02-18 18:36:29 +01:00
var active = this . Game . IsActive ;
2019-08-29 18:12:02 +02:00
if ( this . HandleKeyboard ) {
2019-08-07 22:25:33 +02:00
this . LastKeyboardState = this . KeyboardState ;
2021-02-18 18:36:29 +01:00
this . KeyboardState = active ? Keyboard . GetState ( ) : default ;
2019-09-04 18:49:59 +02:00
this . PressedKeys = this . KeyboardState . GetPressedKeys ( ) ;
if ( this . HandleKeyboardRepeats ) {
2019-09-09 20:56:10 +02:00
this . triggerKeyRepeat = false ;
2019-09-04 18:49:59 +02:00
if ( this . heldKey = = Keys . None ) {
// if we're not repeating a key, set the first key being held to the repeat key
// note that modifier keys don't count as that wouldn't really make sense
var key = this . PressedKeys . FirstOrDefault ( k = > ! k . IsModifier ( ) ) ;
if ( key ! = Keys . None ) {
this . heldKey = key ;
this . heldKeyStart = DateTime . UtcNow ;
}
} else {
// if the repeating key isn't being held anymore, reset
2019-09-04 18:52:50 +02:00
if ( ! this . IsKeyDown ( this . heldKey ) ) {
2019-09-04 18:49:59 +02:00
this . heldKey = Keys . None ;
} else {
var now = DateTime . UtcNow ;
var holdTime = now - this . heldKeyStart ;
// if we've been holding the key longer than the initial delay...
if ( holdTime > = this . KeyRepeatDelay ) {
var diff = now - this . lastKeyRepeat ;
// and we've been holding it for longer than a repeat...
if ( diff > = this . KeyRepeatRate ) {
this . lastKeyRepeat = now ;
// then trigger a repeat, causing IsKeyPressed to be true once
2019-09-09 20:56:10 +02:00
this . triggerKeyRepeat = true ;
2019-09-04 18:49:59 +02:00
}
}
}
}
}
2019-08-07 22:25:33 +02:00
}
2019-09-09 20:56:10 +02:00
2019-08-29 18:12:02 +02:00
if ( this . HandleMouse ) {
2019-08-07 22:25:33 +02:00
this . LastMouseState = this . MouseState ;
2021-02-19 02:47:32 +01:00
var state = Mouse . GetState ( ) ;
if ( active & & this . Game . GraphicsDevice . Viewport . Bounds . Contains ( state . Position ) ) {
this . MouseState = state ;
} else {
// mouse position and scroll wheel value should be preserved when the mouse is out of bounds
this . MouseState = new MouseState ( state . X , state . Y , state . ScrollWheelValue , 0 , 0 , 0 , 0 , 0 , state . HorizontalScrollWheelValue ) ;
2021-02-19 02:31:38 +01:00
}
2019-08-07 22:25:33 +02:00
}
2019-09-09 20:56:10 +02:00
2019-08-29 18:12:02 +02:00
if ( this . HandleGamepads ) {
2019-09-09 15:22:15 +02:00
this . ConnectedGamepads = GamePad . MaximumGamePadCount ;
2019-08-07 22:25:33 +02:00
for ( var i = 0 ; i < GamePad . MaximumGamePadCount ; i + + ) {
this . lastGamepads [ i ] = this . gamepads [ i ] ;
2021-02-18 18:36:29 +01:00
this . gamepads [ i ] = active ? GamePad . GetState ( i ) : default ;
if ( this . ConnectedGamepads > i & & ! GamePad . GetCapabilities ( i ) . IsConnected )
2019-08-29 10:26:18 +02:00
this . ConnectedGamepads = i ;
2019-08-07 22:25:33 +02:00
}
2019-09-09 20:56:10 +02:00
if ( this . HandleGamepadRepeats ) {
for ( var i = 0 ; i < this . ConnectedGamepads ; i + + ) {
this . triggerGamepadButtonRepeat [ i ] = false ;
2019-12-05 17:52:25 +01:00
2019-09-09 20:56:10 +02:00
if ( ! this . heldGamepadButtons [ i ] . HasValue ) {
foreach ( var b in EnumHelper . Buttons ) {
if ( this . IsGamepadButtonDown ( b , i ) ) {
this . heldGamepadButtons [ i ] = b ;
this . heldGamepadButtonStarts [ i ] = DateTime . UtcNow ;
break ;
}
}
} else {
if ( ! this . IsGamepadButtonDown ( this . heldGamepadButtons [ i ] . Value , i ) ) {
this . heldGamepadButtons [ i ] = null ;
} else {
var now = DateTime . UtcNow ;
var holdTime = now - this . heldGamepadButtonStarts [ i ] ;
if ( holdTime > = this . KeyRepeatDelay ) {
var diff = now - this . lastGamepadButtonRepeats [ i ] ;
if ( diff > = this . KeyRepeatRate ) {
this . lastGamepadButtonRepeats [ i ] = now ;
this . triggerGamepadButtonRepeat [ i ] = true ;
}
}
}
}
}
}
2019-08-07 22:25:33 +02:00
}
2019-09-09 20:56:10 +02:00
2019-08-29 18:12:02 +02:00
if ( this . HandleTouch ) {
this . LastTouchState = this . TouchState ;
2021-02-18 18:36:29 +01:00
this . TouchState = active ? TouchPanel . GetState ( ) : default ;
2019-08-29 18:12:02 +02:00
this . gestures . Clear ( ) ;
2021-02-18 18:36:29 +01:00
while ( active & & TouchPanel . IsGestureAvailable )
2019-08-29 18:12:02 +02:00
this . gestures . Add ( TouchPanel . ReadGesture ( ) ) ;
}
2019-08-07 22:25:33 +02:00
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="Update()"/>
2019-12-05 17:52:25 +01:00
public override void Update ( GameTime gameTime ) {
this . Update ( ) ;
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns the state of the <c>index</c>th gamepad from the last update call
/// </summary>
/// <param name="index">The zero-based gamepad index</param>
/// <returns>The state of the gamepad last update</returns>
2019-08-07 22:25:33 +02:00
public GamePadState GetLastGamepadState ( int index ) {
return this . lastGamepads [ index ] ;
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns the current state of the <c>index</c>th gamepad
/// </summary>
/// <param name="index">The zero-based gamepad index</param>
/// <returns>The current state of the gamepad</returns>
2019-08-07 22:25:33 +02:00
public GamePadState GetGamepadState ( int index ) {
return this . gamepads [ index ] ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyDown"/>
2019-08-07 22:25:33 +02:00
public bool IsKeyDown ( Keys key ) {
return this . KeyboardState . IsKeyDown ( key ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyUp"/>
2019-08-07 22:25:33 +02:00
public bool IsKeyUp ( Keys key ) {
return this . KeyboardState . IsKeyUp ( key ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyDown"/>
2019-08-07 22:25:33 +02:00
public bool WasKeyDown ( Keys key ) {
return this . LastKeyboardState . IsKeyDown ( key ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="Microsoft.Xna.Framework.Input.KeyboardState.IsKeyUp"/>
2019-08-07 22:25:33 +02:00
public bool WasKeyUp ( Keys key ) {
return this . LastKeyboardState . IsKeyUp ( key ) ;
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given key is considered pressed.
/// A key is considered pressed if it was not down the last update call, but is down the current update call.
2021-03-14 17:09:45 +01:00
/// If <see cref="HandleKeyboardRepeats"/> is true, this method will also return true to signify a key repeat.
2020-05-21 17:21:34 +02:00
/// </summary>
/// <param name="key">The key to query</param>
/// <returns>If the key is pressed</returns>
2019-08-07 22:25:33 +02:00
public bool IsKeyPressed ( Keys key ) {
2019-09-04 18:49:59 +02:00
// if the queried key is the held key and a repeat should be triggered, return true
2019-09-09 20:56:10 +02:00
if ( this . HandleKeyboardRepeats & & key = = this . heldKey & & this . triggerKeyRepeat )
2019-09-04 18:49:59 +02:00
return true ;
2021-03-14 17:09:45 +01:00
return this . IsKeyPressedIgnoreRepeats ( key ) ;
}
/// <summary>
/// Returns whether the given key is considered pressed.
/// This has the same behavior as <see cref="IsKeyPressed"/>, but ignores keyboard repeat events.
/// If <see cref="HandleKeyboardRepeats"/> is false, this method does the same as <see cref="IsKeyPressed"/>.
/// </summary>
/// <param name="key">The key to query</param>
/// <returns>If the key is pressed</returns>
public bool IsKeyPressedIgnoreRepeats ( Keys key ) {
2019-08-07 22:25:33 +02:00
return this . WasKeyUp ( key ) & & this . IsKeyDown ( key ) ;
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given modifier key is down.
/// </summary>
/// <param name="modifier">The modifier key</param>
/// <returns>If the modifier key is down</returns>
2019-08-28 18:27:17 +02:00
public bool IsModifierKeyDown ( ModifierKey modifier ) {
2019-09-04 18:49:59 +02:00
return modifier . GetKeys ( ) . Any ( this . IsKeyDown ) ;
2019-08-28 18:27:17 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given mouse button is currently down.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button is down</returns>
2019-08-07 22:25:33 +02:00
public bool IsMouseButtonDown ( MouseButton button ) {
2019-09-04 18:49:59 +02:00
return this . MouseState . GetState ( button ) = = ButtonState . Pressed ;
2019-08-07 22:25:33 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given mouse button is currently up.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button is up</returns>
2019-08-07 22:25:33 +02:00
public bool IsMouseButtonUp ( MouseButton button ) {
2019-09-04 18:49:59 +02:00
return this . MouseState . GetState ( button ) = = ButtonState . Released ;
2019-08-07 22:25:33 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given mouse button was down the last update call.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button was down</returns>
2019-08-07 22:25:33 +02:00
public bool WasMouseButtonDown ( MouseButton button ) {
2019-09-04 18:49:59 +02:00
return this . LastMouseState . GetState ( button ) = = ButtonState . Pressed ;
2019-08-07 22:25:33 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given mouse button was up the last update call.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether or not the queried button was up</returns>
2019-08-07 22:25:33 +02:00
public bool WasMouseButtonUp ( MouseButton button ) {
2019-09-04 18:49:59 +02:00
return this . LastMouseState . GetState ( button ) = = ButtonState . Released ;
2019-08-07 22:25:33 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given mouse button is considered pressed.
/// A mouse button is considered pressed if it was up the last update call, and is down the current update call.
/// </summary>
/// <param name="button">The button to query</param>
/// <returns>Whether the button is pressed</returns>
2019-08-07 22:25:33 +02:00
public bool IsMouseButtonPressed ( MouseButton button ) {
return this . WasMouseButtonUp ( button ) & & this . IsMouseButtonDown ( button ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="GamePadState.IsButtonDown"/>
2019-08-28 22:44:59 +02:00
public bool IsGamepadButtonDown ( Buttons button , int index = - 1 ) {
if ( index < 0 ) {
2019-08-29 10:26:18 +02:00
for ( var i = 0 ; i < this . ConnectedGamepads ; i + + )
2019-08-28 22:44:59 +02:00
if ( this . GetGamepadState ( i ) . IsButtonDown ( button ) )
return true ;
return false ;
}
2019-08-07 22:25:33 +02:00
return this . GetGamepadState ( index ) . IsButtonDown ( button ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="GamePadState.IsButtonUp"/>
2019-08-28 22:44:59 +02:00
public bool IsGamepadButtonUp ( Buttons button , int index = - 1 ) {
if ( index < 0 ) {
2019-08-29 10:26:18 +02:00
for ( var i = 0 ; i < this . ConnectedGamepads ; i + + )
2019-08-28 22:44:59 +02:00
if ( this . GetGamepadState ( i ) . IsButtonUp ( button ) )
return true ;
return false ;
}
2019-08-07 22:25:33 +02:00
return this . GetGamepadState ( index ) . IsButtonUp ( button ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="GamePadState.IsButtonDown"/>
2019-08-28 22:44:59 +02:00
public bool WasGamepadButtonDown ( Buttons button , int index = - 1 ) {
if ( index < 0 ) {
2019-08-29 10:26:18 +02:00
for ( var i = 0 ; i < this . ConnectedGamepads ; i + + )
2019-08-28 22:44:59 +02:00
if ( this . GetLastGamepadState ( i ) . IsButtonDown ( button ) )
return true ;
return false ;
}
2019-08-07 22:25:33 +02:00
return this . GetLastGamepadState ( index ) . IsButtonDown ( button ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="GamePadState.IsButtonUp"/>
2019-08-28 22:44:59 +02:00
public bool WasGamepadButtonUp ( Buttons button , int index = - 1 ) {
if ( index < 0 ) {
2019-08-29 10:26:18 +02:00
for ( var i = 0 ; i < this . ConnectedGamepads ; i + + )
2019-08-28 22:44:59 +02:00
if ( this . GetLastGamepadState ( i ) . IsButtonUp ( button ) )
return true ;
return false ;
}
2019-08-07 22:25:33 +02:00
return this . GetLastGamepadState ( index ) . IsButtonUp ( button ) ;
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns whether the given gamepad button on the given index is considered pressed.
/// A gamepad button is considered pressed if it was down the last update call, and is up the current update call.
2021-03-14 17:09:45 +01:00
/// If <see cref="HandleGamepadRepeats"/> is true, this method will also return true to signify a gamepad button repeat.
2020-05-21 17:21:34 +02:00
/// </summary>
/// <param name="button">The button to query</param>
/// <param name="index">The zero-based index of the gamepad, or -1 for any gamepad</param>
/// <returns>Whether the given button is pressed</returns>
2019-08-28 22:44:59 +02:00
public bool IsGamepadButtonPressed ( Buttons button , int index = - 1 ) {
2019-09-09 20:56:10 +02:00
if ( this . HandleGamepadRepeats ) {
if ( index < 0 ) {
for ( var i = 0 ; i < this . ConnectedGamepads ; i + + )
if ( this . heldGamepadButtons [ i ] = = button & & this . triggerGamepadButtonRepeat [ i ] )
return true ;
} else if ( this . heldGamepadButtons [ index ] = = button & & this . triggerGamepadButtonRepeat [ index ] ) {
return true ;
}
}
2021-03-14 17:09:45 +01:00
return this . IsGamepadButtonPressedIgnoreRepeats ( button , index ) ;
}
/// <summary>
/// Returns whether the given key is considered pressed.
/// This has the same behavior as <see cref="IsGamepadButtonPressed"/>, but ignores gamepad repeat events.
/// If <see cref="HandleGamepadRepeats"/> is false, this method does the same as <see cref="IsGamepadButtonPressed"/>.
/// </summary>
/// <param name="button">The button to query</param>
/// <param name="index">The zero-based index of the gamepad, or -1 for any gamepad</param>
/// <returns>Whether the given button is pressed</returns>
public bool IsGamepadButtonPressedIgnoreRepeats ( Buttons button , int index = - 1 ) {
2019-08-28 22:44:59 +02:00
return this . WasGamepadButtonUp ( button , index ) & & this . IsGamepadButtonDown ( button , index ) ;
2019-08-07 22:25:33 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Queries for a gesture of a given type that finished during the current update call.
/// </summary>
/// <param name="type">The type of gesture to query for</param>
/// <param name="sample">The resulting gesture sample, or default if there isn't one</param>
/// <returns>True if a gesture of the type was found, otherwise false</returns>
2019-08-30 18:15:50 +02:00
public bool GetGesture ( GestureType type , out GestureSample sample ) {
2019-08-29 18:12:02 +02:00
foreach ( var gesture in this . Gestures ) {
2020-06-05 23:56:53 +02:00
if ( type . HasFlag ( gesture . GestureType ) ) {
2019-08-30 18:15:50 +02:00
sample = gesture ;
return true ;
}
2019-08-29 18:12:02 +02:00
}
2019-08-30 18:15:50 +02:00
return false ;
2019-08-29 18:12:02 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns if a given control of any kind is down.
/// This is a helper function that can be passed a <see cref="Keys"/>, <see cref="Buttons"/> or <see cref="MouseButton"/>.
/// </summary>
/// <param name="control">The control whose down state to query</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>
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
2020-06-12 17:09:35 +02:00
public bool IsDown ( GenericInput control , int index = - 1 ) {
2020-06-18 17:24:35 +02:00
switch ( control . Type ) {
case GenericInput . InputType . Keyboard :
return this . IsKeyDown ( control ) ;
case GenericInput . InputType . Gamepad :
return this . IsGamepadButtonDown ( control , index ) ;
case GenericInput . InputType . Mouse :
return this . IsMouseButtonDown ( control ) ;
default :
throw new ArgumentException ( nameof ( control ) ) ;
}
2019-08-28 19:36:24 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns if a given control of any kind is up.
/// This is a helper function that can be passed a <see cref="Keys"/>, <see cref="Buttons"/> or <see cref="MouseButton"/>.
/// </summary>
/// <param name="control">The control whose up state to query</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>
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
2020-06-12 17:09:35 +02:00
public bool IsUp ( GenericInput control , int index = - 1 ) {
2020-06-18 17:24:35 +02:00
switch ( control . Type ) {
case GenericInput . InputType . Keyboard :
return this . IsKeyUp ( control ) ;
case GenericInput . InputType . Gamepad :
return this . IsGamepadButtonUp ( control , index ) ;
case GenericInput . InputType . Mouse :
return this . IsMouseButtonUp ( control ) ;
default :
throw new ArgumentException ( nameof ( control ) ) ;
}
2019-08-28 19:36:24 +02:00
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Returns if a given control of any kind is pressed.
/// This is a helper function that can be passed a <see cref="Keys"/>, <see cref="Buttons"/> or <see cref="MouseButton"/>.
/// </summary>
/// <param name="control">The control whose pressed state to query</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>
/// <exception cref="ArgumentException">If the passed control isn't of a supported type</exception>
2020-06-12 17:09:35 +02:00
public bool IsPressed ( GenericInput control , int index = - 1 ) {
2020-06-18 17:24:35 +02:00
switch ( control . Type ) {
case GenericInput . InputType . Keyboard :
return this . IsKeyPressed ( control ) ;
case GenericInput . InputType . Gamepad :
return this . IsGamepadButtonPressed ( control , index ) ;
case GenericInput . InputType . Mouse :
return this . IsMouseButtonPressed ( control ) ;
default :
throw new ArgumentException ( nameof ( control ) ) ;
}
2019-08-28 19:36:24 +02:00
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="IsDown"/>
2020-06-12 17:09:35 +02:00
public bool IsAnyDown ( params GenericInput [ ] control ) {
2020-05-04 16:41:54 +02:00
return control . Any ( c = > this . IsDown ( c ) ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="IsUp"/>
2020-06-12 17:09:35 +02:00
public bool IsAnyUp ( params GenericInput [ ] control ) {
2020-05-04 16:41:54 +02:00
return control . Any ( c = > this . IsUp ( c ) ) ;
}
2020-05-21 17:21:34 +02:00
/// <inheritdoc cref="IsPressed"/>
2020-06-12 17:09:35 +02:00
public bool IsAnyPressed ( params GenericInput [ ] control ) {
2020-05-04 16:41:54 +02:00
return control . Any ( c = > this . IsPressed ( c ) ) ;
}
2020-05-21 17:21:34 +02:00
/// <summary>
/// Helper function to enable gestures for a <see cref="TouchPanel"/> easily.
/// Note that, if other gestures were previously enabled, they will not get overridden.
/// </summary>
/// <param name="gestures">The gestures to enable</param>
2019-08-31 19:32:22 +02:00
public static void EnableGestures ( params GestureType [ ] gestures ) {
foreach ( var gesture in gestures )
TouchPanel . EnabledGestures | = gesture ;
}
2020-05-31 20:49:03 +02:00
/// <summary>
/// Helper function to disable gestures for a <see cref="TouchPanel"/> easily.
/// </summary>
/// <param name="gestures">The gestures to disable</param>
public static void DisableGestures ( params GestureType [ ] gestures ) {
foreach ( var gesture in gestures )
TouchPanel . EnabledGestures & = ~ gesture ;
}
2020-05-31 21:10:01 +02:00
/// <summary>
/// Helper function to enable or disable the given gestures for a <see cref="TouchPanel"/> easily.
/// This method is equivalent to calling <see cref="EnableGestures"/> if the <c>enabled</c> value is true and calling <see cref="DisableGestures"/> if it is false.
/// Note that, if other gestures were previously enabled, they will not get overridden.
/// </summary>
/// <param name="enabled">Whether to enable or disable the gestures</param>
/// <param name="gestures">The gestures to enable or disable</param>
public static void SetGesturesEnabled ( bool enabled , params GestureType [ ] gestures ) {
if ( enabled ) {
EnableGestures ( gestures ) ;
} else {
DisableGestures ( gestures ) ;
}
}
2019-08-28 18:27:17 +02:00
}
2019-08-07 22:25:33 +02:00
}