File size: 6,100 Bytes
18a519f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | using System.ComponentModel;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Scripting;
////TODO: remove this once we can break the API
namespace UnityEngine.InputSystem.Composites
{
/// <summary>
/// A button with an additional modifier. The button only triggers when
/// the modifier is pressed.
/// </summary>
/// <remarks>
/// This composite can be used to require another button to be held while
/// pressing the button that triggers the action. This is most commonly used
/// on keyboards to require one of the modifier keys (shift, ctrl, or alt)
/// to be held in combination with another key, e.g. "CTRL+1".
///
/// <example>
/// <code>
/// // Create a button action that triggers when CTRL+1
/// // is pressed on the keyboard.
/// var action = new InputAction(type: InputActionType.Button);
/// action.AddCompositeBinding("ButtonWithOneModifier")
/// .With("Modifier", "<Keyboard>/leftCtrl")
/// .With("Modifier", "<Keyboard>/rightControl")
/// .With("Button", "<Keyboard>/1")
/// </code>
/// </example>
///
/// Note that this is not restricted to the keyboard and will preserve
/// the full value of the button.
///
/// <example>
/// <code>
/// // Create a button action that requires the A button on the
/// // gamepad to be held and will then trigger from the gamepad's
/// // left trigger button.
/// var action = new InputAction(type: InputActionType.Button);
/// action.AddCompositeBinding("ButtonWithOneModifier")
/// .With("Modifier", "<Gamepad>/buttonSouth")
/// .With("Button", "<Gamepad>/leftTrigger");
/// </code>
/// </example>
/// </remarks>
/// <seealso cref="ButtonWithTwoModifiers"/>
[DesignTimeVisible(false)] // Obsoleted by OneModifierComposite
[DisplayStringFormat("{modifier}+{button}")]
public class ButtonWithOneModifier : InputBindingComposite<float>
{
/// <summary>
/// Binding for the button that acts as a modifier, e.g. <c><Keyboard/leftCtrl</c>.
/// </summary>
/// <value>Part index to use with <see cref="InputBindingCompositeContext.ReadValue{T}(int)"/>.</value>
/// <remarks>
/// This property is automatically assigned by the input system.
/// </remarks>
// ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once FieldCanBeMadeReadOnly.Global
// ReSharper disable once UnassignedField.Global
[InputControl(layout = "Button")] public int modifier;
/// <summary>
/// Binding for the button that is gated by the modifier. The composite will assume the value
/// of this button while the modifier is pressed.
/// </summary>
/// <value>Part index to use with <see cref="InputBindingCompositeContext.ReadValue{T}(int)"/>.</value>
/// <remarks>
/// This property is automatically assigned by the input system.
/// </remarks>
// ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once FieldCanBeMadeReadOnly.Global
// ReSharper disable once UnassignedField.Global
[InputControl(layout = "Button")] public int button;
/// <summary>
/// If set to <c>true</c>, <see cref="modifier"/> can be pressed after <see cref="button"/> and the composite will
/// still trigger. Default is false.
/// </summary>
/// <remarks>
/// By default, <see cref="modifier"/> is required to be in pressed state before or at the same time that <see cref="button"/>
/// goes into pressed state for the composite as a whole to trigger. This means that binding to, for example, <c>Shift+B</c>,
/// the <c>shift</c> key has to be pressed before pressing the <c>B</c> key. This is the behavior usually expected with
/// keyboard shortcuts.
///
/// This parameter can be used to bypass this behavior and allow any timing between <see cref="modifier"/> and <see cref="button"/>.
/// The only requirement is for them both to concurrently be in pressed state.
/// </remarks>
public bool overrideModifiersNeedToBePressedFirst;
/// <summary>
/// Return the value of the <see cref="button"/> part if <see cref="modifier"/> is pressed. Otherwise
/// return 0.
/// </summary>
/// <param name="context">Evaluation context passed in from the input system.</param>
/// <returns>The current value of the composite.</returns>
public override float ReadValue(ref InputBindingCompositeContext context)
{
if (ModifierIsPressed(ref context))
return context.ReadValue<float>(button);
return default;
}
private bool ModifierIsPressed(ref InputBindingCompositeContext context)
{
var modifierDown = context.ReadValueAsButton(modifier);
if (modifierDown && !overrideModifiersNeedToBePressedFirst)
{
var timestamp = context.GetPressTime(button);
var timestamp1 = context.GetPressTime(modifier);
return timestamp1 <= timestamp;
}
return modifierDown;
}
/// <summary>
/// Same as <see cref="ReadValue"/> in this case.
/// </summary>
/// <param name="context">Evaluation context passed in from the input system.</param>
/// <returns>A >0 value if the composite is currently actuated.</returns>
public override float EvaluateMagnitude(ref InputBindingCompositeContext context)
{
return ReadValue(ref context);
}
protected override void FinishSetup(ref InputBindingCompositeContext context)
{
if (!overrideModifiersNeedToBePressedFirst)
overrideModifiersNeedToBePressedFirst = !InputSystem.settings.shortcutKeysConsumeInput;
}
}
}
|