SteamVR_LaserPointer.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. using UnityEngine;
  3. using System.Collections;
  4. namespace Valve.VR.Extras
  5. {
  6. public class SteamVR_LaserPointer : MonoBehaviour
  7. {
  8. public SteamVR_Behaviour_Pose pose;
  9. //public SteamVR_Action_Boolean interactWithUI = SteamVR_Input.__actions_default_in_InteractUI;
  10. public SteamVR_Action_Boolean interactWithUI = SteamVR_Input.GetBooleanAction("InteractUI");
  11. public bool active = true;
  12. public Color color;
  13. public float thickness = 0.002f;
  14. public Color clickColor = Color.green;
  15. public GameObject holder;
  16. public GameObject pointer;
  17. bool isActive = false;
  18. public bool addRigidBody = false;
  19. public Transform reference;
  20. public event PointerEventHandler PointerIn;
  21. public event PointerEventHandler PointerOut;
  22. public event PointerEventHandler PointerClick;
  23. Transform previousContact = null;
  24. private void Start()
  25. {
  26. if (pose == null)
  27. pose = this.GetComponent<SteamVR_Behaviour_Pose>();
  28. if (pose == null)
  29. Debug.LogError("No SteamVR_Behaviour_Pose component found on this object", this);
  30. if (interactWithUI == null)
  31. Debug.LogError("No ui interaction action has been set on this component.", this);
  32. holder = new GameObject();
  33. holder.transform.parent = this.transform;
  34. holder.transform.localPosition = Vector3.zero;
  35. holder.transform.localRotation = Quaternion.identity;
  36. pointer = GameObject.CreatePrimitive(PrimitiveType.Cube);
  37. pointer.transform.parent = holder.transform;
  38. pointer.transform.localScale = new Vector3(thickness, thickness, 100f);
  39. pointer.transform.localPosition = new Vector3(0f, 0f, 50f);
  40. pointer.transform.localRotation = Quaternion.identity;
  41. BoxCollider collider = pointer.GetComponent<BoxCollider>();
  42. if (addRigidBody)
  43. {
  44. if (collider)
  45. {
  46. collider.isTrigger = true;
  47. }
  48. Rigidbody rigidBody = pointer.AddComponent<Rigidbody>();
  49. rigidBody.isKinematic = true;
  50. }
  51. else
  52. {
  53. if (collider)
  54. {
  55. Object.Destroy(collider);
  56. }
  57. }
  58. Material newMaterial = new Material(Shader.Find("Unlit/Color"));
  59. newMaterial.SetColor("_Color", color);
  60. pointer.GetComponent<MeshRenderer>().material = newMaterial;
  61. }
  62. public virtual void OnPointerIn(PointerEventArgs e)
  63. {
  64. if (PointerIn != null)
  65. PointerIn(this, e);
  66. }
  67. public virtual void OnPointerClick(PointerEventArgs e)
  68. {
  69. if (PointerClick != null)
  70. PointerClick(this, e);
  71. }
  72. public virtual void OnPointerOut(PointerEventArgs e)
  73. {
  74. if (PointerOut != null)
  75. PointerOut(this, e);
  76. }
  77. private void Update()
  78. {
  79. if (!isActive)
  80. {
  81. isActive = true;
  82. this.transform.GetChild(0).gameObject.SetActive(true);
  83. }
  84. float dist = 100f;
  85. Ray raycast = new Ray(transform.position, transform.forward);
  86. RaycastHit hit;
  87. bool bHit = Physics.Raycast(raycast, out hit);
  88. if (previousContact && previousContact != hit.transform)
  89. {
  90. PointerEventArgs args = new PointerEventArgs();
  91. args.fromInputSource = pose.inputSource;
  92. args.distance = 0f;
  93. args.flags = 0;
  94. args.target = previousContact;
  95. OnPointerOut(args);
  96. previousContact = null;
  97. }
  98. if (bHit && previousContact != hit.transform)
  99. {
  100. PointerEventArgs argsIn = new PointerEventArgs();
  101. argsIn.fromInputSource = pose.inputSource;
  102. argsIn.distance = hit.distance;
  103. argsIn.flags = 0;
  104. argsIn.target = hit.transform;
  105. OnPointerIn(argsIn);
  106. previousContact = hit.transform;
  107. }
  108. if (!bHit)
  109. {
  110. previousContact = null;
  111. }
  112. if (bHit && hit.distance < 100f)
  113. {
  114. dist = hit.distance;
  115. }
  116. if (bHit && interactWithUI.GetStateUp(pose.inputSource))
  117. {
  118. PointerEventArgs argsClick = new PointerEventArgs();
  119. argsClick.fromInputSource = pose.inputSource;
  120. argsClick.distance = hit.distance;
  121. argsClick.flags = 0;
  122. argsClick.target = hit.transform;
  123. OnPointerClick(argsClick);
  124. }
  125. if (interactWithUI != null && interactWithUI.GetState(pose.inputSource))
  126. {
  127. pointer.transform.localScale = new Vector3(thickness * 5f, thickness * 5f, dist);
  128. pointer.GetComponent<MeshRenderer>().material.color = clickColor;
  129. }
  130. else
  131. {
  132. pointer.transform.localScale = new Vector3(thickness, thickness, dist);
  133. pointer.GetComponent<MeshRenderer>().material.color = color;
  134. }
  135. pointer.transform.localPosition = new Vector3(0f, 0f, dist / 2f);
  136. }
  137. }
  138. public struct PointerEventArgs
  139. {
  140. public SteamVR_Input_Sources fromInputSource;
  141. public uint flags;
  142. public float distance;
  143. public Transform target;
  144. }
  145. public delegate void PointerEventHandler(object sender, PointerEventArgs e);
  146. }