t1 / TFDContents / Assets / KinectScripts / InteractionManager.cs @ 3
이력 | 보기 | 이력해설 | 다운로드 (35.5 KB)
1 |
using UnityEngine; |
---|---|
2 |
using UnityEngine.UI; |
3 |
//using Windows.Kinect; |
4 |
|
5 |
using System.Collections; |
6 |
using System.Collections.Generic; |
7 |
using System.Runtime.InteropServices; |
8 |
using System; |
9 |
using System.IO; |
10 |
|
11 |
|
12 |
/// <summary> |
13 |
/// This interface needs to be implemented by all interaction listeners |
14 |
/// </summary> |
15 |
public interface InteractionListenerInterface |
16 |
{ |
17 |
/// <summary> |
18 |
/// Invoked when hand grip is detected. |
19 |
/// </summary> |
20 |
/// <param name="userId">User ID</param> |
21 |
/// <param name="userIndex">User index</param> |
22 |
/// <param name="isRightHand">Whether it is the right hand or not</param> |
23 |
/// <param name="isHandInteracting">Whether this hand is the interacting one or not</param> |
24 |
/// <param name="handScreenPos">Hand screen position, including depth (Z)</param> |
25 |
void HandGripDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos); |
26 |
|
27 |
/// <summary> |
28 |
/// Invoked when hand release is detected. |
29 |
/// </summary> |
30 |
/// <param name="userId">User ID</param> |
31 |
/// <param name="userIndex">User index</param> |
32 |
/// <param name="isRightHand">Whether it is the right hand or not</param> |
33 |
/// <param name="isHandInteracting">Whether this hand is the interacting one or not</param> |
34 |
/// <param name="handScreenPos">Hand screen position, including depth (Z)</param> |
35 |
void HandReleaseDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos); |
36 |
|
37 |
/// <summary> |
38 |
/// Invoked when hand click is detected. |
39 |
/// </summary> |
40 |
/// <returns><c>true</c>, if the click detection must be restarted, <c>false</c> otherwise.</returns> |
41 |
/// <param name="userId">User ID</param> |
42 |
/// <param name="userIndex">User index</param> |
43 |
/// <param name="isRightHand">Whether it is the right hand or not</param> |
44 |
/// <param name="handScreenPos">Hand screen position, including depth (Z)</param> |
45 |
bool HandClickDetected(long userId, int userIndex, bool isRightHand, Vector3 handScreenPos); |
46 |
} |
47 |
|
48 |
|
49 |
/// <summary> |
50 |
/// Interaction manager is component that controls the hand cursor and manages the hand interactions. |
51 |
/// </summary> |
52 |
public class InteractionManager : MonoBehaviour |
53 |
{ |
54 |
/// <summary> |
55 |
/// The hand event types. |
56 |
/// </summary> |
57 |
public enum HandEventType : int |
58 |
{ |
59 |
None = 0, |
60 |
Grip = 1, |
61 |
Release = 2 |
62 |
} |
63 |
|
64 |
[Tooltip("Index of the player, tracked by this component. 0 means the 1st player, 1 - the 2nd one, 2 - the 3rd one, etc.")] |
65 |
public int playerIndex = 0; |
66 |
|
67 |
[Tooltip("The image that may be used to show the hand-moved cursor on the screen or not. The sprite textures below need to be set too.")] |
68 |
public Image guiHandCursor; |
69 |
|
70 |
[Tooltip("Hand-cursor sprite texture, for the hand-grip state.")] |
71 |
public Sprite gripHandTexture; |
72 |
[Tooltip("Hand-cursor sprite texture, for the hand-release state.")] |
73 |
public Sprite releaseHandTexture; |
74 |
[Tooltip("Hand-cursor sprite texture, for the non-tracked state.")] |
75 |
public Sprite normalHandTexture; |
76 |
|
77 |
[Tooltip("Whether the cursor should overlay user's hand on screen or not.")] |
78 |
public bool handOverlayCursor = false; |
79 |
|
80 |
[Tooltip("Smooth factor for cursor movement.")] |
81 |
public float smoothFactor = 10f; |
82 |
|
83 |
[Tooltip("Whether the hand clicks (i.e. hand staying in place for ~2 seconds) are enabled or not.")] |
84 |
public bool allowHandClicks = true; |
85 |
|
86 |
[Tooltip("Whether the hand pushes need to be considered as clicks or not.")] |
87 |
public bool allowPushToClick = true; |
88 |
|
89 |
[Tooltip("Whether the hand cursor and interactions control the mouse cursor or not.")] |
90 |
public bool controlMouseCursor = false; |
91 |
|
92 |
[Tooltip("Whether the hand grips and releases control mouse dragging or not.")] |
93 |
public bool controlMouseDrag = false; |
94 |
|
95 |
// Bool to specify whether to convert Unity screen coordinates to full screen mouse coordinates |
96 |
//public bool convertMouseToFullScreen = false; |
97 |
|
98 |
[Tooltip("List of the interaction listeners in the scene. If the list is empty, the available interaction listeners will be detected at scene start up.")] |
99 |
public List<MonoBehaviour> interactionListeners; |
100 |
|
101 |
[Tooltip("GUI-Text to display the interaction-manager debug messages.")] |
102 |
public GUIText debugText; |
103 |
|
104 |
// tracked userId |
105 |
private long playerUserID = 0; |
106 |
private long lastUserID = 0; |
107 |
|
108 |
// hand press properties |
109 |
private bool isLeftHandPrimary = false; |
110 |
private bool isRightHandPrimary = false; |
111 |
|
112 |
private bool isLeftHandPress = false; |
113 |
private bool isRightHandPress = false; |
114 |
|
115 |
private float lastLeftHandPressTime = 0f; |
116 |
private float lastRightHandPressTime = 0f; |
117 |
|
118 |
private float leftHandPressProgress = 0f; |
119 |
private float rightHandPressProgress = 0f; |
120 |
|
121 |
// cursor properties |
122 |
private Vector3 cursorScreenPos = Vector3.zero; |
123 |
private bool dragInProgress = false; |
124 |
|
125 |
private Image cursorProgressBar; |
126 |
private float cursorClickProgress = 0f; |
127 |
|
128 |
// hand states |
129 |
private KinectInterop.HandState leftHandState = KinectInterop.HandState.Unknown; |
130 |
private KinectInterop.HandState rightHandState = KinectInterop.HandState.Unknown; |
131 |
|
132 |
// left hand properties |
133 |
private HandEventType leftHandEvent = HandEventType.None; |
134 |
private HandEventType lastLeftHandEvent = HandEventType.Release; |
135 |
|
136 |
private Vector3 leftHandPos = Vector3.zero; |
137 |
private Vector3 leftHandScreenPos = Vector3.zero; |
138 |
private Vector3 leftIboxLeftBotBack = Vector3.zero; |
139 |
private Vector3 leftIboxRightTopFront = Vector3.zero; |
140 |
private bool isleftIboxValid = false; |
141 |
private bool isLeftHandInteracting = false; |
142 |
private float leftHandInteractingSince = 0f; |
143 |
|
144 |
// left hand click properties |
145 |
private Vector3 lastLeftHandPos = Vector3.zero; |
146 |
private float lastLeftHandClickTime = 0f; |
147 |
private bool isLeftHandClick = false; |
148 |
private float leftHandClickProgress = 0f; |
149 |
|
150 |
// left hand properties |
151 |
private HandEventType rightHandEvent = HandEventType.None; |
152 |
private HandEventType lastRightHandEvent = HandEventType.Release; |
153 |
|
154 |
private Vector3 rightHandPos = Vector3.zero; |
155 |
private Vector3 rightHandScreenPos = Vector3.zero; |
156 |
private Vector3 rightIboxLeftBotBack = Vector3.zero; |
157 |
private Vector3 rightIboxRightTopFront = Vector3.zero; |
158 |
private bool isRightIboxValid = false; |
159 |
private bool isRightHandInteracting = false; |
160 |
private float rightHandInteractingSince = 0f; |
161 |
|
162 |
// right hand click properties |
163 |
private Vector3 lastRightHandPos = Vector3.zero; |
164 |
private float lastRightHandClickTime = 0f; |
165 |
private bool isRightHandClick = false; |
166 |
private float rightHandClickProgress = 0f; |
167 |
|
168 |
// Bool to keep track whether Kinect and Interaction library have been initialized |
169 |
private bool interactionInited = false; |
170 |
|
171 |
// The single instance of FacetrackingManager |
172 |
private static InteractionManager instance; |
173 |
|
174 |
|
175 |
/// <summary> |
176 |
/// Gets the single InteractionManager instance. |
177 |
/// </summary> |
178 |
/// <value>The InteractionManager instance.</value> |
179 |
public static InteractionManager Instance |
180 |
{ |
181 |
get |
182 |
{ |
183 |
return instance; |
184 |
} |
185 |
} |
186 |
|
187 |
/// <summary> |
188 |
/// Determines whether the InteractionManager was successfully initialized. |
189 |
/// </summary> |
190 |
/// <returns><c>true</c> if InteractionManager was successfully initialized; otherwise, <c>false</c>.</returns> |
191 |
public bool IsInteractionInited() |
192 |
{ |
193 |
return interactionInited; |
194 |
} |
195 |
|
196 |
/// <summary> |
197 |
/// Gets the current user ID, or 0 if no user is currently tracked. |
198 |
/// </summary> |
199 |
/// <returns>The user ID</returns> |
200 |
public long GetUserID() |
201 |
{ |
202 |
return playerUserID; |
203 |
} |
204 |
|
205 |
/// <summary> |
206 |
/// Gets the current left hand event (none, grip or release). |
207 |
/// </summary> |
208 |
/// <returns>The current left hand event.</returns> |
209 |
public HandEventType GetLeftHandEvent() |
210 |
{ |
211 |
return leftHandEvent; |
212 |
} |
213 |
|
214 |
/// <summary> |
215 |
/// Gets the last detected left hand event (grip or release). |
216 |
/// </summary> |
217 |
/// <returns>The last left hand event.</returns> |
218 |
public HandEventType GetLastLeftHandEvent() |
219 |
{ |
220 |
return lastLeftHandEvent; |
221 |
} |
222 |
|
223 |
/// <summary> |
224 |
/// Gets the current normalized viewport position of the left hand, in range [0, 1]. |
225 |
/// </summary> |
226 |
/// <returns>The left hand viewport position.</returns> |
227 |
public Vector3 GetLeftHandScreenPos() |
228 |
{ |
229 |
return leftHandScreenPos; |
230 |
} |
231 |
|
232 |
/// <summary> |
233 |
/// Determines whether the left hand is primary for the user. |
234 |
/// </summary> |
235 |
/// <returns><c>true</c> if the left hand is primary for the user; otherwise, <c>false</c>.</returns> |
236 |
public bool IsLeftHandPrimary() |
237 |
{ |
238 |
return isLeftHandPrimary; |
239 |
} |
240 |
|
241 |
/// <summary> |
242 |
/// Determines whether the left hand is pressing. |
243 |
/// </summary> |
244 |
/// <returns><c>true</c> if the left hand is pressing; otherwise, <c>false</c>.</returns> |
245 |
public bool IsLeftHandPress() |
246 |
{ |
247 |
return isLeftHandPress; |
248 |
} |
249 |
|
250 |
/// <summary> |
251 |
/// Determines whether a left hand click is detected, false otherwise. |
252 |
/// </summary> |
253 |
/// <returns><c>true</c> if a left hand click is detected; otherwise, <c>false</c>.</returns> |
254 |
public bool IsLeftHandClickDetected() |
255 |
{ |
256 |
if(isLeftHandClick) |
257 |
{ |
258 |
isLeftHandClick = false; |
259 |
cursorClickProgress = leftHandClickProgress = 0f; |
260 |
lastLeftHandPos = Vector3.zero; |
261 |
|
262 |
lastLeftHandClickTime = Time.realtimeSinceStartup; |
263 |
lastLeftHandPressTime = Time.realtimeSinceStartup; |
264 |
|
265 |
return true; |
266 |
} |
267 |
|
268 |
return false; |
269 |
} |
270 |
|
271 |
/// <summary> |
272 |
/// Gets the left hand click progress, in range [0, 1]. |
273 |
/// </summary> |
274 |
/// <returns>The left hand click progress.</returns> |
275 |
public float GetLeftHandClickProgress() |
276 |
{ |
277 |
return leftHandClickProgress; |
278 |
} |
279 |
|
280 |
/// <summary> |
281 |
/// Gets the current right hand event (none, grip or release). |
282 |
/// </summary> |
283 |
/// <returns>The current right hand event.</returns> |
284 |
public HandEventType GetRightHandEvent() |
285 |
{ |
286 |
return rightHandEvent; |
287 |
} |
288 |
|
289 |
/// <summary> |
290 |
/// Gets the last detected right hand event (grip or release). |
291 |
/// </summary> |
292 |
/// <returns>The last right hand event.</returns> |
293 |
public HandEventType GetLastRightHandEvent() |
294 |
{ |
295 |
return lastRightHandEvent; |
296 |
} |
297 |
|
298 |
/// <summary> |
299 |
/// Gets the current normalized viewport position of the right hand, in range [0, 1]. |
300 |
/// </summary> |
301 |
/// <returns>The right hand viewport position.</returns> |
302 |
public Vector3 GetRightHandScreenPos() |
303 |
{ |
304 |
return rightHandScreenPos; |
305 |
} |
306 |
|
307 |
/// <summary> |
308 |
/// Determines whether the right hand is primary for the user. |
309 |
/// </summary> |
310 |
/// <returns><c>true</c> if the right hand is primary for the user; otherwise, <c>false</c>.</returns> |
311 |
public bool IsRightHandPrimary() |
312 |
{ |
313 |
return isRightHandPrimary; |
314 |
} |
315 |
|
316 |
/// <summary> |
317 |
/// Determines whether the right hand is pressing. |
318 |
/// </summary> |
319 |
/// <returns><c>true</c> if the right hand is pressing; otherwise, <c>false</c>.</returns> |
320 |
public bool IsRightHandPress() |
321 |
{ |
322 |
return isRightHandPress; |
323 |
} |
324 |
|
325 |
/// <summary> |
326 |
/// Determines whether a right hand click is detected, false otherwise. |
327 |
/// </summary> |
328 |
/// <returns><c>true</c> if a right hand click is detected; otherwise, <c>false</c>.</returns> |
329 |
public bool IsRightHandClickDetected() |
330 |
{ |
331 |
if(isRightHandClick) |
332 |
{ |
333 |
isRightHandClick = false; |
334 |
cursorClickProgress = rightHandClickProgress = 0f; |
335 |
lastRightHandPos = Vector3.zero; |
336 |
|
337 |
lastRightHandClickTime = Time.realtimeSinceStartup; |
338 |
lastRightHandPressTime = Time.realtimeSinceStartup; |
339 |
|
340 |
return true; |
341 |
} |
342 |
|
343 |
return false; |
344 |
} |
345 |
|
346 |
/// <summary> |
347 |
/// Gets the right hand click progress, in range [0, 1]. |
348 |
/// </summary> |
349 |
/// <returns>The right hand click progress.</returns> |
350 |
public float GetRightHandClickProgress() |
351 |
{ |
352 |
return rightHandClickProgress; |
353 |
} |
354 |
|
355 |
/// <summary> |
356 |
/// Gets the current cursor normalized viewport position. |
357 |
/// </summary> |
358 |
/// <returns>The cursor viewport position.</returns> |
359 |
public Vector3 GetCursorPosition() |
360 |
{ |
361 |
return cursorScreenPos; |
362 |
} |
363 |
|
364 |
/// <summary> |
365 |
/// Gets the cursor click progress, in range [0, 1]. |
366 |
/// </summary> |
367 |
/// <returns>The right hand click progress.</returns> |
368 |
public float GetCursorClickProgress() |
369 |
{ |
370 |
return cursorClickProgress; |
371 |
} |
372 |
|
373 |
|
374 |
//----------------------------------- end of public functions --------------------------------------// |
375 |
|
376 |
void Awake() |
377 |
{ |
378 |
instance = this; |
379 |
} |
380 |
|
381 |
|
382 |
void Start() |
383 |
{ |
384 |
// get the progress bar reference if any |
385 |
GameObject objProgressBar = guiHandCursor && guiHandCursor.gameObject.transform.childCount > 0 ? guiHandCursor.transform.GetChild(0).gameObject : null; |
386 |
cursorProgressBar = objProgressBar ? objProgressBar.GetComponent<Image>() : null; |
387 |
|
388 |
interactionInited = true; |
389 |
|
390 |
// try to automatically detect the available interaction listeners in the scene |
391 |
if(interactionListeners.Count == 0) |
392 |
{ |
393 |
MonoBehaviour[] monoScripts = FindObjectsOfType(typeof(MonoBehaviour)) as MonoBehaviour[]; |
394 |
|
395 |
foreach(MonoBehaviour monoScript in monoScripts) |
396 |
{ |
397 |
// if(typeof(InteractionListenerInterface).IsAssignableFrom(monoScript.GetType()) && |
398 |
// monoScript.enabled) |
399 |
if((monoScript is InteractionListenerInterface) && monoScript.enabled) |
400 |
{ |
401 |
interactionListeners.Add(monoScript); |
402 |
} |
403 |
} |
404 |
} |
405 |
|
406 |
} |
407 |
|
408 |
void OnDestroy() |
409 |
{ |
410 |
interactionInited = false; |
411 |
instance = null; |
412 |
} |
413 |
|
414 |
void Update () |
415 |
{ |
416 |
KinectManager kinectManager = KinectManager.Instance; |
417 |
|
418 |
// update Kinect interaction |
419 |
if(kinectManager && kinectManager.IsInitialized()) |
420 |
{ |
421 |
playerUserID = kinectManager.GetUserIdByIndex(playerIndex); |
422 |
|
423 |
if(playerUserID != 0) |
424 |
{ |
425 |
lastUserID = playerUserID; |
426 |
HandEventType handEvent = HandEventType.None; |
427 |
|
428 |
// get the left hand state |
429 |
leftHandState = kinectManager.GetLeftHandState(playerUserID); |
430 |
|
431 |
// check if the left hand is interacting |
432 |
isleftIboxValid = kinectManager.GetLeftHandInteractionBox(playerUserID, ref leftIboxLeftBotBack, ref leftIboxRightTopFront, isleftIboxValid); |
433 |
//bool bLeftHandPrimaryNow = false; |
434 |
|
435 |
// was the left hand interacting till now |
436 |
bool wasLeftHandInteracting = isLeftHandInteracting; |
437 |
|
438 |
if(isleftIboxValid && //bLeftHandPrimaryNow && |
439 |
kinectManager.GetJointTrackingState(playerUserID, (int)KinectInterop.JointType.HandLeft) != KinectInterop.TrackingState.NotTracked) |
440 |
{ |
441 |
leftHandPos = kinectManager.GetJointPosition(playerUserID, (int)KinectInterop.JointType.HandLeft); |
442 |
leftHandScreenPos.z = Mathf.Clamp01((leftIboxLeftBotBack.z - leftHandPos.z) / (leftIboxLeftBotBack.z - leftIboxRightTopFront.z)); |
443 |
|
444 |
if (!handOverlayCursor) |
445 |
{ |
446 |
leftHandScreenPos.x = Mathf.Clamp01((leftHandPos.x - leftIboxLeftBotBack.x) / (leftIboxRightTopFront.x - leftIboxLeftBotBack.x)); |
447 |
leftHandScreenPos.y = Mathf.Clamp01((leftHandPos.y - leftIboxLeftBotBack.y) / (leftIboxRightTopFront.y - leftIboxLeftBotBack.y)); |
448 |
|
449 |
isLeftHandInteracting = (leftHandPos.x >= (leftIboxLeftBotBack.x - 1.0f)) && (leftHandPos.x <= (leftIboxRightTopFront.x + 0.5f)) && |
450 |
(leftHandPos.y >= (leftIboxLeftBotBack.y - 0.1f)) && (leftHandPos.y <= (leftIboxRightTopFront.y + 0.7f)) && |
451 |
(leftIboxLeftBotBack.z >= leftHandPos.z) && (leftIboxRightTopFront.z * 0.8f <= leftHandPos.z); |
452 |
} |
453 |
else |
454 |
{ |
455 |
isLeftHandInteracting = GetHandOverlayScreenPos (kinectManager, (int)KinectInterop.JointType.HandLeft, ref leftHandScreenPos) && |
456 |
(leftHandPos.y >= (leftIboxLeftBotBack.y - 0.15f)) && (leftHandPos.y <= (leftIboxRightTopFront.y + 0.7f)) && |
457 |
(leftIboxLeftBotBack.z >= leftHandPos.z) && (leftIboxRightTopFront.z * 0.8f <= leftHandPos.z); |
458 |
} |
459 |
|
460 |
//bLeftHandPrimaryNow = isLeftHandInteracting; |
461 |
// start interacting? |
462 |
if(!wasLeftHandInteracting && isLeftHandInteracting) |
463 |
{ |
464 |
leftHandInteractingSince = Time.realtimeSinceStartup; |
465 |
} |
466 |
|
467 |
// check for left press |
468 |
isLeftHandPress = leftHandScreenPos.z > 0.99f; // ((leftIboxRightTopFront.z - 0.1f) >= leftHandPos.z); |
469 |
leftHandPressProgress = (Time.realtimeSinceStartup - lastLeftHandPressTime) >= KinectInterop.Constants.ClickStayDuration && |
470 |
leftHandScreenPos.z >= 0.7f ? (leftHandScreenPos.z - 0.7f) / 0.3f : 0f; |
471 |
|
472 |
// check for left hand click |
473 |
if(!dragInProgress && isLeftHandInteracting && |
474 |
((allowHandClicks && ((leftHandPos - lastLeftHandPos).magnitude < KinectInterop.Constants.ClickMaxDistance)) || |
475 |
(allowPushToClick && leftHandPressProgress > 0f))) |
476 |
{ |
477 |
if((allowHandClicks && (Time.realtimeSinceStartup - lastLeftHandClickTime) >= KinectInterop.Constants.ClickStayDuration) || |
478 |
(allowPushToClick && leftHandPressProgress > 0.99f && isLeftHandPress)) |
479 |
{ |
480 |
if(!isLeftHandClick) |
481 |
{ |
482 |
isLeftHandClick = true; |
483 |
cursorClickProgress = leftHandClickProgress = 1f; |
484 |
|
485 |
foreach(InteractionListenerInterface listener in interactionListeners) |
486 |
{ |
487 |
if (listener.HandClickDetected (playerUserID, playerIndex, false, leftHandScreenPos)) |
488 |
{ |
489 |
isLeftHandClick = false; |
490 |
cursorClickProgress = leftHandClickProgress = 0f; |
491 |
lastLeftHandPos = Vector3.zero; |
492 |
|
493 |
lastLeftHandClickTime = Time.realtimeSinceStartup; |
494 |
lastLeftHandPressTime = Time.realtimeSinceStartup; |
495 |
} |
496 |
} |
497 |
|
498 |
if(controlMouseCursor) |
499 |
{ |
500 |
MouseControl.MouseClick(); |
501 |
|
502 |
isLeftHandClick = false; |
503 |
cursorClickProgress = leftHandClickProgress = 0f; |
504 |
lastLeftHandPos = Vector3.zero; |
505 |
|
506 |
lastLeftHandClickTime = Time.realtimeSinceStartup; |
507 |
lastLeftHandPressTime = Time.realtimeSinceStartup; |
508 |
} |
509 |
} |
510 |
} |
511 |
else |
512 |
{ |
513 |
// show progress after the 1st half of the needed duration |
514 |
float leftHandTimeProgress = allowHandClicks && (Time.realtimeSinceStartup - lastLeftHandClickTime) >= (KinectInterop.Constants.ClickStayDuration / 2f) ? |
515 |
((Time.realtimeSinceStartup - lastLeftHandClickTime - (KinectInterop.Constants.ClickStayDuration / 2f)) * 2f / KinectInterop.Constants.ClickStayDuration) : 0f; |
516 |
cursorClickProgress = leftHandClickProgress = allowPushToClick && leftHandScreenPos.z >= 0.7f ? leftHandPressProgress : leftHandTimeProgress; |
517 |
} |
518 |
} |
519 |
else |
520 |
{ |
521 |
isLeftHandClick = false; |
522 |
leftHandClickProgress = 0f; |
523 |
lastLeftHandPos = leftHandPos; |
524 |
lastLeftHandClickTime = Time.realtimeSinceStartup; |
525 |
} |
526 |
} |
527 |
else |
528 |
{ |
529 |
isLeftHandInteracting = false; |
530 |
isLeftHandPress = false; |
531 |
leftHandPressProgress = 0f; |
532 |
} |
533 |
|
534 |
// get the right hand state |
535 |
rightHandState = kinectManager.GetRightHandState(playerUserID); |
536 |
|
537 |
// check if the right hand is interacting |
538 |
isRightIboxValid = kinectManager.GetRightHandInteractionBox(playerUserID, ref rightIboxLeftBotBack, ref rightIboxRightTopFront, isRightIboxValid); |
539 |
//bool bRightHandPrimaryNow = false; |
540 |
|
541 |
// was the right hand interacting till now |
542 |
bool wasRightHandInteracting = isRightHandInteracting; |
543 |
|
544 |
if(isRightIboxValid && //bRightHandPrimaryNow && |
545 |
kinectManager.GetJointTrackingState(playerUserID, (int)KinectInterop.JointType.HandRight) != KinectInterop.TrackingState.NotTracked) |
546 |
{ |
547 |
rightHandPos = kinectManager.GetJointPosition(playerUserID, (int)KinectInterop.JointType.HandRight); |
548 |
rightHandScreenPos.z = Mathf.Clamp01((rightIboxLeftBotBack.z - rightHandPos.z) / (rightIboxLeftBotBack.z - rightIboxRightTopFront.z)); |
549 |
|
550 |
if (!handOverlayCursor) |
551 |
{ |
552 |
rightHandScreenPos.x = Mathf.Clamp01((rightHandPos.x - rightIboxLeftBotBack.x) / (rightIboxRightTopFront.x - rightIboxLeftBotBack.x)); |
553 |
rightHandScreenPos.y = Mathf.Clamp01((rightHandPos.y - rightIboxLeftBotBack.y) / (rightIboxRightTopFront.y - rightIboxLeftBotBack.y)); |
554 |
|
555 |
isRightHandInteracting = (rightHandPos.x >= (rightIboxLeftBotBack.x - 0.5f)) && (rightHandPos.x <= (rightIboxRightTopFront.x + 1.0f)) && |
556 |
(rightHandPos.y >= (rightIboxLeftBotBack.y - 0.1f)) && (rightHandPos.y <= (rightIboxRightTopFront.y + 0.7f)) && |
557 |
(rightIboxLeftBotBack.z >= rightHandPos.z) && (rightIboxRightTopFront.z * 0.8f <= rightHandPos.z); |
558 |
} |
559 |
else |
560 |
{ |
561 |
isRightHandInteracting = GetHandOverlayScreenPos(kinectManager, (int)KinectInterop.JointType.HandRight, ref rightHandScreenPos) && |
562 |
(rightHandPos.y >= (rightIboxLeftBotBack.y - 0.15f)) && (rightHandPos.y <= (rightIboxRightTopFront.y + 0.7f)) && |
563 |
(rightIboxLeftBotBack.z >= rightHandPos.z) && (rightIboxRightTopFront.z * 0.8f <= rightHandPos.z); |
564 |
} |
565 |
|
566 |
//bRightHandPrimaryNow = isRightHandInteracting; |
567 |
if(!wasRightHandInteracting && isRightHandInteracting) |
568 |
{ |
569 |
rightHandInteractingSince = Time.realtimeSinceStartup; |
570 |
} |
571 |
|
572 |
// check for right press |
573 |
isRightHandPress = rightHandScreenPos.z > 0.99f; // ((rightIboxRightTopFront.z - 0.1f) >= rightHandPos.z); |
574 |
rightHandPressProgress = (Time.realtimeSinceStartup - lastRightHandPressTime) >= KinectInterop.Constants.ClickStayDuration && |
575 |
rightHandScreenPos.z >= 0.7f ? (rightHandScreenPos.z - 0.7f) / 0.3f : 0f; |
576 |
|
577 |
// check for right hand click |
578 |
if(!dragInProgress && isRightHandInteracting && |
579 |
((allowHandClicks && ((rightHandPos - lastRightHandPos).magnitude < KinectInterop.Constants.ClickMaxDistance)) || |
580 |
(allowPushToClick && rightHandPressProgress > 0f))) |
581 |
{ |
582 |
if((allowHandClicks && (Time.realtimeSinceStartup - lastRightHandClickTime) >= KinectInterop.Constants.ClickStayDuration) || |
583 |
(allowPushToClick && rightHandPressProgress > 0.99f && isRightHandPress)) |
584 |
{ |
585 |
if(!isRightHandClick) |
586 |
{ |
587 |
isRightHandClick = true; |
588 |
cursorClickProgress = rightHandClickProgress = 1f; |
589 |
|
590 |
foreach(InteractionListenerInterface listener in interactionListeners) |
591 |
{ |
592 |
if (listener.HandClickDetected (playerUserID, playerIndex, true, rightHandScreenPos)) |
593 |
{ |
594 |
isRightHandClick = false; |
595 |
cursorClickProgress = rightHandClickProgress = 0f; |
596 |
lastRightHandPos = Vector3.zero; |
597 |
|
598 |
lastRightHandClickTime = Time.realtimeSinceStartup; |
599 |
lastRightHandPressTime = Time.realtimeSinceStartup; |
600 |
} |
601 |
} |
602 |
|
603 |
if(controlMouseCursor) |
604 |
{ |
605 |
MouseControl.MouseClick(); |
606 |
|
607 |
isRightHandClick = false; |
608 |
cursorClickProgress = rightHandClickProgress = 0f; |
609 |
lastRightHandPos = Vector3.zero; |
610 |
|
611 |
lastRightHandClickTime = Time.realtimeSinceStartup; |
612 |
lastRightHandPressTime = Time.realtimeSinceStartup; |
613 |
} |
614 |
} |
615 |
} |
616 |
else |
617 |
{ |
618 |
// show progress after the 1st half of the needed duration |
619 |
float rightHandTimeProgress = allowHandClicks && (Time.realtimeSinceStartup - lastRightHandClickTime) >= (KinectInterop.Constants.ClickStayDuration / 2f) ? |
620 |
((Time.realtimeSinceStartup - lastRightHandClickTime - (KinectInterop.Constants.ClickStayDuration / 2f)) * 2f / KinectInterop.Constants.ClickStayDuration) : 0f; |
621 |
cursorClickProgress = rightHandClickProgress = allowPushToClick && rightHandScreenPos.z >= 0.7f ? rightHandPressProgress : rightHandTimeProgress; |
622 |
} |
623 |
} |
624 |
else |
625 |
{ |
626 |
isRightHandClick = false; |
627 |
rightHandClickProgress = 0f; |
628 |
lastRightHandPos = rightHandPos; |
629 |
lastRightHandClickTime = Time.realtimeSinceStartup; |
630 |
} |
631 |
} |
632 |
else |
633 |
{ |
634 |
isRightHandInteracting = false; |
635 |
isRightHandPress = false; |
636 |
rightHandPressProgress = 0f; |
637 |
} |
638 |
|
639 |
// stop the cursor click progress, if both left and right hand are not clicking |
640 |
if (leftHandClickProgress == 0f && rightHandClickProgress == 0f && cursorClickProgress > 0f) |
641 |
{ |
642 |
cursorClickProgress = 0f; |
643 |
} |
644 |
|
645 |
// if both hands are interacting, check which one interacts longer than the other |
646 |
if(isLeftHandInteracting && isRightHandInteracting) |
647 |
{ |
648 |
if(rightHandInteractingSince <= leftHandInteractingSince) |
649 |
isLeftHandInteracting = false; |
650 |
else |
651 |
isRightHandInteracting = false; |
652 |
} |
653 |
|
654 |
// if left hand just stopped interacting, send extra non-interaction event |
655 |
if (wasLeftHandInteracting && !isLeftHandInteracting) |
656 |
{ |
657 |
foreach(InteractionListenerInterface listener in interactionListeners) |
658 |
{ |
659 |
if(lastLeftHandEvent == HandEventType.Grip) |
660 |
listener.HandReleaseDetected (playerUserID, playerIndex, false, true, leftHandScreenPos); |
661 |
} |
662 |
|
663 |
lastLeftHandEvent = HandEventType.Release; |
664 |
} |
665 |
|
666 |
|
667 |
// if right hand just stopped interacting, send extra non-interaction event |
668 |
if (wasRightHandInteracting && !isRightHandInteracting) |
669 |
{ |
670 |
foreach(InteractionListenerInterface listener in interactionListeners) |
671 |
{ |
672 |
if(lastRightHandEvent == HandEventType.Grip) |
673 |
listener.HandReleaseDetected (playerUserID, playerIndex, true, true, rightHandScreenPos); |
674 |
} |
675 |
|
676 |
lastRightHandEvent = HandEventType.Release; |
677 |
} |
678 |
|
679 |
|
680 |
// process left hand |
681 |
handEvent = HandStateToEvent(leftHandState, lastLeftHandEvent); |
682 |
|
683 |
if((isLeftHandInteracting != isLeftHandPrimary) || (isRightHandInteracting != isRightHandPrimary)) |
684 |
{ |
685 |
if(controlMouseCursor && dragInProgress) |
686 |
{ |
687 |
MouseControl.MouseRelease(); |
688 |
dragInProgress = false; |
689 |
} |
690 |
|
691 |
lastLeftHandEvent = HandEventType.Release; |
692 |
lastRightHandEvent = HandEventType.Release; |
693 |
} |
694 |
|
695 |
if(controlMouseCursor && (handEvent != lastLeftHandEvent)) |
696 |
{ |
697 |
if(controlMouseDrag && !dragInProgress && (handEvent == HandEventType.Grip)) |
698 |
{ |
699 |
dragInProgress = true; |
700 |
MouseControl.MouseDrag(); |
701 |
} |
702 |
else if(dragInProgress && (handEvent == HandEventType.Release)) |
703 |
{ |
704 |
MouseControl.MouseRelease(); |
705 |
dragInProgress = false; |
706 |
} |
707 |
} |
708 |
|
709 |
leftHandEvent = handEvent; |
710 |
if(handEvent != HandEventType.None) |
711 |
{ |
712 |
// no clicks, while hand grip is detected |
713 |
if (leftHandEvent == HandEventType.Grip && leftHandClickProgress > 0f) |
714 |
{ |
715 |
cursorClickProgress = leftHandClickProgress = 0f; |
716 |
lastLeftHandClickTime = Time.realtimeSinceStartup; |
717 |
} |
718 |
|
719 |
if (leftHandEvent != lastLeftHandEvent) |
720 |
{ |
721 |
// invoke interaction listeners |
722 |
foreach(InteractionListenerInterface listener in interactionListeners) |
723 |
{ |
724 |
if(leftHandEvent == HandEventType.Grip) |
725 |
listener.HandGripDetected (playerUserID, playerIndex, false, isLeftHandInteracting, leftHandScreenPos); |
726 |
else if(leftHandEvent == HandEventType.Release) |
727 |
listener.HandReleaseDetected (playerUserID, playerIndex, false, isLeftHandInteracting, leftHandScreenPos); |
728 |
} |
729 |
} |
730 |
|
731 |
lastLeftHandEvent = handEvent; |
732 |
} |
733 |
|
734 |
// if the hand is primary, set the cursor position |
735 |
if(isLeftHandInteracting) |
736 |
{ |
737 |
isLeftHandPrimary = true; |
738 |
|
739 |
if(leftHandClickProgress < 0.8f) // stop the cursor after 80% click progress |
740 |
{ |
741 |
float smooth = smoothFactor * Time.deltaTime; |
742 |
if(smooth == 0f) smooth = 1f; |
743 |
|
744 |
cursorScreenPos = Vector3.Lerp(cursorScreenPos, leftHandScreenPos, smooth); |
745 |
} |
746 |
|
747 |
// move mouse-only if there is no cursor texture |
748 |
if(controlMouseCursor && |
749 |
(!guiHandCursor || (!gripHandTexture && !releaseHandTexture && !normalHandTexture))) |
750 |
{ |
751 |
MouseControl.MouseMove(cursorScreenPos, debugText); |
752 |
} |
753 |
} |
754 |
else |
755 |
{ |
756 |
isLeftHandPrimary = false; |
757 |
} |
758 |
|
759 |
|
760 |
// process right hand |
761 |
handEvent = HandStateToEvent(rightHandState, lastRightHandEvent); |
762 |
|
763 |
if(controlMouseCursor && (handEvent != lastRightHandEvent)) |
764 |
{ |
765 |
if(controlMouseDrag && !dragInProgress && (handEvent == HandEventType.Grip)) |
766 |
{ |
767 |
dragInProgress = true; |
768 |
MouseControl.MouseDrag(); |
769 |
} |
770 |
else if(dragInProgress && (handEvent == HandEventType.Release)) |
771 |
{ |
772 |
MouseControl.MouseRelease(); |
773 |
dragInProgress = false; |
774 |
} |
775 |
} |
776 |
|
777 |
rightHandEvent = handEvent; |
778 |
if(handEvent != HandEventType.None) |
779 |
{ |
780 |
// no clicks, while hand grip is detected |
781 |
if (rightHandEvent == HandEventType.Grip && rightHandClickProgress > 0f) |
782 |
{ |
783 |
cursorClickProgress = rightHandClickProgress = 0f; |
784 |
lastRightHandClickTime = Time.realtimeSinceStartup; |
785 |
} |
786 |
|
787 |
if (rightHandEvent != lastRightHandEvent) |
788 |
{ |
789 |
// invoke interaction listeners |
790 |
foreach(InteractionListenerInterface listener in interactionListeners) |
791 |
{ |
792 |
if(rightHandEvent == HandEventType.Grip) |
793 |
listener.HandGripDetected (playerUserID, playerIndex, true, isRightHandInteracting, rightHandScreenPos); |
794 |
else if(rightHandEvent == HandEventType.Release) |
795 |
listener.HandReleaseDetected (playerUserID, playerIndex, true, isRightHandInteracting, rightHandScreenPos); |
796 |
} |
797 |
} |
798 |
|
799 |
lastRightHandEvent = handEvent; |
800 |
} |
801 |
|
802 |
// if the hand is primary, set the cursor position |
803 |
if(isRightHandInteracting) |
804 |
{ |
805 |
isRightHandPrimary = true; |
806 |
|
807 |
if(rightHandClickProgress < 0.8f) // stop the cursor after 80% click progress |
808 |
{ |
809 |
float smooth = smoothFactor * Time.deltaTime; |
810 |
if(smooth == 0f) smooth = 1f; |
811 |
|
812 |
cursorScreenPos = Vector3.Lerp(cursorScreenPos, rightHandScreenPos, smooth); |
813 |
} |
814 |
|
815 |
// move mouse-only if there is no cursor texture |
816 |
if(controlMouseCursor && |
817 |
(!guiHandCursor || (!gripHandTexture && !releaseHandTexture && !normalHandTexture))) |
818 |
{ |
819 |
MouseControl.MouseMove(cursorScreenPos, debugText); |
820 |
} |
821 |
} |
822 |
else |
823 |
{ |
824 |
isRightHandPrimary = false; |
825 |
} |
826 |
|
827 |
} |
828 |
else |
829 |
{ |
830 |
// send release events |
831 |
if (lastLeftHandEvent == HandEventType.Grip || lastRightHandEvent == HandEventType.Grip) |
832 |
{ |
833 |
foreach(InteractionListenerInterface listener in interactionListeners) |
834 |
{ |
835 |
if(lastLeftHandEvent == HandEventType.Grip) |
836 |
listener.HandReleaseDetected (lastUserID, playerIndex, false, true, leftHandScreenPos); |
837 |
if(lastRightHandEvent == HandEventType.Grip) |
838 |
listener.HandReleaseDetected (lastUserID, playerIndex, true, true, leftHandScreenPos); |
839 |
} |
840 |
} |
841 |
|
842 |
leftHandState = KinectInterop.HandState.NotTracked; |
843 |
rightHandState = KinectInterop.HandState.NotTracked; |
844 |
|
845 |
isLeftHandPrimary = isRightHandPrimary = false; |
846 |
isLeftHandInteracting = isRightHandInteracting = false; |
847 |
leftHandInteractingSince = rightHandInteractingSince = 0f; |
848 |
|
849 |
isLeftHandClick = isRightHandClick = false; |
850 |
cursorClickProgress = leftHandClickProgress = rightHandClickProgress = 0f; |
851 |
lastLeftHandClickTime = lastRightHandClickTime = Time.realtimeSinceStartup; |
852 |
lastLeftHandPressTime = lastRightHandPressTime = Time.realtimeSinceStartup; |
853 |
|
854 |
isLeftHandPress = false; |
855 |
isRightHandPress = false; |
856 |
|
857 |
leftHandPressProgress = 0f; |
858 |
rightHandPressProgress = 0f; |
859 |
|
860 |
leftHandEvent = HandEventType.None; |
861 |
rightHandEvent = HandEventType.None; |
862 |
|
863 |
lastLeftHandEvent = HandEventType.Release; |
864 |
lastRightHandEvent = HandEventType.Release; |
865 |
|
866 |
if(controlMouseCursor && dragInProgress) |
867 |
{ |
868 |
MouseControl.MouseRelease(); |
869 |
dragInProgress = false; |
870 |
} |
871 |
} |
872 |
|
873 |
// update cursor texture and position |
874 |
UpdateGUI(); |
875 |
} |
876 |
|
877 |
} |
878 |
|
879 |
|
880 |
// updates cursor texture and position |
881 |
private void UpdateGUI() |
882 |
{ |
883 |
if(!interactionInited) |
884 |
return; |
885 |
|
886 |
// display debug information |
887 |
if(debugText) |
888 |
{ |
889 |
string sGuiText = string.Empty; |
890 |
|
891 |
//if(isLeftHandPrimary) |
892 |
{ |
893 |
sGuiText += "L.Hand" + (isLeftHandInteracting ? "*: " : " : ") + leftHandScreenPos.ToString(); |
894 |
|
895 |
if(lastLeftHandEvent == HandEventType.Grip) |
896 |
{ |
897 |
sGuiText += " LeftGrip"; |
898 |
} |
899 |
else if(lastLeftHandEvent == HandEventType.Release) |
900 |
{ |
901 |
sGuiText += " LeftRelease"; |
902 |
} |
903 |
|
904 |
if(isLeftHandClick) |
905 |
{ |
906 |
sGuiText += " LeftClick"; |
907 |
} |
908 |
// else if(leftHandClickProgress > 0.5f) |
909 |
// { |
910 |
// sGuiText += String.Format(" {0:F0}%", leftHandClickProgress * 100); |
911 |
// } |
912 |
|
913 |
if(isLeftHandPress) |
914 |
{ |
915 |
sGuiText += " LeftPress"; |
916 |
} |
917 |
|
918 |
//sGuiText += " " + leftHandClickProgress; |
919 |
} |
920 |
|
921 |
//if(isRightHandPrimary) |
922 |
{ |
923 |
sGuiText += "\nR.Hand" + (isRightHandInteracting ? "*: " : " : ") + rightHandScreenPos.ToString(); |
924 |
|
925 |
if(lastRightHandEvent == HandEventType.Grip) |
926 |
{ |
927 |
sGuiText += " RightGrip"; |
928 |
} |
929 |
else if(lastRightHandEvent == HandEventType.Release) |
930 |
{ |
931 |
sGuiText += " RightRelease"; |
932 |
} |
933 |
|
934 |
if(isRightHandClick) |
935 |
{ |
936 |
sGuiText += " RightClick"; |
937 |
} |
938 |
// else if(rightHandClickProgress > 0.5f) |
939 |
// { |
940 |
// sGuiText += String.Format(" {0:F0}%", rightHandClickProgress * 100); |
941 |
// } |
942 |
|
943 |
if(isRightHandPress) |
944 |
{ |
945 |
sGuiText += " RightPress"; |
946 |
} |
947 |
|
948 |
//sGuiText += " " + rightHandClickProgress; |
949 |
} |
950 |
|
951 |
debugText.text = sGuiText; |
952 |
} |
953 |
|
954 |
// display the cursor status and position |
955 |
if(guiHandCursor) |
956 |
{ |
957 |
Sprite cursorTexture = null; |
958 |
|
959 |
if(isLeftHandPrimary) |
960 |
{ |
961 |
if(lastLeftHandEvent == HandEventType.Grip) |
962 |
cursorTexture = gripHandTexture; |
963 |
else if(lastLeftHandEvent == HandEventType.Release) |
964 |
cursorTexture = releaseHandTexture; |
965 |
} |
966 |
else if(isRightHandPrimary) |
967 |
{ |
968 |
if(lastRightHandEvent == HandEventType.Grip) |
969 |
cursorTexture = gripHandTexture; |
970 |
else if(lastRightHandEvent == HandEventType.Release) |
971 |
cursorTexture = releaseHandTexture; |
972 |
} |
973 |
|
974 |
if(cursorTexture == null) |
975 |
{ |
976 |
cursorTexture = normalHandTexture; |
977 |
} |
978 |
|
979 |
if((cursorTexture != null) /**&& (isLeftHandPrimary || isRightHandPrimary)*/) |
980 |
{ |
981 |
Vector2 posSprite; |
982 |
|
983 |
if(controlMouseCursor) |
984 |
{ |
985 |
MouseControl.MouseMove(cursorScreenPos, debugText); |
986 |
posSprite = new Vector2(Input.mousePosition.x, Input.mousePosition.y); |
987 |
} |
988 |
else |
989 |
{ |
990 |
Rect rectCanvas = guiHandCursor.canvas.pixelRect; |
991 |
posSprite = new Vector2(cursorScreenPos.x * rectCanvas.width, cursorScreenPos.y * rectCanvas.height); |
992 |
} |
993 |
|
994 |
guiHandCursor.sprite = cursorTexture; |
995 |
guiHandCursor.rectTransform.position = posSprite; |
996 |
|
997 |
if (cursorProgressBar) |
998 |
{ |
999 |
cursorProgressBar.fillAmount = cursorClickProgress; |
1000 |
} |
1001 |
} |
1002 |
} |
1003 |
} |
1004 |
|
1005 |
|
1006 |
// estimates screen cursor overlay position for the given hand |
1007 |
private bool GetHandOverlayScreenPos(KinectManager kinectManager, int iHandJointIndex, ref Vector3 handScreenPos) |
1008 |
{ |
1009 |
Vector3 posJointRaw = kinectManager.GetJointKinectPosition(playerUserID, iHandJointIndex); |
1010 |
|
1011 |
if(posJointRaw != Vector3.zero) |
1012 |
{ |
1013 |
Vector2 posDepth = kinectManager.MapSpacePointToDepthCoords(posJointRaw); |
1014 |
ushort depthValue = kinectManager.GetDepthForPixel((int)posDepth.x, (int)posDepth.y); |
1015 |
|
1016 |
if(posDepth != Vector2.zero && depthValue > 0) |
1017 |
{ |
1018 |
// depth pos to color pos |
1019 |
Vector2 posColor = kinectManager.MapDepthPointToColorCoords(posDepth, depthValue); |
1020 |
|
1021 |
if(!float.IsInfinity(posColor.x) && !float.IsInfinity(posColor.y)) |
1022 |
{ |
1023 |
// get the color image x-offset and width (use the portrait background, if available) |
1024 |
float colorWidth = kinectManager.GetColorImageWidth(); |
1025 |
float colorOfsX = 0f; |
1026 |
|
1027 |
PortraitBackground portraitBack = PortraitBackground.Instance; |
1028 |
if(portraitBack && portraitBack.enabled) |
1029 |
{ |
1030 |
colorWidth = kinectManager.GetColorImageHeight() * kinectManager.GetColorImageHeight() / kinectManager.GetColorImageWidth(); |
1031 |
colorOfsX = (kinectManager.GetColorImageWidth() - colorWidth) / 2f; |
1032 |
} |
1033 |
|
1034 |
float xScaled = (posColor.x - colorOfsX) / colorWidth; |
1035 |
float yScaled = posColor.y / kinectManager.GetColorImageHeight(); |
1036 |
|
1037 |
handScreenPos.x = xScaled; |
1038 |
handScreenPos.y = 1f - yScaled; |
1039 |
|
1040 |
return true; |
1041 |
} |
1042 |
} |
1043 |
} |
1044 |
|
1045 |
return false; |
1046 |
} |
1047 |
|
1048 |
|
1049 |
// converts hand state to hand event type |
1050 |
public static HandEventType HandStateToEvent(KinectInterop.HandState handState, HandEventType lastEventType) |
1051 |
{ |
1052 |
switch(handState) |
1053 |
{ |
1054 |
case KinectInterop.HandState.Open: |
1055 |
return HandEventType.Release; |
1056 |
|
1057 |
case KinectInterop.HandState.Closed: |
1058 |
case KinectInterop.HandState.Lasso: |
1059 |
return HandEventType.Grip; |
1060 |
|
1061 |
case KinectInterop.HandState.Unknown: |
1062 |
return lastEventType; |
1063 |
} |
1064 |
|
1065 |
return HandEventType.None; |
1066 |
} |
1067 |
|
1068 |
|
1069 |
} |