123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- using System;
- using UnityEngine.InputSystem.Layouts;
- using UnityEngine.InputSystem.LowLevel;
-
- namespace UnityEngine.InputSystem.Controls
- {
- /// <summary>
- /// A control made up of four discrete, directional buttons. Forms a vector
- /// but can also be addressed as individual buttons.
- /// </summary>
- /// <remarks>
- /// Is stored as four bits by default.
- ///
- /// The vector that is aggregated from the button states is normalized. I.e.
- /// even if pressing diagonally, the vector will have a length of 1 (instead
- /// of reading something like <c>(1,1)</c> for example).
- /// </remarks>
- public class DpadControl : Vector2Control
- {
- [InputControlLayout(hideInUI = true)]
- public class DpadAxisControl : AxisControl
- {
- public int component { get; set; }
-
- protected override void FinishSetup()
- {
- base.FinishSetup();
- component = name == "x" ? 0 : 1;
-
- // Set the state block to be the parent's state block. We don't use that to read
- // the axis directly (we call the parent control to do that), but we need to set
- // it up the actions know to monitor this memory for changes to the control.
- m_StateBlock = m_Parent.m_StateBlock;
- }
-
- public override unsafe float ReadUnprocessedValueFromState(void* statePtr)
- {
- var value = ((DpadControl)m_Parent).ReadUnprocessedValueFromState(statePtr);
- return value[component];
- }
- }
-
- // The DpadAxisControl has it's own logic to read state from the parent dpad.
- // The useStateFrom argument here is not actually used by that. The only reason
- // it is set up here is to avoid any state bytes being reserved for the DpadAxisControl.
- [InputControl(name = "x", layout = "DpadAxis", useStateFrom = "right", synthetic = true)]
- [InputControl(name = "y", layout = "DpadAxis", useStateFrom = "up", synthetic = true)]
-
- /// <summary>
- /// The button representing the vertical upwards state of the D-Pad.
- /// </summary>
- [InputControl(bit = (int)ButtonBits.Up, displayName = "Up")]
- public ButtonControl up { get; set; }
-
- /// <summary>
- /// The button representing the vertical downwards state of the D-Pad.
- /// </summary>
- [InputControl(bit = (int)ButtonBits.Down, displayName = "Down")]
- public ButtonControl down { get; set; }
-
- /// <summary>
- /// The button representing the horizontal left state of the D-Pad.
- /// </summary>
- [InputControl(bit = (int)ButtonBits.Left, displayName = "Left")]
- public ButtonControl left { get; set; }
-
- /// <summary>
- /// The button representing the horizontal right state of the D-Pad.
- /// </summary>
- [InputControl(bit = (int)ButtonBits.Right, displayName = "Right")]
- public ButtonControl right { get; set; }
-
- ////TODO: should have X and Y child controls as well
-
- public DpadControl()
- {
- m_StateBlock.sizeInBits = 4;
- m_StateBlock.format = InputStateBlock.FormatBit;
- }
-
- protected override void FinishSetup()
- {
- up = GetChildControl<ButtonControl>("up");
- down = GetChildControl<ButtonControl>("down");
- left = GetChildControl<ButtonControl>("left");
- right = GetChildControl<ButtonControl>("right");
- base.FinishSetup();
- }
-
- public override unsafe Vector2 ReadUnprocessedValueFromState(void* statePtr)
- {
- var upIsPressed = up.ReadValueFromStateWithCaching(statePtr) >= up.pressPointOrDefault;
- var downIsPressed = down.ReadValueFromStateWithCaching(statePtr) >= down.pressPointOrDefault;
- var leftIsPressed = left.ReadValueFromStateWithCaching(statePtr) >= left.pressPointOrDefault;
- var rightIsPressed = right.ReadValueFromStateWithCaching(statePtr) >= right.pressPointOrDefault;
-
- return MakeDpadVector(upIsPressed, downIsPressed, leftIsPressed, rightIsPressed);
- }
-
- public override unsafe void WriteValueIntoState(Vector2 value, void* statePtr)
- {
- var upIsPressed = up.IsValueConsideredPressed(value.y);
- var downIsPressed = down.IsValueConsideredPressed(value.y * -1f);
- var leftIsPressed = left.IsValueConsideredPressed(value.x * -1f);
- var rightIsPressed = right.IsValueConsideredPressed(value.x);
-
- up.WriteValueIntoState(upIsPressed && !downIsPressed ? value.y : 0f, statePtr);
- down.WriteValueIntoState(downIsPressed && !upIsPressed ? value.y * -1f : 0f, statePtr);
- left.WriteValueIntoState(leftIsPressed && !rightIsPressed ? value.x * -1f : 0f, statePtr);
- right.WriteValueIntoState(rightIsPressed && !leftIsPressed ? value.x : 0f, statePtr);
- }
-
- /// <summary>
- /// Create a direction vector from the given four button states.
- /// </summary>
- /// <param name="up">Whether button representing the up direction is pressed.</param>
- /// <param name="down">Whether button representing the down direction is pressed.</param>
- /// <param name="left">Whether button representing the left direction is pressed.</param>
- /// <param name="right">Whether button representing the right direction is pressed.</param>
- /// <param name="normalize">Whether to normalize the resulting vector. If this is false, vectors in the diagonal
- /// directions will have a magnitude of greater than 1. For example, up-left will be (-1,1).</param>
- /// <returns>A 2D direction vector.</returns>
- public static Vector2 MakeDpadVector(bool up, bool down, bool left, bool right, bool normalize = true)
- {
- var upValue = up ? 1.0f : 0.0f;
- var downValue = down ? -1.0f : 0.0f;
- var leftValue = left ? -1.0f : 0.0f;
- var rightValue = right ? 1.0f : 0.0f;
-
- var result = new Vector2(leftValue + rightValue, upValue + downValue);
-
- if (normalize)
- {
- // If press is diagonal, adjust coordinates to produce vector of length 1.
- // pow(0.707107) is roughly 0.5 so sqrt(pow(0.707107)+pow(0.707107)) is ~1.
- const float diagonal = 0.707107f;
- if (result.x != 0 && result.y != 0)
- result = new Vector2(result.x * diagonal, result.y * diagonal);
- }
-
- return result;
- }
-
- /// <summary>
- /// Create a direction vector from the given axis states.
- /// </summary>
- /// <param name="up">Axis value representing the up direction.</param>
- /// <param name="down">Axis value representing the down direction.</param>
- /// <param name="left">Axis value representing the left direction.</param>
- /// <param name="right">Axis value representing the right direction.</param>
- /// <returns>A 2D direction vector.</returns>
- public static Vector2 MakeDpadVector(float up, float down, float left, float right)
- {
- return new Vector2(-left + right, up - down);
- }
-
- internal enum ButtonBits
- {
- Up,
- Down,
- Left,
- Right,
- }
- }
- }
|