Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
11 KiB

  1. // Headset Controller Aware|Presence|70040
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. /// <summary>
  6. /// Event Payload
  7. /// </summary>
  8. /// <param name="raycastHit">The Raycast Hit struct of item that is obscuring the path to the controller.</param>
  9. /// <param name="controllerReference">The reference to the controller that is being or has been obscured or being or has been glanced.</param>
  10. public struct HeadsetControllerAwareEventArgs
  11. {
  12. public RaycastHit raycastHit;
  13. public VRTK_ControllerReference controllerReference;
  14. }
  15. /// <summary>
  16. /// Event Payload
  17. /// </summary>
  18. /// <param name="sender">this object</param>
  19. /// <param name="e"><see cref="HeadsetControllerAwareEventArgs"/></param>
  20. public delegate void HeadsetControllerAwareEventHandler(object sender, HeadsetControllerAwareEventArgs e);
  21. /// <summary>
  22. /// Determines whether the HMD is in line of sight to the controllers or if the headset is directly looking at one of the controllers.
  23. /// </summary>
  24. /// <remarks>
  25. /// **Script Usage:**
  26. /// * Place the `VRTK_HeadsetControllerAware` script on any active scene GameObject.
  27. /// </remarks>
  28. /// <example>
  29. /// `VRTK/Examples/029_Controller_Tooltips` displays tooltips that have been added to the controllers and are only visible when the controller is being looked at.
  30. /// </example>
  31. [AddComponentMenu("VRTK/Scripts/Presence/VRTK_HeadsetControllerAware")]
  32. public class VRTK_HeadsetControllerAware : MonoBehaviour
  33. {
  34. [Tooltip("If this is checked then the left controller will be checked if items obscure it's path from the headset.")]
  35. public bool trackLeftController = true;
  36. [Tooltip("If this is checked then the right controller will be checked if items obscure it's path from the headset.")]
  37. public bool trackRightController = true;
  38. [Tooltip("The radius of the accepted distance from the controller origin point to determine if the controller is being looked at.")]
  39. public float controllerGlanceRadius = 0.15f;
  40. [Tooltip("A custom transform to provide the world space position of the right controller.")]
  41. public Transform customRightControllerOrigin;
  42. [Tooltip("A custom transform to provide the world space position of the left controller.")]
  43. public Transform customLeftControllerOrigin;
  44. [Tooltip("A custom raycaster to use when raycasting to find controllers.")]
  45. public VRTK_CustomRaycast customRaycast;
  46. /// <summary>
  47. /// Emitted when the controller is obscured by another object.
  48. /// </summary>
  49. public event HeadsetControllerAwareEventHandler ControllerObscured;
  50. /// <summary>
  51. /// Emitted when the controller is no longer obscured by an object.
  52. /// </summary>
  53. public event HeadsetControllerAwareEventHandler ControllerUnobscured;
  54. /// <summary>
  55. /// Emitted when the controller is seen by the headset view.
  56. /// </summary>
  57. public event HeadsetControllerAwareEventHandler ControllerGlanceEnter;
  58. /// <summary>
  59. /// Emitted when the controller is no longer seen by the headset view.
  60. /// </summary>
  61. public event HeadsetControllerAwareEventHandler ControllerGlanceExit;
  62. protected GameObject leftController;
  63. protected GameObject rightController;
  64. protected Transform headset;
  65. protected bool leftControllerObscured = false;
  66. protected bool rightControllerObscured = false;
  67. protected bool leftControllerLastState = false;
  68. protected bool rightControllerLastState = false;
  69. protected bool leftControllerGlance = false;
  70. protected bool rightControllerGlance = false;
  71. protected bool leftControllerGlanceLastState = false;
  72. protected bool rightControllerGlanceLastState = false;
  73. public virtual void OnControllerObscured(HeadsetControllerAwareEventArgs e)
  74. {
  75. if (ControllerObscured != null)
  76. {
  77. ControllerObscured(this, e);
  78. }
  79. }
  80. public virtual void OnControllerUnobscured(HeadsetControllerAwareEventArgs e)
  81. {
  82. if (ControllerUnobscured != null)
  83. {
  84. ControllerUnobscured(this, e);
  85. }
  86. }
  87. public virtual void OnControllerGlanceEnter(HeadsetControllerAwareEventArgs e)
  88. {
  89. if (ControllerGlanceEnter != null)
  90. {
  91. ControllerGlanceEnter(this, e);
  92. }
  93. }
  94. public virtual void OnControllerGlanceExit(HeadsetControllerAwareEventArgs e)
  95. {
  96. if (ControllerGlanceExit != null)
  97. {
  98. ControllerGlanceExit(this, e);
  99. }
  100. }
  101. /// <summary>
  102. /// The LeftControllerObscured method returns the state of if the left controller is being obscured from the path of the headset.
  103. /// </summary>
  104. /// <returns>Returns `true` if the path between the headset and the controller is obscured.</returns>
  105. public virtual bool LeftControllerObscured()
  106. {
  107. return leftControllerObscured;
  108. }
  109. /// <summary>
  110. /// The RightControllerObscured method returns the state of if the right controller is being obscured from the path of the headset.
  111. /// </summary>
  112. /// <returns>Returns `true` if the path between the headset and the controller is obscured.</returns>
  113. public virtual bool RightControllerObscured()
  114. {
  115. return rightControllerObscured;
  116. }
  117. /// <summary>
  118. /// the LeftControllerGlanced method returns the state of if the headset is currently looking at the left controller or not.
  119. /// </summary>
  120. /// <returns>Returns `true` if the headset can currently see the controller within the given radius threshold.</returns>
  121. public virtual bool LeftControllerGlanced()
  122. {
  123. return leftControllerGlance;
  124. }
  125. /// <summary>
  126. /// the RightControllerGlanced method returns the state of if the headset is currently looking at the right controller or not.
  127. /// </summary>
  128. /// <returns>Returns `true` if the headset can currently see the controller within the given radius threshold.</returns>
  129. public virtual bool RightControllerGlanced()
  130. {
  131. return rightControllerGlance;
  132. }
  133. protected virtual void Awake()
  134. {
  135. VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
  136. }
  137. protected virtual void OnEnable()
  138. {
  139. headset = VRTK_DeviceFinder.HeadsetTransform();
  140. leftController = VRTK_DeviceFinder.GetControllerLeftHand();
  141. rightController = VRTK_DeviceFinder.GetControllerRightHand();
  142. }
  143. protected virtual void OnDisable()
  144. {
  145. leftController = null;
  146. rightController = null;
  147. }
  148. protected virtual void OnDestroy()
  149. {
  150. VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
  151. }
  152. protected virtual void Update()
  153. {
  154. if (trackLeftController)
  155. {
  156. RayCastToController(leftController, customLeftControllerOrigin, ref leftControllerObscured, ref leftControllerLastState);
  157. }
  158. if (trackRightController)
  159. {
  160. RayCastToController(rightController, customRightControllerOrigin, ref rightControllerObscured, ref rightControllerLastState);
  161. }
  162. CheckHeadsetView(leftController, customLeftControllerOrigin, ref leftControllerGlance, ref leftControllerGlanceLastState);
  163. CheckHeadsetView(rightController, customRightControllerOrigin, ref rightControllerGlance, ref rightControllerGlanceLastState);
  164. }
  165. protected virtual HeadsetControllerAwareEventArgs SetHeadsetControllerAwareEvent(RaycastHit raycastHit, VRTK_ControllerReference controllerReference)
  166. {
  167. HeadsetControllerAwareEventArgs e;
  168. e.raycastHit = raycastHit;
  169. e.controllerReference = controllerReference;
  170. return e;
  171. }
  172. protected virtual void RayCastToController(GameObject controller, Transform customDestination, ref bool obscured, ref bool lastState)
  173. {
  174. obscured = false;
  175. if (controller != null && controller.gameObject.activeInHierarchy)
  176. {
  177. Vector3 destination = (customDestination ? customDestination.position : controller.transform.position);
  178. RaycastHit hitInfo;
  179. if (VRTK_CustomRaycast.Linecast(customRaycast, headset.position, destination, out hitInfo, Physics.IgnoreRaycastLayer, QueryTriggerInteraction.Ignore))
  180. {
  181. obscured = true;
  182. }
  183. if (lastState != obscured)
  184. {
  185. ObscuredStateChanged(controller.gameObject, obscured, hitInfo);
  186. }
  187. lastState = obscured;
  188. }
  189. }
  190. protected virtual void ObscuredStateChanged(GameObject controller, bool obscured, RaycastHit hitInfo)
  191. {
  192. VRTK_ControllerReference controllerReference = VRTK_ControllerReference.GetControllerReference(controller);
  193. if (obscured)
  194. {
  195. OnControllerObscured(SetHeadsetControllerAwareEvent(hitInfo, controllerReference));
  196. }
  197. else
  198. {
  199. OnControllerUnobscured(SetHeadsetControllerAwareEvent(hitInfo, controllerReference));
  200. }
  201. }
  202. protected virtual void CheckHeadsetView(GameObject controller, Transform customDestination, ref bool controllerGlance, ref bool controllerGlanceLastState)
  203. {
  204. controllerGlance = false;
  205. if (controller != null && controller.gameObject.activeInHierarchy)
  206. {
  207. Vector3 controllerPosition = (customDestination ? customDestination.position : controller.transform.position);
  208. float distanceFromHeadsetToController = Vector3.Distance(headset.position, controllerPosition);
  209. Vector3 lookPoint = headset.position + (headset.forward * distanceFromHeadsetToController);
  210. if (Vector3.Distance(controllerPosition, lookPoint) <= controllerGlanceRadius)
  211. {
  212. controllerGlance = true;
  213. }
  214. if (controllerGlanceLastState != controllerGlance)
  215. {
  216. GlanceStateChanged(controller.gameObject, controllerGlance);
  217. }
  218. controllerGlanceLastState = controllerGlance;
  219. }
  220. }
  221. protected virtual void GlanceStateChanged(GameObject controller, bool glance)
  222. {
  223. RaycastHit emptyHit = new RaycastHit();
  224. VRTK_ControllerReference controllerReference = VRTK_ControllerReference.GetControllerReference(controller);
  225. if (glance)
  226. {
  227. OnControllerGlanceEnter(SetHeadsetControllerAwareEvent(emptyHit, controllerReference));
  228. }
  229. else
  230. {
  231. OnControllerGlanceExit(SetHeadsetControllerAwareEvent(emptyHit, controllerReference));
  232. }
  233. }
  234. }
  235. }