NRPointerRaycaster.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /****************************************************************************
  2. * Copyright 2019 Nreal Techonology Limited. All rights reserved.
  3. *
  4. * This file is part of NRSDK.
  5. *
  6. * https://www.nreal.ai/
  7. *
  8. *****************************************************************************/
  9. namespace NRKernal
  10. {
  11. using System;
  12. using System.Collections;
  13. using System.Collections.Generic;
  14. using System.Collections.ObjectModel;
  15. using UnityEngine;
  16. using UnityEngine.EventSystems;
  17. using UnityEngine.UI;
  18. /// <summary> A nr pointer raycaster. </summary>
  19. [DisallowMultipleComponent]
  20. public class NRPointerRaycaster : EventCameraRaycaster
  21. {
  22. /// <summary> Values that represent mask type enums. </summary>
  23. public enum MaskTypeEnum
  24. {
  25. /// <summary> An enum constant representing the inclusive option. </summary>
  26. Inclusive,
  27. /// <summary> An enum constant representing the exclusive option. </summary>
  28. Exclusive
  29. }
  30. /// <summary> The hits. </summary>
  31. private static readonly RaycastHit[] hits = new RaycastHit[64];
  32. /// <summary> Type of the mask. </summary>
  33. public MaskTypeEnum maskType = MaskTypeEnum.Exclusive;
  34. /// <summary> The mask. </summary>
  35. public LayerMask mask;
  36. /// <summary> Gets the raycast mask. </summary>
  37. /// <value> The raycast mask. </value>
  38. public int raycastMask { get { return maskType == MaskTypeEnum.Inclusive ? (int)mask : ~mask; } }
  39. /// <summary> True to show, false to hide the debug ray. </summary>
  40. public bool showDebugRay = true;
  41. /// <summary> True to enable, false to disable the physics raycast. </summary>
  42. public bool enablePhysicsRaycast = true;
  43. /// <summary> True to enable, false to disable the graphic raycast. </summary>
  44. public bool enableGraphicRaycast = true;
  45. /// <summary> List of button event data. </summary>
  46. protected readonly List<NRPointerEventData> buttonEventDataList = new List<NRPointerEventData>();
  47. /// <summary> The sorted raycast results. </summary>
  48. protected readonly List<RaycastResult> sortedRaycastResults = new List<RaycastResult>();
  49. /// <summary> The break points. </summary>
  50. protected readonly List<Vector3> breakPoints = new List<Vector3>();
  51. /// <summary> Temporary raycast results. </summary>
  52. private readonly List<RaycastResult> temporaryRaycastResults = new List<RaycastResult>();
  53. /// <summary> The related hand. </summary>
  54. private ControllerHandEnum m_RelatedHand;
  55. /// <summary> Gets or sets the related hand. </summary>
  56. /// <value> The related hand. </value>
  57. public ControllerHandEnum RelatedHand
  58. {
  59. get
  60. {
  61. return NRInput.RaycastMode == RaycastModeEnum.Gaze ? NRInput.DomainHand : m_RelatedHand;
  62. }
  63. internal set
  64. {
  65. m_RelatedHand = value;
  66. }
  67. }
  68. /// <summary> Gets the break points. </summary>
  69. /// <value> The break points. </value>
  70. public List<Vector3> BreakPoints { get { return breakPoints; } }
  71. /// <summary> Gets information describing the hover event. </summary>
  72. /// <value> Information describing the hover event. </value>
  73. public NRPointerEventData HoverEventData { get { return buttonEventDataList.Count > 0 ? buttonEventDataList[0] : null; } }
  74. /// <summary> Gets a list of button event data. </summary>
  75. /// <value> A list of button event data. </value>
  76. private ReadOnlyCollection<NRPointerEventData> readonlyButtonEventDataList;
  77. public ReadOnlyCollection<NRPointerEventData> ButtonEventDataList
  78. {
  79. get
  80. {
  81. if (readonlyButtonEventDataList == null)
  82. readonlyButtonEventDataList = buttonEventDataList.AsReadOnly();
  83. return readonlyButtonEventDataList;
  84. }
  85. }
  86. /// <summary> <para>See MonoBehaviour.Start.</para> </summary>
  87. protected override void Start()
  88. {
  89. base.Start();
  90. buttonEventDataList.Add(new NRPointerEventData(this, EventSystem.current));
  91. }
  92. /// <summary> called by StandaloneInputModule, not supported. </summary>
  93. /// <param name="eventData"> Information describing the event.</param>
  94. /// <param name="resultAppendList"> List of result appends.</param>
  95. public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
  96. {
  97. }
  98. /// <summary> Raycasts. </summary>
  99. public virtual void Raycast()
  100. {
  101. sortedRaycastResults.Clear();
  102. breakPoints.Clear();
  103. var zScale = transform.lossyScale.z;
  104. var amountDistance = (FarDistance - NearDistance) * zScale;
  105. if (!gameObject.activeInHierarchy)
  106. {
  107. amountDistance = 0.0001f;
  108. }
  109. var origin = transform.TransformPoint(0f, 0f, NearDistance);
  110. breakPoints.Add(origin);
  111. Vector3 direction;
  112. float distance;
  113. Ray ray;
  114. RaycastResult firstHit = default(RaycastResult);
  115. direction = transform.forward;
  116. distance = amountDistance;
  117. ray = new Ray(origin, direction);
  118. eventCamera.farClipPlane = eventCamera.nearClipPlane + distance;
  119. eventCamera.transform.position = ray.origin - (ray.direction * eventCamera.nearClipPlane);
  120. eventCamera.transform.rotation = Quaternion.LookRotation(ray.direction, transform.up);
  121. Raycast(ray, distance, sortedRaycastResults);
  122. firstHit = FirstRaycastResult();
  123. breakPoints.Add(firstHit.isValid ? firstHit.worldPosition : ray.GetPoint(distance));
  124. #if UNITY_EDITOR
  125. if (showDebugRay)
  126. {
  127. Debug.DrawLine(breakPoints[0], breakPoints[1], firstHit.isValid ? Color.green : Color.red);
  128. }
  129. #endif
  130. }
  131. /// <summary> Gets raycaster result comparer. </summary>
  132. /// <returns> The raycaster result comparer. </returns>
  133. protected virtual Comparison<RaycastResult> GetRaycasterResultComparer()
  134. {
  135. return NRInputModule.defaultRaycastComparer;
  136. }
  137. /// <summary>
  138. /// override OnEnable & OnDisable on purpose so that this BaseRaycaster won't be registered into
  139. /// RaycasterManager. </summary>
  140. protected override void OnEnable()
  141. {
  142. //base.OnEnable();
  143. NRInputModule.AddRaycaster(this);
  144. }
  145. /// <summary> <para>See MonoBehaviour.OnDisable.</para> </summary>
  146. protected override void OnDisable()
  147. {
  148. //base.OnDisable();
  149. NRInputModule.RemoveRaycaster(this);
  150. }
  151. /// <summary> Gets scroll delta. </summary>
  152. /// <returns> The scroll delta. </returns>
  153. public virtual Vector2 GetScrollDelta()
  154. {
  155. return Vector2.zero;
  156. }
  157. /// <summary> First raycast result. </summary>
  158. /// <returns> A RaycastResult. </returns>
  159. public RaycastResult FirstRaycastResult()
  160. {
  161. for (int i = 0, imax = sortedRaycastResults.Count; i < imax; ++i)
  162. {
  163. if (!sortedRaycastResults[i].isValid)
  164. continue;
  165. return sortedRaycastResults[i];
  166. }
  167. return default(RaycastResult);
  168. }
  169. /// <summary> Raycasts. </summary>
  170. /// <param name="ray"> The ray.</param>
  171. /// <param name="distance"> The distance.</param>
  172. /// <param name="raycastResults"> The raycast results.</param>
  173. public void Raycast(Ray ray, float distance, List<RaycastResult> raycastResults)
  174. {
  175. temporaryRaycastResults.Clear();
  176. if (enablePhysicsRaycast)
  177. {
  178. PhysicsRaycast(ray, distance, temporaryRaycastResults);
  179. }
  180. if (enableGraphicRaycast)
  181. {
  182. var tempCanvases = CanvasTargetCollector.GetCanvases();
  183. for (int i = tempCanvases.Count - 1; i >= 0; --i)
  184. {
  185. var target = tempCanvases[i];
  186. if (target == null || !target.enabled)
  187. continue;
  188. GraphicRaycast(target, target.ignoreReversedGraphics, ray, distance, this, temporaryRaycastResults);
  189. }
  190. }
  191. var comparer = GetRaycasterResultComparer();
  192. if (comparer != null)
  193. {
  194. temporaryRaycastResults.Sort(comparer);
  195. }
  196. for (int i = 0, imax = temporaryRaycastResults.Count; i < imax; ++i)
  197. {
  198. raycastResults.Add(temporaryRaycastResults[i]);
  199. }
  200. }
  201. /// <summary> Physics raycast. </summary>
  202. /// <param name="ray"> The ray.</param>
  203. /// <param name="distance"> The distance.</param>
  204. /// <param name="raycastResults"> The raycast results.</param>
  205. public virtual void PhysicsRaycast(Ray ray, float distance, List<RaycastResult> raycastResults)
  206. {
  207. var hitCount = Physics.RaycastNonAlloc(ray, hits, distance, raycastMask);
  208. for (int i = 0; i < hitCount; ++i)
  209. {
  210. raycastResults.Add(new RaycastResult
  211. {
  212. gameObject = hits[i].collider.gameObject,
  213. module = this,
  214. distance = hits[i].distance,
  215. worldPosition = hits[i].point,
  216. worldNormal = hits[i].normal,
  217. screenPosition = NRInputModule.ScreenCenterPoint,
  218. index = raycastResults.Count,
  219. sortingLayer = 0,
  220. sortingOrder = 0
  221. });
  222. }
  223. }
  224. /// <summary> Graphic raycast. </summary>
  225. /// <param name="canvas"> The canvas.</param>
  226. /// <param name="ignoreReversedGraphics"> True to ignore reversed graphics.</param>
  227. /// <param name="ray"> The ray.</param>
  228. /// <param name="distance"> The distance.</param>
  229. /// <param name="raycaster"> The raycaster.</param>
  230. /// <param name="raycastResults"> The raycast results.</param>
  231. public virtual void GraphicRaycast(ICanvasRaycastTarget raycastTarget, bool ignoreReversedGraphics, Ray ray, float distance, NRPointerRaycaster raycaster, List<RaycastResult> raycastResults)
  232. {
  233. if (raycastTarget.canvas == null)
  234. return;
  235. var eventCamera = raycaster.eventCamera;
  236. var screenCenterPoint = NRInputModule.ScreenCenterPoint;
  237. raycastTarget.GraphicRaycast(ignoreReversedGraphics, ray, distance, screenCenterPoint, raycaster, raycastResults);
  238. }
  239. }
  240. }