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 { /// /// A button with an additional modifier. The button only triggers when /// the modifier is pressed. /// /// /// 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". /// /// /// /// // 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") /// /// /// /// Note that this is not restricted to the keyboard and will preserve /// the full value of the button. /// /// /// /// // 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"); /// /// /// /// [DesignTimeVisible(false)] // Obsoleted by OneModifierComposite [DisplayStringFormat("{modifier}+{button}")] public class ButtonWithOneModifier : InputBindingComposite { /// /// Binding for the button that acts as a modifier, e.g. <Keyboard/leftCtrl. /// /// Part index to use with . /// /// This property is automatically assigned by the input system. /// // ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once FieldCanBeMadeReadOnly.Global // ReSharper disable once UnassignedField.Global [InputControl(layout = "Button")] public int modifier; /// /// Binding for the button that is gated by the modifier. The composite will assume the value /// of this button while the modifier is pressed. /// /// Part index to use with . /// /// This property is automatically assigned by the input system. /// // ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once FieldCanBeMadeReadOnly.Global // ReSharper disable once UnassignedField.Global [InputControl(layout = "Button")] public int button; /// /// If set to true, can be pressed after and the composite will /// still trigger. Default is false. /// /// /// By default, is required to be in pressed state before or at the same time that /// goes into pressed state for the composite as a whole to trigger. This means that binding to, for example, Shift+B, /// the shift key has to be pressed before pressing the B key. This is the behavior usually expected with /// keyboard shortcuts. /// /// This parameter can be used to bypass this behavior and allow any timing between and . /// The only requirement is for them both to concurrently be in pressed state. /// public bool overrideModifiersNeedToBePressedFirst; /// /// Return the value of the part if is pressed. Otherwise /// return 0. /// /// Evaluation context passed in from the input system. /// The current value of the composite. public override float ReadValue(ref InputBindingCompositeContext context) { if (ModifierIsPressed(ref context)) return context.ReadValue(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; } /// /// Same as in this case. /// /// Evaluation context passed in from the input system. /// A >0 value if the composite is currently actuated. public override float EvaluateMagnitude(ref InputBindingCompositeContext context) { return ReadValue(ref context); } protected override void FinishSetup(ref InputBindingCompositeContext context) { if (!overrideModifiersNeedToBePressedFirst) overrideModifiersNeedToBePressedFirst = !InputSystem.settings.shortcutKeysConsumeInput; } } }