Brought XInput GamePad to 100% implementation (final testing still needs to be done)

This commit is contained in:
SND\AstrorEnales_cp 2012-09-01 13:22:52 +00:00
parent 55fac0cc5a
commit ce07f40b4c

View File

@ -2,8 +2,8 @@ using System;
using ANX.Framework; using ANX.Framework;
using ANX.Framework.Input; using ANX.Framework.Input;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using SharpDX.XInput;
using ANX.Framework.NonXNA.Development; using ANX.Framework.NonXNA.Development;
using SharpDX.XInput;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -11,39 +11,49 @@ using ANX.Framework.NonXNA.Development;
namespace ANX.InputDevices.Windows.XInput namespace ANX.InputDevices.Windows.XInput
{ {
[PercentageComplete(90)] [PercentageComplete(100)]
[TestState(TestStateAttribute.TestState.InProgress)] [TestState(TestStateAttribute.TestState.InProgress)]
[Developer("AstrorEnales")] [Developer("AstrorEnales")]
public class GamePad : IGamePad public class GamePad : IGamePad
{ {
#region Private #region Constants
private Controller[] controller; private const int LeftThumbDeadZoneSquare = 7849 * 7849;
private const float thumbstickRangeFactor = 1f / short.MaxValue; private const int RightThumbDeadZoneSquare = 8689 * 8689;
private const float triggerRangeFactor = 1f / byte.MaxValue;
private GamePadCapabilities emptyCaps;
private GamePadState emptyState;
#endregion #endregion
#region Private
private Controller[] controller;
private const float triggerRangeFactor = 1f / byte.MaxValue;
private GamePadCapabilities emptyCaps = new GamePadCapabilities();
private GamePadState emptyState = new GamePadState();
#endregion
#region Constructor
public GamePad() public GamePad()
{ {
controller = new Controller[4]; controller = new Controller[4];
for (int index = 0; index < controller.Length; index++) for (int index = 0; index < controller.Length; index++)
controller[index] = new Controller((UserIndex)index); controller[index] = new Controller((UserIndex)index);
} }
#endregion
#region GetCapabilities
public GamePadCapabilities GetCapabilities(PlayerIndex playerIndex) public GamePadCapabilities GetCapabilities(PlayerIndex playerIndex)
{ {
var gamepad = controller[(int)playerIndex];
if (gamepad.IsConnected == false)
return emptyCaps;
try try
{ {
Capabilities nativeCaps = controller[(int)playerIndex].GetCapabilities(DeviceQueryType.Gamepad); Capabilities nativeCaps = gamepad.GetCapabilities(DeviceQueryType.Gamepad);
return new GamePadCapabilities() return new GamePadCapabilities()
{ {
GamePadType = FormatConverter.Translate(nativeCaps.SubType), GamePadType = FormatConverter.Translate(nativeCaps.SubType),
IsConnected = controller[(int)playerIndex].IsConnected, IsConnected = gamepad.IsConnected,
HasAButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.A) != 0, HasAButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.A) != 0,
HasBackButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.Back) != 0, HasBackButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.Back) != 0,
HasBButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.B) != 0, HasBButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.B) != 0,
HasBigButton = false, // TODO
HasDPadDownButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0, HasDPadDownButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.DPadDown) != 0,
HasDPadLeftButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0, HasDPadLeftButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.DPadLeft) != 0,
HasDPadRightButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0, HasDPadRightButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.DPadRight) != 0,
@ -55,48 +65,37 @@ namespace ANX.InputDevices.Windows.XInput
HasStartButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.Start) != 0, HasStartButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.Start) != 0,
HasXButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.X) != 0, HasXButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.X) != 0,
HasYButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.Y) != 0, HasYButton = (nativeCaps.Gamepad.Buttons & GamepadButtonFlags.Y) != 0,
HasLeftVibrationMotor = false, HasLeftVibrationMotor = nativeCaps.Vibration.LeftMotorSpeed != 0,
HasRightVibrationMotor = false, // TODO HasRightVibrationMotor = nativeCaps.Vibration.RightMotorSpeed != 0,
HasVoiceSupport = false, // TODO HasVoiceSupport = (nativeCaps.Flags & CapabilityFlags.VoiceSupported) != 0,
HasRightXThumbStick = false, // TODO HasRightXThumbStick = nativeCaps.Gamepad.RightThumbX != 0,
HasRightYThumbStick = false, // TODO HasRightYThumbStick = nativeCaps.Gamepad.RightThumbY != 0,
HasLeftXThumbStick = false, // TODO HasLeftXThumbStick = nativeCaps.Gamepad.LeftThumbX != 0,
HasLeftYThumbStick = false, // TODO HasLeftYThumbStick = nativeCaps.Gamepad.LeftThumbY != 0,
HasLeftTrigger = false, // TODO HasLeftTrigger = nativeCaps.Gamepad.LeftTrigger > 0,
HasRightTrigger = false, // TODO HasRightTrigger = nativeCaps.Gamepad.RightTrigger > 0,
// Impossible to check
HasBigButton = false,
}; };
} }
catch catch (Exception ex)
{ {
Logger.Info("Failed to get caps for gamepad " + playerIndex + ": " + ex);
return emptyCaps; return emptyCaps;
} }
} }
#endregion
#region GetState
public GamePadState GetState(PlayerIndex playerIndex, out bool isConnected, out int packetNumber) public GamePadState GetState(PlayerIndex playerIndex, out bool isConnected, out int packetNumber)
{ {
isConnected = controller[(int)playerIndex].IsConnected; return GetState(playerIndex, GamePadDeadZone.None, out isConnected, out packetNumber);
if (isConnected == false)
{
packetNumber = 0;
return emptyState;
}
State nativeState = controller[(int)playerIndex].GetState();
var result = new GamePadState(
new Vector2(nativeState.Gamepad.LeftThumbX, nativeState.Gamepad.LeftThumbY) * thumbstickRangeFactor,
new Vector2(nativeState.Gamepad.RightThumbX, nativeState.Gamepad.RightThumbY) * thumbstickRangeFactor,
nativeState.Gamepad.LeftTrigger * triggerRangeFactor, nativeState.Gamepad.RightTrigger * triggerRangeFactor,
FormatConverter.Translate(nativeState.Gamepad.Buttons));
packetNumber = nativeState.PacketNumber;
return result;
} }
public GamePadState GetState(PlayerIndex playerIndex, GamePadDeadZone deadZoneMode, out bool isConnected, public GamePadState GetState(PlayerIndex playerIndex, GamePadDeadZone deadZoneMode, out bool isConnected,
out int packetNumber) out int packetNumber)
{ {
// TODO: deadZoneMode
isConnected = controller[(int)playerIndex].IsConnected; isConnected = controller[(int)playerIndex].IsConnected;
if (isConnected == false) if (isConnected == false)
{ {
@ -105,10 +104,10 @@ namespace ANX.InputDevices.Windows.XInput
} }
State nativeState = controller[(int)playerIndex].GetState(); State nativeState = controller[(int)playerIndex].GetState();
Vector2 leftThumb = ConvertThumbStick(nativeState.Gamepad.LeftThumbX, nativeState.Gamepad.LeftThumbY, Vector2 leftThumb = ApplyDeadZone(nativeState.Gamepad.LeftThumbX, nativeState.Gamepad.LeftThumbY,
SharpDX.XInput.Gamepad.LeftThumbDeadZone, deadZoneMode); LeftThumbDeadZoneSquare, deadZoneMode);
Vector2 rightThumb = ConvertThumbStick(nativeState.Gamepad.RightThumbX, nativeState.Gamepad.RightThumbY, Vector2 rightThumb = ApplyDeadZone(nativeState.Gamepad.RightThumbX, nativeState.Gamepad.RightThumbY,
SharpDX.XInput.Gamepad.LeftThumbDeadZone, deadZoneMode); RightThumbDeadZoneSquare, deadZoneMode);
var result = new GamePadState(leftThumb, rightThumb, nativeState.Gamepad.LeftTrigger * triggerRangeFactor, var result = new GamePadState(leftThumb, rightThumb, nativeState.Gamepad.LeftTrigger * triggerRangeFactor,
nativeState.Gamepad.RightTrigger * triggerRangeFactor, FormatConverter.Translate(nativeState.Gamepad.Buttons)); nativeState.Gamepad.RightTrigger * triggerRangeFactor, FormatConverter.Translate(nativeState.Gamepad.Buttons));
@ -116,7 +115,9 @@ namespace ANX.InputDevices.Windows.XInput
packetNumber = nativeState.PacketNumber; packetNumber = nativeState.PacketNumber;
return result; return result;
} }
#endregion
#region SetVibration
public bool SetVibration(PlayerIndex playerIndex, float leftMotor, float rightMotor) public bool SetVibration(PlayerIndex playerIndex, float leftMotor, float rightMotor)
{ {
if (controller[(int)playerIndex].IsConnected == false) if (controller[(int)playerIndex].IsConnected == false)
@ -124,35 +125,37 @@ namespace ANX.InputDevices.Windows.XInput
var vib = new Vibration() var vib = new Vibration()
{ {
LeftMotorSpeed = (short)((Math.Abs(leftMotor) > 1) ? 1 : Math.Abs(leftMotor) * short.MaxValue), LeftMotorSpeed = (short)(Math.Min(Math.Abs(leftMotor), 1f) * short.MaxValue),
RightMotorSpeed = (short)((Math.Abs(rightMotor) > 1) ? 1 : Math.Abs(rightMotor) * short.MaxValue), RightMotorSpeed = (short)(Math.Min(Math.Abs(rightMotor), 1f) * short.MaxValue),
}; };
controller[(int)playerIndex].SetVibration(vib); controller[(int)playerIndex].SetVibration(vib);
return true; return true;
} }
#endregion
private Vector2 ConvertThumbStick(int x, int y, int deadZone, GamePadDeadZone deadZoneMode) #region ApplyDeadZone
private Vector2 ApplyDeadZone(int x, int y, int deadZone, GamePadDeadZone deadZoneMode)
{ {
int deadZoneSquare = deadZone * deadZone; if (deadZoneMode != GamePadDeadZone.None)
if (deadZoneMode == GamePadDeadZone.IndependentAxes)
{ {
if (x * x < deadZoneSquare) int xSquare = x * x;
x = 0; int ySquare = y * y;
if (y * y < deadZoneSquare) if (deadZoneMode == GamePadDeadZone.IndependentAxes)
y = 0;
}
else if (deadZoneMode == GamePadDeadZone.Circular)
{
if ((x * x) + (y * y) < deadZoneSquare)
{ {
x = 0; if (xSquare < deadZone)
y = 0; x = 0;
if (ySquare < deadZone)
y = 0;
} }
else if (deadZoneMode == GamePadDeadZone.Circular && xSquare + ySquare < deadZone)
x = y = 0;
} }
return new Vector2(x < 0 ? -((float)x / (float)short.MinValue) : (float)x / (float)short.MaxValue, float fx = x < 0 ? -(x / (float)short.MinValue) : x / (float)short.MaxValue;
y < 0 ? -((float)y / (float)short.MinValue) : (float)y / (float)short.MaxValue); float fy = y < 0 ? -(y / (float)short.MinValue) : y / (float)short.MaxValue;
return new Vector2(fx, fy);
} }
#endregion
} }
} }