File size: 5,584 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 139 140 141 142 143 144 145 | using System;
using System.ComponentModel;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Scripting;
#if UNITY_EDITOR
using UnityEngine.InputSystem.Editor;
using UnityEngine.UIElements;
#endif
namespace UnityEngine.InputSystem.Interactions
{
/// <summary>
/// Performs the action if the control is pressed and held for at least the
/// set duration (which defaults to <see cref="InputSettings.defaultHoldTime"/>).
/// </summary>
/// <remarks>
/// The action is started when the control is pressed. If the control is released before the
/// set <see cref="duration"/>, 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.
///
/// <example>
/// <code>
/// // 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)");
/// </code>
/// </example>
/// </remarks>
[DisplayName("Hold")]
public class HoldInteraction : IInputInteraction
{
/// <summary>
/// Duration in seconds that the control must be pressed for the hold to register.
/// </summary>
/// <remarks>
/// If this is less than or equal to 0 (the default), <see cref="InputSettings.defaultHoldTime"/> is used.
///
/// Duration is expressed in real time and measured against the timestamps of input events
/// (<see cref="LowLevel.InputEvent.time"/>) not against game time (<see cref="Time.time"/>).
/// </remarks>
public float duration;
/// <summary>
/// Magnitude threshold that must be crossed by an actuated control for the control to
/// be considered pressed.
/// </summary>
/// <remarks>
/// If this is less than or equal to 0 (the default), <see cref="InputSettings.defaultButtonPressPoint"/> is used instead.
/// </remarks>
/// <seealso cref="InputControl.EvaluateMagnitude()"/>
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;
/// <inheritdoc />
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;
}
}
/// <inheritdoc />
public void Reset()
{
m_TimePressed = 0;
}
}
#if UNITY_EDITOR
/// <summary>
/// UI that is displayed when editing <see cref="HoldInteraction"/> in the editor.
/// </summary>
internal class HoldInteractionEditor : InputParameterEditor<HoldInteraction>
{
protected override void OnEnable()
{
m_PressPointSetting.Initialize("Press Point",
"Float value that an axis control has to cross for it to be considered pressed.",
"Default Button Press Point",
() => target.pressPoint, v => target.pressPoint = v, () => ButtonControl.s_GlobalDefaultButtonPressPoint);
m_DurationSetting.Initialize("Hold Time",
"Time (in seconds) that a control has to be held in order for it to register as a hold.",
"Default Hold Time",
() => target.duration, x => target.duration = x, () => InputSystem.settings.defaultHoldTime);
}
public override void OnGUI()
{
m_PressPointSetting.OnGUI();
m_DurationSetting.OnGUI();
}
#if UNITY_INPUT_SYSTEM_UI_TK_ASSET_EDITOR
public override void OnDrawVisualElements(VisualElement root, Action onChangedCallback)
{
m_PressPointSetting.OnDrawVisualElements(root, onChangedCallback);
m_DurationSetting.OnDrawVisualElements(root, onChangedCallback);
}
#endif
private CustomOrDefaultSetting m_PressPointSetting;
private CustomOrDefaultSetting m_DurationSetting;
}
#endif
}
|