Maze / Library /PackageCache /com.unity.inputsystem@1.6.1 /InputSystem /Actions /Composites /AxisComposite.cs
| using System.ComponentModel; | |
| using UnityEngine.InputSystem.Layouts; | |
| using UnityEngine.InputSystem.Processors; | |
| using UnityEngine.InputSystem.Utilities; | |
| namespace UnityEngine.InputSystem.Composites | |
| { | |
| /// <summary> | |
| /// A single axis value computed from one axis that pulls in the <see cref="negative"/> direction (<see cref="minValue"/>) and one | |
| /// axis that pulls in the <see cref="positive"/> direction (<see cref="maxValue"/>). | |
| /// </summary> | |
| /// <remarks> | |
| /// The limits of the axis are determined by <see cref="minValue"/> and <see cref="maxValue"/>. | |
| /// By default, they are set to <c>[-1..1]</c>. The values can be set as parameters. | |
| /// | |
| /// <example> | |
| /// <code> | |
| /// var action = new InputAction(); | |
| /// action.AddCompositeBinding("Axis(minValue=0,maxValue=2") | |
| /// .With("Negative", "<Keyboard>/a") | |
| /// .With("Positive", "<Keyboard>/d"); | |
| /// </code> | |
| /// </example> | |
| /// | |
| /// If both axes are actuated at the same time, the behavior depends on <see cref="whichSideWins"/>. | |
| /// By default, neither side will win (<see cref="WhichSideWins.Neither"/>) and the result | |
| /// will be 0 (or, more precisely, the midpoint between <see cref="minValue"/> and <see cref="maxValue"/>). | |
| /// This can be customized to make the positive side win (<see cref="WhichSideWins.Positive"/>) | |
| /// or the negative one (<see cref="WhichSideWins.Negative"/>). | |
| /// | |
| /// This is useful, for example, in a driving game where break should cancel out accelerate. | |
| /// By binding <see cref="negative"/> to the break control(s) and <see cref="positive"/> to the | |
| /// acceleration control(s), and setting <see cref="whichSideWins"/> to <see cref="WhichSideWins.Negative"/>, | |
| /// if the break button is pressed, it will always cause the acceleration button to be ignored. | |
| /// | |
| /// The actual <em>absolute</em> values of <see cref="negative"/> and <see cref="positive"/> are used | |
| /// to scale <see cref="minValue"/> and <see cref="maxValue"/> respectively. So if, for example, <see cref="positive"/> | |
| /// is bound to <see cref="Gamepad.rightTrigger"/> and the trigger is at a value of 0.5, then the resulting | |
| /// value is <c>maxValue * 0.5</c> (the actual formula is <c>midPoint + (maxValue - midPoint) * positive</c>). | |
| /// </remarks> | |
| [] | |
| [] | |
| public class AxisComposite : InputBindingComposite<float> | |
| { | |
| /// <summary> | |
| /// Binding for the axis input that controls the negative [<see cref="minValue"/>..0] direction of the | |
| /// combined axis. | |
| /// </summary> | |
| /// <remarks> | |
| /// This property is automatically assigned by the input system. | |
| /// </remarks> | |
| // ReSharper disable once MemberCanBePrivate.Global | |
| // ReSharper disable once FieldCanBeMadeReadOnly.Global | |
| [] public int negative = 0; | |
| /// <summary> | |
| /// Binding for the axis input that controls the positive [0..<see cref="maxValue"/>] direction of the | |
| /// combined axis. | |
| /// </summary> | |
| /// <remarks> | |
| /// This property is automatically assigned by the input system. | |
| /// </remarks> | |
| // ReSharper disable once MemberCanBePrivate.Global | |
| // ReSharper disable once FieldCanBeMadeReadOnly.Global | |
| [] public int positive = 0; | |
| /// <summary> | |
| /// The lower bound that the axis is limited to. -1 by default. | |
| /// </summary> | |
| /// <remarks> | |
| /// This value corresponds to the full actuation of the control(s) bound to <see cref="negative"/>. | |
| /// | |
| /// <example> | |
| /// <code> | |
| /// var action = new InputAction(); | |
| /// action.AddCompositeBinding("Axis(minValue=0,maxValue=2") | |
| /// .With("Negative", "<Keyboard>/a") | |
| /// .With("Positive", "<Keyboard>/d"); | |
| /// </code> | |
| /// </example> | |
| /// </remarks> | |
| /// <seealso cref="maxValue"/> | |
| /// <seealso cref="negative"/> | |
| // ReSharper disable once MemberCanBePrivate.Global | |
| // ReSharper disable once FieldCanBeMadeReadOnly.Global | |
| [] | |
| public float minValue = -1; | |
| /// <summary> | |
| /// The upper bound that the axis is limited to. 1 by default. | |
| /// </summary> | |
| /// <remarks> | |
| /// This value corresponds to the full actuation of the control(s) bound to <see cref="positive"/>. | |
| /// | |
| /// <example> | |
| /// <code> | |
| /// var action = new InputAction(); | |
| /// action.AddCompositeBinding("Axis(minValue=0,maxValue=2") | |
| /// .With("Negative", "<Keyboard>/a") | |
| /// .With("Positive", "<Keyboard>/d"); | |
| /// </code> | |
| /// </example> | |
| /// </remarks> | |
| /// <seealso cref="minValue"/> | |
| /// <seealso cref="positive"/> | |
| // ReSharper disable once MemberCanBePrivate.Global | |
| // ReSharper disable once FieldCanBeMadeReadOnly.Global | |
| [] | |
| public float maxValue = 1; | |
| /// <summary> | |
| /// If both the <see cref="positive"/> and <see cref="negative"/> button are actuated, this | |
| /// determines which value is returned from the composite. | |
| /// </summary> | |
| [ | |
| ] | |
| public WhichSideWins whichSideWins = WhichSideWins.Neither; | |
| /// <summary> | |
| /// The value that is returned if the composite is in a neutral position, that is, if | |
| /// neither <see cref="positive"/> nor <see cref="negative"/> are actuated or if | |
| /// <see cref="whichSideWins"/> is set to <see cref="WhichSideWins.Neither"/> and | |
| /// both <see cref="positive"/> and <see cref="negative"/> are actuated. | |
| /// </summary> | |
| public float midPoint => (maxValue + minValue) / 2; | |
| ////TODO: add parameters to control ramp up&down | |
| /// <inheritdoc /> | |
| public override float ReadValue(ref InputBindingCompositeContext context) | |
| { | |
| var negativeValue = Mathf.Abs(context.ReadValue<float>(negative)); | |
| var positiveValue = Mathf.Abs(context.ReadValue<float>(positive)); | |
| var negativeIsActuated = negativeValue > Mathf.Epsilon; | |
| var positiveIsActuated = positiveValue > Mathf.Epsilon; | |
| if (negativeIsActuated == positiveIsActuated) | |
| { | |
| switch (whichSideWins) | |
| { | |
| case WhichSideWins.Negative: | |
| positiveIsActuated = false; | |
| break; | |
| case WhichSideWins.Positive: | |
| negativeIsActuated = false; | |
| break; | |
| case WhichSideWins.Neither: | |
| return midPoint; | |
| } | |
| } | |
| var mid = midPoint; | |
| if (negativeIsActuated) | |
| return mid - (mid - minValue) * negativeValue; | |
| return mid + (maxValue - mid) * positiveValue; | |
| } | |
| /// <inheritdoc /> | |
| public override float EvaluateMagnitude(ref InputBindingCompositeContext context) | |
| { | |
| var value = ReadValue(ref context); | |
| if (value < midPoint) | |
| { | |
| value = Mathf.Abs(value - midPoint); | |
| return NormalizeProcessor.Normalize(value, 0, Mathf.Abs(minValue), 0); | |
| } | |
| value = Mathf.Abs(value - midPoint); | |
| return NormalizeProcessor.Normalize(value, 0, Mathf.Abs(maxValue), 0); | |
| } | |
| /// <summary> | |
| /// What happens to the value of an <see cref="AxisComposite"/> if both <see cref="positive"/> | |
| /// and <see cref="negative"/> are actuated at the same time. | |
| /// </summary> | |
| [] | |
| public enum WhichSideWins | |
| { | |
| /// <summary> | |
| /// If both <see cref="positive"/> and <see cref="negative"/> are actuated, the sides cancel | |
| /// each other out and the result is 0. | |
| /// </summary> | |
| Neither = 0, | |
| /// <summary> | |
| /// If both <see cref="positive"/> and <see cref="negative"/> are actuated, the value of | |
| /// <see cref="positive"/> wins and <see cref="negative"/> is ignored. | |
| /// </summary> | |
| Positive = 1, | |
| /// <summary> | |
| /// If both <see cref="positive"/> and <see cref="negative"/> are actuated, the value of | |
| /// <see cref="negative"/> wins and <see cref="positive"/> is ignored. | |
| /// </summary> | |
| Negative = 2, | |
| } | |
| } | |
| } | |