BunnyPlacement.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using System.Collections;
  4. using System;
  5. /// <summary>
  6. /// Handles detecting whether or not a real-world location is valid for placing a Bunny object
  7. /// in the ZED plane detection samples. To be valid, it must find a plane at the given location
  8. /// and that plane must face upward. Turns a placeholder object blue when valid, and red when not.
  9. /// Also works with VR controllers if the SteamVR or Oculus Integration plugins are installed.
  10. /// </summary>
  11. public class BunnyPlacement : MonoBehaviour
  12. {
  13. /// <summary>
  14. /// Textures assigned to the placeholder object when placement is valid.
  15. /// Index of each texture corresponds to the index of the material on the placeholder object.
  16. /// </summary>
  17. [Tooltip("Textures assigned to the placeholder object when placement is valid. " +
  18. "Index of each texture corresponds to the index of the material on the placeholder object.")]
  19. public Texture[] goodPlacementTex;
  20. /// <summary>
  21. /// Textures assigned to the placeholder object when placement is not valid.
  22. /// Index of each texture corresponds to the index of the material on the placeholder object.
  23. /// </summary>
  24. [Tooltip("Textures assigned to the placeholder object when placement is not valid. " +
  25. "Index of each texture corresponds to the index of the material on the placeholder object.")]
  26. public Texture[] badPlacementTex;
  27. /// <summary>
  28. /// Light object in the placeholder object. We change its color based on placement validity.
  29. /// </summary>
  30. private Light pointlight;
  31. /// <summary>
  32. /// The ZEDControllerTracker object in the VR controller used to place the object, if applicable.
  33. /// </summary>
  34. private ZEDControllerTracker_DemoInputs tracker;
  35. /// <summary>
  36. /// The scene's ZED Plane Detection Manager.
  37. /// </summary>
  38. private ZEDPlaneDetectionManager zedPlane;
  39. /// <summary>
  40. /// The BunnySpawner object, normally on the same object as this component.
  41. /// </summary>
  42. private BunnySpawner bunnySpawner;
  43. /// <summary>
  44. /// The placeholder object's transform.
  45. /// </summary>
  46. private Transform placeholder;
  47. /// <summary>
  48. /// Whether or not we are able to spawn a bunny here.
  49. /// </summary>
  50. private bool canspawnbunny;
  51. /// <summary>
  52. /// Possible states of the button used for input, whether the spacebar, a VR controller trigger, etc.
  53. /// </summary>
  54. public enum state
  55. {
  56. Idle,
  57. Down,
  58. Press,
  59. Up
  60. };
  61. /// <summary>
  62. /// The current state of the button used for input.
  63. /// </summary>
  64. public state button { get; private set; }
  65. /// <summary>
  66. /// Awake is used to initialize any variables or game state before the game starts.
  67. /// </summary>
  68. void Awake()
  69. {
  70. canspawnbunny = false;
  71. tracker = GetComponent<ZEDControllerTracker_DemoInputs>();
  72. zedPlane = FindObjectOfType<ZEDPlaneDetectionManager>();
  73. bunnySpawner = GetComponent<BunnySpawner>();
  74. }
  75. /// <summary>
  76. /// Sets a reference to the placeholder object. Set from BunnySpawner.cs.
  77. /// </summary>
  78. /// <param name="pointer">The placeholder object.</param>
  79. public void SetPlaceholder(Transform pointer)
  80. {
  81. placeholder = pointer;
  82. pointlight = pointer.GetChild(0).GetComponentInChildren<Light>();
  83. }
  84. /// <summary>
  85. /// Update is called every frame.
  86. /// Here we receive the input from the Controller.
  87. /// Then we decide what to do in each case.
  88. /// </summary>
  89. private void Update()
  90. {
  91. if (tracker == null)
  92. {
  93. if (Input.GetKeyDown(KeyCode.Space))
  94. button = state.Down;
  95. else if (Input.GetKey(KeyCode.Space))
  96. button = state.Press;
  97. else if (Input.GetKeyUp(KeyCode.Space))
  98. button = state.Up;
  99. else
  100. button = state.Idle;
  101. }
  102. else
  103. {
  104. if (tracker.CheckClickButton(ControllerButtonState.Down))
  105. button = state.Down;
  106. else if (tracker.CheckClickButton(ControllerButtonState.Held))
  107. button = state.Press;
  108. else if (tracker.CheckClickButton(ControllerButtonState.Up))
  109. button = state.Up;
  110. else button = state.Idle;
  111. }
  112. //If the Trigger Button is being used.
  113. if (button != state.Idle)
  114. {
  115. //It just got pressed.
  116. if (button == state.Down)
  117. {
  118. //Enable the bunnySpawner to display the placeholder.
  119. bunnySpawner.canDisplayPlaceholder = true;
  120. //If we were holding the baseball bat but the user wants to re-place the bunny, hide the baseball bat.
  121. if (bunnySpawner.baseballBat != null)
  122. bunnySpawner.baseballBat.SetActive(false);
  123. //Clean up the list of detected planes.
  124. if (zedPlane.hitPlaneList.Count > 0)
  125. {
  126. for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
  127. {
  128. Destroy(zedPlane.hitPlaneList[i].gameObject);
  129. zedPlane.hitPlaneList.RemoveAt(i);
  130. }
  131. }
  132. //Destroy the current Bunny, if any, on the scene.
  133. if (!bunnySpawner.canSpawnMultipleBunnies && bunnySpawner.currentBunny != null)
  134. {
  135. Destroy(bunnySpawner.currentBunny);
  136. bunnySpawner.currentBunny = null;
  137. }
  138. }
  139. //From the first input to the next ones as it keeps being hold down.
  140. if (button == state.Press || button == state.Down)
  141. {
  142. if (zedPlane.hitPlaneList.Count == 0)
  143. {
  144. //Start detecting planes through the ZED Plane Detection Manager.
  145. foreach (ZEDManager manager in ZEDManager.GetInstances()) //Check all active ZED cameras for planes.
  146. {
  147. if (zedPlane.DetectPlaneAtHit(manager, manager.GetMainCamera().WorldToScreenPoint(placeholder.position)))
  148. {
  149. //Get the normal of the plane.
  150. ZEDPlaneGameObject currentPlane = zedPlane.hitPlaneList[zedPlane.hitPlaneList.Count - 1];
  151. Vector3 planeNormal = currentPlane.worldNormal;
  152. //Check if the plane has a normal close enough to Y (horizontal surface) to be stable for the Bunny to spawn into.
  153. if (Vector3.Dot(planeNormal, Vector3.up) > 0.85f)
  154. {
  155. //Allow spawning the Bunny, and set the placeholder to a positive color.
  156. if (canspawnbunny == false)
  157. {
  158. canspawnbunny = true;
  159. bunnySpawner.placeHolderMat[0].mainTexture = goodPlacementTex[0];
  160. bunnySpawner.placeHolderMat[1].mainTexture = goodPlacementTex[1];
  161. pointlight.color = Color.blue;
  162. }
  163. else //Clear the list of planes.
  164. {
  165. for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
  166. {
  167. if (i == 0)
  168. {
  169. Destroy(zedPlane.hitPlaneList[i].gameObject);
  170. zedPlane.hitPlaneList.RemoveAt(i);
  171. }
  172. }
  173. }
  174. }
  175. else //Surface wasn't horizontal enough
  176. {
  177. //Don't allow the Bunny to spawn, and set the placeholder to a negative color.
  178. canspawnbunny = false;
  179. bunnySpawner.placeHolderMat[0].mainTexture = badPlacementTex[0];
  180. bunnySpawner.placeHolderMat[1].mainTexture = badPlacementTex[1];
  181. pointlight.color = Color.red;
  182. //Clear the list of planes.
  183. for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
  184. {
  185. Destroy(zedPlane.hitPlaneList[i].gameObject);
  186. zedPlane.hitPlaneList.RemoveAt(i);
  187. }
  188. }
  189. break; //If we detected a plane in one view, no need to go through the rest of the cameras.
  190. }
  191. }
  192. }
  193. else if (zedPlane.hitPlaneList.Count > 0)
  194. {
  195. if (!Physics.Raycast(transform.position, placeholder.position - transform.position))
  196. {
  197. //Don't allow for the Bunny to spawn, and set the placeholder to a negative color.
  198. canspawnbunny = false;
  199. bunnySpawner.placeHolderMat[0].mainTexture = badPlacementTex[0];
  200. bunnySpawner.placeHolderMat[1].mainTexture = badPlacementTex[1];
  201. pointlight.color = Color.red;
  202. //Clear the list of planes.
  203. for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
  204. {
  205. Destroy(zedPlane.hitPlaneList[i].gameObject);
  206. zedPlane.hitPlaneList.RemoveAt(i);
  207. }
  208. }
  209. }
  210. }
  211. //Button is released.
  212. if (button == state.Up)
  213. {
  214. //If at that moment the bunny was allowed to spawn, proceed ot make the call.
  215. if (canspawnbunny)
  216. {
  217. bunnySpawner.SpawnBunny(placeholder.position);
  218. }
  219. else //Clear the list of planes.
  220. {
  221. for (int i = 0; i < zedPlane.hitPlaneList.Count; i++)
  222. {
  223. Destroy(zedPlane.hitPlaneList[i].gameObject);
  224. zedPlane.hitPlaneList.RemoveAt(i);
  225. }
  226. }
  227. //Reset the booleans.
  228. canspawnbunny = false;
  229. bunnySpawner.canDisplayPlaceholder = false;
  230. }
  231. }
  232. }
  233. }