From 5145ebceb773eda457e59af751157703658ef9a2 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Fri, 31 Jan 2014 16:17:04 +0100 Subject: [PATCH] [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