Aucune description
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

DpadControl.cs 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using System;
  2. using UnityEngine.InputSystem.Layouts;
  3. using UnityEngine.InputSystem.LowLevel;
  4. namespace UnityEngine.InputSystem.Controls
  5. {
  6. /// <summary>
  7. /// A control made up of four discrete, directional buttons. Forms a vector
  8. /// but can also be addressed as individual buttons.
  9. /// </summary>
  10. /// <remarks>
  11. /// Is stored as four bits by default.
  12. ///
  13. /// The vector that is aggregated from the button states is normalized. I.e.
  14. /// even if pressing diagonally, the vector will have a length of 1 (instead
  15. /// of reading something like <c>(1,1)</c> for example).
  16. /// </remarks>
  17. public class DpadControl : Vector2Control
  18. {
  19. [InputControlLayout(hideInUI = true)]
  20. public class DpadAxisControl : AxisControl
  21. {
  22. public int component { get; set; }
  23. protected override void FinishSetup()
  24. {
  25. base.FinishSetup();
  26. component = name == "x" ? 0 : 1;
  27. // Set the state block to be the parent's state block. We don't use that to read
  28. // the axis directly (we call the parent control to do that), but we need to set
  29. // it up the actions know to monitor this memory for changes to the control.
  30. m_StateBlock = m_Parent.m_StateBlock;
  31. }
  32. public override unsafe float ReadUnprocessedValueFromState(void* statePtr)
  33. {
  34. var value = ((DpadControl)m_Parent).ReadUnprocessedValueFromState(statePtr);
  35. return value[component];
  36. }
  37. }
  38. // The DpadAxisControl has it's own logic to read state from the parent dpad.
  39. // The useStateFrom argument here is not actually used by that. The only reason
  40. // it is set up here is to avoid any state bytes being reserved for the DpadAxisControl.
  41. [InputControl(name = "x", layout = "DpadAxis", useStateFrom = "right", synthetic = true)]
  42. [InputControl(name = "y", layout = "DpadAxis", useStateFrom = "up", synthetic = true)]
  43. /// <summary>
  44. /// The button representing the vertical upwards state of the D-Pad.
  45. /// </summary>
  46. [InputControl(bit = (int)ButtonBits.Up, displayName = "Up")]
  47. public ButtonControl up { get; set; }
  48. /// <summary>
  49. /// The button representing the vertical downwards state of the D-Pad.
  50. /// </summary>
  51. [InputControl(bit = (int)ButtonBits.Down, displayName = "Down")]
  52. public ButtonControl down { get; set; }
  53. /// <summary>
  54. /// The button representing the horizontal left state of the D-Pad.
  55. /// </summary>
  56. [InputControl(bit = (int)ButtonBits.Left, displayName = "Left")]
  57. public ButtonControl left { get; set; }
  58. /// <summary>
  59. /// The button representing the horizontal right state of the D-Pad.
  60. /// </summary>
  61. [InputControl(bit = (int)ButtonBits.Right, displayName = "Right")]
  62. public ButtonControl right { get; set; }
  63. ////TODO: should have X and Y child controls as well
  64. public DpadControl()
  65. {
  66. m_StateBlock.sizeInBits = 4;
  67. m_StateBlock.format = InputStateBlock.FormatBit;
  68. }
  69. protected override void FinishSetup()
  70. {
  71. up = GetChildControl<ButtonControl>("up");
  72. down = GetChildControl<ButtonControl>("down");
  73. left = GetChildControl<ButtonControl>("left");
  74. right = GetChildControl<ButtonControl>("right");
  75. base.FinishSetup();
  76. }
  77. public override unsafe Vector2 ReadUnprocessedValueFromState(void* statePtr)
  78. {
  79. var upIsPressed = up.ReadValueFromStateWithCaching(statePtr) >= up.pressPointOrDefault;
  80. var downIsPressed = down.ReadValueFromStateWithCaching(statePtr) >= down.pressPointOrDefault;
  81. var leftIsPressed = left.ReadValueFromStateWithCaching(statePtr) >= left.pressPointOrDefault;
  82. var rightIsPressed = right.ReadValueFromStateWithCaching(statePtr) >= right.pressPointOrDefault;
  83. return MakeDpadVector(upIsPressed, downIsPressed, leftIsPressed, rightIsPressed);
  84. }
  85. public override unsafe void WriteValueIntoState(Vector2 value, void* statePtr)
  86. {
  87. var upIsPressed = up.IsValueConsideredPressed(value.y);
  88. var downIsPressed = down.IsValueConsideredPressed(value.y * -1f);
  89. var leftIsPressed = left.IsValueConsideredPressed(value.x * -1f);
  90. var rightIsPressed = right.IsValueConsideredPressed(value.x);
  91. up.WriteValueIntoState(upIsPressed && !downIsPressed ? value.y : 0f, statePtr);
  92. down.WriteValueIntoState(downIsPressed && !upIsPressed ? value.y * -1f : 0f, statePtr);
  93. left.WriteValueIntoState(leftIsPressed && !rightIsPressed ? value.x * -1f : 0f, statePtr);
  94. right.WriteValueIntoState(rightIsPressed && !leftIsPressed ? value.x : 0f, statePtr);
  95. }
  96. /// <summary>
  97. /// Create a direction vector from the given four button states.
  98. /// </summary>
  99. /// <param name="up">Whether button representing the up direction is pressed.</param>
  100. /// <param name="down">Whether button representing the down direction is pressed.</param>
  101. /// <param name="left">Whether button representing the left direction is pressed.</param>
  102. /// <param name="right">Whether button representing the right direction is pressed.</param>
  103. /// <param name="normalize">Whether to normalize the resulting vector. If this is false, vectors in the diagonal
  104. /// directions will have a magnitude of greater than 1. For example, up-left will be (-1,1).</param>
  105. /// <returns>A 2D direction vector.</returns>
  106. public static Vector2 MakeDpadVector(bool up, bool down, bool left, bool right, bool normalize = true)
  107. {
  108. var upValue = up ? 1.0f : 0.0f;
  109. var downValue = down ? -1.0f : 0.0f;
  110. var leftValue = left ? -1.0f : 0.0f;
  111. var rightValue = right ? 1.0f : 0.0f;
  112. var result = new Vector2(leftValue + rightValue, upValue + downValue);
  113. if (normalize)
  114. {
  115. // If press is diagonal, adjust coordinates to produce vector of length 1.
  116. // pow(0.707107) is roughly 0.5 so sqrt(pow(0.707107)+pow(0.707107)) is ~1.
  117. const float diagonal = 0.707107f;
  118. if (result.x != 0 && result.y != 0)
  119. result = new Vector2(result.x * diagonal, result.y * diagonal);
  120. }
  121. return result;
  122. }
  123. /// <summary>
  124. /// Create a direction vector from the given axis states.
  125. /// </summary>
  126. /// <param name="up">Axis value representing the up direction.</param>
  127. /// <param name="down">Axis value representing the down direction.</param>
  128. /// <param name="left">Axis value representing the left direction.</param>
  129. /// <param name="right">Axis value representing the right direction.</param>
  130. /// <returns>A 2D direction vector.</returns>
  131. public static Vector2 MakeDpadVector(float up, float down, float left, float right)
  132. {
  133. return new Vector2(-left + right, up - down);
  134. }
  135. internal enum ButtonBits
  136. {
  137. Up,
  138. Down,
  139. Left,
  140. Right,
  141. }
  142. }
  143. }