Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using System;
  2. using System.ComponentModel;
  3. using UnityEngine.InputSystem.Controls;
  4. using UnityEngine.InputSystem.Layouts;
  5. using UnityEngine.InputSystem.Utilities;
  6. #if UNITY_EDITOR
  7. using UnityEditor;
  8. using UnityEngine.InputSystem.Editor;
  9. using UnityEngine.UIElements;
  10. #endif
  11. ////TODO: add support for ramp up/down
  12. namespace UnityEngine.InputSystem.Composites
  13. {
  14. /// <summary>
  15. /// A 2D planar motion vector computed from an up+down button pair and a left+right
  16. /// button pair.
  17. /// </summary>
  18. /// <remarks>
  19. /// This composite allows to grab arbitrary buttons from a device and arrange them in
  20. /// a D-Pad like configuration. Based on button presses, the composite will return a
  21. /// normalized direction vector (normalization can be turned off via <see cref="mode"/>).
  22. ///
  23. /// Opposing motions cancel each other out. This means that if, for example, both the left
  24. /// and right horizontal button are pressed, the resulting horizontal movement value will
  25. /// be zero.
  26. ///
  27. /// <example>
  28. /// <code>
  29. /// // Set up WASD style keyboard controls.
  30. /// action.AddCompositeBinding("2DVector")
  31. /// .With("Up", "&lt;Keyboard&gt;/w")
  32. /// .With("Left", "&lt;Keyboard&gt;/a")
  33. /// .With("Down", "&lt;Keyboard&gt;/s")
  34. /// .With("Right", "&lt;Keyboard&gt;/d");
  35. /// </code>
  36. /// </example>
  37. /// </remarks>
  38. /// <seealso cref="Vector3Composite"/>
  39. [DisplayStringFormat("{up}/{left}/{down}/{right}")] // This results in WASD.
  40. [DisplayName("Up/Down/Left/Right Composite")]
  41. public class Vector2Composite : InputBindingComposite<Vector2>
  42. {
  43. /// <summary>
  44. /// Binding for the button that represents the up (that is, <c>(0,1)</c>) direction of the vector.
  45. /// </summary>
  46. /// <remarks>
  47. /// This property is automatically assigned by the input system.
  48. /// </remarks>
  49. // ReSharper disable once MemberCanBePrivate.Global
  50. // ReSharper disable once FieldCanBeMadeReadOnly.Global
  51. [InputControl(layout = "Axis")] public int up;
  52. /// <summary>
  53. /// Binding for the button represents the down (that is, <c>(0,-1)</c>) direction of the vector.
  54. /// </summary>
  55. /// <remarks>
  56. /// This property is automatically assigned by the input system.
  57. /// </remarks>
  58. // ReSharper disable once MemberCanBePrivate.Global
  59. // ReSharper disable once FieldCanBeMadeReadOnly.Global
  60. [InputControl(layout = "Axis")] public int down;
  61. /// <summary>
  62. /// Binding for the button represents the left (that is, <c>(-1,0)</c>) direction of the vector.
  63. /// </summary>
  64. /// <remarks>
  65. /// This property is automatically assigned by the input system.
  66. /// </remarks>
  67. // ReSharper disable once MemberCanBePrivate.Global
  68. // ReSharper disable once FieldCanBeMadeReadOnly.Global
  69. [InputControl(layout = "Axis")] public int left;
  70. /// <summary>
  71. /// Binding for the button that represents the right (that is, <c>(1,0)</c>) direction of the vector.
  72. /// </summary>
  73. /// <remarks>
  74. /// This property is automatically assigned by the input system.
  75. /// </remarks>
  76. [InputControl(layout = "Axis")] public int right;
  77. [Obsolete("Use Mode.DigitalNormalized with 'mode' instead")]
  78. public bool normalize = true;
  79. /// <summary>
  80. /// How to synthesize a <c>Vector2</c> from the values read from <see cref="up"/>, <see cref="down"/>,
  81. /// <see cref="left"/>, and <see cref="right"/>.
  82. /// </summary>
  83. /// <value>Determines how X and Y of the resulting <c>Vector2</c> are formed from input values.</value>
  84. /// <remarks>
  85. /// <example>
  86. /// <code>
  87. /// var action = new InputAction();
  88. ///
  89. /// // DigitalNormalized composite (the default). Turns gamepad left stick into
  90. /// // control equivalent to the D-Pad.
  91. /// action.AddCompositeBinding("2DVector(mode=0)")
  92. /// .With("up", "&lt;Gamepad&gt;/leftStick/up")
  93. /// .With("down", "&lt;Gamepad&gt;/leftStick/down")
  94. /// .With("left", "&lt;Gamepad&gt;/leftStick/left")
  95. /// .With("right", "&lt;Gamepad&gt;/leftStick/right");
  96. ///
  97. /// // Digital composite. Turns gamepad left stick into control equivalent
  98. /// // to the D-Pad except that diagonals will not be normalized.
  99. /// action.AddCompositeBinding("2DVector(mode=1)")
  100. /// .With("up", "&lt;Gamepad&gt;/leftStick/up")
  101. /// .With("down", "&lt;Gamepad&gt;/leftStick/down")
  102. /// .With("left", "&lt;Gamepad&gt;/leftStick/left")
  103. /// .With("right", "&lt;Gamepad&gt;/leftStick/right");
  104. ///
  105. /// // Analog composite. In this case results in setup that behaves exactly
  106. /// // the same as leftStick already does. But you could use it, for example,
  107. /// // to swap directions by binding "up" to leftStick/down and "down" to
  108. /// // leftStick/up.
  109. /// action.AddCompositeBinding("2DVector(mode=2)")
  110. /// .With("up", "&lt;Gamepad&gt;/leftStick/up")
  111. /// .With("down", "&lt;Gamepad&gt;/leftStick/down")
  112. /// .With("left", "&lt;Gamepad&gt;/leftStick/left")
  113. /// .With("right", "&lt;Gamepad&gt;/leftStick/right");
  114. /// </code>
  115. /// </example>
  116. /// </remarks>
  117. public Mode mode;
  118. /// <inheritdoc />
  119. public override Vector2 ReadValue(ref InputBindingCompositeContext context)
  120. {
  121. var mode = this.mode;
  122. if (mode == Mode.Analog)
  123. {
  124. var upValue = context.ReadValue<float>(up);
  125. var downValue = context.ReadValue<float>(down);
  126. var leftValue = context.ReadValue<float>(left);
  127. var rightValue = context.ReadValue<float>(right);
  128. return DpadControl.MakeDpadVector(upValue, downValue, leftValue, rightValue);
  129. }
  130. var upIsPressed = context.ReadValueAsButton(up);
  131. var downIsPressed = context.ReadValueAsButton(down);
  132. var leftIsPressed = context.ReadValueAsButton(left);
  133. var rightIsPressed = context.ReadValueAsButton(right);
  134. // Legacy. We need to reference the obsolete member here so temporarily
  135. // turn of the warning.
  136. #pragma warning disable CS0618
  137. if (!normalize) // Was on by default.
  138. mode = Mode.Digital;
  139. #pragma warning restore CS0618
  140. return DpadControl.MakeDpadVector(upIsPressed, downIsPressed, leftIsPressed, rightIsPressed, mode == Mode.DigitalNormalized);
  141. }
  142. /// <inheritdoc />
  143. public override float EvaluateMagnitude(ref InputBindingCompositeContext context)
  144. {
  145. var value = ReadValue(ref context);
  146. return value.magnitude;
  147. }
  148. /// <summary>
  149. /// Determines how a <c>Vector2</c> is synthesized from part controls.
  150. /// </summary>
  151. public enum Mode
  152. {
  153. /// <summary>
  154. /// Part controls are treated as analog meaning that the floating-point values read from controls
  155. /// will come through as is (minus the fact that the down and left direction values are negated).
  156. /// </summary>
  157. Analog = 2,
  158. /// <summary>
  159. /// Part controls are treated as buttons (on/off) and the resulting vector is normalized. This means
  160. /// that if, for example, both left and up are pressed, instead of returning a vector (-1,1), a vector
  161. /// of roughly (-0.7,0.7) (that is, corresponding to <c>new Vector2(-1,1).normalized</c>) is returned instead.
  162. /// The resulting 2D area is diamond-shaped.
  163. /// </summary>
  164. DigitalNormalized = 0,
  165. /// <summary>
  166. /// Part controls are treated as buttons (on/off) and the resulting vector is not normalized. This means
  167. /// that if, for example, both left and up are pressed, the resulting vector is (-1,1) and has a length
  168. /// greater than 1. The resulting 2D area is box-shaped.
  169. /// </summary>
  170. Digital = 1
  171. }
  172. }
  173. #if UNITY_EDITOR
  174. internal class Vector2CompositeEditor : InputParameterEditor<Vector2Composite>
  175. {
  176. private GUIContent m_ModeLabel = new GUIContent("Mode",
  177. "How to synthesize a Vector2 from the inputs. Digital "
  178. + "treats part bindings as buttons (on/off) whereas Analog preserves "
  179. + "floating-point magnitudes as read from controls.");
  180. public override void OnGUI()
  181. {
  182. target.mode = (Vector2Composite.Mode)EditorGUILayout.EnumPopup(m_ModeLabel, target.mode);
  183. }
  184. #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
  185. public override void OnDrawVisualElements(VisualElement root, Action onChangedCallback)
  186. {
  187. var modeField = new EnumField(m_ModeLabel.text, target.mode)
  188. {
  189. tooltip = m_ModeLabel.tooltip
  190. };
  191. modeField.RegisterValueChangedCallback(evt =>
  192. {
  193. target.mode = (Vector2Composite.Mode)evt.newValue;
  194. onChangedCallback();
  195. });
  196. root.Add(modeField);
  197. }
  198. #endif
  199. }
  200. #endif
  201. }