mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-22 18:29:30 +00:00
New functionality: GamePadListener with associated eventargs, listenerSettings. This addition is feature-complete and entirely documented.
This commit is contained in:
@@ -24,7 +24,7 @@ MonoGame.Extended is designed to build on top of MonoGame, but may work with XNA
|
||||
- **Tile based maps** using [Tiled](http://www.mapeditor.org/) (orthogonal only in v0.3, isometric in master)
|
||||
- **Bitmap fonts** using [BMFont](http://www.angelcode.com/products/bmfont/)
|
||||
- **[Sprites](http://dylanwilson.net/sprites-and-spritebatch-extensions-in-monogame-extended)** (with SpriteBatch extensions!)
|
||||
- **Input listeners** for event driven input handling (Keyboard, Mouse, Touch)
|
||||
- **Input listeners** for event driven input handling (Keyboard, Mouse, Touch) (GamePad in master)
|
||||
- **Texture Atlases** using the JSON format in [TexturePacker](https://www.codeandweb.com/texturepacker)
|
||||
- **2D Camera** with pan, zoom, and rotation
|
||||
- **Viewport Adapters** for resolution independent rendering
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace MonoGame.Extended.InputListeners
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains all information resulting from events fired by
|
||||
/// <see cref="GamePadListener"/>.
|
||||
/// </summary>
|
||||
public class GamePadEventArgs : EventArgs
|
||||
{
|
||||
internal GamePadEventArgs(GamePadState previousState, GamePadState currentState,
|
||||
TimeSpan elapsedTime, PlayerIndex playerIndex, Buttons? button = null,
|
||||
float triggerState = 0, Vector2? thumbStickState = null)
|
||||
{
|
||||
PlayerIndex = playerIndex;
|
||||
PreviousState = previousState;
|
||||
CurrentState = currentState;
|
||||
ElapsedTime = elapsedTime;
|
||||
if (button != null)
|
||||
Button = button.Value;
|
||||
TriggerState = triggerState;
|
||||
ThumbStickState = thumbStickState ?? Vector2.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The index of the controller.
|
||||
/// </summary>
|
||||
public PlayerIndex PlayerIndex { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The state of the controller in the previous update.
|
||||
/// </summary>
|
||||
public GamePadState PreviousState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The state of the controller in this update.
|
||||
/// </summary>
|
||||
public GamePadState CurrentState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The button that triggered this event, if appliable.
|
||||
/// </summary>
|
||||
public Buttons Button { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time elapsed since last event.
|
||||
/// </summary>
|
||||
public TimeSpan ElapsedTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a TriggerMoved event, displays the responsible trigger's position.
|
||||
/// </summary>
|
||||
public float TriggerState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a ThumbStickMoved event, displays the responsible stick's position.
|
||||
/// </summary>
|
||||
public Vector2 ThumbStickState { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,486 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace MonoGame.Extended.InputListeners
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a listener that exposes several events for easier handling of gamepads.
|
||||
/// <para>In order to initialise it, call the <see cref="InputListenerManager.AddListener"/> method
|
||||
/// with a <see cref="GamePadListenerSettings"/> object.</para>
|
||||
/// </summary>
|
||||
public class GamePadListener : InputListener
|
||||
{
|
||||
internal GamePadListener(GamePadListenerSettings settings)
|
||||
{
|
||||
PlayerIndex = settings.PlayerIndex;
|
||||
VibrationEnabled = settings.VibrationEnabled;
|
||||
VibrationStrengthLeft = settings.VibrationStrengthLeft;
|
||||
VibrationStrengthRight = settings.VibrationStrengthRight;
|
||||
ThumbStickDeltaTreshold = settings.ThumbStickDeltaTreshold;
|
||||
ThumbstickDownTreshold = settings.ThumbstickDownTreshold;
|
||||
TriggerDeltaTreshold = settings.TriggerDeltaTreshold;
|
||||
TriggerDownTreshold = settings.TriggerDownTreshold;
|
||||
RepeatInitialDelay = settings.RepeatInitialDelay;
|
||||
RepeatDelay = settings.RepeatDelay;
|
||||
|
||||
_previousGameTime = new GameTime();
|
||||
_previousState = GamePadState.Default;
|
||||
}
|
||||
|
||||
#region events
|
||||
|
||||
/// <summary>
|
||||
/// This event fires whenever a controller connects or disconnects. <para>In order
|
||||
/// for it to work, the <see cref="CheckControllerConnections"/> property must
|
||||
/// be set to true.</para>
|
||||
/// </summary>
|
||||
public static event EventHandler<GamePadEventArgs> ControllerConnectionChanged;
|
||||
|
||||
/// <summary>
|
||||
/// This event fires whenever a button changes from the Up
|
||||
/// to the Down state.
|
||||
/// </summary>
|
||||
public event EventHandler<GamePadEventArgs> ButtonDown;
|
||||
|
||||
/// <summary>
|
||||
/// This event fires whenever a button changes from the Down
|
||||
/// to the Up state.
|
||||
/// </summary>
|
||||
public event EventHandler<GamePadEventArgs> ButtonUp;
|
||||
|
||||
/// <summary>
|
||||
/// This event fires repeatedly whenever a button is held sufficiently
|
||||
/// long. Use this for things like menu navigation.
|
||||
/// </summary>
|
||||
public event EventHandler<GamePadEventArgs> ButtonRepeated;
|
||||
|
||||
/// <summary>
|
||||
/// This event fires whenever a thumbstick changes position.
|
||||
/// <para>The parameter governing the sensitivity of this functionality
|
||||
/// is <see cref="GamePadListenerSettings.ThumbStickDeltaTreshold"/>.</para>
|
||||
/// </summary>
|
||||
public event EventHandler<GamePadEventArgs> ThumbStickMoved;
|
||||
|
||||
/// <summary>
|
||||
/// This event fires whenever a trigger changes position.
|
||||
/// <para>The parameter governing the sensitivity of this functionality
|
||||
/// is <see cref="GamePadListenerSettings.TriggerDeltaTreshold"/>.</para>
|
||||
/// </summary>
|
||||
public event EventHandler<GamePadEventArgs> TriggerMoved;
|
||||
|
||||
#endregion
|
||||
|
||||
#region public properties
|
||||
|
||||
/// <summary>
|
||||
/// If set to true, the static event <see cref="ControllerConnectionChanged"/>
|
||||
/// will fire when any controller changes in connectivity status.
|
||||
/// <para>This functionality requires that you have one actively updating
|
||||
/// <see cref="InputListenerManager"/>.</para>
|
||||
/// </summary>
|
||||
public static bool CheckControllerConnections { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The index of the controller.
|
||||
/// </summary>
|
||||
public PlayerIndex PlayerIndex { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// When a button is held down, the interval in which
|
||||
/// ButtonRepeated fires. Value in milliseconds.
|
||||
/// </summary>
|
||||
public int RepeatDelay { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of time a button has to be held down
|
||||
/// in order to fire ButtonRepeated the first time.
|
||||
/// Value in milliseconds.
|
||||
/// </summary>
|
||||
public int RepeatInitialDelay { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether vibration is enabled for this controller.
|
||||
/// </summary>
|
||||
public bool VibrationEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// General setting for the strength of the left motor.
|
||||
/// This motor has a slow, deep, powerful rumble.
|
||||
/// <para>This setting will modify all future vibrations
|
||||
/// through this listener.</para>
|
||||
/// </summary>
|
||||
public float VibrationStrengthLeft
|
||||
{
|
||||
get { return _vibrationStrengthLeft; }
|
||||
// Clamp the value, just to be sure.
|
||||
set { _vibrationStrengthLeft = MathHelper.Clamp(value, 0, 1); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// General setting for the strength of the right motor.
|
||||
/// This motor has a snappy, quick, high-pitched rumble.
|
||||
/// <para>This setting will modify all future vibrations
|
||||
/// through this listener.</para>
|
||||
/// </summary>
|
||||
public float VibrationStrengthRight
|
||||
{
|
||||
get { return _vibrationStrengthRight; }
|
||||
// Clamp the value, just to be sure.
|
||||
set { _vibrationStrengthRight = MathHelper.Clamp(value, 0, 1); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The treshold of movement that has to be met in order
|
||||
/// for the listener to fire an event with the trigger's
|
||||
/// updated position.
|
||||
/// <para>In essence this defines the event's
|
||||
/// resolution.</para>
|
||||
/// At a value of 0 this will fire every time
|
||||
/// the trigger's position is not 0f.
|
||||
/// </summary>
|
||||
public float TriggerDeltaTreshold { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The treshold of movement that has to be met in order
|
||||
/// for the listener to fire an event with the thumbstick's
|
||||
/// updated position.
|
||||
/// <para>In essence this defines the event's
|
||||
/// resolution.</para>
|
||||
/// At a value of 0 this will fire every time
|
||||
/// the thumbstick's position is not {x:0, y:0}.
|
||||
/// </summary>
|
||||
public float ThumbStickDeltaTreshold { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// How deep the triggers have to be depressed in order to
|
||||
/// register as a ButtonDown event.
|
||||
/// </summary>
|
||||
public float TriggerDownTreshold { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// How deep the triggers have to be depressed in order to
|
||||
/// register as a ButtonDown event.
|
||||
/// </summary>
|
||||
public float ThumbstickDownTreshold { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region private fields
|
||||
private static readonly bool[] GamePadConnections = new bool[4];
|
||||
|
||||
private float _vibrationStrengthLeft;
|
||||
private float _vibrationStrengthRight;
|
||||
|
||||
private GamePadState _currentState;
|
||||
private GamePadState _previousState;
|
||||
//private int _lastPacketNumber;
|
||||
// Implementation doesn't work, see explanation in CheckAllButtons().
|
||||
private GameTime _gameTime;
|
||||
private GameTime _previousGameTime;
|
||||
private Buttons _lastButton;
|
||||
private int _repeatedButtonTimer;
|
||||
|
||||
private GamePadState _lastTriggerState;
|
||||
private GamePadState _lastThumbStickState;
|
||||
private bool _leftTriggerDown;
|
||||
private bool _rightTriggerDown;
|
||||
private bool _leftStickDown;
|
||||
private bool _rightStickDown;
|
||||
private Buttons _lastRightStickDirection;
|
||||
private Buttons _lastLeftStickDirection;
|
||||
|
||||
private float _leftCurVibrationStrength;
|
||||
private float _rightCurVibrationStrength;
|
||||
private TimeSpan _vibrationStart;
|
||||
private TimeSpan _vibrationDurationLeft;
|
||||
private TimeSpan _vibrationDurationRight;
|
||||
private bool _leftVibrating;
|
||||
private bool _rightVibrating;
|
||||
|
||||
// These buttons are not to be evaluated normally, but with the debounce filter
|
||||
// in their respective methods.
|
||||
private readonly Buttons[] _excludedButtons =
|
||||
{
|
||||
Buttons.LeftTrigger, Buttons.RightTrigger,
|
||||
Buttons.LeftThumbstickDown, Buttons.LeftThumbstickUp, Buttons.LeftThumbstickRight, Buttons.LeftThumbstickLeft,
|
||||
Buttons.RightThumbstickLeft, Buttons.RightThumbstickRight, Buttons.RightThumbstickUp, Buttons.RightThumbstickDown
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Send a vibration command to the controller.
|
||||
/// Returns true if the operation succeeded.
|
||||
/// <para>Motor values that are unset preserve
|
||||
/// their current vibration strength and duration.</para>
|
||||
/// Note: Vibration currently only works on select platforms,
|
||||
/// like Monogame.Windows.
|
||||
/// </summary>
|
||||
/// <param name="durationMs">Duration of the vibration in milliseconds.</param>
|
||||
/// <param name="leftStrength">The strength of the left motor.
|
||||
/// This motor has a slow, deep, powerful rumble.</param>
|
||||
/// <param name="rightStrength">The strength of the right motor.
|
||||
/// This motor has a snappy, quick, high-pitched rumble.</param>
|
||||
/// <returns>Returns true if the operation succeeded.</returns>
|
||||
public bool Vibrate(int durationMs, float leftStrength = float.NegativeInfinity,
|
||||
float rightStrength = float.NegativeInfinity)
|
||||
{
|
||||
if (!VibrationEnabled)
|
||||
return false;
|
||||
|
||||
var lstrength = MathHelper.Clamp(leftStrength, 0, 1);
|
||||
var rstrength = MathHelper.Clamp(rightStrength, 0, 1);
|
||||
|
||||
if (float.IsNegativeInfinity(leftStrength))
|
||||
lstrength = _leftCurVibrationStrength;
|
||||
if (float.IsNegativeInfinity(rightStrength))
|
||||
rstrength = _rightCurVibrationStrength;
|
||||
|
||||
var success = GamePad.SetVibration(PlayerIndex, lstrength * VibrationStrengthLeft,
|
||||
rstrength * VibrationStrengthRight);
|
||||
if (success)
|
||||
{
|
||||
_leftVibrating = true;
|
||||
_rightVibrating = true;
|
||||
|
||||
if (leftStrength > 0)
|
||||
_vibrationDurationLeft = new TimeSpan(0, 0, 0, 0, durationMs);
|
||||
else if (lstrength > 0)
|
||||
_vibrationDurationLeft -= _gameTime.TotalGameTime - _vibrationStart;
|
||||
else
|
||||
_leftVibrating = false;
|
||||
|
||||
if (rightStrength > 0)
|
||||
_vibrationDurationRight = new TimeSpan(0, 0, 0, 0, durationMs);
|
||||
else if (rstrength > 0)
|
||||
_vibrationDurationRight -= _gameTime.TotalGameTime - _vibrationStart;
|
||||
else
|
||||
_rightVibrating = false;
|
||||
|
||||
_vibrationStart = _gameTime.TotalGameTime;
|
||||
|
||||
_leftCurVibrationStrength = lstrength;
|
||||
_rightCurVibrationStrength = rstrength;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private void CheckAllButtons()
|
||||
{
|
||||
// PacketNumber only and always changes if there is a difference between GamePadStates.
|
||||
// ...At least, that's the theory. It doesn't seem to be implemented. Disabled for now.
|
||||
//if (_lastPacketNumber == _currentState.PacketNumber)
|
||||
// return;
|
||||
foreach (Buttons button in Enum.GetValues(typeof (Buttons)))
|
||||
{
|
||||
if (_excludedButtons.Contains(button))
|
||||
break;
|
||||
if (_currentState.IsButtonDown(button) && _previousState.IsButtonUp(button))
|
||||
RaiseButtonDown(button);
|
||||
if (_currentState.IsButtonUp(button) && _previousState.IsButtonDown(button))
|
||||
RaiseButtonUp(button);
|
||||
}
|
||||
|
||||
// Checks triggers as buttons and floats
|
||||
CheckTriggers(s => s.Triggers.Left, Buttons.LeftTrigger);
|
||||
CheckTriggers(s => s.Triggers.Right, Buttons.RightTrigger);
|
||||
|
||||
// Checks thumbsticks as vector2s
|
||||
CheckThumbSticks(s => s.ThumbSticks.Right, Buttons.RightStick);
|
||||
CheckThumbSticks(s => s.ThumbSticks.Left, Buttons.LeftStick);
|
||||
}
|
||||
|
||||
private void CheckTriggers(Func<GamePadState, float> getButtonState, Buttons button)
|
||||
{
|
||||
float debounce = 0.05f; // Value used to qualify a trigger as coming Up from a Down state
|
||||
var curstate = getButtonState(_currentState);
|
||||
bool curdown = curstate > TriggerDownTreshold;
|
||||
bool prevdown = button == Buttons.RightTrigger ? _rightTriggerDown : _leftTriggerDown;
|
||||
|
||||
if (!prevdown && curdown)
|
||||
{
|
||||
RaiseButtonDown(button);
|
||||
if (button == Buttons.RightTrigger)
|
||||
_rightTriggerDown = true;
|
||||
else
|
||||
_leftTriggerDown = true;
|
||||
|
||||
}
|
||||
else if (prevdown && curstate < debounce)
|
||||
{
|
||||
RaiseButtonUp(button);
|
||||
if (button == Buttons.RightTrigger)
|
||||
_rightTriggerDown = false;
|
||||
else
|
||||
_leftTriggerDown = false;
|
||||
}
|
||||
|
||||
var prevstate = getButtonState(_lastTriggerState);
|
||||
if (curstate > TriggerDeltaTreshold)
|
||||
{
|
||||
if (Math.Abs(prevstate - curstate) >= TriggerDeltaTreshold)
|
||||
{
|
||||
TriggerMoved.Raise(this, MakeArgs(button, triggerstate: curstate));
|
||||
_lastTriggerState = _currentState;
|
||||
}
|
||||
}
|
||||
else if (prevstate > TriggerDeltaTreshold)
|
||||
{
|
||||
TriggerMoved.Raise(this, MakeArgs(button, triggerstate: curstate));
|
||||
_lastTriggerState = _currentState;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckThumbSticks(Func<GamePadState, Vector2> getButtonState, Buttons button)
|
||||
{
|
||||
const float debounce = 0.15f;
|
||||
var curVector = getButtonState(_currentState);
|
||||
bool curdown = curVector.Length() > ThumbstickDownTreshold;
|
||||
bool right = button == Buttons.RightStick;
|
||||
bool prevdown = right ? _rightStickDown : _leftStickDown;
|
||||
|
||||
var prevdir = button == Buttons.RightStick ? _lastRightStickDirection : _lastLeftStickDirection;
|
||||
Buttons curdir;
|
||||
if (curVector.Y > curVector.X)
|
||||
{
|
||||
if (curVector.Y > -curVector.X)
|
||||
curdir = right ? Buttons.RightThumbstickUp : Buttons.LeftThumbstickUp;
|
||||
else
|
||||
curdir = right ? Buttons.RightThumbstickLeft : Buttons.LeftThumbstickLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curVector.Y < -curVector.X)
|
||||
curdir = right ? Buttons.RightThumbstickDown : Buttons.LeftThumbstickDown;
|
||||
else
|
||||
curdir = right ? Buttons.RightThumbstickRight : Buttons.LeftThumbstickRight;
|
||||
}
|
||||
|
||||
if (!prevdown && curdown)
|
||||
{
|
||||
if (right)
|
||||
_lastRightStickDirection = curdir;
|
||||
else
|
||||
_lastLeftStickDirection = curdir;
|
||||
|
||||
RaiseButtonDown(curdir);
|
||||
if (button == Buttons.RightStick)
|
||||
_rightStickDown = true;
|
||||
else
|
||||
_leftStickDown = true;
|
||||
}
|
||||
else if (prevdown && curVector.Length() < debounce)
|
||||
{
|
||||
RaiseButtonUp(prevdir);
|
||||
if (button == Buttons.RightStick)
|
||||
_rightStickDown = false;
|
||||
else
|
||||
_leftStickDown = false;
|
||||
}
|
||||
else if (prevdown && curdown && curdir != prevdir)
|
||||
{
|
||||
RaiseButtonUp(prevdir);
|
||||
if (right)
|
||||
_lastRightStickDirection = curdir;
|
||||
else
|
||||
_lastLeftStickDirection = curdir;
|
||||
RaiseButtonDown(curdir);
|
||||
}
|
||||
|
||||
var prevVector = getButtonState(_lastThumbStickState);
|
||||
if (curVector.Length() > ThumbStickDeltaTreshold)
|
||||
{
|
||||
if (Vector2.Distance(curVector, prevVector) >= ThumbStickDeltaTreshold)
|
||||
{
|
||||
ThumbStickMoved.Raise(this, MakeArgs(button, thumbStickState: curVector));
|
||||
_lastThumbStickState = _currentState;
|
||||
}
|
||||
} else if (prevVector.Length() > ThumbStickDeltaTreshold)
|
||||
{
|
||||
ThumbStickMoved.Raise(this, MakeArgs(button, thumbStickState: curVector));
|
||||
_lastThumbStickState = _currentState;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void CheckConnections()
|
||||
{
|
||||
if (!CheckControllerConnections)
|
||||
return;
|
||||
|
||||
foreach (PlayerIndex index in Enum.GetValues(typeof(PlayerIndex)))
|
||||
{
|
||||
if (GamePad.GetState(index).IsConnected ^ GamePadConnections[(int) index]) // We need more XORs in this world
|
||||
{
|
||||
GamePadConnections[(int) index] = !GamePadConnections[(int) index];
|
||||
ControllerConnectionChanged.Raise(null,
|
||||
new GamePadEventArgs(GamePadState.Default, GamePad.GetState(index), TimeSpan.Zero, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckVibrate()
|
||||
{
|
||||
if (_leftVibrating && _vibrationStart + _vibrationDurationLeft < _gameTime.TotalGameTime)
|
||||
Vibrate(0, leftStrength: 0);
|
||||
if (_rightVibrating && _vibrationStart + _vibrationDurationRight < _gameTime.TotalGameTime)
|
||||
Vibrate(0, rightStrength: 0);
|
||||
}
|
||||
|
||||
internal override void Update(GameTime gameTime)
|
||||
{
|
||||
_gameTime = gameTime;
|
||||
_currentState = GamePad.GetState(PlayerIndex);
|
||||
CheckVibrate();
|
||||
if (!_currentState.IsConnected)
|
||||
return;
|
||||
CheckAllButtons();
|
||||
CheckRepeatButton();
|
||||
//_lastPacketNumber = _currentState.PacketNumber;
|
||||
_previousGameTime = gameTime;
|
||||
_previousState = _currentState;
|
||||
}
|
||||
private GamePadEventArgs MakeArgs(Buttons? button,
|
||||
float triggerstate = 0, Vector2? thumbStickState = null)
|
||||
{
|
||||
var elapsedTime = _gameTime.TotalGameTime - _previousGameTime.TotalGameTime;
|
||||
return new GamePadEventArgs(_previousState, _currentState,
|
||||
elapsedTime, PlayerIndex, button, triggerstate, thumbStickState);
|
||||
}
|
||||
|
||||
private void RaiseButtonDown(Buttons button)
|
||||
{
|
||||
ButtonDown.Raise(this, MakeArgs(button));
|
||||
ButtonRepeated.Raise(this, MakeArgs(button));
|
||||
_lastButton = button;
|
||||
_repeatedButtonTimer = 0;
|
||||
}
|
||||
|
||||
private void RaiseButtonUp(Buttons button)
|
||||
{
|
||||
ButtonUp.Raise(this, MakeArgs(button));
|
||||
_lastButton = 0;
|
||||
}
|
||||
|
||||
private void CheckRepeatButton()
|
||||
{
|
||||
_repeatedButtonTimer += _gameTime.ElapsedGameTime.Milliseconds;
|
||||
|
||||
if(_repeatedButtonTimer < RepeatInitialDelay || _lastButton == 0)
|
||||
return;
|
||||
|
||||
if (_repeatedButtonTimer < RepeatInitialDelay + RepeatDelay)
|
||||
{
|
||||
ButtonRepeated.Raise(this, MakeArgs(_lastButton));
|
||||
_repeatedButtonTimer = RepeatDelay + RepeatInitialDelay;
|
||||
}
|
||||
else if (_repeatedButtonTimer > RepeatInitialDelay + RepeatDelay*2)
|
||||
{
|
||||
ButtonRepeated.Raise(this, MakeArgs(_lastButton));
|
||||
_repeatedButtonTimer = RepeatDelay + RepeatInitialDelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MonoGame.Extended.InputListeners
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a class that contains settings to be used to initialise a <see cref="GamePadListener"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="InputListenerManager"/>
|
||||
public class GamePadListenerSettings : InputListenerSettings<GamePadListener>
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a class that contains settings to be used to initialise a <see cref="GamePadListener"/>.
|
||||
/// <para>Note: There are a number of extra settings that are settable properties.</para>
|
||||
/// </summary>
|
||||
/// <param name="playerIndex">The index of the controller the listener will be tied to.</param>
|
||||
/// <param name="vibrationEnabled">Whether vibration is enabled on the controller.</param>
|
||||
/// <param name="vibrationStrengthLeft">General setting for the strength of the left motor.
|
||||
/// This motor has a slow, deep, powerful rumble.
|
||||
/// This setting will modify all future vibrations
|
||||
/// through this listener.</param>
|
||||
/// <param name="vibrationStrengthRight">General setting for the strength of the right motor.
|
||||
/// This motor has a snappy, quick, high-pitched rumble.
|
||||
/// This setting will modify all future vibrations
|
||||
/// through this listener.</param>
|
||||
public GamePadListenerSettings(PlayerIndex playerIndex, bool vibrationEnabled = true,
|
||||
float vibrationStrengthLeft = 1.0f, float vibrationStrengthRight = 1.0f)
|
||||
{
|
||||
PlayerIndex = playerIndex;
|
||||
VibrationEnabled = vibrationEnabled;
|
||||
VibrationStrengthLeft = vibrationStrengthLeft;
|
||||
VibrationStrengthRight = vibrationStrengthRight;
|
||||
TriggerDownTreshold = 0.15f;
|
||||
ThumbstickDownTreshold = 0.5f;
|
||||
RepeatInitialDelay = 500;
|
||||
RepeatDelay = 50;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The index of the controller.
|
||||
/// </summary>
|
||||
public PlayerIndex PlayerIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When a button is held down, the interval in which
|
||||
/// ButtonRepeated fires. Value in milliseconds.
|
||||
/// </summary>
|
||||
public int RepeatDelay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of time a button has to be held down
|
||||
/// in order to fire ButtonRepeated the first time.
|
||||
/// Value in milliseconds.
|
||||
/// </summary>
|
||||
public int RepeatInitialDelay { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Whether vibration is enabled for this controller.
|
||||
/// </summary>
|
||||
public bool VibrationEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// General setting for the strength of the left motor.
|
||||
/// This motor has a slow, deep, powerful rumble.
|
||||
/// <para>This setting will modify all future vibrations
|
||||
/// through this listener.</para>
|
||||
/// </summary>
|
||||
public float VibrationStrengthLeft { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// General setting for the strength of the right motor.
|
||||
/// This motor has a snappy, quick, high-pitched rumble.
|
||||
/// <para>This setting will modify all future vibrations
|
||||
/// through this listener.</para>
|
||||
/// </summary>
|
||||
public float VibrationStrengthRight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The treshold of movement that has to be met in order
|
||||
/// for the listener to fire an event with the trigger's
|
||||
/// updated position.
|
||||
/// <para>In essence this defines the event's
|
||||
/// resolution.</para>
|
||||
/// At a value of 0 this will fire every time
|
||||
/// the trigger's position is not 0f.
|
||||
/// </summary>
|
||||
public float TriggerDeltaTreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The treshold of movement that has to be met in order
|
||||
/// for the listener to fire an event with the thumbstick's
|
||||
/// updated position.
|
||||
/// <para>In essence this defines the event's
|
||||
/// resolution.</para>
|
||||
/// At a value of 0 this will fire every time
|
||||
/// the thumbstick's position is not {x:0, y:0}.
|
||||
/// </summary>
|
||||
public float ThumbStickDeltaTreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How deep the triggers have to be depressed in order to
|
||||
/// register as a ButtonDown event.
|
||||
/// </summary>
|
||||
public float TriggerDownTreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How deep the triggers have to be depressed in order to
|
||||
/// register as a ButtonDown event.
|
||||
/// </summary>
|
||||
public float ThumbstickDownTreshold { get; private set; }
|
||||
|
||||
internal override GamePadListener CreateListener()
|
||||
{
|
||||
return new GamePadListener(this);
|
||||
}
|
||||
|
||||
// For internal use only. This limits the user to only having
|
||||
// one controller.
|
||||
internal GamePadListenerSettings() : this(PlayerIndex.One) { }
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,8 @@ namespace MonoGame.Extended.InputListeners
|
||||
{
|
||||
foreach (var listener in _listeners)
|
||||
listener.Update(gameTime);
|
||||
|
||||
GamePadListener.CheckConnections();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user