using System; using System.ComponentModel; using UnityEngine.InputSystem.Controls; namespace UnityEngine.InputSystem.Interactions { /// /// Performs the action if the control is pressed and held for at least the /// set duration (which defaults to ). /// /// /// The action is started when the control is pressed. If the control is released before the /// set , the action is canceled. As soon as the hold time is reached, /// the action performs. The action then stays performed until the control is released, at /// which point the action cancels. /// /// /// /// // Action that requires A button on gamepad to be held for half a second. /// var action = new InputAction(binding: "<Gamepad>/buttonSouth", interactions: "hold(duration=0.5)"); /// /// /// [DisplayName("Hold")] public class HoldInteraction : IInputInteraction { /// /// Duration in seconds that the control must be pressed for the hold to register. /// /// /// If this is less than or equal to 0 (the default), is used. /// /// Duration is expressed in real time and measured against the timestamps of input events /// () not against game time (). /// public float duration; /// /// Magnitude threshold that must be crossed by an actuated control for the control to /// be considered pressed. /// /// /// If this is less than or equal to 0 (the default), is used instead. /// /// public float pressPoint; private float durationOrDefault => duration > 0.0 ? duration : InputSystem.settings.defaultHoldTime; private float pressPointOrDefault => pressPoint > 0.0 ? pressPoint : ButtonControl.s_GlobalDefaultButtonPressPoint; private double m_TimePressed; /// public void Process(ref InputInteractionContext context) { if (context.timerHasExpired) { context.PerformedAndStayPerformed(); return; } switch (context.phase) { case InputActionPhase.Waiting: if (context.ControlIsActuated(pressPointOrDefault)) { m_TimePressed = context.time; context.Started(); context.SetTimeout(durationOrDefault); } break; case InputActionPhase.Started: // If we've reached our hold time threshold, perform the hold. // We do this regardless of what state the control changed to. if (context.time - m_TimePressed >= durationOrDefault) { context.PerformedAndStayPerformed(); } if (!context.ControlIsActuated()) { // Control is no longer actuated so we're done. context.Canceled(); } break; case InputActionPhase.Performed: if (!context.ControlIsActuated(pressPointOrDefault)) context.Canceled(); break; } } /// public void Reset() { m_TimePressed = 0; } } }