Skip to content

Commit 08af3d8

Browse files
Merge branch 'HTK-master' into HTK-local
2 parents 1094f55 + a3c27fb commit 08af3d8

File tree

2 files changed

+89
-29
lines changed

2 files changed

+89
-29
lines changed

Assets/HoloToolkit-Examples/SavingSpatialMeshes/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Process: Scan, save, download, and load.
1616

1717
1. Install the app on a device.
1818
2. Scan room.
19-
3. When your ready to save the mesh say, "Capture Mesh". Text will display to acknowledge the completion of the action.
19+
3. When you're ready to save the mesh say, "Capture Mesh". Text will display to acknowledge the completion of the action.
2020
4. Pull the saved mesh off of the device by going to the Device Portal. Navigate to System > File Explorer > User Files > LocalAppData > [Your App Name] > RoamingState. This is where .room files are saved.
2121
5. Download the .room file to your computer in the location opened by FileSurfaceObserver's "Open File Location" button.
2222
6. Press the Play button.

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)