IMHOTEP Framework
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Pages
Player.cs
1 //======= Copyright (c) Valve Corporation, All rights reserved. ===============
2 //
3 // Purpose: Player interface used to query HMD transforms and VR hands
4 //
5 //=============================================================================
6 
7 using UnityEngine;
8 using System.Collections;
9 using System.Collections.Generic;
10 
11 namespace Valve.VR.InteractionSystem
12 {
13  //-------------------------------------------------------------------------
14  // Singleton representing the local VR player/user, with methods for getting
15  // the player's hands, head, tracking origin, and guesses for various properties.
16  //-------------------------------------------------------------------------
17  public class Player : MonoBehaviour
18  {
19  [Tooltip( "Virtual transform corresponding to the meatspace tracking origin. Devices are tracked relative to this." )]
20  public Transform trackingOriginTransform;
21 
22  [Tooltip( "List of possible transforms for the head/HMD, including the no-SteamVR fallback camera." )]
23  public Transform[] hmdTransforms;
24 
25  [Tooltip( "List of possible Hands, including no-SteamVR fallback Hands." )]
26  public Hand[] hands;
27 
28  [Tooltip( "Reference to the physics collider that follows the player's HMD position." )]
29  public Collider headCollider;
30 
31  [Tooltip( "These objects are enabled when SteamVR is available" )]
32  public GameObject rigSteamVR;
33 
34  [Tooltip( "These objects are enabled when SteamVR is not available, or when the user toggles out of VR" )]
35  public GameObject rig2DFallback;
36 
37  [Tooltip( "The audio listener for this player" )]
38  public Transform audioListener;
39 
40  public bool allowToggleTo2D = true;
41 
42 
43  //-------------------------------------------------
44  // Singleton instance of the Player. Only one can exist at a time.
45  //-------------------------------------------------
46  private static Player _instance;
47  public static Player instance
48  {
49  get
50  {
51  if ( _instance == null )
52  {
53  _instance = FindObjectOfType<Player>();
54  }
55  return _instance;
56  }
57  }
58 
59 
60  //-------------------------------------------------
61  // Get the number of active Hands.
62  //-------------------------------------------------
63  public int handCount
64  {
65  get
66  {
67  int count = 0;
68  for ( int i = 0; i < hands.Length; i++ )
69  {
70  if ( hands[i].gameObject.activeInHierarchy )
71  {
72  count++;
73  }
74  }
75  return count;
76  }
77  }
78 
79 
80  //-------------------------------------------------
81  // Get the i-th active Hand.
82  //
83  // i - Zero-based index of the active Hand to get
84  //-------------------------------------------------
85  public Hand GetHand( int i )
86  {
87  for ( int j = 0; j < hands.Length; j++ )
88  {
89  if ( !hands[j].gameObject.activeInHierarchy )
90  {
91  continue;
92  }
93 
94  if ( i > 0 )
95  {
96  i--;
97  continue;
98  }
99 
100  return hands[j];
101  }
102 
103  return null;
104  }
105 
106 
107  //-------------------------------------------------
108  public Hand leftHand
109  {
110  get
111  {
112  for ( int j = 0; j < hands.Length; j++ )
113  {
114  if ( !hands[j].gameObject.activeInHierarchy )
115  {
116  continue;
117  }
118 
119  if ( hands[j].GuessCurrentHandType() != Hand.HandType.Left )
120  {
121  continue;
122  }
123 
124  return hands[j];
125  }
126 
127  return null;
128  }
129  }
130 
131 
132  //-------------------------------------------------
133  public Hand rightHand
134  {
135  get
136  {
137  for ( int j = 0; j < hands.Length; j++ )
138  {
139  if ( !hands[j].gameObject.activeInHierarchy )
140  {
141  continue;
142  }
143 
144  if ( hands[j].GuessCurrentHandType() != Hand.HandType.Right )
145  {
146  continue;
147  }
148 
149  return hands[j];
150  }
151 
152  return null;
153  }
154  }
155 
156 
157  //-------------------------------------------------
158  public SteamVR_Controller.Device leftController
159  {
160  get
161  {
162  Hand h = leftHand;
163  if ( h )
164  {
165  return h.controller;
166  }
167  return null;
168  }
169  }
170 
171 
172  //-------------------------------------------------
173  public SteamVR_Controller.Device rightController
174  {
175  get
176  {
177  Hand h = rightHand;
178  if ( h )
179  {
180  return h.controller;
181  }
182  return null;
183  }
184  }
185 
186 
187  //-------------------------------------------------
188  // Get the HMD transform. This might return the fallback camera transform if SteamVR is unavailable or disabled.
189  //-------------------------------------------------
190  public Transform hmdTransform
191  {
192  get
193  {
194  for ( int i = 0; i < hmdTransforms.Length; i++ )
195  {
196  if ( hmdTransforms[i].gameObject.activeInHierarchy )
197  return hmdTransforms[i];
198  }
199  return null;
200  }
201  }
202 
203 
204  //-------------------------------------------------
205  // Height of the eyes above the ground - useful for estimating player height.
206  //-------------------------------------------------
207  public float eyeHeight
208  {
209  get
210  {
211  Transform hmd = hmdTransform;
212  if ( hmd )
213  {
214  Vector3 eyeOffset = Vector3.Project( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up );
215  return eyeOffset.magnitude / trackingOriginTransform.lossyScale.x;
216  }
217  return 0.0f;
218  }
219  }
220 
221 
222  //-------------------------------------------------
223  // Guess for the world-space position of the player's feet, directly beneath the HMD.
224  //-------------------------------------------------
225  public Vector3 feetPositionGuess
226  {
227  get
228  {
229  Transform hmd = hmdTransform;
230  if ( hmd )
231  {
232  return trackingOriginTransform.position + Vector3.ProjectOnPlane( hmd.position - trackingOriginTransform.position, trackingOriginTransform.up );
233  }
234  return trackingOriginTransform.position;
235  }
236  }
237 
238 
239  //-------------------------------------------------
240  // Guess for the world-space direction of the player's hips/torso. This is effectively just the gaze direction projected onto the floor plane.
241  //-------------------------------------------------
242  public Vector3 bodyDirectionGuess
243  {
244  get
245  {
246  Transform hmd = hmdTransform;
247  if ( hmd )
248  {
249  Vector3 direction = Vector3.ProjectOnPlane( hmd.forward, trackingOriginTransform.up );
250  if ( Vector3.Dot( hmd.up, trackingOriginTransform.up ) < 0.0f )
251  {
252  // The HMD is upside-down. Either
253  // -The player is bending over backwards
254  // -The player is bent over looking through their legs
255  direction = -direction;
256  }
257  return direction;
258  }
259  return trackingOriginTransform.forward;
260  }
261  }
262 
263 
264  //-------------------------------------------------
265  void Awake()
266  {
267  if ( trackingOriginTransform == null )
268  {
269  trackingOriginTransform = this.transform;
270  }
271  }
272 
273 
274  //-------------------------------------------------
275  void OnEnable()
276  {
277  _instance = this;
278 
279  if ( SteamVR.instance != null )
280  {
281  ActivateRig( rigSteamVR );
282  }
283  else
284  {
285 #if !HIDE_DEBUG_UI
286  ActivateRig( rig2DFallback );
287 #endif
288  }
289  }
290 
291 
292  //-------------------------------------------------
293  void OnDrawGizmos()
294  {
295  if ( this != instance )
296  {
297  return;
298  }
299 
300  //NOTE: These gizmo icons don't work in the plugin since the icons need to exist in a specific "Gizmos"
301  // folder in your Asset tree. These icons are included under Core/Icons. Moving them into a
302  // "Gizmos" folder should make them work again.
303 
304  Gizmos.color = Color.white;
305  Gizmos.DrawIcon( feetPositionGuess, "vr_interaction_system_feet.png" );
306 
307  Gizmos.color = Color.cyan;
308  Gizmos.DrawLine( feetPositionGuess, feetPositionGuess + trackingOriginTransform.up * eyeHeight );
309 
310  // Body direction arrow
311  Gizmos.color = Color.blue;
312  Vector3 bodyDirection = bodyDirectionGuess;
313  Vector3 bodyDirectionTangent = Vector3.Cross( trackingOriginTransform.up, bodyDirection );
314  Vector3 startForward = feetPositionGuess + trackingOriginTransform.up * eyeHeight * 0.75f;
315  Vector3 endForward = startForward + bodyDirection * 0.33f;
316  Gizmos.DrawLine( startForward, endForward );
317  Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection + bodyDirectionTangent ) );
318  Gizmos.DrawLine( endForward, endForward - 0.033f * ( bodyDirection - bodyDirectionTangent ) );
319 
320  Gizmos.color = Color.red;
321  int count = handCount;
322  for ( int i = 0; i < count; i++ )
323  {
324  Hand hand = GetHand( i );
325 
326  if ( hand.startingHandType == Hand.HandType.Left )
327  {
328  Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand.png" );
329  }
330  else if ( hand.startingHandType == Hand.HandType.Right )
331  {
332  Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand.png" );
333  }
334  else
335  {
336  Hand.HandType guessHandType = hand.GuessCurrentHandType();
337 
338  if ( guessHandType == Hand.HandType.Left )
339  {
340  Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_left_hand_question.png" );
341  }
342  else if ( guessHandType == Hand.HandType.Right )
343  {
344  Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_right_hand_question.png" );
345  }
346  else
347  {
348  Gizmos.DrawIcon( hand.transform.position, "vr_interaction_system_unknown_hand.png" );
349  }
350  }
351  }
352  }
353 
354 
355  //-------------------------------------------------
356  public void Draw2DDebug()
357  {
358  if ( !allowToggleTo2D )
359  return;
360 
361  if ( !SteamVR.active )
362  return;
363 
364  int width = 100;
365  int height = 25;
366  int left = Screen.width / 2 - width / 2;
367  int top = Screen.height - height - 10;
368 
369  string text = ( rigSteamVR.activeSelf ) ? "2D Debug" : "VR";
370 
371  if ( GUI.Button( new Rect( left, top, width, height ), text ) )
372  {
373  if ( rigSteamVR.activeSelf )
374  {
375  ActivateRig( rig2DFallback );
376  }
377  else
378  {
379  ActivateRig( rigSteamVR );
380  }
381  }
382  }
383 
384 
385  //-------------------------------------------------
386  private void ActivateRig( GameObject rig )
387  {
388  rigSteamVR.SetActive( rig == rigSteamVR );
389  rig2DFallback.SetActive( rig == rig2DFallback );
390 
391  if ( audioListener )
392  {
393  audioListener.transform.parent = hmdTransform;
394  audioListener.transform.localPosition = Vector3.zero;
395  audioListener.transform.localRotation = Quaternion.identity;
396  }
397  }
398 
399 
400  //-------------------------------------------------
401  public void PlayerShotSelf()
402  {
403  //Do something appropriate here
404  }
405  }
406 }