HIDSupport.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using System.Linq;
  2. using UnityEngine.InputSystem.Utilities;
  3. #if UNITY_EDITOR
  4. using UnityEditor;
  5. using UnityEngine.InputSystem.Editor;
  6. using UnityEngine.InputSystem.HID.Editor;
  7. #endif
  8. namespace UnityEngine.InputSystem.HID
  9. {
  10. using ShouldCreateHIDCallback = System.Func<HID.HIDDeviceDescriptor, bool?>;
  11. /// <summary>
  12. /// Adds support for generic HID devices to the input system.
  13. /// </summary>
  14. /// <remarks>
  15. /// Even without this module, HIDs can be used on platforms where we
  16. /// support HID has a native backend (Windows and OSX, at the moment).
  17. /// However, each supported HID requires a layout specifically targeting
  18. /// it as a product.
  19. ///
  20. /// What this module adds is the ability to turn any HID with usable
  21. /// controls into an InputDevice. It will make a best effort to figure
  22. /// out a suitable class for the device and will use the HID elements
  23. /// present in the HID report descriptor to populate the device.
  24. ///
  25. /// If there is an existing product-specific layout for a HID, it will
  26. /// take precedence and HIDSupport will leave the device alone.
  27. /// </remarks>
  28. public static class HIDSupport
  29. {
  30. /// <summary>
  31. /// A pair of HID usage page and HID usage number.
  32. /// </summary>
  33. /// <remarks>
  34. /// Used to describe a HID usage for the <see cref="supportedHIDUsages"/> property.
  35. /// </remarks>
  36. public struct HIDPageUsage
  37. {
  38. /// <summary>
  39. /// The usage page.
  40. /// </summary>
  41. public HID.UsagePage page;
  42. /// <summary>
  43. /// A number specifying the usage on the usage page.
  44. /// </summary>
  45. public int usage;
  46. /// <summary>
  47. /// Create a HIDPageUsage struct by specifying a page and usage.
  48. /// </summary>
  49. public HIDPageUsage(HID.UsagePage page, int usage)
  50. {
  51. this.page = page;
  52. this.usage = usage;
  53. }
  54. /// <summary>
  55. /// Create a HIDPageUsage struct from the GenericDesktop usage page by specifying the usage.
  56. /// </summary>
  57. public HIDPageUsage(HID.GenericDesktop usage)
  58. {
  59. page = HID.UsagePage.GenericDesktop;
  60. this.usage = (int)usage;
  61. }
  62. }
  63. private static HIDPageUsage[] s_SupportedHIDUsages;
  64. /// <summary>
  65. /// An array of HID usages the input is configured to support.
  66. /// </summary>
  67. /// <remarks>
  68. /// The input system will only create <see cref="InputDevice"/>s for HIDs with usages
  69. /// listed in this array. Any other HID will be ignored. This saves the input system from
  70. /// spending resources on creating layouts and devices for HIDs which are not supported or
  71. /// not usable for game input.
  72. ///
  73. /// By default, this includes only <see cref="HID.GenericDesktop.Joystick"/>,
  74. /// <see cref="HID.GenericDesktop.Gamepad"/> and <see cref="HID.GenericDesktop.MultiAxisController"/>,
  75. /// but you can set this property to include any other HID usages.
  76. ///
  77. /// Note that currently on macOS, the only HID usages which can be enabled are
  78. /// <see cref="HID.GenericDesktop.Joystick"/>, <see cref="HID.GenericDesktop.Gamepad"/>,
  79. /// <see cref="HID.GenericDesktop.MultiAxisController"/>, <see cref="HID.GenericDesktop.TabletPCControls"/>,
  80. /// and <see cref="HID.GenericDesktop.AssistiveControl"/>.
  81. /// </remarks>
  82. public static ReadOnlyArray<HIDPageUsage> supportedHIDUsages
  83. {
  84. get => s_SupportedHIDUsages;
  85. set
  86. {
  87. s_SupportedHIDUsages = value.ToArray();
  88. // Add HIDs we now support.
  89. InputSystem.s_Manager.AddAvailableDevicesThatAreNowRecognized();
  90. // Remove HIDs we no longer support.
  91. for (var i = 0; i < InputSystem.devices.Count; ++i)
  92. {
  93. var device = InputSystem.devices[i];
  94. if (device is HID hid && !s_SupportedHIDUsages.Contains(new HIDPageUsage(hid.hidDescriptor.usagePage, hid.hidDescriptor.usage)))
  95. {
  96. // Remove the entire generated layout. This will also remove all devices based on it.
  97. InputSystem.RemoveLayout(device.layout);
  98. --i;
  99. }
  100. }
  101. }
  102. }
  103. /// <summary>
  104. /// Add support for generic HIDs to InputSystem.
  105. /// </summary>
  106. #if UNITY_DISABLE_DEFAULT_INPUT_PLUGIN_INITIALIZATION
  107. public
  108. #else
  109. internal
  110. #endif
  111. static void Initialize()
  112. {
  113. s_SupportedHIDUsages = new[]
  114. {
  115. new HIDPageUsage(HID.GenericDesktop.Joystick),
  116. new HIDPageUsage(HID.GenericDesktop.Gamepad),
  117. new HIDPageUsage(HID.GenericDesktop.MultiAxisController),
  118. };
  119. InputSystem.RegisterLayout<HID>();
  120. InputSystem.onFindLayoutForDevice += HID.OnFindLayoutForDevice;
  121. // Add toolbar button to any devices using the "HID" interface. Opens
  122. // a windows to browse the HID descriptor of the device.
  123. #if UNITY_EDITOR
  124. InputDeviceDebuggerWindow.onToolbarGUI +=
  125. device =>
  126. {
  127. if (device.description.interfaceName == HID.kHIDInterface)
  128. {
  129. if (GUILayout.Button(s_HIDDescriptor, EditorStyles.toolbarButton))
  130. {
  131. HIDDescriptorWindow.CreateOrShowExisting(device.deviceId, device.description);
  132. }
  133. }
  134. };
  135. #endif
  136. }
  137. #if UNITY_EDITOR
  138. private static readonly GUIContent s_HIDDescriptor = new GUIContent("HID Descriptor");
  139. #endif
  140. }
  141. }