From 71d6da80dea8c422cb7d04de567034de402b1745 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Thu, 30 Jan 2014 10:18:11 +0100 Subject: [PATCH 01/12] [Win] Faster WinMM GetCapabilities() and GetState() joyGetDevCaps() is an extremely slow call that allocates memory. WinMMJoystick is now caching its results for a significant speedup in Joystick.GetCapabilities() and GetState(). The cache is updated whenever a joystick device is removed. WIP to handle device added notifications. --- .../OpenTK/Platform/Windows/WinMMJoystick.cs | 315 ++++++++++++------ 1 file changed, 209 insertions(+), 106 deletions(-) diff --git a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs index 313abdd9..37d6f209 100644 --- a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs +++ b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs @@ -27,12 +27,12 @@ using System; using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using OpenTK.Input; -using System.Security; -using Microsoft.Win32; using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Microsoft.Win32; +using OpenTK.Input; namespace OpenTK.Platform.Windows { @@ -43,6 +43,9 @@ namespace OpenTK.Platform.Windows List sticks = new List(); IList sticks_readonly; + readonly Dictionary index_to_stick = + new Dictionary(); + // Todo: Read the joystick name from the registry. //static readonly string RegistryJoyConfig = @"Joystick%dConfiguration"; //static readonly string RegistryJoyName = @"Joystick%dOEMName"; @@ -62,11 +65,7 @@ namespace OpenTK.Platform.Windows int number = 0; while (number < UnsafeNativeMethods.joyGetNumDevs()) { - JoystickDevice stick = OpenJoystick(number++); - if (stick != null) - { - sticks.Add(stick); - } + OpenJoystick(number++); } } @@ -80,56 +79,67 @@ namespace OpenTK.Platform.Windows JoyCaps caps; JoystickError result = UnsafeNativeMethods.joyGetDevCaps(number, out caps, JoyCaps.SizeInBytes); - if (result != JoystickError.NoError) - return null; - - int num_axes = caps.NumAxes; - if ((caps.Capabilities & JoystCapsFlags.HasPov) != 0) - num_axes += 2; - - stick = new JoystickDevice(number, num_axes, caps.NumButtons); - stick.Details = new WinMMJoyDetails(num_axes); - - // Make sure to reverse the vertical axes, so that +1 points up and -1 points down. - int axis = 0; - if (axis < caps.NumAxes) - { stick.Details.Min[axis] = caps.XMin; stick.Details.Max[axis] = caps.XMax; axis++; } - if (axis < caps.NumAxes) - { stick.Details.Min[axis] = caps.YMax; stick.Details.Max[axis] = caps.YMin; axis++; } - if (axis < caps.NumAxes) - { stick.Details.Min[axis] = caps.ZMax; stick.Details.Max[axis] = caps.ZMin; axis++; } - if (axis < caps.NumAxes) - { stick.Details.Min[axis] = caps.RMin; stick.Details.Max[axis] = caps.RMax; axis++; } - if (axis < caps.NumAxes) - { stick.Details.Min[axis] = caps.UMin; stick.Details.Max[axis] = caps.UMax; axis++; } - if (axis < caps.NumAxes) - { stick.Details.Min[axis] = caps.VMax; stick.Details.Max[axis] = caps.VMin; axis++; } - - if ((caps.Capabilities & JoystCapsFlags.HasPov) != 0) + if (result == JoystickError.NoError) { - stick.Details.PovType = PovType.Exists; - if ((caps.Capabilities & JoystCapsFlags.HasPov4Dir) != 0) - stick.Details.PovType |= PovType.Discrete; - if ((caps.Capabilities & JoystCapsFlags.HasPovContinuous) != 0) - stick.Details.PovType |= PovType.Continuous; + if (caps.NumAxes > JoystickState.MaxAxes) + { + Debug.Print("[Input] Device has {0} axes, which is higher than OpenTK maximum {1}. Please report a bug at http://www.opentk.com", + caps.NumAxes, JoystickState.MaxAxes); + caps.NumAxes = JoystickState.MaxAxes; + } + + if (caps.NumAxes > JoystickState.MaxButtons) + { + Debug.Print("[Input] Device has {0} buttons, which is higher than OpenTK maximum {1}. Please report a bug at http://www.opentk.com", + caps.NumButtons, JoystickState.MaxButtons); + caps.NumButtons = JoystickState.MaxButtons; + } + + JoystickCapabilities joycaps = new JoystickCapabilities( + caps.NumAxes, caps.NumButtons, true); + + int num_axes = caps.NumAxes; + if ((caps.Capabilities & JoystCapsFlags.HasPov) != 0) + num_axes += 2; + + stick = new JoystickDevice(number, num_axes, caps.NumButtons); + stick.Details = new WinMMJoyDetails(joycaps); + + // 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 ((caps.Capabilities & JoystCapsFlags.HasPov) != 0) + { + stick.Details.PovType = PovType.Exists; + if ((caps.Capabilities & JoystCapsFlags.HasPov4Dir) != 0) + stick.Details.PovType |= PovType.Discrete; + if ((caps.Capabilities & JoystCapsFlags.HasPovContinuous) != 0) + stick.Details.PovType |= PovType.Continuous; + } + + // Todo: Implement joystick name detection for WinMM. + stick.Description = String.Format("Joystick/Joystick #{0} ({1} axes, {2} buttons)", number, stick.Axis.Count, stick.Button.Count); + // Todo: Try to get the device name from the registry. Oh joy! + //string key_path = String.Format("{0}\\{1}\\{2}", RegistryJoyConfig, caps.RegKey, RegstryJoyCurrent); + //RegistryKey key = Registry.LocalMachine.OpenSubKey(key_path, false); + //if (key == null) + // key = Registry.CurrentUser.OpenSubKey(key_path, false); + //if (key == null) + // stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons)", number, stick.Axis.Count, stick.Button.Count); + //else + //{ + // key.Close(); + //} + + Debug.Print("Found joystick on device number {0}", number); + index_to_stick.Add(index_to_stick.Count, sticks.Count); + sticks.Add(stick); } -#warning "Implement joystick name detection for WinMM." - stick.Description = String.Format("Joystick/Joystick #{0} ({1} axes, {2} buttons)", number, stick.Axis.Count, stick.Button.Count); - // Todo: Try to get the device name from the registry. Oh joy! - //string key_path = String.Format("{0}\\{1}\\{2}", RegistryJoyConfig, caps.RegKey, RegstryJoyCurrent); - //RegistryKey key = Registry.LocalMachine.OpenSubKey(key_path, false); - //if (key == null) - // key = Registry.CurrentUser.OpenSubKey(key_path, false); - //if (key == null) - // stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons)", number, stick.Axis.Count, stick.Button.Count); - //else - //{ - // key.Close(); - //} - - if (stick != null) - Debug.Print("Found joystick on device number {0}", number); return stick; } @@ -141,11 +151,26 @@ namespace OpenTK.Platform.Windows // impossible to reconnect a disconnected user. UnsafeNativeMethods.joyConfigChanged(0); Debug.Print("[Win] WinMM joystick {0} unplugged", index); + JoystickDevice stick = + sticks[index] as JoystickDevice; + + if (stick != null) + { + index_to_stick.Remove(index); + } } bool IsValid(int index) { - return index >= 0 && index < UnsafeNativeMethods.joyGetNumDevs(); + if (index_to_stick.ContainsKey(index)) + { + return true; + } + else if (index >= 0 && index < UnsafeNativeMethods.joyGetNumDevs()) + { + return OpenJoystick(index) != null; + } + return false; } static short CalculateOffset(int pos, int min, int max) @@ -260,75 +285,86 @@ namespace OpenTK.Platform.Windows #region IJoystickDriver2 Members - public JoystickCapabilities GetCapabilities(int index) + public JoystickCapabilities GetCapabilities(int player_index) { - if (IsValid(index)) + if (IsValid(player_index)) { - JoyCaps mmcaps; - JoystickError result = UnsafeNativeMethods.joyGetDevCaps(index, out mmcaps, JoyCaps.SizeInBytes); - if (result == JoystickError.NoError) - { - JoystickCapabilities caps = new JoystickCapabilities( - mmcaps.NumAxes, mmcaps.NumButtons, true); - //if ((caps.Capabilities & JoystCapsFlags.HasPov) != 0) - // gpcaps.DPadCount++; - return caps; - } - else if (result == JoystickError.Unplugged) - { - UnplugJoystick(index); - } - } - else - { - Debug.Print("[Win] Invalid WinMM joystick device {0}", index); + JoystickDevice stick = + sticks[index_to_stick[player_index]] as JoystickDevice; + + return stick.Details.Capabilities; } return new JoystickCapabilities(); } - public JoystickState GetState(int index) + public JoystickState GetState(int player_index) { JoystickState state = new JoystickState(); - if (IsValid(index)) + if (IsValid(player_index)) { - JoyInfoEx info = new JoyInfoEx(); - info.Size = JoyInfoEx.SizeInBytes; - info.Flags = JoystickFlags.All; + int index = index_to_stick[player_index]; + JoystickDevice stick = + sticks[index] as JoystickDevice; - JoystickError result = UnsafeNativeMethods.joyGetPosEx(index, ref info); - if (result == JoystickError.NoError) + // For joysticks with fewer than three axes or four buttons, we must + // use joyGetPos; otherwise, joyGetPosEx. This is not just a cosmetic + // difference, simple devices will return incorrect results if we use + // joyGetPosEx on them. + if (stick.Details.Capabilities.AxisCount <= 3 || stick.Details.Capabilities.ButtonCount <= 4) { - JoyCaps caps; - result = UnsafeNativeMethods.joyGetDevCaps(index, out caps, JoyCaps.SizeInBytes); + // Use joyGetPos + JoyInfo info = new JoyInfo(); + + JoystickError result = UnsafeNativeMethods.joyGetPos(index, ref info); if (result == JoystickError.NoError) { - state.SetAxis(JoystickAxis.Axis0, CalculateOffset(info.XPos, caps.XMin, caps.XMax)); - state.SetAxis(JoystickAxis.Axis1, CalculateOffset(info.YPos, caps.YMin, caps.YMax)); - state.SetAxis(JoystickAxis.Axis2, CalculateOffset(info.ZPos, caps.ZMin, caps.ZMax)); - state.SetAxis(JoystickAxis.Axis3, CalculateOffset(info.RPos, caps.RMin, caps.RMax)); - state.SetAxis(JoystickAxis.Axis4, CalculateOffset(info.UPos, caps.UMin, caps.UMax)); - state.SetAxis(JoystickAxis.Axis5, CalculateOffset(info.VPos, caps.VMin, caps.VMax)); + 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])); + } - for (int i = 0; i < 16; i++) + for (int i = 0; i < stick.Details.Capabilities.ButtonCount; i++) { state.SetButton(JoystickButton.Button0 + i, (info.Buttons & 1 << i) != 0); } state.SetIsConnected(true); } + else if (result == JoystickError.Unplugged) + { + UnplugJoystick(index); + } } - - if (result == JoystickError.Unplugged) + else { - UnplugJoystick(index); + // Use joyGetPosEx + JoyInfoEx info = new JoyInfoEx(); + info.Size = JoyInfoEx.SizeInBytes; + info.Flags = JoystickFlags.All; + + JoystickError result = UnsafeNativeMethods.joyGetPosEx(index, ref info); + 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])); + } + + for (int i = 0; i < stick.Details.Capabilities.ButtonCount; i++) + { + state.SetButton(JoystickButton.Button0 + i, (info.Buttons & 1 << i) != 0); + } + + state.SetIsConnected(true); + } + else if (result == JoystickError.Unplugged) + { + UnplugJoystick(index); + } } } - else - { - Debug.Print("[Win] Invalid WinMM joystick device {0}", index); - } return state; } @@ -420,6 +456,7 @@ namespace OpenTK.Platform.Windows Backward = 18000, Left = 27000 } + struct JoyCaps { public ushort Mid; @@ -456,6 +493,53 @@ namespace OpenTK.Platform.Windows { SizeInBytes = Marshal.SizeOf(default(JoyCaps)); } + + public int GetMin(int i) + { + switch (i) + { + case 0: return XMin; + case 1: return YMin; + case 2: return ZMin; + case 3: return RMin; + case 4: return UMin; + case 5: return VMin; + default: return 0; + } + } + + public int GetMax(int i) + { + switch (i) + { + case 0: return XMax; + case 1: return YMax; + case 2: return ZMax; + case 3: return RMax; + case 4: return UMax; + case 5: return VMax; + default: return 0; + } + } + } + + struct JoyInfo + { + public int XPos; + public int YPos; + public int ZPos; + public uint Buttons; + + public int GetAxis(int i) + { + switch (i) + { + case 0: return XPos; + case 1: return YPos; + case 2: return ZPos; + default: return 0; + } + } } struct JoyInfoEx @@ -472,8 +556,10 @@ namespace OpenTK.Platform.Windows public uint Buttons; public uint ButtonNumber; public int Pov; + #pragma warning disable 0169 uint Reserved1; uint Reserved2; + #pragma warning restore 0169 public static readonly int SizeInBytes; @@ -481,6 +567,20 @@ namespace OpenTK.Platform.Windows { SizeInBytes = Marshal.SizeOf(default(JoyInfoEx)); } + + public int GetAxis(int i) + { + switch (i) + { + case 0: return XPos; + case 1: return YPos; + case 2: return ZPos; + case 3: return RPos; + case 4: return UPos; + case 5: return VPos; + default: return 0; + } + } } static class UnsafeNativeMethods @@ -488,6 +588,8 @@ namespace OpenTK.Platform.Windows [DllImport("Winmm.dll"), SuppressUnmanagedCodeSecurity] public static extern JoystickError joyGetDevCaps(int uJoyID, out JoyCaps pjc, int cbjc); [DllImport("Winmm.dll"), SuppressUnmanagedCodeSecurity] + public static extern JoystickError joyGetPos(int uJoyID, ref JoyInfo pji); + [DllImport("Winmm.dll"), SuppressUnmanagedCodeSecurity] public static extern JoystickError joyGetPosEx(int uJoyID, ref JoyInfoEx pji); [DllImport("Winmm.dll"), SuppressUnmanagedCodeSecurity] public static extern int joyGetNumDevs(); @@ -514,14 +616,15 @@ namespace OpenTK.Platform.Windows struct WinMMJoyDetails { - public readonly float[] Min, Max; // Minimum and maximum offset of each axis. + public readonly int[] Min, Max; // Minimum and maximum offset of each axis. public PovType PovType; + public JoystickCapabilities Capabilities; - public WinMMJoyDetails(int num_axes) + public WinMMJoyDetails(JoystickCapabilities caps) + : this() { - Min = new float[num_axes]; - Max = new float[num_axes]; - PovType = PovType.None; + Min = new int[caps.AxisCount]; + Max = new int[caps.AxisCount]; } public float CalculateOffset(float pos, int axis) From 5fe2d608573d382a974c97d41a839fa4d35e1260 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Wed, 29 Jan 2014 10:21:52 +0100 Subject: [PATCH 02/12] [Input] Added structures for joystick hat input --- Source/OpenTK/Input/HatPosition.cs | 51 ++++++++++++++++++++++++++++ Source/OpenTK/Input/JoystickHat.cs | 54 ++++++++++++++++++++++++++++++ Source/OpenTK/OpenTK.csproj | 2 ++ 3 files changed, 107 insertions(+) create mode 100644 Source/OpenTK/Input/HatPosition.cs create mode 100644 Source/OpenTK/Input/JoystickHat.cs diff --git a/Source/OpenTK/Input/HatPosition.cs b/Source/OpenTK/Input/HatPosition.cs new file mode 100644 index 00000000..a709a3f1 --- /dev/null +++ b/Source/OpenTK/Input/HatPosition.cs @@ -0,0 +1,51 @@ +#region License +// +// HatPosition.cs +// +// Author: +// Stefanos A. +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +using System; + +namespace OpenTK.Input +{ + /// + /// Enumerates discrete positions for a joystick hat. + /// + [Flags] + public enum HatPosition : byte + { + Centered = 0x00, + Up = 0x01, + Right = 0x02, + Down = 0x03, + Left = 0x04, + RightUp = Right | Up, + RightDown = Right | Down, + LeftUp = Left | Up, + LeftDown = Left | Down + } +} + diff --git a/Source/OpenTK/Input/JoystickHat.cs b/Source/OpenTK/Input/JoystickHat.cs new file mode 100644 index 00000000..0dc07caf --- /dev/null +++ b/Source/OpenTK/Input/JoystickHat.cs @@ -0,0 +1,54 @@ +#region License +// +// JoystickHat.cs +// +// Author: +// Stefanos A. +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +using System; + +namespace OpenTK.Input +{ + /// + /// Describes the state of a joystick hat. + /// + public struct JoystickHat + { + HatPosition position; + + internal JoystickHat(HatPosition pos) + { + position = pos; + } + + /// + /// Gets a value indicating + /// the position of this hat. + /// + /// The position. + public HatPosition Position { get { return position; } } + } +} + diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 4ee4c230..0248face 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -798,6 +798,8 @@ + + From a4ce2182d2f3136a0c3939d26edd4746af58a2f4 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 31 Jan 2014 15:01:35 +0100 Subject: [PATCH 03/12] [Input] Added JoystickHatState structure --- Source/OpenTK/Input/JoystickHat.cs | 34 ++++--- Source/OpenTK/Input/JoystickHatState.cs | 118 ++++++++++++++++++++++++ Source/OpenTK/OpenTK.csproj | 1 + 3 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 Source/OpenTK/Input/JoystickHatState.cs diff --git a/Source/OpenTK/Input/JoystickHat.cs b/Source/OpenTK/Input/JoystickHat.cs index 0dc07caf..bc2f1df8 100644 --- a/Source/OpenTK/Input/JoystickHat.cs +++ b/Source/OpenTK/Input/JoystickHat.cs @@ -32,23 +32,29 @@ using System; namespace OpenTK.Input { /// - /// Describes the state of a joystick hat. + /// Defines available Joystick hats. /// - public struct JoystickHat + public enum JoystickHat { - HatPosition position; - - internal JoystickHat(HatPosition pos) - { - position = pos; - } - /// - /// Gets a value indicating - /// the position of this hat. + /// The first hat of the Joystick device. /// - /// The position. - public HatPosition Position { get { return position; } } + Hat0, + /// + /// The second hat of the Joystick device. + /// + Hat1, + /// + /// The third hat of the Joystick device. + /// + Hat2, + /// + /// The fourth hat of the Joystick device. + /// + Hat3, + /// + /// The last hat of the Joystick device. + /// + Last = Hat3 } } - diff --git a/Source/OpenTK/Input/JoystickHatState.cs b/Source/OpenTK/Input/JoystickHatState.cs new file mode 100644 index 00000000..4e92dedb --- /dev/null +++ b/Source/OpenTK/Input/JoystickHatState.cs @@ -0,0 +1,118 @@ +#region License +// +// JoystickHatState.cs +// +// Author: +// Stefanos A. +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +using System; + +namespace OpenTK.Input +{ + /// + /// Describes the state of a joystick hat. + /// + public struct JoystickHatState + { + HatPosition position; + + internal JoystickHatState(HatPosition pos) + { + position = pos; + } + + /// + /// Gets a value indicating + /// the position of this hat. + /// + /// The position. + public HatPosition Position { get { return position; } } + + /// + /// Gets a indicating + /// whether this hat lies in the top hemicircle. + /// + /// true if this hat lies in the top hemicircle; otherwise, false. + public bool IsUp + { + get + { + return + Position == HatPosition.Up || + Position == HatPosition.UpLeft || + Position == HatPosition.UpRight; + } + } + + /// + /// Gets a indicating + /// whether this hat lies in the bottom hemicircle. + /// + /// true if this hat lies in the bottom hemicircle; otherwise, false. + public bool IsDown + { + get + { + return + Position == HatPosition.Down || + Position == HatPosition.DownLeft || + Position == HatPosition.DownRight; + } + } + + /// + /// Gets a indicating + /// whether this hat lies in the left hemicircle. + /// + /// true if this hat lies in the left hemicircle; otherwise, false. + public bool IsLeft + { + get + { + return + Position == HatPosition.Left || + Position == HatPosition.UpLeft || + Position == HatPosition.DownLeft; + } + } + + /// + /// Gets a indicating + /// whether this hat lies in the right hemicircle. + /// + /// true if this hat lies in the right hemicircle; otherwise, false. + public bool IsRight + { + get + { + return + Position == HatPosition.Right || + Position == HatPosition.UpRight || + Position == HatPosition.DownRight; + } + } + } +} + diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj index 0248face..9a010dc4 100644 --- a/Source/OpenTK/OpenTK.csproj +++ b/Source/OpenTK/OpenTK.csproj @@ -800,6 +800,7 @@ + From 0cacdf6ae4f26181680d628d4bd1de6a6c72f9f7 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 31 Jan 2014 15:03:19 +0100 Subject: [PATCH 04/12] [Input] Do not use a bitfield for hat position MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a bitfield does not save storage space in this case, and also stops pattern matching from working (switch() statement in C# or match … with expressions in F#.) --- Source/OpenTK/Input/HatPosition.cs | 46 +++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/Source/OpenTK/Input/HatPosition.cs b/Source/OpenTK/Input/HatPosition.cs index a709a3f1..c0db4019 100644 --- a/Source/OpenTK/Input/HatPosition.cs +++ b/Source/OpenTK/Input/HatPosition.cs @@ -34,18 +34,44 @@ namespace OpenTK.Input /// /// Enumerates discrete positions for a joystick hat. /// - [Flags] public enum HatPosition : byte { - Centered = 0x00, - Up = 0x01, - Right = 0x02, - Down = 0x03, - Left = 0x04, - RightUp = Right | Up, - RightDown = Right | Down, - LeftUp = Left | Up, - LeftDown = Left | Down + /// + /// The hat is in its centered (neutral) position + /// + Centered = 0, + /// + /// The hat is in its top position. + /// + Up, + /// + /// The hat is in its top-right position. + /// + UpRight, + /// + /// The hat is in its right position. + /// + Right, + /// + /// The hat is in its bottom-right position. + /// + DownRight, + /// + /// The hat is in its bottom position. + /// + Down, + /// + /// The hat is in its bottom-left position. + /// + DownLeft, + /// + /// The hat is in its left position. + /// + Left, + /// + /// The hat is in its top-left position. + /// + UpLeft, } } From 801d6ead04869715cad12e9c5532851be52ac7ee Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 31 Jan 2014 15:03:30 +0100 Subject: [PATCH 05/12] [Input] Added hat state to JoystickState --- Source/OpenTK/Input/JoystickState.cs | 51 ++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/Source/OpenTK/Input/JoystickState.cs b/Source/OpenTK/Input/JoystickState.cs index aad66590..ef18267f 100644 --- a/Source/OpenTK/Input/JoystickState.cs +++ b/Source/OpenTK/Input/JoystickState.cs @@ -42,12 +42,17 @@ namespace OpenTK.Input // then we'll need to increase these limits. internal const int MaxAxes = (int)JoystickAxis.Last + 1; internal const int MaxButtons = (int)JoystickButton.Last + 1; + internal const int MaxHats = (int)JoystickHat.Last + 1; const float ConversionFactor = 1.0f / (short.MaxValue + 0.5f); - unsafe fixed short axes[MaxAxes]; - int buttons; int packet_number; + int buttons; + unsafe fixed short axes[MaxAxes]; + JoystickHatState hat0; + JoystickHatState hat1; + JoystickHatState hat2; + JoystickHatState hat3; bool is_connected; #region Public Members @@ -76,6 +81,28 @@ namespace OpenTK.Input return (buttons & (1 << (int)button)) != 0 ? ButtonState.Pressed : ButtonState.Released; } + /// + /// Gets the hat. + /// + /// The hat. + /// Hat. + public JoystickHatState GetHat(JoystickHat hat) + { + switch (hat) + { + case JoystickHat.Hat0: + return hat0; + case JoystickHat.Hat1: + return hat1; + case JoystickHat.Hat2: + return hat2; + case JoystickHat.Hat3: + return hat3; + default: + return new JoystickHatState(); + } + } + /// /// Gets a value indicating whether the specified is currently pressed. /// @@ -198,6 +225,9 @@ namespace OpenTK.Input internal void SetButton(JoystickButton button, bool value) { int index = 1 << (int)button; + if (index < 0 || index >= MaxButtons) + throw new ArgumentOutOfRangeException("button"); + if (value) { buttons |= index; @@ -208,6 +238,23 @@ namespace OpenTK.Input } } + internal void SetHat(JoystickHat hat, JoystickHatState value) + { + switch (hat) + { + case JoystickHat.Hat0: + hat0 = value; + case JoystickHat.Hat1: + hat1 = value; + case JoystickHat.Hat2: + hat2 = value; + case JoystickHat.Hat3: + hat3 = value; + default: + throw new ArgumentOutOfRangeException("hat"); + } + } + internal void SetIsConnected(bool value) { is_connected = value; From 168c45f0e2ae10c40253cb4813ed5f1dfe534f0b Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 31 Jan 2014 15:03:51 +0100 Subject: [PATCH 06/12] [SDL2] Implemented support for hat state --- .../Platform/SDL2/Sdl2JoystickDriver.cs | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs b/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs index 8a08151a..f097b000 100644 --- a/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs +++ b/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs @@ -46,6 +46,8 @@ namespace OpenTK.Platform.SDL2 public int HatCount { get; set; } public int BallCount { get; set; } public bool IsConnected { get; set; } + public readonly JoystickHatState[] Hat = + new JoystickHatState[JoystickState.MaxHats]; } // For IJoystickDriver2 implementation @@ -127,6 +129,35 @@ namespace OpenTK.Platform.SDL2 return sdl_instanceid_to_joysticks.ContainsKey(instance_id); } + OpenTK.Input.HatPosition TranslateHat(HatPosition value) + { + if ((value & HatPosition.LeftUp) == value) + return OpenTK.Input.HatPosition.UpLeft; + + if ((value & HatPosition.RightUp) == value) + return OpenTK.Input.HatPosition.UpRight; + + if ((value & HatPosition.LeftDown) == value) + return OpenTK.Input.HatPosition.DownLeft; + + if ((value & HatPosition.RightDown) == value) + return OpenTK.Input.HatPosition.DownRight; + + if ((value & HatPosition.Up) == value) + return OpenTK.Input.HatPosition.Up; + + if ((value & HatPosition.Right) == value) + return OpenTK.Input.HatPosition.Right; + + if ((value & HatPosition.Down) == value) + return OpenTK.Input.HatPosition.Down; + + if ((value & HatPosition.Left) == value) + return OpenTK.Input.HatPosition.Left; + + return OpenTK.Input.HatPosition.Centered; + } + #if USE_SDL2_GAMECONTROLLER bool IsControllerValid(int id) { @@ -386,7 +417,14 @@ namespace OpenTK.Platform.SDL2 { int index = sdl_instanceid_to_joysticks[id]; JoystickDevice joystick = (JoystickDevice)joysticks[index]; - // Todo: map hat to an extra axis + if (ev.Hat >= 0 && ev.Hat < JoystickState.MaxHats) + { + joystick.Details.Hat[ev.Hat] = new JoystickHatState(TranslateHat(ev.Value)); + } + else + { + Debug.Print("[SDL2] Hat {0} out of range [0, {1}]", ev.Hat, JoystickState.MaxHats); + } joystick.Details.PacketNumber = Math.Max(0, unchecked(joystick.Details.PacketNumber + 1)); } else @@ -596,6 +634,11 @@ namespace OpenTK.Platform.SDL2 state.SetButton(JoystickButton.Button0 + i, joystick.Button[i]); } + for (int i = 0; i < joystick.Details.HatCount; i++) + { + state.SetHat(JoystickHat.Hat0 + i, joystick.Details.Hat[i]); + } + state.SetIsConnected(joystick.Details.IsConnected); state.SetPacketNumber(joystick.Details.PacketNumber); } From a7228274aa32a70772355963d690a2b39a1189a9 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 31 Jan 2014 15:40:07 +0100 Subject: [PATCH 07/12] [Input] Added JoystickCapabilities.HatCount --- Source/OpenTK/Input/JoystickCapabilities.cs | 35 ++++++++++--------- Source/OpenTK/Platform/MacOS/HIDInput.cs | 6 ++-- .../Platform/SDL2/Sdl2JoystickDriver.cs | 1 + .../OpenTK/Platform/Windows/WinMMJoystick.cs | 5 ++- Source/OpenTK/Platform/X11/X11Joystick.cs | 5 ++- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/Source/OpenTK/Input/JoystickCapabilities.cs b/Source/OpenTK/Input/JoystickCapabilities.cs index 3bfab7a1..1e5f88ab 100644 --- a/Source/OpenTK/Input/JoystickCapabilities.cs +++ b/Source/OpenTK/Input/JoystickCapabilities.cs @@ -40,21 +40,23 @@ namespace OpenTK.Input { byte axis_count; byte button_count; - byte dpad_count; + byte hat_count; bool is_connected; #region Constructors - internal JoystickCapabilities(int axis_count, int button_count, bool is_connected) + internal JoystickCapabilities(int axis_count, int button_count, int hat_count, bool is_connected) { - if (axis_count < 0 || axis_count >= JoystickState.MaxAxes) + if (axis_count < 0 || axis_count > JoystickState.MaxAxes) throw new ArgumentOutOfRangeException("axis_count"); - if (button_count < 0 || button_count >= JoystickState.MaxButtons) + if (button_count < 0 || button_count > JoystickState.MaxButtons) throw new ArgumentOutOfRangeException("axis_count"); + if (hat_count < 0 || hat_count > JoystickState.MaxHats) + throw new ArgumentOutOfRangeException("hat_count"); this.axis_count = (byte)axis_count; this.button_count = (byte)button_count; - this.dpad_count = 0; // Todo: either remove dpad_count or add it as a parameter + this.hat_count = (byte)hat_count; this.is_connected = is_connected; } @@ -78,6 +80,14 @@ namespace OpenTK.Input get { return button_count; } } + /// + /// Gets the number of hats supported by this . + /// + public int HatCount + { + get { return hat_count; } + } + /// /// Gets a value indicating whether this is connected. /// @@ -94,8 +104,8 @@ namespace OpenTK.Input public override string ToString() { return String.Format( - "{{Axes: {0}; Buttons: {1}; IsConnected: {2}}}", - AxisCount, ButtonCount, IsConnected); + "{{Axes: {0}; Buttons: {1}; Hats: {2}; IsConnected: {2}}}", + AxisCount, ButtonCount, HatCount, IsConnected); } /// @@ -108,6 +118,7 @@ namespace OpenTK.Input return AxisCount.GetHashCode() ^ ButtonCount.GetHashCode() ^ + HatCount.GetHashCode() ^ IsConnected.GetHashCode(); } @@ -126,15 +137,6 @@ namespace OpenTK.Input #endregion - #region Private Members - - int DPadCount - { - get { return dpad_count; } - } - - #endregion - #region IEquatable Members /// @@ -148,6 +150,7 @@ namespace OpenTK.Input return AxisCount == other.AxisCount && ButtonCount == other.ButtonCount && + HatCount == other.HatCount && IsConnected == other.IsConnected; } diff --git a/Source/OpenTK/Platform/MacOS/HIDInput.cs b/Source/OpenTK/Platform/MacOS/HIDInput.cs index f54e97c4..1ff19830 100755 --- a/Source/OpenTK/Platform/MacOS/HIDInput.cs +++ b/Source/OpenTK/Platform/MacOS/HIDInput.cs @@ -441,7 +441,7 @@ namespace OpenTK.Platform.MacOS joy = new JoystickData(); int axes = 0; int buttons = 0; - int dpads = 0; + int hats = 0; CFStringRef name_ref = NativeMethods.IOHIDDeviceGetProperty(device, NativeMethods.IOHIDProductKey); string name = CF.CFStringGetCString(name_ref); @@ -475,7 +475,7 @@ namespace OpenTK.Platform.MacOS break; case HIDUsageGD.Hatswitch: - dpads++; + hats++; break; } break; @@ -499,7 +499,7 @@ namespace OpenTK.Platform.MacOS joy.Name = name; joy.Guid = guid; joy.State.SetIsConnected(true); - joy.Capabilities = new JoystickCapabilities(axes, buttons, true); + joy.Capabilities = new JoystickCapabilities(axes, buttons, hats, true); // Map button elements to JoystickButtons for (int button = 0; button < button_elements.Count; button++) diff --git a/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs b/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs index f097b000..71ab3eea 100644 --- a/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs +++ b/Source/OpenTK/Platform/SDL2/Sdl2JoystickDriver.cs @@ -656,6 +656,7 @@ namespace OpenTK.Platform.SDL2 return new JoystickCapabilities( joystick.Axis.Count, joystick.Button.Count, + joystick.Details.HatCount, joystick.Details.IsConnected); } return new JoystickCapabilities(); diff --git a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs index 313abdd9..b5e73dca 100644 --- a/Source/OpenTK/Platform/Windows/WinMMJoystick.cs +++ b/Source/OpenTK/Platform/Windows/WinMMJoystick.cs @@ -269,7 +269,10 @@ namespace OpenTK.Platform.Windows if (result == JoystickError.NoError) { JoystickCapabilities caps = new JoystickCapabilities( - mmcaps.NumAxes, mmcaps.NumButtons, true); + mmcaps.NumAxes, + mmcaps.NumButtons, + (mmcaps.Capabilities & JoystCapsFlags.HasPov) != 0 ? 1 : 0, + true); //if ((caps.Capabilities & JoystCapsFlags.HasPov) != 0) // gpcaps.DPadCount++; return caps; diff --git a/Source/OpenTK/Platform/X11/X11Joystick.cs b/Source/OpenTK/Platform/X11/X11Joystick.cs index 5aaf60d3..8fb7178b 100644 --- a/Source/OpenTK/Platform/X11/X11Joystick.cs +++ b/Source/OpenTK/Platform/X11/X11Joystick.cs @@ -484,7 +484,10 @@ namespace OpenTK.Platform.X11 { JoystickDevice js = sticks[index_to_stick[index]]; caps = new JoystickCapabilities( - js.Axis.Count, js.Button.Count, js.Details.State.IsConnected); + js.Axis.Count, + js.Button.Count, + 0, // hats not supported by /dev/js + js.Details.State.IsConnected); } return caps; } From 5145ebceb773eda457e59af751157703658ef9a2 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 31 Jan 2014 16:17:04 +0100 Subject: [PATCH 08/12] [Mac] Implemented JoystickHat support --- Source/OpenTK/Platform/MacOS/HIDInput.cs | 78 ++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/Source/OpenTK/Platform/MacOS/HIDInput.cs b/Source/OpenTK/Platform/MacOS/HIDInput.cs index 1ff19830..49103d56 100755 --- a/Source/OpenTK/Platform/MacOS/HIDInput.cs +++ b/Source/OpenTK/Platform/MacOS/HIDInput.cs @@ -73,6 +73,8 @@ namespace OpenTK.Platform.MacOS public JoystickCapabilities Capabilities; readonly public Dictionary ElementUsageToButton = new Dictionary(); + readonly public Dictionary ElementToHat = + new Dictionary(new IntPtrEqualityComparer()); } readonly IOHIDManagerRef hidmanager; @@ -449,6 +451,7 @@ namespace OpenTK.Platform.MacOS Guid guid = CreateJoystickGuid(device, name); List button_elements = new List(); + List hat_elements = new List(); CFArray element_array = new CFArray(element_array_ref); for (int i = 0; i < element_array.Count; i++) { @@ -476,6 +479,7 @@ namespace OpenTK.Platform.MacOS case HIDUsageGD.Hatswitch: hats++; + hat_elements.Add(element_ref); break; } break; @@ -496,6 +500,25 @@ namespace OpenTK.Platform.MacOS } } + if (axes > JoystickState.MaxAxes) + { + Debug.Print("[Mac] JoystickAxis limit reached ({0} > {1}), please report a bug at http://www.opentk.com", + axes, JoystickState.MaxAxes); + axes = JoystickState.MaxAxes; + } + if (buttons > JoystickState.MaxButtons) + { + Debug.Print("[Mac] JoystickButton limit reached ({0} > {1}), please report a bug at http://www.opentk.com", + buttons, JoystickState.MaxButtons); + buttons = JoystickState.MaxButtons; + } + if (hats > JoystickState.MaxHats) + { + Debug.Print("[Mac] JoystickHat limit reached ({0} > {1}), please report a bug at http://www.opentk.com", + hats, JoystickState.MaxHats); + hats = JoystickState.MaxHats; + } + joy.Name = name; joy.Guid = guid; joy.State.SetIsConnected(true); @@ -506,6 +529,11 @@ namespace OpenTK.Platform.MacOS { joy.ElementUsageToButton.Add(button_elements[button], JoystickButton.Button0 + button); } + + for (int hat = 0; hat < hat_elements.Count; hat++) + { + joy.ElementToHat.Add(hat_elements[hat], JoystickHat.Hat0 + hat); + } } CF.CFRelease(element_array_ref); @@ -608,6 +636,12 @@ namespace OpenTK.Platform.MacOS break; case HIDUsageGD.Hatswitch: + HatPosition position = GetJoystickHat(val, elem); + JoystickHat hat = TranslateJoystickHat(joy, elem); + if (hat >= JoystickHat.Hat0 && hat <= JoystickHat.Last) + { + joy.State.SetHat(hat, new JoystickHatState(position)); + } break; } break; @@ -709,6 +743,50 @@ namespace OpenTK.Platform.MacOS return JoystickButton.Last + 1; } + static HatPosition GetJoystickHat(IOHIDValueRef val, IOHIDElementRef element) + { + HatPosition position = HatPosition.Centered; + int max = NativeMethods.IOHIDElementGetLogicalMax(element).ToInt32(); + int min = NativeMethods.IOHIDElementGetLogicalMin(element).ToInt32(); + int value = NativeMethods.IOHIDValueGetIntegerValue(val).ToInt32() - min; + int range = Math.Abs(max - min + 1); + + if (value >= 0) + { + if (range == 4) + { + // 4-position hat (no diagonals) + // 0 = up; 1 = right; 2 = down; 3 = left + // map to a 8-position hat (processed below) + value *= 2; + } + + if (range == 8) + { + // 0 = up; 1 = up-right; 2 = right; 3 = right-down; + // 4 = down; 5 = down-left; 6 = left; 7 = up-left + // Our HatPosition enum + position = (HatPosition)value; + } + else + { + // Todo: implement support for continuous hats + } + } + + return position; + } + + static JoystickHat TranslateJoystickHat(JoystickData joy, IOHIDElementRef elem) + { + JoystickHat hat; + if (joy.ElementToHat.TryGetValue(elem, out hat)) + { + return hat; + } + return JoystickHat.Last + 1; + } + #endregion #endregion From 4fceca2f80e7c52b791039a48a3e6b01288e7e63 Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Fri, 31 Jan 2014 16:37:36 +0100 Subject: [PATCH 09/12] [Input] Fixed compilation error --- Source/OpenTK/Input/JoystickState.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/OpenTK/Input/JoystickState.cs b/Source/OpenTK/Input/JoystickState.cs index ef18267f..6972bac9 100644 --- a/Source/OpenTK/Input/JoystickState.cs +++ b/Source/OpenTK/Input/JoystickState.cs @@ -244,12 +244,16 @@ namespace OpenTK.Input { case JoystickHat.Hat0: hat0 = value; + break; case JoystickHat.Hat1: hat1 = value; + break; case JoystickHat.Hat2: hat2 = value; + break; case JoystickHat.Hat3: hat3 = value; + break; default: throw new ArgumentOutOfRangeException("hat"); } From 2dee96d91845bf14ce6309d6fffd995342f44489 Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Fri, 31 Jan 2014 16:40:57 +0100 Subject: [PATCH 10/12] [Input] Fixed SetButton index check --- Source/OpenTK/Input/JoystickState.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/OpenTK/Input/JoystickState.cs b/Source/OpenTK/Input/JoystickState.cs index 6972bac9..1ef3d976 100644 --- a/Source/OpenTK/Input/JoystickState.cs +++ b/Source/OpenTK/Input/JoystickState.cs @@ -224,17 +224,17 @@ namespace OpenTK.Input internal void SetButton(JoystickButton button, bool value) { - int index = 1 << (int)button; + int index = (int)button; if (index < 0 || index >= MaxButtons) throw new ArgumentOutOfRangeException("button"); if (value) { - buttons |= index; + buttons |= 1 << index; } else { - buttons &= ~index; + buttons &= ~(1 << index); } } From 45df508f8fa960c336cd805f3650c8718995ec09 Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Sat, 1 Feb 2014 16:02:02 +0100 Subject: [PATCH 11/12] [Win] Query WinMM joysticks on devicechange event --- Source/OpenTK/Platform/Windows/WinRawInput.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/OpenTK/Platform/Windows/WinRawInput.cs b/Source/OpenTK/Platform/Windows/WinRawInput.cs index 08e57201..80c5b0c2 100644 --- a/Source/OpenTK/Platform/Windows/WinRawInput.cs +++ b/Source/OpenTK/Platform/Windows/WinRawInput.cs @@ -125,6 +125,7 @@ namespace OpenTK.Platform.Windows case WindowMessage.DEVICECHANGE: ((WinRawKeyboard)KeyboardDriver).RefreshDevices(); ((WinRawMouse)MouseDriver).RefreshDevices(); + ((WinMMJoystick)JoystickDriver).RefreshDevices(); break; } return base.WindowProcedure(handle, message, wParam, lParam); From d0522f1073823d9805b12688af1795920ff14803 Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Sat, 1 Feb 2014 16:03:07 +0100 Subject: [PATCH 12/12] [Win] Do not create second WinMMJoystick instance --- Source/OpenTK/Platform/Windows/WinGLNative.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index 999aa85c..79b37605 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -84,7 +84,7 @@ namespace OpenTK.Platform.Windows const ClassStyle DefaultClassStyle = ClassStyle.OwnDC; // Used for IInputDriver implementation - WinMMJoystick joystick_driver = new WinMMJoystick(); + IJoystickDriver joystick_driver = Factory.Default.CreateLegacyJoystickDriver(); KeyboardDevice keyboard = new KeyboardDevice(); MouseDevice mouse = new MouseDevice(); IList keyboards = new List(1); @@ -1403,7 +1403,8 @@ namespace OpenTK.Platform.Windows public void Poll() { - joystick_driver.Poll(); + if (joystick_driver is WinMMJoystick) + (joystick_driver as WinMMJoystick).Poll(); } #endregion