Skip to content

Commit a3c27fb

Browse files
Merge pull request #541 from StephenHodgson/HTK-EditorHands
Modified Editor Input
2 parents 4f88070 + 492e24a commit a3c27fb

File tree

1 file changed

+88
-28
lines changed

1 file changed

+88
-28
lines changed

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

Lines changed: 88 additions & 28 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,13 +41,16 @@ 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

@@ -65,7 +71,7 @@ public EditorHandData(uint handId)
6571
private const int EditorHandsCount = 2;
6672

6773
/// <summary>
68-
/// Array containing the hands data for the two fake hands
74+
/// Array containing the hands data for the two fake hands.
6975
/// </summary>
7076
private readonly EditorHandData[] editorHandsData = new EditorHandData[EditorHandsCount];
7177

@@ -75,10 +81,14 @@ public EditorHandData(uint handId)
7581
private readonly Dictionary<uint, EditorHandData> handIdToData = new Dictionary<uint, EditorHandData>(4);
7682
private readonly List<uint> pendingHandIdDeletes = new List<uint>();
7783

78-
// HashSets used to be able to quickly update the hands data when hands become visible / not visible
84+
// HashSets used to be able to quickly update the hands data when hands become visible / not visible.
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;
@@ -98,7 +108,7 @@ public override bool TryGetPosition(uint sourceId, out Vector3 position)
98108

99109
public override bool TryGetOrientation(uint sourceId, out Quaternion orientation)
100110
{
101-
// Orientation is not supported by hands
111+
// Orientation is not supported by hands.
102112
orientation = Quaternion.identity;
103113
return false;
104114
}
@@ -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
@@ -238,7 +249,6 @@ private EditorHandData GetOrAddHandData(uint sourceId)
238249
handData = new EditorHandData(sourceId);
239250
handIdToData.Add(handData.HandId, handData);
240251
newHands.Add(handData.HandId);
241-
242252
}
243253

244254
return handData;
@@ -249,24 +259,26 @@ private EditorHandData GetOrAddHandData(uint sourceId)
249259
/// </summary>
250260
/// <param name="handSource">Hand source to use to update the position.</param>
251261
/// <param name="editorHandData">EditorHandData structure to update.</param>
262+
/// <param name="deltaTime">Unscaled delta time of last event.</param>
263+
/// <param name="time">Unscaled time of last event.</param>
252264
private void UpdateHandState(DebugInteractionSourceState handSource, EditorHandData editorHandData, float deltaTime, float time)
253265
{
254-
// Update hand position
266+
// Update hand position.
255267
Vector3 handPosition;
256268
if (handSource.Properties.Location.TryGetPosition(out handPosition))
257269
{
258270
editorHandData.HandDelta = handPosition - editorHandData.HandPosition;
259271
editorHandData.HandPosition = handPosition;
260272
}
261273

262-
// Check for finger presses
274+
// Check for finger presses.
263275
if (handSource.Pressed != editorHandData.IsFingerDownPending)
264276
{
265277
editorHandData.IsFingerDownPending = handSource.Pressed;
266278
editorHandData.FingerStateUpdateTimer = FingerPressDelay;
267279
}
268280

269-
// Finger presses are delayed to mitigate issue with hand position shifting during air tap
281+
// Finger presses are delayed to mitigate issue with hand position shifting during air tap.
270282
editorHandData.FingerStateChanged = false;
271283
if (editorHandData.FingerStateUpdateTimer > 0)
272284
{
@@ -289,31 +301,79 @@ private void UpdateHandState(DebugInteractionSourceState handSource, EditorHandD
289301
/// Sends the events for hand state changes.
290302
/// </summary>
291303
/// <param name="editorHandData">Hand data for which events should be sent.</param>
304+
/// <param name="time">Unscaled time of last event.</param>
292305
private void SendHandStateEvents(EditorHandData editorHandData, float time)
293306
{
294-
// Hand moved event
307+
// Hand moved event.
295308
if (editorHandData.HandDelta.sqrMagnitude > 0)
296309
{
297310
HandMoved.RaiseEvent(this, editorHandData.HandId);
298311
}
299312

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

311-
// Also send click event when using this hands replacement input
312-
if (time - editorHandData.FingerDownStartTime < MaxClickDuration)
352+
if (!editorHandData.ManipulationInProgress)
353+
{
354+
// Manipulations are triggered by the amount of movement since the finger was pressed down.
355+
if (editorHandData.CumulativeDelta.magnitude > manipulationStartMovementThreshold)
313356
{
314-
// We currently only support single taps in editor
315-
inputManager.RaiseInputClicked(this, editorHandData.HandId, 1);
316-
}
357+
// Starting a manipulation will cancel an existing hold.
358+
if (editorHandData.HoldInProgress)
359+
{
360+
inputManager.RaiseHoldCanceled(this, editorHandData.HandId);
361+
editorHandData.HoldInProgress = false;
362+
}
363+
364+
inputManager.RaiseManipulationStarted(this, editorHandData.HandId, editorHandData.CumulativeDelta);
365+
editorHandData.ManipulationInProgress = true;
366+
}
367+
// Holds are triggered by time.
368+
else if (!editorHandData.HoldInProgress && (time - editorHandData.FingerDownStartTime >= MaxClickDuration))
369+
{
370+
inputManager.RaiseHoldStarted(this, editorHandData.HandId);
371+
editorHandData.HoldInProgress = true;
372+
}
373+
}
374+
else
375+
{
376+
inputManager.RaiseManipulationUpdated(this, editorHandData.HandId, editorHandData.CumulativeDelta);
317377
}
318378
}
319379
}
@@ -323,13 +383,13 @@ private void SendHandStateEvents(EditorHandData editorHandData, float time)
323383
/// </summary>
324384
private void SendHandVisibilityEvents()
325385
{
326-
// Send event for new hands that were added
386+
// Send event for new hands that were added.
327387
foreach (uint newHand in newHands)
328388
{
329389
inputManager.RaiseSourceDetected(this, newHand);
330390
}
331391

332-
// Send event for hands that are no longer visible and remove them from our dictionary
392+
// Send event for hands that are no longer visible and remove them from our dictionary.
333393
foreach (uint existingHand in handIdToData.Keys)
334394
{
335395
if (!currentHands.Contains(existingHand))
@@ -339,12 +399,12 @@ private void SendHandVisibilityEvents()
339399
}
340400
}
341401

342-
// Remove pending hand IDs
402+
// Remove pending hand IDs.
343403
for (int i = 0; i < pendingHandIdDeletes.Count; ++i)
344404
{
345405
handIdToData.Remove(pendingHandIdDeletes[i]);
346406
}
347407
pendingHandIdDeletes.Clear();
348408
}
349409
}
350-
}
410+
}

0 commit comments

Comments
 (0)