Joystick.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. using UnityEngine.InputSystem.Controls;
  2. using UnityEngine.InputSystem.Layouts;
  3. using UnityEngine.InputSystem.LowLevel;
  4. using UnityEngine.InputSystem.Utilities;
  5. namespace UnityEngine.InputSystem.LowLevel
  6. {
  7. internal struct JoystickState : IInputStateTypeInfo
  8. {
  9. public static FourCC kFormat => new FourCC('J', 'O', 'Y');
  10. [InputControl(name = "trigger", displayName = "Trigger", layout = "Button", usages = new[] { "PrimaryTrigger", "PrimaryAction", "Submit" }, bit = (int)Button.Trigger)]
  11. public int buttons;
  12. [InputControl(displayName = "Stick", layout = "Stick", usage = "Primary2DMotion", processors = "stickDeadzone")]
  13. public Vector2 stick;
  14. public enum Button
  15. {
  16. // IMPORTANT: Order has to match what is expected by DpadControl.
  17. HatSwitchUp,
  18. HatSwitchDown,
  19. HatSwitchLeft,
  20. HatSwitchRight,
  21. Trigger
  22. }
  23. public FourCC format => kFormat;
  24. }
  25. }
  26. namespace UnityEngine.InputSystem
  27. {
  28. /// <summary>
  29. /// A joystick with an arbitrary number of buttons and axes.
  30. /// </summary>
  31. /// <remarks>
  32. /// Joysticks are somewhat hard to classify as there is little commonality other
  33. /// than that there is one main stick 2D control and at least one button. From the
  34. /// input system perspective, everything that is not a <see cref="Gamepad"/> and
  35. /// that has at least one <see cref="stick"/> and one <see cref="trigger"/> control
  36. /// is considered a candidate for being a joystick.
  37. ///
  38. /// Optionally, a joystick may also have the ability to <see cref="twist"/>, i.e.
  39. /// for the stick to rotate around its own axis, and at least one <see cref="hatswitch"/>.
  40. ///
  41. /// Note that devices based on Joystick may have many more controls. Joystick
  42. /// itself only defines a minimum required to separate joysticks as a concept
  43. /// from other types of devices.
  44. /// </remarks>
  45. [InputControlLayout(stateType = typeof(JoystickState), isGenericTypeOfDevice = true)]
  46. [Scripting.Preserve]
  47. public class Joystick : InputDevice
  48. {
  49. /// <summary>
  50. /// The primary trigger button of the joystick.
  51. /// </summary>
  52. /// <value>Control representing the primary trigger button.</value>
  53. /// <remarks>
  54. /// This is the <see cref="ButtonControl"/> type control on the joystick
  55. /// that has the <see cref="CommonUsages.PrimaryTrigger"/> usage.
  56. /// </remarks>
  57. public ButtonControl trigger { get; private set; }
  58. /// <summary>
  59. /// The 2D axis of the stick itself.
  60. /// </summary>
  61. /// <value>Control representing the main joystick axis.</value>
  62. /// <remarks>
  63. /// This is the <see cref="StickControl"/> type control on the joystick
  64. /// that has the <see cref="CommonUsages.Primary2DMotion"/> usage.
  65. /// </remarks>
  66. public StickControl stick { get; private set; }
  67. /// <summary>
  68. /// An optional control representing the rotation of the stick around its
  69. /// own axis (i.e. side-to-side circular motion). If not supported, will be
  70. /// <c>null</c>.
  71. /// </summary>
  72. /// <value>Control representing the twist motion of the joystick.</value>
  73. /// <remarks>
  74. /// This is the <see cref="AxisControl"/> type control on the joystick
  75. /// that has the <see cref="CommonUsages.Twist"/> usage.
  76. /// </remarks>
  77. public AxisControl twist { get; private set; }
  78. /// <summary>
  79. /// An optional control representing a four-way "hat switch" on the
  80. /// joystick. If not supported, will be <c>null</c>.
  81. /// </summary>
  82. /// <value>Control representing a hatswitch on the joystick.</value>
  83. /// <remarks>
  84. /// Hat switches are usually thumb-operated four-way switches that operate
  85. /// much like the "d-pad" on a gamepad (see <see cref="Gamepad.dpad"/>).
  86. /// If present, this is the <see cref="Vector2Control"/> type control on the
  87. /// joystick that has the <see cref="CommonUsages.Hatswitch"/> usage.
  88. /// </remarks>
  89. public Vector2Control hatswitch { get; private set; }
  90. /// <summary>
  91. /// The joystick that was added or used last. Null if there is none.
  92. /// </summary>
  93. /// <value>Joystick that was added or used last.</value>
  94. /// <remarks>
  95. /// See <see cref="InputDevice.MakeCurrent"/> for details about when a device
  96. /// is made current.
  97. /// </remarks>
  98. /// <seealso cref="all"/>
  99. public static Joystick current { get; private set; }
  100. /// <summary>
  101. /// A list of joysticks currently connected to the system.
  102. /// </summary>
  103. /// <value>All currently connected joystick.</value>
  104. /// <remarks>
  105. /// Does not cause GC allocation.
  106. ///
  107. /// Do <em>not</em> hold on to the value returned by this getter but rather query it whenever
  108. /// you need it. Whenever the joystick setup changes, the value returned by this getter
  109. /// is invalidated.
  110. /// </remarks>
  111. /// <seealso cref="current"/>
  112. public new static ReadOnlyArray<Joystick> all => new ReadOnlyArray<Joystick>(s_Joysticks, 0, s_JoystickCount);
  113. /// <summary>
  114. /// Called when the joystick has been created but before it is added
  115. /// to the system.
  116. /// </summary>
  117. protected override void FinishSetup()
  118. {
  119. // Mandatory controls.
  120. trigger = GetChildControl<ButtonControl>("{PrimaryTrigger}");
  121. stick = GetChildControl<StickControl>("{Primary2DMotion}");
  122. // Optional controls.
  123. twist = TryGetChildControl<AxisControl>("{Twist}");
  124. hatswitch = TryGetChildControl<Vector2Control>("{Hatswitch}");
  125. base.FinishSetup();
  126. }
  127. /// <summary>
  128. /// Make the joystick the <see cref="current"/> one.
  129. /// </summary>
  130. /// <remarks>
  131. /// This is called automatically by the input system when a device
  132. /// receives input or is added to the system. See <see cref="InputDevice.MakeCurrent"/>
  133. /// for details.
  134. /// </remarks>
  135. public override void MakeCurrent()
  136. {
  137. base.MakeCurrent();
  138. current = this;
  139. }
  140. /// <summary>
  141. /// Called when the joystick is added to the system.
  142. /// </summary>
  143. protected override void OnAdded()
  144. {
  145. ArrayHelpers.AppendWithCapacity(ref s_Joysticks, ref s_JoystickCount, this);
  146. }
  147. /// <summary>
  148. /// Called when the joystick is removed from the system.
  149. /// </summary>
  150. protected override void OnRemoved()
  151. {
  152. base.OnRemoved();
  153. if (current == this)
  154. current = null;
  155. // Remove from `all`.
  156. var index = ArrayHelpers.IndexOfReference(s_Joysticks, this, s_JoystickCount);
  157. if (index != -1)
  158. ArrayHelpers.EraseAtWithCapacity(s_Joysticks, ref s_JoystickCount, index);
  159. else
  160. {
  161. Debug.Assert(false,
  162. $"Joystick {this} seems to not have been added but is being removed (joystick list: {string.Join(", ", all)})"); // Put in else to not allocate on normal path.
  163. }
  164. }
  165. private static int s_JoystickCount;
  166. private static Joystick[] s_Joysticks;
  167. }
  168. }