From 05bbc0b3f41fb04813419467a5ddf204aea56138 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 17 Mar 2014 00:29:12 +0100 Subject: [PATCH 1/5] [Win] Joystick driver now reports hat positions --- .../OpenTK/Platform/Windows/WinMMJoystick.cs | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs index 77b14cfe..4b4d3cb4 100644 --- a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs +++ b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs @@ -389,21 +389,42 @@ namespace OpenTK.Platform.Windows else { // Use joyGetPosEx - JoyInfoEx info = new JoyInfoEx(); - info.Size = JoyInfoEx.SizeInBytes; - info.Flags = JoystickFlags.All; + JoyInfoEx info_ex = new JoyInfoEx(); + info_ex.Size = JoyInfoEx.SizeInBytes; + info_ex.Flags = JoystickFlags.All; - JoystickError result = UnsafeNativeMethods.joyGetPosEx(device_index, ref info); + JoystickError result = UnsafeNativeMethods.joyGetPosEx(device_index, ref info_ex); if (result == JoystickError.NoError) { for (int i = 0; i < stick.Details.Capabilities.AxisCount; i++) { - state.SetAxis(JoystickAxis.Axis0 + i, CalculateOffset(info.GetAxis(i), stick.Details.Min[i], stick.Details.Max[i])); + state.SetAxis(JoystickAxis.Axis0 + i, CalculateOffset(info_ex.GetAxis(i), stick.Details.Min[i], stick.Details.Max[i])); } for (int i = 0; i < stick.Details.Capabilities.ButtonCount; i++) { - state.SetButton(JoystickButton.Button0 + i, (info.Buttons & 1 << i) != 0); + state.SetButton(JoystickButton.Button0 + i, (info_ex.Buttons & 1 << i) != 0); + } + + for (int i = 0; i < stick.Details.Capabilities.HatCount; i++) + { + // A discrete POV returns specific values for left, right, etc. + // A continuous POV returns an integer indicating an angle in degrees * 100, e.g. 18000 == 180.00 degrees. + // The vast majority of joysticks have discrete POVs, so we'll treat all of them as discrete for simplicity. + if ((JoystickPovPosition)info_ex.Pov != JoystickPovPosition.Centered) + { + HatPosition hatpos = HatPosition.Centered; + if (info_ex.Pov < 4500 || info_ex.Pov >= 31500) + hatpos |= HatPosition.Up; + if (info_ex.Pov >= 4500 && info_ex.Pov < 13500) + hatpos |= HatPosition.Right; + if (info_ex.Pov >= 13500 && info_ex.Pov < 22500) + hatpos |= HatPosition.Down; + if (info_ex.Pov >= 22500 && info_ex.Pov < 31500) + hatpos |= HatPosition.Left; + + state.SetHat(JoystickHat.Hat0 + i, new JoystickHatState(hatpos)); + } } state.SetIsConnected(true); From 01c3b51be60321081db41e851924b2fcdc456c31 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 17 Mar 2014 00:29:45 +0100 Subject: [PATCH 2/5] [Input] JoystickState.ToString now prints hat pos --- Source/OpenTK/Input/JoystickState.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/OpenTK/Input/JoystickState.cs b/Source/OpenTK/Input/JoystickState.cs index 1ef3d976..a2dd64cc 100644 --- a/Source/OpenTK/Input/JoystickState.cs +++ b/Source/OpenTK/Input/JoystickState.cs @@ -145,9 +145,10 @@ namespace OpenTK.Input sb.Append(String.Format("{0:f4}", GetAxis(JoystickAxis.Axis0 + i))); } return String.Format( - "{{Axes:{0}; Buttons: {1}; IsConnected: {2}}}", + "{{Axes:{0}; Buttons: {1}; Hat: {2}; IsConnected: {3}}}", sb.ToString(), Convert.ToString((int)buttons, 2).PadLeft(16, '0'), + hat0, IsConnected); } @@ -303,6 +304,11 @@ namespace OpenTK.Input { equals &= GetAxisUnsafe(i) == other.GetAxisUnsafe(i); } + for (int i = 0; equals && i < MaxHats; i++) + { + JoystickHat hat = JoystickHat.Hat0 + i; + equals &= GetHat(hat).Equals(other.GetHat(hat)); + } return equals; } From f93d464f62d6785b97d0820164a7574983a76f58 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 17 Mar 2014 00:30:04 +0100 Subject: [PATCH 3/5] [Input] JoystickHatState is now IEquatable --- Source/OpenTK/Input/JoystickHatState.cs | 54 ++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/Source/OpenTK/Input/JoystickHatState.cs b/Source/OpenTK/Input/JoystickHatState.cs index 4e92dedb..63a3a943 100644 --- a/Source/OpenTK/Input/JoystickHatState.cs +++ b/Source/OpenTK/Input/JoystickHatState.cs @@ -34,7 +34,7 @@ namespace OpenTK.Input /// /// Describes the state of a joystick hat. /// - public struct JoystickHatState + public struct JoystickHatState : IEquatable { HatPosition position; @@ -113,6 +113,58 @@ namespace OpenTK.Input Position == HatPosition.DownRight; } } + + /// + /// Returns a that represents the current . + /// + /// A that represents the current . + public override string ToString() + { + return String.Format( + "{{{0}{1}{2}{3}}}", + IsUp ? "U" : String.Empty, + IsLeft ? "L" : String.Empty, + IsDown ? "D" : String.Empty, + IsRight ? "R" : String.Empty); + } + + /// + /// Serves as a hash function for a object. + /// + /// A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a + /// hash table. + public override int GetHashCode() + { + return Position.GetHashCode(); + } + + /// + /// Determines whether the specified is equal to the current . + /// + /// The to compare with the current . + /// true if the specified is equal to the current + /// ; otherwise, false. + public override bool Equals(object obj) + { + return + obj is JoystickHatState && + Equals((JoystickHatState)obj); + } + + #region IEquatable implementation + + /// + /// Determines whether the specified is equal to the current . + /// + /// The to compare with the current . + /// true if the specified is equal to the current + /// ; otherwise, false. + public bool Equals(JoystickHatState other) + { + return Position == other.Position; + } + + #endregion } } From cae62151b8cced6bc6a9c09e5f1b995fb659b3ba Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 17 Mar 2014 00:30:19 +0100 Subject: [PATCH 4/5] [Input] LegacyJoystickDriver now reports hat pos --- .../OpenTK/Platform/LegacyJoystickDriver.cs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/Source/OpenTK/Platform/LegacyJoystickDriver.cs b/Source/OpenTK/Platform/LegacyJoystickDriver.cs index 4b2f39cc..b58c21f2 100644 --- a/Source/OpenTK/Platform/LegacyJoystickDriver.cs +++ b/Source/OpenTK/Platform/LegacyJoystickDriver.cs @@ -65,7 +65,10 @@ namespace OpenTK.Platform if (caps.IsConnected && joysticks[i].Description == DisconnectedName) { // New joystick connected - joysticks[i] = new LegacyJoystickDevice(i, caps.AxisCount, caps.ButtonCount); + joysticks[i] = new LegacyJoystickDevice( + i, + caps.AxisCount + 2 * caps.HatCount, + caps.ButtonCount); //device.Description = Joystick.GetName(i); joysticks[i].Description = ConnectedName; @@ -78,16 +81,41 @@ namespace OpenTK.Platform } JoystickState state = Joystick.GetState(i); - for (int axis_index = 0; axis_index < (int)caps.AxisCount; axis_index++) + for (int axis_index = 0; axis_index < caps.AxisCount; axis_index++) { JoystickAxis axis = JoystickAxis.Axis0 + axis_index; joysticks[i].SetAxis(axis, state.GetAxis(axis)); } - for (int button_index = 0; button_index < (int)caps.ButtonCount; button_index++) + for (int button_index = 0; button_index < caps.ButtonCount; button_index++) { JoystickButton button = JoystickButton.Button0 + button_index; joysticks[i].SetButton(button, state.GetButton(button) == ButtonState.Pressed); } + for (int hat_index = 0; hat_index < caps.HatCount; hat_index++) + { + // LegacyJoystickDriver report hats as pairs of axes + // Make sure we have enough axes left for this mapping + int axis_index = caps.AxisCount + 2 * hat_index; + if (axis_index < JoystickState.MaxAxes) + { + JoystickHat hat = JoystickHat.Hat0 + hat_index; + JoystickHatState hat_state = state.GetHat(hat); + JoystickAxis axis = JoystickAxis.Axis0 + axis_index; + float x = 0; + float y = 0; + if (hat_state.IsDown) + y--; + if (hat_state.IsUp) + y++; + if (hat_state.IsLeft) + x--; + if (hat_state.IsRight) + x++; + + joysticks[i].SetAxis(axis, x); + joysticks[i].SetAxis(axis + 1, y); + } + } } } From ccb54082588d7a8ab13fea62985e524d5c73513c Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 17 Mar 2014 00:43:36 +0100 Subject: [PATCH 5/5] [Win] Invert vertical axes to match 1.0 API The 1.0 API defines +y as up and -y as down. This matches XInput but disagrees with WinMM, where we have to invert the vertical axes. --- Source/OpenTK/Platform/Windows/WinMMJoystick.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs index 4b4d3cb4..adcdf1df 100644 --- a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs +++ b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs @@ -131,8 +131,16 @@ namespace OpenTK.Platform.Windows // Make sure to reverse the vertical axes, so that +1 points up and -1 points down. for (int axis = 0; axis < caps.NumAxes; axis++) { - stick.Details.Min[axis] = caps.GetMin(axis); - stick.Details.Max[axis] = caps.GetMax(axis); + if (axis % 2 == 1) + { + stick.Details.Min[axis] = caps.GetMax(axis); + stick.Details.Max[axis] = caps.GetMin(axis); + } + else + { + stick.Details.Min[axis] = caps.GetMin(axis); + stick.Details.Max[axis] = caps.GetMax(axis); + } } if ((caps.Capabilities & JoystCapsFlags.HasPov) != 0)