XInputController.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using System;
  2. using UnityEngine.InputSystem.Controls;
  3. using UnityEngine.InputSystem.Layouts;
  4. ////TODO: expose user index
  5. ////TODO: set displayNames of the controls according to Xbox controller standards
  6. namespace UnityEngine.InputSystem.XInput
  7. {
  8. /// <summary>
  9. /// An XInput-compatible game controller.
  10. /// </summary>
  11. /// <remarks>
  12. /// Note that on non-Microsoft platforms, XInput controllers will not actually use the XInput interface
  13. /// but will rather be interfaced with through different APIs -- on OSX, for example, HID is used to
  14. /// interface with Xbox controlllers. In those cases, XInput-specific functionality (like <see cref="Capabilities"/>)
  15. /// will not be available.
  16. ///
  17. /// On Windows, XInput controllers will be reported with <see cref="InputDeviceDescription.interfaceName"/>
  18. /// set to <c>"XInput"</c> and with a JSON representation of <a
  19. /// href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities">XINPUT_CAPABILITIES</a>
  20. /// available in <see cref="InputDeviceDescription.capabilities"/>. This means that you match on those
  21. /// <c>subType</c> and/or <c>flags</c> for example.
  22. ///
  23. /// <example>
  24. /// <code>
  25. /// // Create an XInput-specific guitar layout subtype.
  26. /// // NOTE: Works only on Windows.
  27. /// InputSystem.RegisterLayout(@"
  28. /// {
  29. /// ""name"" : ""XInputGuitar"",
  30. /// ""displayName"" : ""Guitar"",
  31. /// ""extend"" : ""XInputController"",
  32. /// ""device"" : {
  33. /// ""interface"" : ""XInput"",
  34. /// ""capabilities"" : [
  35. /// { ""path"" : ""subType"", ""value"" : ""6"" }
  36. /// ]
  37. /// }
  38. /// }
  39. /// ");
  40. /// </code>
  41. /// </example>
  42. ///
  43. /// Now, when an XInput controller is connected and reports itself with the
  44. /// subtype "Guitar", it is turned into an "XInputGuitar" instead of an
  45. /// "XInputController".
  46. /// </remarks>
  47. [InputControlLayout(displayName = "Xbox Controller")]
  48. [Scripting.Preserve]
  49. public class XInputController : Gamepad
  50. {
  51. /// <summary>
  52. /// Same as <see cref="Gamepad.startButton"/>.
  53. /// </summary>
  54. /// <value>Same control as <see cref="Gamepad.startButton"/>.</value>
  55. // Change the display names for the buttons to conform to Xbox conventions.
  56. [InputControl(name = "buttonSouth", displayName = "A")]
  57. [InputControl(name = "buttonEast", displayName = "B")]
  58. [InputControl(name = "buttonWest", displayName = "X")]
  59. [InputControl(name = "buttonNorth", displayName = "Y")]
  60. [InputControl(name = "leftShoulder", displayName = "Left Bumper", shortDisplayName = "LB")]
  61. [InputControl(name = "rightShoulder", displayName = "Right Bumper", shortDisplayName = "RB")]
  62. [InputControl(name = "leftTrigger", shortDisplayName = "LT")]
  63. [InputControl(name = "rightTrigger", shortDisplayName = "RT")]
  64. // This follows Xbox One conventions; on Xbox 360, this is start=start and select=back.
  65. [InputControl(name = "start", displayName = "Menu", alias = "menu")]
  66. [InputControl(name = "select", displayName = "View", alias = "view")]
  67. public ButtonControl menu { get; private set; }
  68. /// <summary>
  69. /// Same as <see cref="Gamepad.selectButton"/>
  70. /// </summary>
  71. /// <value>Same control as <see cref="Gamepad.selectButton"/>.</value>
  72. public ButtonControl view { get; private set; }
  73. /// <summary>
  74. /// What specific kind of XInput controller this is.
  75. /// </summary>
  76. /// <value>XInput device subtype.</value>
  77. /// <remarks>
  78. /// When the controller is picked up through interfaces other than XInput or through old versions of
  79. /// XInput, this will always be <see cref="DeviceSubType.Unknown"/>. Put another way, this value is
  80. /// meaningful only on recent Microsoft platforms.
  81. /// </remarks>
  82. /// <seealso href="https://docs.microsoft.com/en-us/windows/win32/xinput/xinput-and-controller-subtypes"/>
  83. public DeviceSubType subType
  84. {
  85. get
  86. {
  87. if (!m_HaveParsedCapabilities)
  88. ParseCapabilities();
  89. return m_SubType;
  90. }
  91. }
  92. /// <summary>
  93. /// Return the device flags as reported by XInput.
  94. /// </summary>
  95. /// <value>XInput device flags.</value>
  96. /// <seealso href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities"/>
  97. public DeviceFlags flags
  98. {
  99. get
  100. {
  101. if (!m_HaveParsedCapabilities)
  102. ParseCapabilities();
  103. return m_Flags;
  104. }
  105. }
  106. /// <inheritdoc />
  107. protected override void FinishSetup()
  108. {
  109. base.FinishSetup();
  110. menu = startButton;
  111. view = selectButton;
  112. }
  113. private bool m_HaveParsedCapabilities;
  114. private DeviceSubType m_SubType;
  115. private DeviceFlags m_Flags;
  116. private void ParseCapabilities()
  117. {
  118. if (!string.IsNullOrEmpty(description.capabilities))
  119. {
  120. var capabilities = JsonUtility.FromJson<Capabilities>(description.capabilities);
  121. m_SubType = capabilities.subType;
  122. m_Flags = capabilities.flags;
  123. }
  124. m_HaveParsedCapabilities = true;
  125. }
  126. /// <summary>
  127. /// Controller type enumeration in <c>Type</c> field of <c>XINPUT_CAPABILITIES</c>.
  128. /// </summary>
  129. /// <remarks>
  130. /// See <a href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities">MSDN</a>.
  131. /// </remarks>
  132. internal enum DeviceType
  133. {
  134. Gamepad = 0x00
  135. }
  136. /// <summary>
  137. /// Controller subtype enumeration in <c>SubType</c> field of <c>XINPUT_CAPABILITIES</c>.
  138. /// </summary>
  139. /// <remarks>
  140. /// See <a href="https://docs.microsoft.com/en-us/windows/win32/xinput/xinput-and-controller-subtypes">MSDN</a>.
  141. /// </remarks>
  142. public enum DeviceSubType
  143. {
  144. Unknown = 0x00,
  145. Gamepad = 0x01,
  146. Wheel = 0x02,
  147. ArcadeStick = 0x03,
  148. FlightStick = 0x04,
  149. DancePad = 0x05,
  150. Guitar = 0x06,
  151. GuitarAlternate = 0x07,
  152. DrumKit = 0x08,
  153. GuitarBass = 0x0B,
  154. ArcadePad = 0x13
  155. }
  156. /// <summary>
  157. /// Controller flags in <c>Flags</c> field of <c>XINPUT_CAPABILITIES</c>.
  158. /// </summary>
  159. /// <remarks>
  160. /// See <a href="https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_capabilities">MSDN</a>.
  161. /// </remarks>
  162. [Flags]
  163. public new enum DeviceFlags
  164. {
  165. ForceFeedbackSupported = 0x01,
  166. Wireless = 0x02,
  167. VoiceSupported = 0x04,
  168. PluginModulesSupported = 0x08,
  169. NoNavigation = 0x10,
  170. }
  171. [Serializable]
  172. internal struct Capabilities
  173. {
  174. public DeviceType type;
  175. public DeviceSubType subType;
  176. public DeviceFlags flags;
  177. }
  178. }
  179. }