Permalink
Browse files

[Mac] Implemented JoystickHat support

  • Loading branch information...
1 parent a722827 commit 5145ebceb773eda457e59af751157703658ef9a2 @thefiddler thefiddler committed Jan 31, 2014
Showing with 78 additions and 0 deletions.
  1. +78 −0 Source/OpenTK/Platform/MacOS/HIDInput.cs
@@ -73,6 +73,8 @@ class JoystickData
public JoystickCapabilities Capabilities;
readonly public Dictionary<int, JoystickButton> ElementUsageToButton =
new Dictionary<int, JoystickButton>();
+ readonly public Dictionary<IOHIDElementRef, JoystickHat> ElementToHat =
+ new Dictionary<IOHIDElementRef, JoystickHat>(new IntPtrEqualityComparer());
}
readonly IOHIDManagerRef hidmanager;
@@ -449,6 +451,7 @@ JoystickData CreateJoystick(IntPtr sender, IntPtr device)
Guid guid = CreateJoystickGuid(device, name);
List<int> button_elements = new List<int>();
+ List<IOHIDElementRef> hat_elements = new List<CFAllocatorRef>();
CFArray element_array = new CFArray(element_array_ref);
for (int i = 0; i < element_array.Count; i++)
{
@@ -476,6 +479,7 @@ JoystickData CreateJoystick(IntPtr sender, IntPtr device)
case HIDUsageGD.Hatswitch:
hats++;
+ hat_elements.Add(element_ref);
break;
}
break;
@@ -496,6 +500,25 @@ JoystickData CreateJoystick(IntPtr sender, IntPtr device)
}
}
+ 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 @@ JoystickData CreateJoystick(IntPtr sender, IntPtr device)
{
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 @@ static void UpdateJoystick(JoystickData joy, IOHIDValueRef val)
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 @@ static JoystickButton TranslateJoystickButton(JoystickData joy, int usage)
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

0 comments on commit 5145ebc

Please sign in to comment.