Skip to content

Commit 2221760

Browse files
author
Stephen Hodgson
committed
Modified Editor Input
1 parent 818815d commit 2221760

File tree

1 file changed

+88
-27
lines changed

1 file changed

+88
-27
lines changed

Assets/HoloToolkit/Input/Scripts/InputSources/EditorHandsInput.cs

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public EditorHandData(uint handId)
2929
IsFingerDownPending = false;
3030
FingerStateChanged = false;
3131
FingerStateUpdateTimer = -1;
32+
ManipulationInProgress = false;
33+
HoldInProgress = false;
34+
CumulativeDelta = Vector3.zero;
3235
}
3336

3437
public readonly uint HandId;
@@ -38,36 +41,39 @@ public EditorHandData(uint handId)
3841
public bool IsFingerDownPending;
3942
public bool FingerStateChanged;
4043
public float FingerStateUpdateTimer;
41-
public float FingerDownStartTime;
44+
public float FingerDownStartTime;
45+
public bool ManipulationInProgress;
46+
public bool HoldInProgress;
47+
public Vector3 CumulativeDelta;
4248
}
4349

4450
private ManualHandControl manualHandControl;
4551

4652
/// <summary>
47-
/// Dispatched each frame that a hand is moving
53+
/// Dispatched each frame that a hand is moving.
4854
/// </summary>
4955
public event Action<IInputSource, uint> HandMoved;
5056

5157
/// <summary>
5258
/// Delay before a finger pressed is considered.
5359
/// This mitigates fake finger taps that can sometimes be detected while the hand is moving.
5460
/// </summary>
55-
private const float FingerPressDelay = 0.07f;
61+
private const float FINGER_PRESS_DELAY = 0.07f;
5662

5763
/// <summary>
5864
/// The maximum interval between button down and button up that will result in a clicked event.
5965
/// </summary>
60-
private const float MaxClickDuration = 0.5f;
66+
private const float MAX_CLICK_DURATION = 0.5f;
6167

6268
/// <summary>
6369
/// Number of fake hands supported in the editor.
6470
/// </summary>
65-
private const int EditorHandsCount = 2;
71+
private const int EDITOR_HANDS_COUNT = 2;
6672

6773
/// <summary>
6874
/// Array containing the hands data for the two fake hands
6975
/// </summary>
70-
private readonly EditorHandData[] editorHandsData = new EditorHandData[EditorHandsCount];
76+
private readonly EditorHandData[] editorHandsData = new EditorHandData[EDITOR_HANDS_COUNT];
7177

7278
/// <summary>
7379
/// Dictionary linking each hand ID to its data.
@@ -79,6 +85,10 @@ public EditorHandData(uint handId)
7985
private readonly HashSet<uint> currentHands = new HashSet<uint>();
8086
private readonly HashSet<uint> newHands = new HashSet<uint>();
8187

88+
[SerializeField]
89+
[Tooltip("The total amount of hand movement that needs to happen to signal intent to start a manipulation. This is a distance, but not a distance in any one direction.")]
90+
private float manipulationStartMovementThreshold = 0.03f;
91+
8292
public override SupportedInputInfo GetSupportedInputInfo(uint sourceId)
8393
{
8494
return SupportedInputInfo.Position;
@@ -112,55 +122,55 @@ public Vector3 GetHandDelta(uint handId)
112122
{
113123
if (handId >= editorHandsData.Length)
114124
{
115-
string message = string.Format("GetHandDelta called with invalid hand ID {0}.", handId);
125+
string message = string.Format("GetHandDelta called with invalid hand ID {0}.", handId.ToString());
116126
throw new ArgumentException(message, "handId");
117127
}
118128

119129
return editorHandsData[handId].HandDelta;
120130
}
121131

122132
/// <summary>
123-
/// Gets the pressed state of the specified hand
133+
/// Gets the pressed state of the specified hand.
124134
/// </summary>
125135
/// <param name="handId">ID of the hand to get.</param>
126136
/// <returns>True if the specified hand is currently in an airtap.</returns>
127137
public bool GetFingerState(uint handId)
128138
{
129139
if (handId >= editorHandsData.Length)
130140
{
131-
var message = string.Format("GetFingerState called with invalid hand ID {0}.", handId);
141+
var message = string.Format("GetFingerState called with invalid hand ID {0}.", handId.ToString());
132142
throw new ArgumentException(message, "handId");
133143
}
134144

135145
return editorHandsData[handId].IsFingerDown;
136146
}
137147

138148
/// <summary>
139-
/// Gets whether the specified hand just started an airtap this frame
149+
/// Gets whether the specified hand just started an airtap this frame.
140150
/// </summary>
141151
/// <param name="handId">ID of the hand to get.</param>
142152
/// <returns>True for the first frame of an airtap</returns>
143153
public bool GetFingerDown(uint handId)
144154
{
145155
if (handId >= editorHandsData.Length)
146156
{
147-
var message = string.Format("GetFingerDown called with invalid hand ID {0}.", handId);
157+
var message = string.Format("GetFingerDown called with invalid hand ID {0}.", handId.ToString());
148158
throw new ArgumentException(message, "handId");
149159
}
150160

151161
return editorHandsData[handId].IsFingerDown && editorHandsData[handId].FingerStateChanged;
152162
}
153163

154164
/// <summary>
155-
/// Gets whether the specified hand just ended an airtap this frame
165+
/// Gets whether the specified hand just ended an airtap this frame.
156166
/// </summary>
157167
/// <param name="handId">ID of the hand to get.</param>
158168
/// <returns>True for the first frame of the release of an airtap</returns>
159169
public bool GetFingerUp(uint handId)
160170
{
161171
if (handId >= editorHandsData.Length)
162172
{
163-
var message = string.Format("GetFingerUp called with invalid hand ID {0}.", handId);
173+
var message = string.Format("GetFingerUp called with invalid hand ID {0}.", handId.ToString());
164174
throw new ArgumentException(message, "handId");
165175
}
166176

@@ -171,12 +181,13 @@ private void Awake()
171181
{
172182
#if !UNITY_EDITOR
173183
Destroy(this);
174-
#endif
184+
#else
175185
manualHandControl = GetComponent<ManualHandControl>();
176186
for (uint i = 0; i < editorHandsData.Length; i++)
177187
{
178188
editorHandsData[i] = new EditorHandData(i);
179189
}
190+
#endif
180191
}
181192

182193
#if UNITY_EDITOR
@@ -249,6 +260,8 @@ private EditorHandData GetOrAddHandData(uint sourceId)
249260
/// </summary>
250261
/// <param name="handSource">Hand source to use to update the position.</param>
251262
/// <param name="editorHandData">EditorHandData structure to update.</param>
263+
/// <param name="deltaTime">Unscaled delta time of last event.</param>
264+
/// <param name="time">Unscaled time of last event.</param>
252265
private void UpdateHandState(DebugInteractionSourceState handSource, EditorHandData editorHandData, float deltaTime, float time)
253266
{
254267
// Update hand position
@@ -263,7 +276,7 @@ private void UpdateHandState(DebugInteractionSourceState handSource, EditorHandD
263276
if (handSource.Pressed != editorHandData.IsFingerDownPending)
264277
{
265278
editorHandData.IsFingerDownPending = handSource.Pressed;
266-
editorHandData.FingerStateUpdateTimer = FingerPressDelay;
279+
editorHandData.FingerStateUpdateTimer = FINGER_PRESS_DELAY;
267280
}
268281

269282
// Finger presses are delayed to mitigate issue with hand position shifting during air tap
@@ -289,31 +302,79 @@ private void UpdateHandState(DebugInteractionSourceState handSource, EditorHandD
289302
/// Sends the events for hand state changes.
290303
/// </summary>
291304
/// <param name="editorHandData">Hand data for which events should be sent.</param>
305+
/// <param name="time">Unscaled time of last event.</param>
292306
private void SendHandStateEvents(EditorHandData editorHandData, float time)
293307
{
294-
// Hand moved event
308+
// Hand moved event.
295309
if (editorHandData.HandDelta.sqrMagnitude > 0)
296310
{
297311
HandMoved.RaiseEvent(this, editorHandData.HandId);
298312
}
299313

300-
// Finger pressed/released events
314+
// If the finger state has just changed to be down vs up.
301315
if (editorHandData.FingerStateChanged)
302316
{
317+
// New down presses are straightforward - fire input down and be on your way.
303318
if (editorHandData.IsFingerDown)
304319
{
305-
inputManager.RaiseSourceDown(this, editorHandData.HandId);
320+
InputManager.Instance.RaiseSourceDown(this, editorHandData.HandId);
321+
editorHandData.CumulativeDelta = Vector3.zero;
306322
}
323+
// New up presses require sending different events depending on whether it's also a click, hold, or manipulation.
307324
else
308325
{
309-
inputManager.RaiseSourceUp(this, editorHandData.HandId);
326+
// A gesture is always either a click, a hold or a manipulation.
327+
if (editorHandData.ManipulationInProgress)
328+
{
329+
InputManager.Instance.RaiseManipulationCompleted(this, editorHandData.HandId, editorHandData.CumulativeDelta);
330+
editorHandData.ManipulationInProgress = false;
331+
}
332+
// Clicks and holds are based on time, and both are overruled by manipulations.
333+
else if (editorHandData.HoldInProgress)
334+
{
335+
InputManager.Instance.RaiseHoldCompleted(this, editorHandData.HandId);
336+
editorHandData.HoldInProgress = false;
337+
}
338+
else
339+
{
340+
// We currently only support single taps in editor.
341+
InputManager.Instance.RaiseInputClicked(this, editorHandData.HandId, 1);
342+
}
343+
344+
InputManager.Instance.RaiseSourceUp(this, editorHandData.HandId);
345+
}
346+
}
347+
// If the finger state hasn't changed, and the finger is down, that means if calculations need to be done
348+
// nothing might change, or it might trigger a hold or a manipulation (or a hold and then a manipulation).
349+
else if (editorHandData.IsFingerDown)
350+
{
351+
editorHandData.CumulativeDelta += editorHandData.HandDelta;
310352

311-
// Also send click event when using this hands replacement input
312-
if (time - editorHandData.FingerDownStartTime < MaxClickDuration)
353+
if (!editorHandData.ManipulationInProgress)
354+
{
355+
// Manipulations are triggered by the amount of movement since the finger was pressed down.
356+
if (editorHandData.CumulativeDelta.magnitude > manipulationStartMovementThreshold)
357+
{
358+
// Starting a manipulation will cancel an existing hold.
359+
if (editorHandData.HoldInProgress)
360+
{
361+
InputManager.Instance.RaiseHoldCanceled(this, editorHandData.HandId);
362+
editorHandData.HoldInProgress = false;
363+
}
364+
365+
InputManager.Instance.RaiseManipulationStarted(this, editorHandData.HandId, editorHandData.CumulativeDelta);
366+
editorHandData.ManipulationInProgress = true;
367+
}
368+
// Holds are triggered by time.
369+
else if (!editorHandData.HoldInProgress && (time - editorHandData.FingerDownStartTime >= MAX_CLICK_DURATION))
313370
{
314-
// We currently only support single taps in editor
315-
inputManager.RaiseInputClicked(this, editorHandData.HandId, 1);
316-
}
371+
InputManager.Instance.RaiseHoldStarted(this, editorHandData.HandId);
372+
editorHandData.HoldInProgress = true;
373+
}
374+
}
375+
else
376+
{
377+
InputManager.Instance.RaiseManipulationUpdated(this, editorHandData.HandId, editorHandData.CumulativeDelta);
317378
}
318379
}
319380
}
@@ -326,7 +387,7 @@ private void SendHandVisibilityEvents()
326387
// Send event for new hands that were added
327388
foreach (uint newHand in newHands)
328389
{
329-
inputManager.RaiseSourceDetected(this, newHand);
390+
InputManager.Instance.RaiseSourceDetected(this, newHand);
330391
}
331392

332393
// Send event for hands that are no longer visible and remove them from our dictionary
@@ -335,7 +396,7 @@ private void SendHandVisibilityEvents()
335396
if (!currentHands.Contains(existingHand))
336397
{
337398
pendingHandIdDeletes.Add(existingHand);
338-
inputManager.RaiseSourceLost(this, existingHand);
399+
InputManager.Instance.RaiseSourceLost(this, existingHand);
339400
}
340401
}
341402

@@ -347,4 +408,4 @@ private void SendHandVisibilityEvents()
347408
pendingHandIdDeletes.Clear();
348409
}
349410
}
350-
}
411+
}

0 commit comments

Comments
 (0)