A game about forced loneliness, made by TACStudios
1using System;
2using System.ComponentModel;
3using UnityEngine.InputSystem.Controls;
4using UnityEngine.Scripting;
5#if UNITY_EDITOR
6using UnityEngine.InputSystem.Editor;
7using UnityEngine.UIElements;
8#endif
9
10namespace UnityEngine.InputSystem.Interactions
11{
12 /// <summary>
13 /// Performs the action if the control is pressed and held for at least the
14 /// set duration (which defaults to <see cref="InputSettings.defaultHoldTime"/>).
15 /// </summary>
16 /// <remarks>
17 /// The action is started when the control is pressed. If the control is released before the
18 /// set <see cref="duration"/>, the action is canceled. As soon as the hold time is reached,
19 /// the action performs. The action then stays performed until the control is released, at
20 /// which point the action cancels.
21 ///
22 /// <example>
23 /// <code>
24 /// // Action that requires A button on gamepad to be held for half a second.
25 /// var action = new InputAction(binding: "<Gamepad>/buttonSouth", interactions: "hold(duration=0.5)");
26 /// </code>
27 /// </example>
28 /// </remarks>
29 [DisplayName("Hold")]
30 public class HoldInteraction : IInputInteraction
31 {
32 /// <summary>
33 /// Duration in seconds that the control must be pressed for the hold to register.
34 /// </summary>
35 /// <remarks>
36 /// If this is less than or equal to 0 (the default), <see cref="InputSettings.defaultHoldTime"/> is used.
37 ///
38 /// Duration is expressed in real time and measured against the timestamps of input events
39 /// (<see cref="LowLevel.InputEvent.time"/>) not against game time (<see cref="Time.time"/>).
40 /// </remarks>
41 public float duration;
42
43 /// <summary>
44 /// Magnitude threshold that must be crossed by an actuated control for the control to
45 /// be considered pressed.
46 /// </summary>
47 /// <remarks>
48 /// If this is less than or equal to 0 (the default), <see cref="InputSettings.defaultButtonPressPoint"/> is used instead.
49 /// </remarks>
50 /// <seealso cref="InputControl.EvaluateMagnitude()"/>
51 public float pressPoint;
52
53 private float durationOrDefault => duration > 0.0 ? duration : InputSystem.settings.defaultHoldTime;
54 private float pressPointOrDefault => pressPoint > 0.0 ? pressPoint : ButtonControl.s_GlobalDefaultButtonPressPoint;
55
56 private double m_TimePressed;
57
58 /// <inheritdoc />
59 public void Process(ref InputInteractionContext context)
60 {
61 if (context.timerHasExpired)
62 {
63 context.PerformedAndStayPerformed();
64 return;
65 }
66
67 switch (context.phase)
68 {
69 case InputActionPhase.Waiting:
70 if (context.ControlIsActuated(pressPointOrDefault))
71 {
72 m_TimePressed = context.time;
73
74 context.Started();
75 context.SetTimeout(durationOrDefault);
76 }
77 break;
78
79 case InputActionPhase.Started:
80 // If we've reached our hold time threshold, perform the hold.
81 // We do this regardless of what state the control changed to.
82 if (context.time - m_TimePressed >= durationOrDefault)
83 {
84 context.PerformedAndStayPerformed();
85 }
86 if (!context.ControlIsActuated())
87 {
88 // Control is no longer actuated so we're done.
89 context.Canceled();
90 }
91 break;
92
93 case InputActionPhase.Performed:
94 if (!context.ControlIsActuated(pressPointOrDefault))
95 context.Canceled();
96 break;
97 }
98 }
99
100 /// <inheritdoc />
101 public void Reset()
102 {
103 m_TimePressed = 0;
104 }
105 }
106
107 #if UNITY_EDITOR
108 /// <summary>
109 /// UI that is displayed when editing <see cref="HoldInteraction"/> in the editor.
110 /// </summary>
111 internal class HoldInteractionEditor : InputParameterEditor<HoldInteraction>
112 {
113 protected override void OnEnable()
114 {
115 m_PressPointSetting.Initialize("Press Point",
116 "Float value that an axis control has to cross for it to be considered pressed.",
117 "Default Button Press Point",
118 () => target.pressPoint, v => target.pressPoint = v, () => ButtonControl.s_GlobalDefaultButtonPressPoint);
119 m_DurationSetting.Initialize("Hold Time",
120 "Time (in seconds) that a control has to be held in order for it to register as a hold.",
121 "Default Hold Time",
122 () => target.duration, x => target.duration = x, () => InputSystem.settings.defaultHoldTime);
123 }
124
125 public override void OnGUI()
126 {
127#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
128 if (!InputSystem.settings.IsFeatureEnabled(InputFeatureNames.kUseIMGUIEditorForAssets)) return;
129#endif
130 m_PressPointSetting.OnGUI();
131 m_DurationSetting.OnGUI();
132 }
133
134#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
135 public override void OnDrawVisualElements(VisualElement root, Action onChangedCallback)
136 {
137 m_PressPointSetting.OnDrawVisualElements(root, onChangedCallback);
138 m_DurationSetting.OnDrawVisualElements(root, onChangedCallback);
139 }
140
141#endif
142
143 private CustomOrDefaultSetting m_PressPointSetting;
144 private CustomOrDefaultSetting m_DurationSetting;
145 }
146 #endif
147}