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.

262 lines
12 KiB

  1. // Straight Pointer Renderer|PointerRenderers|10020
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. /// <summary>
  6. /// A visual pointer representation of a straight beam with an optional cursor at the end.
  7. /// </summary>
  8. /// <remarks>
  9. /// **Optional Components:**
  10. /// * `VRTK_PlayAreaCursor` - A Play Area Cursor that will track the position of the pointer cursor.
  11. /// * `VRTK_PointerDirectionIndicator` - A Pointer Direction Indicator that will track the position of the pointer cursor.
  12. ///
  13. /// **Script Usage:**
  14. /// * Place the `VRTK_StraightPointerRenderer` script on the same GameObject as the Pointer script it is linked to.
  15. /// * Link this Pointer Renderer script to the `Pointer Renderer` parameter on the required Pointer script.
  16. ///
  17. /// **Script Dependencies:**
  18. /// * A Pointer script to control the activation of this Pointer Renderer script.
  19. /// </remarks>
  20. /// <example>
  21. /// `VRTK/Examples/003_Controller_SimplePointer` shows the simple pointer in action and code examples of how the events are utilised and listened to can be viewed in the script `VRTK/Examples/ExampleResources/Scripts/VRTK_ControllerPointerEvents_ListenerExample.cs`
  22. /// </example>
  23. [AddComponentMenu("VRTK/Scripts/Pointers/Pointer Renderers/VRTK_StraightPointerRenderer")]
  24. public class VRTK_StraightPointerRenderer : VRTK_BasePointerRenderer
  25. {
  26. [Header("Straight Pointer Appearance Settings")]
  27. [Tooltip("The maximum length the pointer tracer can reach.")]
  28. public float maximumLength = 100f;
  29. [Tooltip("The scale factor to scale the pointer tracer object by.")]
  30. public float scaleFactor = 0.002f;
  31. [Tooltip("The scale multiplier to scale the pointer cursor object by in relation to the `Scale Factor`.")]
  32. public float cursorScaleMultiplier = 25f;
  33. [Tooltip("The cursor will be rotated to match the angle of the target surface if this is true, if it is false then the pointer cursor will always be horizontal.")]
  34. public bool cursorMatchTargetRotation = false;
  35. [Tooltip("Rescale the cursor proportionally to the distance from the tracer origin.")]
  36. public bool cursorDistanceRescale = false;
  37. [Tooltip("The maximum scale the cursor is allowed to reach. This is only used when rescaling the cursor proportionally to the distance from the tracer origin.")]
  38. public Vector3 maximumCursorScale = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
  39. [Header("Straight Pointer Custom Appearance Settings")]
  40. [Tooltip("A custom game object to use as the appearance for the pointer tracer. If this is empty then a Box primitive will be created and used.")]
  41. public GameObject customTracer;
  42. [Tooltip("A custom game object to use as the appearance for the pointer cursor. If this is empty then a Sphere primitive will be created and used.")]
  43. public GameObject customCursor;
  44. protected GameObject actualContainer;
  45. protected GameObject actualTracer;
  46. protected GameObject actualCursor;
  47. protected Vector3 cursorOriginalScale = Vector3.one;
  48. /// <summary>
  49. /// The UpdateRenderer method is used to run an Update routine on the pointer.
  50. /// </summary>
  51. public override void UpdateRenderer()
  52. {
  53. if ((controllingPointer != null && controllingPointer.IsPointerActive()) || IsVisible())
  54. {
  55. float tracerLength = CastRayForward();
  56. SetPointerAppearance(tracerLength);
  57. MakeRenderersVisible();
  58. }
  59. base.UpdateRenderer();
  60. }
  61. /// <summary>
  62. /// The GetPointerObjects returns an array of the auto generated GameObjects associated with the pointer.
  63. /// </summary>
  64. /// <returns>An array of pointer auto generated GameObjects.</returns>
  65. public override GameObject[] GetPointerObjects()
  66. {
  67. return new GameObject[] { actualContainer, actualCursor, actualTracer };
  68. }
  69. protected override void ToggleRenderer(bool pointerState, bool actualState)
  70. {
  71. ToggleElement(actualTracer, pointerState, actualState, tracerVisibility, ref tracerVisible);
  72. ToggleElement(actualCursor, pointerState, actualState, cursorVisibility, ref cursorVisible);
  73. }
  74. protected override void CreatePointerObjects()
  75. {
  76. actualContainer = new GameObject(VRTK_SharedMethods.GenerateVRTKObjectName(true, gameObject.name, "StraightPointerRenderer_Container"));
  77. actualContainer.transform.SetParent(pointerOriginTransformFollowGameObject.transform);
  78. actualContainer.transform.localPosition = Vector3.zero;
  79. actualContainer.transform.localRotation = Quaternion.identity;
  80. actualContainer.transform.localScale = Vector3.one;
  81. VRTK_PlayerObject.SetPlayerObject(actualContainer, VRTK_PlayerObject.ObjectTypes.Pointer);
  82. CreateTracer();
  83. CreateCursor();
  84. Toggle(false, false);
  85. if (controllingPointer != null)
  86. {
  87. controllingPointer.ResetActivationTimer(true);
  88. controllingPointer.ResetSelectionTimer(true);
  89. }
  90. }
  91. protected override void DestroyPointerObjects()
  92. {
  93. if (actualContainer != null)
  94. {
  95. Destroy(actualContainer);
  96. }
  97. }
  98. protected override void ChangeMaterial(Color givenColor)
  99. {
  100. base.ChangeMaterial(givenColor);
  101. ChangeMaterialColor(actualTracer, givenColor);
  102. ChangeMaterialColor(actualCursor, givenColor);
  103. }
  104. protected override void UpdateObjectInteractor()
  105. {
  106. base.UpdateObjectInteractor();
  107. //if the object interactor is too far from the pointer tip then set it to the pointer tip position to prevent glitching.
  108. if (objectInteractor != null && actualCursor != null && Vector3.Distance(objectInteractor.transform.position, actualCursor.transform.position) > 0f)
  109. {
  110. objectInteractor.transform.position = actualCursor.transform.position;
  111. }
  112. }
  113. protected virtual void CreateTracer()
  114. {
  115. if (customTracer != null)
  116. {
  117. actualTracer = Instantiate(customTracer);
  118. }
  119. else
  120. {
  121. actualTracer = GameObject.CreatePrimitive(PrimitiveType.Cube);
  122. actualTracer.GetComponent<BoxCollider>().isTrigger = true;
  123. actualTracer.AddComponent<Rigidbody>().isKinematic = true;
  124. actualTracer.layer = LayerMask.NameToLayer("Ignore Raycast");
  125. SetupMaterialRenderer(actualTracer);
  126. }
  127. actualTracer.transform.name = VRTK_SharedMethods.GenerateVRTKObjectName(true, gameObject.name, "StraightPointerRenderer_Tracer");
  128. actualTracer.transform.SetParent(actualContainer.transform);
  129. VRTK_PlayerObject.SetPlayerObject(actualTracer, VRTK_PlayerObject.ObjectTypes.Pointer);
  130. }
  131. protected virtual void CreateCursor()
  132. {
  133. if (customCursor != null)
  134. {
  135. actualCursor = Instantiate(customCursor);
  136. }
  137. else
  138. {
  139. actualCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  140. actualCursor.transform.localScale = Vector3.one * (scaleFactor * cursorScaleMultiplier);
  141. actualCursor.GetComponent<Collider>().isTrigger = true;
  142. actualCursor.AddComponent<Rigidbody>().isKinematic = true;
  143. actualCursor.layer = LayerMask.NameToLayer("Ignore Raycast");
  144. SetupMaterialRenderer(actualCursor);
  145. }
  146. cursorOriginalScale = actualCursor.transform.localScale;
  147. actualCursor.transform.name = VRTK_SharedMethods.GenerateVRTKObjectName(true, gameObject.name, "StraightPointerRenderer_Cursor");
  148. actualCursor.transform.SetParent(actualContainer.transform);
  149. VRTK_PlayerObject.SetPlayerObject(actualCursor, VRTK_PlayerObject.ObjectTypes.Pointer);
  150. }
  151. protected virtual void CheckRayMiss(bool rayHit, RaycastHit pointerCollidedWith)
  152. {
  153. if (!rayHit || (destinationHit.collider != null && destinationHit.collider != pointerCollidedWith.collider))
  154. {
  155. if (destinationHit.collider != null)
  156. {
  157. PointerExit(destinationHit);
  158. }
  159. destinationHit = new RaycastHit();
  160. ChangeColor(invalidCollisionColor);
  161. }
  162. }
  163. protected virtual void CheckRayHit(bool rayHit, RaycastHit pointerCollidedWith)
  164. {
  165. if (rayHit)
  166. {
  167. PointerEnter(pointerCollidedWith);
  168. destinationHit = pointerCollidedWith;
  169. ChangeColor(validCollisionColor);
  170. }
  171. }
  172. protected virtual float CastRayForward()
  173. {
  174. Transform origin = GetOrigin();
  175. Ray pointerRaycast = new Ray(origin.position, origin.forward);
  176. RaycastHit pointerCollidedWith;
  177. bool rayHit = VRTK_CustomRaycast.Raycast(customRaycast, pointerRaycast, out pointerCollidedWith, defaultIgnoreLayer, maximumLength);
  178. CheckRayMiss(rayHit, pointerCollidedWith);
  179. CheckRayHit(rayHit, pointerCollidedWith);
  180. float actualLength = maximumLength;
  181. if (rayHit && pointerCollidedWith.distance < maximumLength)
  182. {
  183. actualLength = pointerCollidedWith.distance;
  184. }
  185. return OverrideBeamLength(actualLength);
  186. }
  187. protected virtual void SetPointerAppearance(float tracerLength)
  188. {
  189. if (actualContainer != null)
  190. {
  191. //if the additional decimal isn't added then the beam position glitches
  192. float beamPosition = tracerLength / (2f + BEAM_ADJUST_OFFSET);
  193. actualTracer.transform.localScale = new Vector3(scaleFactor, scaleFactor, tracerLength);
  194. actualTracer.transform.localPosition = Vector3.forward * beamPosition;
  195. actualCursor.transform.localScale = Vector3.one * (scaleFactor * cursorScaleMultiplier);
  196. actualCursor.transform.localPosition = new Vector3(0f, 0f, tracerLength);
  197. Transform origin = GetOrigin();
  198. float objectInteractorScaleIncrease = 1.05f;
  199. ScaleObjectInteractor(actualCursor.transform.lossyScale * objectInteractorScaleIncrease);
  200. if (destinationHit.transform != null)
  201. {
  202. if (cursorMatchTargetRotation)
  203. {
  204. actualCursor.transform.forward = -destinationHit.normal;
  205. }
  206. if (cursorDistanceRescale)
  207. {
  208. float collisionDistance = Vector3.Distance(destinationHit.point, origin.position);
  209. actualCursor.transform.localScale = Vector3.Min(cursorOriginalScale * collisionDistance, maximumCursorScale);
  210. }
  211. }
  212. else
  213. {
  214. if (cursorMatchTargetRotation)
  215. {
  216. actualCursor.transform.forward = origin.forward;
  217. }
  218. if (cursorDistanceRescale)
  219. {
  220. actualCursor.transform.localScale = Vector3.Min(cursorOriginalScale * tracerLength, maximumCursorScale);
  221. }
  222. }
  223. ToggleRenderer(controllingPointer.IsPointerActive(), false);
  224. UpdateDependencies(actualCursor.transform.position);
  225. }
  226. }
  227. }
  228. }