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 two additional modifiers. The button only triggers when
/// both modifiers are pressed.
///
///
/// This composite can be used to require two other buttons to be held while
/// using the control that triggers the action. This is most commonly used
/// on keyboards to require two of the modifier keys (shift, ctrl, or alt)
/// to be held in combination with another key, e.g. "CTRL+SHIFT+1".
///
///
///
/// // Create a button action that triggers when CTRL+SHIFT+1
/// // is pressed on the keyboard.
/// var action = new InputAction(type: InputActionType.Button);
/// action.AddCompositeBinding("TwoModifiers")
/// .With("Modifier1", "<Keyboard>/leftCtrl")
/// .With("Modifier1", "<Keyboard>/rightCtrl")
/// .With("Modifier2", "<Keyboard>/leftShift")
/// .With("Modifier2", "<Keyboard>/rightShift")
/// .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 and X 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("ButtonWithTwoModifiers")
/// .With("Modifier1", "<Gamepad>/buttonSouth")
/// .With("Modifier2", "<Gamepad>/buttonWest")
/// .With("Button", "<Gamepad>/leftTrigger");
///
///
///
///
[DesignTimeVisible(false)] // Obsoleted by TwoModifiersComposite
[DisplayStringFormat("{modifier1}+{modifier2}+{button}")]
public class ButtonWithTwoModifiers : InputBindingComposite
{
///
/// Binding for the first 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 modifier1;
///
/// Binding for the second 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 modifier2;
///
/// Binding for the button that is gated by and .
/// The composite will assume the value of this button while both of the modifiers are 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, and/or can be pressed after
/// and the composite will still trigger. Default is false.
///
///
/// By default, and are 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, Ctrl+Shift+B, the ctrl shift keys have 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 all of them to concurrently be in pressed state.
///
public bool overrideModifiersNeedToBePressedFirst;
///
/// Return the value of the part while both and
/// are 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 (ModifiersArePressed(ref context))
return context.ReadValue(button);
return default;
}
private bool ModifiersArePressed(ref InputBindingCompositeContext context)
{
var modifiersDown = context.ReadValueAsButton(modifier1) && context.ReadValueAsButton(modifier2);
if (modifiersDown && !overrideModifiersNeedToBePressedFirst)
{
var timestamp = context.GetPressTime(button);
var timestamp1 = context.GetPressTime(modifier1);
var timestamp2 = context.GetPressTime(modifier2);
return timestamp1 <= timestamp && timestamp2 <= timestamp;
}
return modifiersDown;
}
///
/// 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.IsFeatureEnabled(InputFeatureNames.kDisableShortcutSupport);
}
}
}