-
Notifications
You must be signed in to change notification settings - Fork 333
Expand file tree
/
Copy pathHoldInteraction.cs
More file actions
144 lines (129 loc) · 5.49 KB
/
HoldInteraction.cs
File metadata and controls
144 lines (129 loc) · 5.49 KB
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
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()
{
if (!InputSystem.settings.useIMGUIEditorForAssets)
return;
m_PressPointSetting.OnGUI();
m_DurationSetting.OnGUI();
}
public override void OnDrawVisualElements(VisualElement root, Action onChangedCallback)
{
m_PressPointSetting.OnDrawVisualElements(root, onChangedCallback);
m_DurationSetting.OnDrawVisualElements(root, onChangedCallback);
}
private CustomOrDefaultSetting m_PressPointSetting;
private CustomOrDefaultSetting m_DurationSetting;
}
#endif
}