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