Implemented thumbsticks and trigger caps

This commit is contained in:
Stefanos A 2013-12-24 12:47:09 +01:00 committed by thefiddler
parent 7e5307bd4a
commit 2839db587e
7 changed files with 230 additions and 108 deletions

View file

@ -27,12 +27,15 @@ using System;
namespace OpenTK.Input
{
internal enum GamePadAxis
[Flags]
internal enum GamePadAxes : byte
{
LeftX,
LeftY,
RightX,
RightY
LeftX = 1 << 0,
LeftY = 1 << 1,
LeftTrigger = 1 << 2,
RightX = 1 << 3,
RightY = 1 << 4,
RightTrigger = 1 << 5,
}
}

View file

@ -35,15 +35,17 @@ namespace OpenTK.Input
public struct GamePadCapabilities : IEquatable<GamePadCapabilities>
{
Buttons buttons;
GamePadAxes axes;
byte gamepad_type;
bool is_connected;
#region Constructors
public GamePadCapabilities(GamePadType type, Buttons buttons, bool is_connected)
internal GamePadCapabilities(GamePadType type, GamePadAxes axes, Buttons buttons, bool is_connected)
: this()
{
gamepad_type = (byte)type;
this.axes = axes;
this.buttons = buttons;
this.is_connected = is_connected;
}
@ -134,32 +136,32 @@ namespace OpenTK.Input
public bool HasLeftXThumbStick
{
get { return false; }
get { return (axes & GamePadAxes.LeftX) != 0; }
}
public bool HasLeftYThumbStick
{
get { return false; }
get { return (axes & GamePadAxes.LeftY) != 0; }
}
public bool HasRightXThumbStick
{
get { return false; }
get { return (axes & GamePadAxes.RightX) != 0; }
}
public bool HasRightYThumbStick
{
get { return false; }
get { return (axes & GamePadAxes.RightY) != 0; }
}
public bool HasLeftTrigger
{
get { return false; }
get { return (axes & GamePadAxes.LeftTrigger) != 0; }
}
public bool HasRightTrigger
{
get { return false; }
get { return (axes & GamePadAxes.RightTrigger) != 0; }
}
public bool HasLeftVibrationMotor
@ -195,8 +197,11 @@ namespace OpenTK.Input
public override string ToString()
{
return String.Format(
"{{Type: {0}; Buttons: {1}; Connected: {2}}}",
GamePadType, Convert.ToString((int)buttons, 2), IsConnected);
"{{Type: {0}; Axes: {1}; Buttons: {2}; Connected: {3}}}",
GamePadType,
Convert.ToString((int)axes, 2),
Convert.ToString((int)buttons, 2),
IsConnected);
}
public override int GetHashCode()

View file

@ -62,6 +62,11 @@ namespace OpenTK.Input
get { return new GamePadDPad(buttons); }
}
public GamePadTriggers Triggers
{
get { return new GamePadTriggers(left_trigger, right_trigger); }
}
public bool IsConnected
{
get { return is_connected; }
@ -104,23 +109,23 @@ namespace OpenTK.Input
#region Internal Members
internal void SetAxis(GamePadAxis axis, short value)
internal void SetAxis(GamePadAxes axis, short value)
{
switch (axis)
{
case GamePadAxis.LeftX:
case GamePadAxes.LeftX:
left_stick_x = value;
break;
case GamePadAxis.LeftY:
case GamePadAxes.LeftY:
left_stick_y = value;
break;
case GamePadAxis.RightX:
case GamePadAxes.RightX:
right_stick_x = value;
break;
case GamePadAxis.RightY:
case GamePadAxes.RightY:
right_stick_y = value;
break;
@ -146,11 +151,17 @@ namespace OpenTK.Input
is_connected = connected;
}
internal void SetTriggers(byte left, byte right)
{
left_trigger = left;
right_trigger = right;
}
#endregion
#region Private Members
bool IsAxisValid(GamePadAxis axis)
bool IsAxisValid(GamePadAxes axis)
{
int index = (int)axis;
return index >= 0 && index < GamePad.MaxAxisCount;

View file

@ -41,5 +41,7 @@ namespace OpenTK.Input
BigButtonPad,
DrumKit,
GamePad,
ArcadePad,
BassGuitar,
}
}

View file

@ -258,7 +258,7 @@ namespace OpenTK.Platform.SDL2
int id = ev.Which;
if (IsControllerValid(id))
{
controllers[id].State.SetAxis((GamePadAxis)ev.Axis, ev.Value);
controllers[id].State.SetAxis((GamePadAxes)ev.Axis, ev.Value);
}
else
{

View file

@ -470,10 +470,10 @@ namespace OpenTK.Platform.Windows
info.Flags = JoystickFlags.All;
UnsafeNativeMethods.joyGetPosEx(index, ref info);
state.SetAxis(GamePadAxis.LeftX, (short)info.XPos);
state.SetAxis(GamePadAxis.LeftY, (short)info.YPos);
state.SetAxis(GamePadAxis.RightX, (short)info.ZPos);
state.SetAxis(GamePadAxis.RightY, (short)info.RPos);
state.SetAxis(GamePadAxes.LeftX, (short)info.XPos);
state.SetAxis(GamePadAxes.LeftY, (short)info.YPos);
state.SetAxis(GamePadAxes.RightX, (short)info.ZPos);
state.SetAxis(GamePadAxes.RightY, (short)info.RPos);
//state.SetAxis(GamePadAxis.RightX, (short)info.ZPos);
//state.SetAxis(GamePadAxis.RightY, (short)info.RPos);

View file

@ -33,41 +33,56 @@ using System.Text;
using OpenTK.Input;
using System.Runtime.InteropServices;
using System.Security;
using System.Diagnostics;
namespace OpenTK.Platform.Windows
{
class XInputJoystick : IGamePadDriver
class XInputJoystick : IGamePadDriver, IDisposable
{
XInput xinput = new XInput();
#region IGamePadDriver Members
public GamePadState GetState(int index)
{
XInputState xstate;
XInput910.GetState((XInputUserIndex)index, out xstate);
XInputErrorCode error = xinput.GetState((XInputUserIndex)index, out xstate);
GamePadState state = new GamePadState();
state.SetButton(Buttons.A, (xstate.GamePad.Buttons & XInputButtons.A) != 0);
state.SetButton(Buttons.B, (xstate.GamePad.Buttons & XInputButtons.B) != 0);
state.SetButton(Buttons.X, (xstate.GamePad.Buttons & XInputButtons.X) != 0);
state.SetButton(Buttons.Y, (xstate.GamePad.Buttons & XInputButtons.Y) != 0);
state.SetButton(Buttons.Start, (xstate.GamePad.Buttons & XInputButtons.Start) != 0);
state.SetButton(Buttons.Back, (xstate.GamePad.Buttons & XInputButtons.Back) != 0);
//state.SetButton(Buttons.BigButton, (xstate.GamePad.Buttons & XInputButtons.???) != 0);
state.SetButton(Buttons.LeftShoulder, (xstate.GamePad.Buttons & XInputButtons.LeftShoulder) != 0);
state.SetButton(Buttons.RightShoulder, (xstate.GamePad.Buttons & XInputButtons.RightShoulder) != 0);
state.SetButton(Buttons.LeftStick, (xstate.GamePad.Buttons & XInputButtons.LeftThumb) != 0);
state.SetButton(Buttons.RightStick, (xstate.GamePad.Buttons & XInputButtons.RightThumb) != 0);
state.SetButton(Buttons.DPadDown, (xstate.GamePad.Buttons & XInputButtons.DPadDown) != 0);
state.SetButton(Buttons.DPadUp, (xstate.GamePad.Buttons & XInputButtons.DPadUp) != 0);
state.SetButton(Buttons.DPadLeft, (xstate.GamePad.Buttons & XInputButtons.DPadLeft) != 0);
state.SetButton(Buttons.DPadRight, (xstate.GamePad.Buttons & XInputButtons.DPadRight) != 0);
if (error == XInputErrorCode.Success)
{
state.SetConnected(true);
state.SetAxis(GamePadAxes.LeftX, xstate.GamePad.ThumbLX);
state.SetAxis(GamePadAxes.LeftY, xstate.GamePad.ThumbLY);
state.SetAxis(GamePadAxes.RightX, xstate.GamePad.ThumbRX);
state.SetAxis(GamePadAxes.RightY, xstate.GamePad.ThumbRY);
state.SetTriggers(xstate.GamePad.LeftTrigger, xstate.GamePad.RightTrigger);
state.SetButton(TranslateButtons(xstate.GamePad.Buttons), true);
}
return state;
}
public GamePadCapabilities GetCapabilities(int index)
{
throw new NotImplementedException();
XInputDeviceCapabilities xcaps;
XInputErrorCode error = xinput.GetCapabilities(
(XInputUserIndex)index,
XInputCapabilitiesFlags.Default,
out xcaps);
if (error == XInputErrorCode.Success)
{
GamePadType type = TranslateSubType(xcaps.SubType);
Buttons buttons = TranslateButtons(xcaps.GamePad.Buttons);
GamePadAxes axes = TranslateAxes(ref xcaps.GamePad);
return new GamePadCapabilities(type, axes, buttons, true);
}
return new GamePadCapabilities();
}
public string GetName(int index)
@ -78,6 +93,58 @@ namespace OpenTK.Platform.Windows
#endregion
#region Private Members
GamePadAxes TranslateAxes(ref XInputGamePad pad)
{
GamePadAxes axes = 0;
axes |= pad.ThumbLX != 0 ? GamePadAxes.LeftX : 0;
axes |= pad.ThumbLY != 0 ? GamePadAxes.LeftY : 0;
axes |= pad.LeftTrigger != 0 ? GamePadAxes.LeftTrigger : 0;
axes |= pad.ThumbRX != 0 ? GamePadAxes.RightX : 0;
axes |= pad.ThumbRY != 0 ? GamePadAxes.RightY : 0;
axes |= pad.RightTrigger != 0 ? GamePadAxes.RightTrigger : 0;
return axes;
}
Buttons TranslateButtons(XInputButtons xbuttons)
{
Buttons buttons = 0;
buttons |= (xbuttons & XInputButtons.A) != 0 ? Buttons.A : 0;
buttons |= (xbuttons & XInputButtons.B) != 0 ? Buttons.B : 0;
buttons |= (xbuttons & XInputButtons.X) != 0 ? Buttons.X : 0;
buttons |= (xbuttons & XInputButtons.Y) != 0 ? Buttons.Y : 0;
buttons |= (xbuttons & XInputButtons.Start) != 0 ? Buttons.Start : 0;
buttons |= (xbuttons & XInputButtons.Back) != 0 ? Buttons.Back : 0;
//buttons |= (xbuttons & XInputButtons.BigButton) != 0 ? Buttons.BigButton : 0;
buttons |= (xbuttons & XInputButtons.LeftShoulder) != 0 ? Buttons.LeftShoulder : 0;
buttons |= (xbuttons & XInputButtons.RightShoulder) != 0 ? Buttons.RightShoulder : 0;
buttons |= (xbuttons & XInputButtons.LeftThumb) != 0 ? Buttons.LeftStick : 0;
buttons |= (xbuttons & XInputButtons.RightThumb) != 0 ? Buttons.RightStick : 0;
buttons |= (xbuttons & XInputButtons.DPadDown) != 0 ? Buttons.DPadDown : 0;
buttons |= (xbuttons & XInputButtons.DPadUp) != 0 ? Buttons.DPadUp : 0;
buttons |= (xbuttons & XInputButtons.DPadLeft) != 0 ? Buttons.DPadLeft : 0;
buttons |= (xbuttons & XInputButtons.DPadRight) != 0 ? Buttons.DPadRight : 0;
return buttons;
}
GamePadType TranslateSubType(XInputDeviceSubType xtype)
{
switch (xtype)
{
case XInputDeviceSubType.ArcadePad: return GamePadType.ArcadePad;
case XInputDeviceSubType.ArcadeStick: return GamePadType.ArcadeStick;
case XInputDeviceSubType.DancePad: return GamePadType.DancePad;
case XInputDeviceSubType.DrumKit: return GamePadType.DrumKit;
case XInputDeviceSubType.FlightStick: return GamePadType.FlightStick;
case XInputDeviceSubType.GamePad: return GamePadType.GamePad;
case XInputDeviceSubType.Guitar: return GamePadType.Guitar;
case XInputDeviceSubType.GuitarAlternate: return GamePadType.AlternateGuitar;
case XInputDeviceSubType.GuitarBass: return GamePadType.BassGuitar;
case XInputDeviceSubType.Wheel: return GamePadType.Wheel;
case XInputDeviceSubType.Unknown:
default:
return GamePadType.Unknown;
}
}
enum XInputErrorCode
{
@ -85,12 +152,12 @@ namespace OpenTK.Platform.Windows
DeviceNotConnected
}
enum XInputType
enum XInputDeviceType : byte
{
GamePad
}
enum XInputSubType
enum XInputDeviceSubType : byte
{
Unknown = 0,
GamePad = 1,
@ -107,10 +174,10 @@ namespace OpenTK.Platform.Windows
enum XInputCapabilities
{
Ffb = 0x0001,
ForceFeedback = 0x0001,
Wireless = 0x0002,
Voice = 0x0004,
Pmd = 0x0008,
PluginModules = 0x0008,
NoNavigation = 0x0010,
}
@ -197,8 +264,8 @@ namespace OpenTK.Platform.Windows
struct XInputDeviceCapabilities
{
public byte Type;
public byte SubType;
public XInputDeviceType Type;
public XInputDeviceSubType SubType;
public short Flags;
public XInputGamePad GamePad;
public XInputVibration Vibration;
@ -210,90 +277,124 @@ namespace OpenTK.Platform.Windows
public XInputBatteryLevel Level;
}
static class XInput910
class XInput : IDisposable
{
const string dll = "XINPUT9_1_0";
IntPtr dll;
internal XInput()
{
// Try to load the newest XInput***.dll installed on the system
// The delegates below will be loaded dynamically from that dll
dll = Functions.LoadLibrary("XINPUT1_4");
if (dll == IntPtr.Zero)
dll = Functions.LoadLibrary("XINPUT1_3");
if (dll == IntPtr.Zero)
dll = Functions.LoadLibrary("XINPUT1_2");
if (dll == IntPtr.Zero)
dll = Functions.LoadLibrary("XINPUT1_1");
if (dll == IntPtr.Zero)
dll = Functions.LoadLibrary("XINPUT9_1_0");
if (dll == IntPtr.Zero)
throw new NotSupportedException("XInput was not found on this platform");
// Load the entry points we are interested in from that dll
GetCapabilities = (XInputGetCapabilities)Load("XInputGetCapabilities", typeof(XInputGetCapabilities));
GetState = (XInputGetState)Load("XInputGetState", typeof(XInputGetState));
SetState = (XInputSetState)Load("XInputSetState", typeof(XInputSetState));
}
#region Private Members
Delegate Load(string name, Type type)
{
IntPtr pfunc = Functions.GetProcAddress(dll, name);
if (pfunc != IntPtr.Zero)
return Marshal.GetDelegateForFunctionPointer(pfunc, type);
return null;
}
#endregion
#region Internal Members
internal XInputGetCapabilities GetCapabilities;
internal XInputGetState GetState;
internal XInputSetState SetState;
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputGetCapabilities", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode GetCapabilities(
internal delegate XInputErrorCode XInputGetCapabilities(
XInputUserIndex dwUserIndex,
XInputCapabilitiesFlags dwFlags,
ref XInputDeviceCapabilities pCapabilities);
out XInputDeviceCapabilities pCapabilities);
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputGetState", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode GetState
internal delegate XInputErrorCode XInputGetState
(
XInputUserIndex dwUserIndex,
out XInputState pState
);
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputSetState", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode SetState
internal delegate XInputErrorCode XInputSetState
(
XInputUserIndex dwUserIndex,
ref XInputVibration pVibration
);
#endregion
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
void Dispose(bool manual)
{
if (manual)
{
if (dll != IntPtr.Zero)
{
Functions.FreeLibrary(dll);
dll = IntPtr.Zero;
}
}
}
#endregion
}
static class XInput13
#endregion
#region IDisposable Members
public void Dispose()
{
const string dll = "XINPUT1_3";
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputGetCapabilities", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode GetCapabilities(
XInputUserIndex dwUserIndex,
XInputCapabilitiesFlags dwFlags,
ref XInputDeviceCapabilities pCapabilities);
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputGetState", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode GetState
(
XInputUserIndex dwUserIndex,
out XInputState pState
);
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputSetState", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode SetState
(
XInputUserIndex dwUserIndex,
ref XInputVibration pVibration
);
Dispose(true);
GC.SuppressFinalize(this);
}
static class XInput14
void Dispose(bool manual)
{
const string dll = "XINPUT1_4";
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputGetCapabilities", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode GetCapabilities(
XInputUserIndex dwUserIndex,
XInputCapabilitiesFlags dwFlags,
ref XInputDeviceCapabilities pCapabilities);
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputGetState", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode GetState
(
XInputUserIndex dwUserIndex,
out XInputState pState
);
[SuppressUnmanagedCodeSecurity]
[DllImport(dll, EntryPoint = "XInputSetState", ExactSpelling = true, SetLastError = false)]
public static extern XInputErrorCode SetState
(
XInputUserIndex dwUserIndex,
ref XInputVibration pVibration
);
if (manual)
{
xinput.Dispose();
}
else
{
Debug.Print("{0} leaked, did you forget to call Dispose()?", typeof(XInputJoystick).Name);
}
}
#if DEBUG
~XInputJoystick()
{
Dispose(false);
}
#endif
#endregion
}
}