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.

684 lines
31 KiB

  1. // Base Pointer Renderer|PointerRenderers|10010
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. using System;
  6. using System.Collections.Generic;
  7. #if UNITY_5_5_OR_NEWER
  8. using UnityEngine.AI;
  9. #endif
  10. /// <summary>
  11. /// Provides a base that all pointer renderers can inherit from.
  12. /// </summary>
  13. /// <remarks>
  14. /// **Script Usage:**
  15. /// > This is an abstract class that is to be inherited to a concrete class that provides pointer renderer functionality, therefore this script should not be directly used.
  16. /// </remarks>
  17. public abstract class VRTK_BasePointerRenderer : MonoBehaviour
  18. {
  19. /// <summary>
  20. /// States of Pointer Visibility.
  21. /// </summary>
  22. public enum VisibilityStates
  23. {
  24. /// <summary>
  25. /// Only shows the object when the pointer is active.
  26. /// </summary>
  27. OnWhenActive,
  28. /// <summary>
  29. /// Ensures the object is always.
  30. /// </summary>
  31. AlwaysOn,
  32. /// <summary>
  33. /// Ensures the object beam is never visible.
  34. /// </summary>
  35. AlwaysOff
  36. }
  37. [Serializable]
  38. public sealed class PointerOriginSmoothingSettings
  39. {
  40. [Tooltip("Whether or not to smooth the position of the pointer origin when positioning the pointer tip.")]
  41. public bool smoothsPosition;
  42. [Tooltip("The maximum allowed distance between the unsmoothed pointer origin and the smoothed pointer origin per frame to use for smoothing.")]
  43. public float maxAllowedPerFrameDistanceDifference = 0.003f;
  44. [Tooltip("Whether or not to smooth the rotation of the pointer origin when positioning the pointer tip.")]
  45. public bool smoothsRotation;
  46. [Tooltip("The maximum allowed angle between the unsmoothed pointer origin and the smoothed pointer origin per frame to use for smoothing.")]
  47. public float maxAllowedPerFrameAngleDifference = 1.5f;
  48. }
  49. [Header("Renderer Supplement Settings")]
  50. [Tooltip("An optional Play Area Cursor generator to add to the destination position of the pointer tip.")]
  51. public VRTK_PlayAreaCursor playareaCursor;
  52. [Tooltip("A custom VRTK_PointerDirectionIndicator to use to determine the rotation given to the destination set event.")]
  53. public VRTK_PointerDirectionIndicator directionIndicator;
  54. [Header("General Renderer Settings")]
  55. [Tooltip("A custom raycaster to use for the pointer's raycasts to ignore.")]
  56. public VRTK_CustomRaycast customRaycast;
  57. [Tooltip("Specifies the smoothing to be applied to the pointer origin when positioning the pointer tip.")]
  58. public PointerOriginSmoothingSettings pointerOriginSmoothingSettings = new PointerOriginSmoothingSettings();
  59. [Header("General Appearance Settings")]
  60. [Tooltip("The colour to change the pointer materials when the pointer collides with a valid object. Set to `Color.clear` to bypass changing material colour on valid collision.")]
  61. public Color validCollisionColor = Color.green;
  62. [Tooltip("The colour to change the pointer materials when the pointer is not colliding with anything or with an invalid object. Set to `Color.clear` to bypass changing material colour on invalid collision.")]
  63. public Color invalidCollisionColor = Color.red;
  64. [Tooltip("Determines when the main tracer of the pointer renderer will be visible.")]
  65. public VisibilityStates tracerVisibility = VisibilityStates.OnWhenActive;
  66. [Tooltip("Determines when the cursor/tip of the pointer renderer will be visible.")]
  67. public VisibilityStates cursorVisibility = VisibilityStates.OnWhenActive;
  68. protected const float BEAM_ADJUST_OFFSET = 0.0001f;
  69. protected VRTK_Pointer controllingPointer;
  70. protected RaycastHit destinationHit = new RaycastHit();
  71. protected Material defaultMaterial;
  72. protected Color previousColor;
  73. protected Color currentColor;
  74. protected VRTK_PolicyList invalidListPolicy;
  75. protected VRTK_NavMeshData navMeshData;
  76. protected bool headsetPositionCompensation;
  77. protected GameObject objectInteractor;
  78. protected GameObject objectInteractorAttachPoint;
  79. protected GameObject pointerOriginTransformFollowGameObject;
  80. protected VRTK_TransformFollow pointerOriginTransformFollow;
  81. protected VRTK_InteractGrab controllerGrabScript;
  82. protected Rigidbody savedAttachPoint;
  83. protected bool attachedToInteractorAttachPoint = false;
  84. protected float savedBeamLength = 0f;
  85. protected HashSet<GameObject> makeRendererVisible = new HashSet<GameObject>();
  86. protected bool tracerVisible;
  87. protected bool cursorVisible;
  88. protected LayerMask defaultIgnoreLayer = Physics.IgnoreRaycastLayer;
  89. protected SDK_BaseController.ControllerHand cachedAttachedHand = SDK_BaseController.ControllerHand.None;
  90. protected Transform cachedPointerAttachPoint = null;
  91. /// <summary>
  92. /// The GetPointerObjects returns an array of the auto generated GameObjects associated with the pointer.
  93. /// </summary>
  94. /// <returns>An array of pointer auto generated GameObjects.</returns>
  95. public abstract GameObject[] GetPointerObjects();
  96. /// <summary>
  97. /// The InitalizePointer method is used to set up the state of the pointer renderer.
  98. /// </summary>
  99. /// <param name="givenPointer">The VRTK_Pointer that is controlling the pointer renderer.</param>
  100. /// <param name="givenInvalidListPolicy">The VRTK_PolicyList for managing valid and invalid pointer locations.</param>
  101. /// <param name="givenNavMeshCheckDistance">The given distance from a nav mesh that the pointer can be to be valid.</param>
  102. /// <param name="givenHeadsetPositionCompensation">Determines whether the play area cursor will take the headset position within the play area into account when being displayed.</param>
  103. [Obsolete("`VRTK_BasePointerRenderer.InitalizePointer(givenPointer, givenInvalidListPolicy, givenNavMeshCheckDistance, givenHeadsetPositionCompensation)` has been replaced with the method `VRTK_BasePointerRenderer.InitalizePointer(givenPointer, givenInvalidListPolicy, givenNavMeshData, givenHeadsetPositionCompensation)`. This method will be removed in a future version of VRTK.")]
  104. public virtual void InitalizePointer(VRTK_Pointer givenPointer, VRTK_PolicyList givenInvalidListPolicy, float givenNavMeshCheckDistance, bool givenHeadsetPositionCompensation)
  105. {
  106. VRTK_NavMeshData givenData = gameObject.AddComponent<VRTK_NavMeshData>();
  107. givenData.distanceLimit = givenNavMeshCheckDistance;
  108. InitalizePointer(givenPointer, givenInvalidListPolicy, givenData, givenHeadsetPositionCompensation);
  109. }
  110. /// <summary>
  111. /// The InitalizePointer method is used to set up the state of the pointer renderer.
  112. /// </summary>
  113. /// <param name="givenPointer">The VRTK_Pointer that is controlling the pointer renderer.</param>
  114. /// <param name="givenInvalidListPolicy">The VRTK_PolicyList for managing valid and invalid pointer locations.</param>
  115. /// <param name="givenNavMeshData">The NavMeshData object that contains the Nav Mesh restriction options.</param>
  116. /// <param name="givenHeadsetPositionCompensation">Determines whether the play area cursor will take the headset position within the play area into account when being displayed.</param>
  117. public virtual void InitalizePointer(VRTK_Pointer givenPointer, VRTK_PolicyList givenInvalidListPolicy, VRTK_NavMeshData givenNavMeshData, bool givenHeadsetPositionCompensation)
  118. {
  119. controllingPointer = givenPointer;
  120. invalidListPolicy = givenInvalidListPolicy;
  121. navMeshData = givenNavMeshData;
  122. headsetPositionCompensation = givenHeadsetPositionCompensation;
  123. if (controllingPointer != null && controllingPointer.interactWithObjects && controllingPointer.controllerEvents != null && objectInteractor == null)
  124. {
  125. controllerGrabScript = controllingPointer.controllerEvents.GetComponentInChildren<VRTK_InteractGrab>();
  126. CreateObjectInteractor();
  127. }
  128. SetupDirectionIndicator();
  129. }
  130. /// <summary>
  131. /// The ResetPointerObjects method is used to destroy any existing pointer objects and recreate them at runtime.
  132. /// </summary>
  133. public virtual void ResetPointerObjects()
  134. {
  135. DestroyPointerOriginTransformFollow();
  136. DestroyPointerObjects();
  137. CreatePointerOriginTransformFollow();
  138. CreatePointerObjects();
  139. }
  140. /// <summary>
  141. /// The Toggle Method is used to enable or disable the pointer renderer.
  142. /// </summary>
  143. /// <param name="pointerState">The activation state of the pointer.</param>
  144. /// <param name="actualState">The actual state of the activation button press.</param>
  145. public virtual void Toggle(bool pointerState, bool actualState)
  146. {
  147. if (pointerState)
  148. {
  149. destinationHit = new RaycastHit();
  150. }
  151. else if (controllingPointer != null)
  152. {
  153. controllingPointer.ResetActivationTimer();
  154. PointerExit(destinationHit);
  155. }
  156. ToggleInteraction(pointerState);
  157. ToggleRenderer(pointerState, actualState);
  158. }
  159. /// <summary>
  160. /// The ToggleInteraction method is used to enable or disable the controller extension interactions.
  161. /// </summary>
  162. /// <param name="state">If true then the object interactor will be enabled.</param>
  163. public virtual void ToggleInteraction(bool state)
  164. {
  165. ToggleObjectInteraction(state);
  166. }
  167. /// <summary>
  168. /// The UpdateRenderer method is used to run an Update routine on the pointer.
  169. /// </summary>
  170. public virtual void UpdateRenderer()
  171. {
  172. if (playareaCursor != null)
  173. {
  174. playareaCursor.SetHeadsetPositionCompensation(headsetPositionCompensation);
  175. playareaCursor.ToggleState(IsCursorVisible());
  176. }
  177. if (directionIndicator != null)
  178. {
  179. UpdateDirectionIndicator();
  180. }
  181. }
  182. /// <summary>
  183. /// The GetDestinationHit method is used to get the RaycastHit of the pointer destination.
  184. /// </summary>
  185. /// <returns>The RaycastHit containing the information where the pointer is hitting.</returns>
  186. public virtual RaycastHit GetDestinationHit()
  187. {
  188. return destinationHit;
  189. }
  190. /// <summary>
  191. /// The ValidPlayArea method is used to determine if there is a valid play area and if it has had any collisions.
  192. /// </summary>
  193. /// <returns>Returns true if there is a valid play area and no collisions. Returns false if there is no valid play area or there is but with a collision detected.</returns>
  194. public virtual bool ValidPlayArea()
  195. {
  196. return (playareaCursor == null || !playareaCursor.IsActive() || !playareaCursor.HasCollided());
  197. }
  198. /// <summary>
  199. /// The IsVisible method determines if the pointer renderer is at all visible by checking the state of the tracer and the cursor.
  200. /// </summary>
  201. /// <returns>Returns true if either the tracer or cursor renderers are visible. Returns false if none are visible.</returns>
  202. public virtual bool IsVisible()
  203. {
  204. return (IsTracerVisible() || IsCursorVisible());
  205. }
  206. /// <summary>
  207. /// The IsTracerVisible method determines if the pointer tracer renderer is visible.
  208. /// </summary>
  209. /// <returns>Returns true if the tracer renderers are visible.</returns>
  210. public virtual bool IsTracerVisible()
  211. {
  212. return (tracerVisibility == VisibilityStates.AlwaysOn || tracerVisible);
  213. }
  214. /// <summary>
  215. /// The IsCursorVisible method determines if the pointer cursor renderer is visible.
  216. /// </summary>
  217. /// <returns>Returns true if the cursor renderers are visible.</returns>
  218. public virtual bool IsCursorVisible()
  219. {
  220. return (cursorVisibility == VisibilityStates.AlwaysOn || cursorVisible);
  221. }
  222. /// <summary>
  223. /// The IsValidCollision method determines if the pointer is currently in it's valid collision state.
  224. /// </summary>
  225. /// <returns>Returns true if the pointer is in a valid collision, returns false if the pointer is in an invalid collision state.</returns>
  226. public virtual bool IsValidCollision()
  227. {
  228. return (currentColor != invalidCollisionColor);
  229. }
  230. /// <summary>
  231. /// The GetObjectInteractor method returns the auto generated GameObject that acts as the controller extension for interacting with objects.
  232. /// </summary>
  233. /// <returns>The auto generated object interactor GameObject.</returns>
  234. /// <returns></returns>
  235. public virtual GameObject GetObjectInteractor()
  236. {
  237. return objectInteractor;
  238. }
  239. protected abstract void CreatePointerObjects();
  240. protected abstract void DestroyPointerObjects();
  241. protected abstract void ToggleRenderer(bool pointerState, bool actualState);
  242. protected virtual void Awake()
  243. {
  244. VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
  245. }
  246. protected virtual void OnEnable()
  247. {
  248. cachedPointerAttachPoint = null;
  249. cachedAttachedHand = SDK_BaseController.ControllerHand.None;
  250. defaultMaterial = Resources.Load("WorldPointer") as Material;
  251. makeRendererVisible.Clear();
  252. CreatePointerOriginTransformFollow();
  253. CreatePointerObjects();
  254. }
  255. protected virtual void OnDisable()
  256. {
  257. DestroyPointerObjects();
  258. if (objectInteractor != null)
  259. {
  260. Destroy(objectInteractor);
  261. }
  262. controllerGrabScript = null;
  263. DestroyPointerOriginTransformFollow();
  264. }
  265. protected virtual void OnDestroy()
  266. {
  267. VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
  268. }
  269. protected virtual void OnValidate()
  270. {
  271. pointerOriginSmoothingSettings.maxAllowedPerFrameDistanceDifference = Mathf.Max(0.0001f, pointerOriginSmoothingSettings.maxAllowedPerFrameDistanceDifference);
  272. pointerOriginSmoothingSettings.maxAllowedPerFrameAngleDifference = Mathf.Max(0.0001f, pointerOriginSmoothingSettings.maxAllowedPerFrameAngleDifference);
  273. }
  274. protected virtual void FixedUpdate()
  275. {
  276. if (controllingPointer != null && controllingPointer.interactWithObjects && objectInteractor != null && objectInteractor.activeInHierarchy)
  277. {
  278. UpdateObjectInteractor();
  279. }
  280. if (pointerOriginTransformFollow != null)
  281. {
  282. UpdatePointerOriginTransformFollow();
  283. }
  284. }
  285. protected virtual void ToggleObjectInteraction(bool state)
  286. {
  287. if (controllingPointer != null && controllingPointer.interactWithObjects)
  288. {
  289. if (state && controllingPointer.grabToPointerTip && controllerGrabScript != null && objectInteractorAttachPoint != null)
  290. {
  291. savedAttachPoint = controllerGrabScript.controllerAttachPoint;
  292. controllerGrabScript.controllerAttachPoint = objectInteractorAttachPoint.GetComponent<Rigidbody>();
  293. attachedToInteractorAttachPoint = true;
  294. }
  295. if (!state && controllingPointer.grabToPointerTip && controllerGrabScript != null)
  296. {
  297. if (attachedToInteractorAttachPoint)
  298. {
  299. controllerGrabScript.ForceRelease(true);
  300. }
  301. if (savedAttachPoint != null)
  302. {
  303. controllerGrabScript.controllerAttachPoint = savedAttachPoint;
  304. savedAttachPoint = null;
  305. }
  306. attachedToInteractorAttachPoint = false;
  307. savedBeamLength = 0f;
  308. }
  309. if (objectInteractor != null)
  310. {
  311. objectInteractor.SetActive(state);
  312. }
  313. }
  314. }
  315. protected virtual void UpdateObjectInteractor()
  316. {
  317. objectInteractor.transform.position = destinationHit.point;
  318. }
  319. protected virtual VRTK_ControllerReference GetControllerReference(GameObject reference = null)
  320. {
  321. reference = (reference == null && controllingPointer != null && controllingPointer.controllerEvents != null ? controllingPointer.controllerEvents.gameObject : reference);
  322. return VRTK_ControllerReference.GetControllerReference(reference);
  323. }
  324. protected virtual Transform GetPointerOriginTransform()
  325. {
  326. VRTK_ControllerReference controllerReference = GetControllerReference((controllingPointer != null ? controllingPointer.attachedTo : null));
  327. if (VRTK_ControllerReference.IsValid(controllerReference) && (cachedAttachedHand != controllerReference.hand || cachedPointerAttachPoint == null))
  328. {
  329. cachedPointerAttachPoint = controllerReference.model.transform.Find(VRTK_SDK_Bridge.GetControllerElementPath(SDK_BaseController.ControllerElements.AttachPoint, controllerReference.hand));
  330. cachedAttachedHand = controllerReference.hand;
  331. pointerOriginTransformFollow.gameObject.SetActive(false);
  332. }
  333. return (cachedPointerAttachPoint != null ? cachedPointerAttachPoint : transform);
  334. }
  335. protected virtual void UpdatePointerOriginTransformFollow()
  336. {
  337. pointerOriginTransformFollow.gameObject.SetActive((controllingPointer != null));
  338. if (controllingPointer != null)
  339. {
  340. pointerOriginTransformFollow.gameObjectToFollow = (controllingPointer.customOrigin == null ? GetPointerOriginTransform() : controllingPointer.customOrigin).gameObject;
  341. pointerOriginTransformFollow.enabled = controllingPointer != null;
  342. pointerOriginTransformFollowGameObject.SetActive(controllingPointer != null);
  343. pointerOriginTransformFollow.smoothsPosition = pointerOriginSmoothingSettings.smoothsPosition;
  344. pointerOriginTransformFollow.maxAllowedPerFrameDistanceDifference = pointerOriginSmoothingSettings.maxAllowedPerFrameDistanceDifference;
  345. pointerOriginTransformFollow.smoothsRotation = pointerOriginSmoothingSettings.smoothsRotation;
  346. pointerOriginTransformFollow.maxAllowedPerFrameAngleDifference = pointerOriginSmoothingSettings.maxAllowedPerFrameAngleDifference;
  347. }
  348. }
  349. protected Transform GetOrigin(bool smoothed = true)
  350. {
  351. return (smoothed ? pointerOriginTransformFollow.gameObjectToChange.transform : (controllingPointer.customOrigin == null ? GetPointerOriginTransform() : controllingPointer.customOrigin));
  352. }
  353. protected virtual void PointerEnter(RaycastHit givenHit)
  354. {
  355. controllingPointer.PointerEnter(givenHit);
  356. }
  357. protected virtual void PointerExit(RaycastHit givenHit)
  358. {
  359. controllingPointer.PointerExit(givenHit);
  360. }
  361. protected virtual bool ValidDestination()
  362. {
  363. bool validNavMeshLocation = false;
  364. if (navMeshData != null)
  365. {
  366. if (destinationHit.transform != null)
  367. {
  368. NavMeshHit hit;
  369. validNavMeshLocation = NavMesh.SamplePosition(destinationHit.point, out hit, navMeshData.distanceLimit, navMeshData.validAreas);
  370. }
  371. }
  372. else
  373. {
  374. validNavMeshLocation = true;
  375. }
  376. return (validNavMeshLocation && destinationHit.collider != null && !(VRTK_PolicyList.Check(destinationHit.collider.gameObject, invalidListPolicy)));
  377. }
  378. protected virtual void ToggleElement(GameObject givenObject, bool pointerState, bool actualState, VisibilityStates givenVisibility, ref bool currentVisible)
  379. {
  380. if (givenObject != null)
  381. {
  382. currentVisible = (givenVisibility == VisibilityStates.AlwaysOn ? true : pointerState);
  383. givenObject.SetActive(currentVisible);
  384. if (givenVisibility == VisibilityStates.AlwaysOff)
  385. {
  386. currentVisible = false;
  387. ToggleRendererVisibility(givenObject, false);
  388. }
  389. else
  390. {
  391. if (actualState && givenVisibility != VisibilityStates.AlwaysOn)
  392. {
  393. ToggleRendererVisibility(givenObject, false);
  394. AddVisibleRenderer(givenObject);
  395. }
  396. else
  397. {
  398. ToggleRendererVisibility(givenObject, true);
  399. }
  400. }
  401. }
  402. }
  403. protected virtual void AddVisibleRenderer(GameObject givenObject)
  404. {
  405. makeRendererVisible.Add(givenObject);
  406. }
  407. protected virtual void MakeRenderersVisible()
  408. {
  409. foreach (GameObject currentRenderer in new HashSet<GameObject>(makeRendererVisible))
  410. {
  411. ToggleRendererVisibility(currentRenderer, true);
  412. }
  413. makeRendererVisible.Clear();
  414. }
  415. protected virtual void ToggleRendererVisibility(GameObject givenObject, bool state)
  416. {
  417. if (givenObject != null)
  418. {
  419. Renderer[] renderers = givenObject.GetComponentsInChildren<Renderer>();
  420. for (int i = 0; i < renderers.Length; i++)
  421. {
  422. renderers[i].enabled = state;
  423. }
  424. }
  425. }
  426. protected virtual void SetupMaterialRenderer(GameObject givenObject)
  427. {
  428. if (givenObject != null)
  429. {
  430. MeshRenderer pointerRenderer = givenObject.GetComponent<MeshRenderer>();
  431. pointerRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
  432. pointerRenderer.receiveShadows = false;
  433. pointerRenderer.material = defaultMaterial;
  434. }
  435. }
  436. protected virtual void ChangeColor(Color givenColor)
  437. {
  438. previousColor = currentColor;
  439. if ((playareaCursor != null && playareaCursor.IsActive() && playareaCursor.HasCollided()) || !ValidDestination() || (controllingPointer != null && !controllingPointer.CanSelect()))
  440. {
  441. givenColor = invalidCollisionColor;
  442. }
  443. if (givenColor != Color.clear)
  444. {
  445. currentColor = givenColor;
  446. ChangeMaterial(givenColor);
  447. }
  448. if (previousColor != currentColor)
  449. {
  450. EmitStateEvent();
  451. }
  452. }
  453. protected virtual void EmitStateEvent()
  454. {
  455. if (controllingPointer != null)
  456. {
  457. if (IsValidCollision())
  458. {
  459. controllingPointer.OnPointerStateValid();
  460. }
  461. else
  462. {
  463. controllingPointer.OnPointerStateInvalid();
  464. }
  465. }
  466. }
  467. protected virtual void ChangeMaterial(Color givenColor)
  468. {
  469. if (playareaCursor != null)
  470. {
  471. playareaCursor.SetMaterialColor(givenColor, IsValidCollision());
  472. }
  473. if (directionIndicator != null)
  474. {
  475. directionIndicator.SetMaterialColor(givenColor, IsValidCollision());
  476. }
  477. }
  478. protected virtual void ChangeMaterialColor(GameObject givenObject, Color givenColor)
  479. {
  480. if (givenObject != null)
  481. {
  482. Renderer[] foundRenderers = givenObject.GetComponentsInChildren<Renderer>();
  483. for (int i = 0; i < foundRenderers.Length; i++)
  484. {
  485. Renderer foundRenderer = foundRenderers[i];
  486. if (foundRenderer.material != null)
  487. {
  488. foundRenderer.material.EnableKeyword("_EMISSION");
  489. if (foundRenderer.material.HasProperty("_Color"))
  490. {
  491. foundRenderer.material.color = givenColor;
  492. }
  493. if (foundRenderer.material.HasProperty("_EmissionColor"))
  494. {
  495. foundRenderer.material.SetColor("_EmissionColor", VRTK_SharedMethods.ColorDarken(givenColor, 50));
  496. }
  497. }
  498. }
  499. }
  500. }
  501. protected virtual void CreateObjectInteractor()
  502. {
  503. objectInteractor = new GameObject(VRTK_SharedMethods.GenerateVRTKObjectName(true, gameObject.name, "BasePointerRenderer_ObjectInteractor_Container"));
  504. objectInteractor.transform.SetParent(controllingPointer.controllerEvents.transform);
  505. objectInteractor.transform.localPosition = Vector3.zero;
  506. objectInteractor.layer = LayerMask.NameToLayer("Ignore Raycast");
  507. VRTK_PlayerObject.SetPlayerObject(objectInteractor, VRTK_PlayerObject.ObjectTypes.Pointer);
  508. GameObject objectInteractorCollider = new GameObject(VRTK_SharedMethods.GenerateVRTKObjectName(true, gameObject.name, "BasePointerRenderer_ObjectInteractor_Collider"));
  509. objectInteractorCollider.transform.SetParent(objectInteractor.transform);
  510. objectInteractorCollider.transform.localPosition = Vector3.zero;
  511. objectInteractorCollider.layer = LayerMask.NameToLayer("Ignore Raycast");
  512. SphereCollider tmpCollider = objectInteractorCollider.AddComponent<SphereCollider>();
  513. tmpCollider.isTrigger = true;
  514. VRTK_PlayerObject.SetPlayerObject(objectInteractorCollider, VRTK_PlayerObject.ObjectTypes.Pointer);
  515. if (controllingPointer.grabToPointerTip)
  516. {
  517. objectInteractorAttachPoint = new GameObject(VRTK_SharedMethods.GenerateVRTKObjectName(true, gameObject.name, "BasePointerRenderer_ObjectInteractor_AttachPoint"));
  518. objectInteractorAttachPoint.transform.SetParent(objectInteractor.transform);
  519. objectInteractorAttachPoint.transform.localPosition = Vector3.zero;
  520. objectInteractorAttachPoint.layer = LayerMask.NameToLayer("Ignore Raycast");
  521. Rigidbody objectInteratorRigidBody = objectInteractorAttachPoint.AddComponent<Rigidbody>();
  522. objectInteratorRigidBody.isKinematic = true;
  523. objectInteratorRigidBody.freezeRotation = true;
  524. #if UNITY_2018_3_OR_NEWER
  525. objectInteratorRigidBody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
  526. #else
  527. objectInteratorRigidBody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
  528. #endif
  529. VRTK_PlayerObject.SetPlayerObject(objectInteractorAttachPoint, VRTK_PlayerObject.ObjectTypes.Pointer);
  530. }
  531. ScaleObjectInteractor(Vector3.one);
  532. objectInteractor.SetActive(false);
  533. }
  534. protected virtual void ScaleObjectInteractor(Vector3 scaleAmount)
  535. {
  536. if (objectInteractor != null)
  537. {
  538. VRTK_SharedMethods.SetGlobalScale(objectInteractor.transform, scaleAmount);
  539. }
  540. }
  541. protected virtual void CreatePointerOriginTransformFollow()
  542. {
  543. pointerOriginTransformFollowGameObject = new GameObject(VRTK_SharedMethods.GenerateVRTKObjectName(true, gameObject.name, "BasePointerRenderer_Origin_Smoothed"));
  544. pointerOriginTransformFollow = pointerOriginTransformFollowGameObject.AddComponent<VRTK_TransformFollow>();
  545. pointerOriginTransformFollow.enabled = false;
  546. pointerOriginTransformFollow.moment = VRTK_TransformFollow.FollowMoment.OnFixedUpdate;
  547. pointerOriginTransformFollow.followsScale = false;
  548. }
  549. protected virtual void DestroyPointerOriginTransformFollow()
  550. {
  551. if (pointerOriginTransformFollowGameObject != null)
  552. {
  553. Destroy(pointerOriginTransformFollowGameObject);
  554. pointerOriginTransformFollowGameObject = null;
  555. pointerOriginTransformFollow = null;
  556. }
  557. }
  558. protected virtual float OverrideBeamLength(float currentLength)
  559. {
  560. if (controllerGrabScript == null || !controllerGrabScript.GetGrabbedObject())
  561. {
  562. savedBeamLength = 0f;
  563. }
  564. if (controllingPointer != null && controllingPointer.interactWithObjects && controllingPointer.grabToPointerTip && attachedToInteractorAttachPoint && controllerGrabScript != null && controllerGrabScript.GetGrabbedObject())
  565. {
  566. savedBeamLength = (savedBeamLength == 0f ? currentLength : savedBeamLength);
  567. return savedBeamLength;
  568. }
  569. return currentLength;
  570. }
  571. protected virtual void UpdateDependencies(Vector3 location)
  572. {
  573. if (playareaCursor != null)
  574. {
  575. playareaCursor.SetPlayAreaCursorTransform(location);
  576. }
  577. }
  578. protected virtual void SetupDirectionIndicator()
  579. {
  580. if (directionIndicator != null && controllingPointer != null && controllingPointer.controllerEvents != null)
  581. {
  582. directionIndicator.Initialize(controllingPointer.controllerEvents);
  583. }
  584. }
  585. protected virtual void UpdateDirectionIndicator()
  586. {
  587. RaycastHit destinationHit = GetDestinationHit();
  588. directionIndicator.SetPosition((ShowDirectionIndicator() && destinationHit.collider != null), destinationHit.point);
  589. }
  590. protected virtual bool ShowDirectionIndicator()
  591. {
  592. switch (directionIndicator.indicatorVisibility)
  593. {
  594. case VRTK_PointerDirectionIndicator.VisibilityState.OnWhenPointerActive:
  595. return controllingPointer.IsPointerActive();
  596. case VRTK_PointerDirectionIndicator.VisibilityState.AlwaysOnWithPointerCursor:
  597. return (IsCursorVisible() || controllingPointer.IsPointerActive());
  598. }
  599. return false;
  600. }
  601. }
  602. }