ZEDTransformController.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /// <summary>
  5. /// Moves/rotates the attached object using the keyboard or, if the
  6. /// Oculus/SteamVR plugins are imported, by buttons on the VR controllers.
  7. /// To use VR controllers, you must also have a ZEDControllerTracker component in the scene
  8. /// that's set to track the controller you want to use.
  9. /// Used in the ZED Planetarium and Movie Screen example scenes to move the solar system/screen.
  10. /// </summary>
  11. public class ZEDTransformController : MonoBehaviour
  12. {
  13. //Public variables
  14. /// <summary>
  15. /// Rotational reference point for moving forward, backward, left, right, etc.
  16. /// </summary>
  17. [Header("Object motion relative to:")]
  18. [Tooltip("Rotational reference point for moving forward, backward, left, right, etc.")]
  19. public RelativeMotion motion;
  20. /// <summary>
  21. /// Whether to rotate in the opposite direction specified, eg rotating 'right' means counter-clockwise.
  22. /// </summary>
  23. [Tooltip("Whether to rotate in the opposite direction specified, eg rotating 'right' means counter-clockwise.")]
  24. public bool invertRotation;
  25. /// <summary>
  26. /// If true, the object will teleport to a meter in front of the ZED once it's finished initializing.
  27. /// </summary>
  28. [Tooltip("If true, the object will teleport to a meter in front of the ZED once it's finished initializing.")]
  29. public bool repositionAtStart = true;
  30. /// <summary>
  31. /// Reference to the scene's ZEDManager component.
  32. /// Used when RelativeMotion is set to Camera, for finding the current position of the ZED.
  33. /// </summary>
  34. [Tooltip("Reference to the scene's ZEDManager component. Used when RelativeMotion is set to Camera, " +
  35. "and also for positioning it at start. If left blank, the first ZED camera indexed will be set.")]
  36. public ZEDManager zedManager = null;
  37. /// <summary>
  38. /// How fast the object moves/translates, in meters per second.
  39. /// </summary>
  40. [Space(5)]
  41. [Header("Motion Options")]
  42. [Tooltip("How fast the object moves/translates, in meters per second. ")]
  43. public float movementSpeed = 0.5F;
  44. /// <summary>
  45. /// How fast the object rotates, in revolutions per second.
  46. /// </summary>
  47. [Tooltip("How fast the object rotates, in revolutions per second.")]
  48. public float rotationSpeed = 0.1f;
  49. /// <summary>
  50. /// How quickly an object gets bigger or smaller.
  51. /// Scale increases/decreases by this factor every second.
  52. /// </summary>
  53. [Tooltip("How quickly an object gets bigger or smaller. Scale increases/decreases by this factor every second.")]
  54. public float scaleSpeed = 0.25F;
  55. /// <summary>
  56. /// The largest amount to which the object can scale.
  57. /// </summary>
  58. [Tooltip("The largest amount to which the object can scale.")]
  59. public float maxScale = 2.0F;
  60. /// <summary>
  61. /// The smallest amount down to which the object can scale.
  62. /// </summary>
  63. [Tooltip("The smallest amount down to which the object can scale. ")]
  64. public float minScale = 0.25F;
  65. /// <summary>
  66. /// Optional reference to a light that is enabled only when moving.
  67. /// Used in the ZED Movie Screen sample to project a light underneath the screen when moved.
  68. /// </summary>
  69. [Space(5)]
  70. [Tooltip("Optional reference to a light that is enabled only when moving.")]
  71. public Light spotLight;
  72. //Private variables
  73. /// <summary>
  74. /// List of all ZEDControllerTrackers in the scene. Used to get input in an SDK/agnostic way.
  75. /// </summary>
  76. private List<ZEDControllerTracker_DemoInputs> objectTrackers = new List<ZEDControllerTracker_DemoInputs>();
  77. /// <summary>
  78. /// Left Camera component in the ZED rig, that represents the ZED's left sensor.
  79. /// Used when RelativeMotion is set to Camera for providing relative values.
  80. /// </summary>
  81. private Camera leftCamera;
  82. /// <summary>
  83. /// Whether the object is moving/translating.
  84. /// </summary>
  85. private bool isMoving;
  86. private IEnumerator Start()
  87. {
  88. isMoving = false;
  89. if (!zedManager)
  90. {
  91. zedManager = FindObjectOfType<ZEDManager>();
  92. if (ZEDManager.GetInstances().Count > 1) //They let the plugin auto-assign a ZED but there are multiple ZED's. Warn the user.
  93. {
  94. Debug.Log("Warning: ZEDTransformController's zedManager field was not specified, but there are multiple ZEDManagers in the scene " +
  95. "so first available ZED was assigned. This can cause the object to move relative to the wrong camera. " +
  96. "It's recommended to assign the desired ZEDManager in the Inspector.");
  97. }
  98. }
  99. //Find the available VR controllers and assigning them to our List.
  100. yield return new WaitForSeconds(1f);
  101. var trackers = FindObjectsOfType<ZEDControllerTracker>();
  102. foreach (ZEDControllerTracker_DemoInputs tracker in trackers)
  103. {
  104. objectTrackers.Add(tracker);
  105. }
  106. if (repositionAtStart) //If the user wants, move the object in front of the ZED once it's initialized.
  107. {
  108. zedManager.OnZEDReady += RepositionInFrontOfZED;
  109. }
  110. }
  111. private void Update()
  112. {
  113. Vector3 moveAxis = Vector3.zero; //Translation. Used by keyboard only.
  114. float inputRotation = 0f; //Applied rotation, between -1 and 1. Cumulative between keyboard and controllers.
  115. float inputScale = 0f; //Applied scale change, either -1, 0 or 1. Cumulative between keyboard and controllers.
  116. //Keyboard inputs.
  117. if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.Q))
  118. {
  119. inputRotation = -1 * (rotationSpeed * 360) * Time.deltaTime;
  120. }
  121. if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.E))
  122. {
  123. inputRotation = 1 * (rotationSpeed * 360) * Time.deltaTime;
  124. }
  125. if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))
  126. {
  127. moveAxis = Vector3.forward * movementSpeed * Time.deltaTime;
  128. }
  129. if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S))
  130. {
  131. moveAxis = Vector3.back * movementSpeed * Time.deltaTime;
  132. }
  133. if (Input.GetKey(KeyCode.A))
  134. {
  135. moveAxis = Vector3.left * movementSpeed * Time.deltaTime;
  136. }
  137. if (Input.GetKey(KeyCode.D))
  138. {
  139. moveAxis = Vector3.right * movementSpeed * Time.deltaTime;
  140. }
  141. if (Input.GetKey(KeyCode.R))
  142. {
  143. moveAxis = Vector3.up * movementSpeed * Time.deltaTime;
  144. }
  145. if (Input.GetKey(KeyCode.F))
  146. {
  147. moveAxis = Vector3.down * movementSpeed * Time.deltaTime;
  148. }
  149. Quaternion gravity = Quaternion.identity;
  150. if (moveAxis != Vector3.zero)
  151. {
  152. isMoving = true;
  153. if (motion == RelativeMotion.Itself)
  154. {
  155. transform.Translate(moveAxis.x, moveAxis.y, moveAxis.z);
  156. }
  157. else if (motion == RelativeMotion.Camera)
  158. {
  159. gravity = Quaternion.FromToRotation(zedManager.GetZedRootTansform().up, Vector3.up);
  160. transform.localPosition += zedManager.GetMainCameraTransform().right * moveAxis.x;
  161. transform.localPosition += zedManager.GetMainCameraTransform().forward * moveAxis.z;
  162. transform.localPosition += gravity * zedManager.GetMainCameraTransform().up * moveAxis.y;
  163. }
  164. }
  165. else
  166. {
  167. isMoving = false;
  168. }
  169. if (Input.GetKey(KeyCode.Mouse0))
  170. inputScale = 1f;
  171. else if (Input.GetKey(KeyCode.Mouse1))
  172. inputScale = -1f;
  173. if (zedManager)
  174. {
  175. Vector3 moveaxis = new Vector3(); //Position change by controller. Added to keyboard version if both are applied.
  176. //Looks for any input from this controller through SteamVR.
  177. //Left controller controls rotation and increasing scale.
  178. if (objectTrackers.Count > 0)
  179. {
  180. moveaxis = objectTrackers[0].CheckNavigateUIAxis();
  181. if (Mathf.Abs(moveaxis.x) < 0.1f) moveaxis.x = 0; //Add slight deadzone.
  182. if (Mathf.Abs(moveaxis.y) < 0.1f) moveaxis.y = 0;
  183. inputRotation += moveaxis.x * rotationSpeed * 360f * Time.deltaTime;
  184. gravity = Quaternion.FromToRotation(zedManager.GetZedRootTansform().up, Vector3.up);
  185. transform.localPosition += gravity * zedManager.GetMainCameraTransform().up * moveaxis.y * movementSpeed * Time.deltaTime;
  186. if (objectTrackers[0].CheckClickButton(ControllerButtonState.Held))
  187. {
  188. inputScale = 1f;
  189. }
  190. }
  191. //Right controller controls translation and lowering scale.
  192. if (objectTrackers.Count > 1)
  193. {
  194. moveaxis = objectTrackers[1].CheckNavigateUIAxis();
  195. if (Mathf.Abs(moveaxis.x) < 0.1f) moveaxis.x = 0; //Add slight deadzone.
  196. if (Mathf.Abs(moveaxis.y) < 0.1f) moveaxis.y = 0;
  197. if (moveaxis.x != 0 || moveaxis.y != 0)
  198. {
  199. isMoving = true;
  200. gravity = Quaternion.FromToRotation(zedManager.GetZedRootTansform().up, Vector3.up);
  201. transform.localPosition += zedManager.GetMainCameraTransform().right * moveaxis.x * movementSpeed * Time.deltaTime;
  202. transform.localPosition += gravity * zedManager.GetMainCameraTransform().forward * moveaxis.y * movementSpeed * Time.deltaTime;
  203. }
  204. else
  205. isMoving = false;
  206. if (objectTrackers[1].CheckClickButton(ControllerButtonState.Held))
  207. {
  208. inputScale = -1f;
  209. }
  210. }
  211. }
  212. //Rotation
  213. float h = inputRotation;
  214. if (invertRotation)
  215. transform.Rotate(0, h, 0);
  216. else
  217. transform.Rotate(0, -h, 0);
  218. //Scale
  219. float s = scaleSpeed * (inputScale * Time.deltaTime);
  220. transform.localScale = new Vector3(transform.localScale.x + s,
  221. transform.localScale.y + s,
  222. transform.localScale.z + s);
  223. if (transform.localScale.x > maxScale)
  224. transform.localScale = new Vector3(maxScale, maxScale, maxScale);
  225. else if (transform.localScale.x < minScale)
  226. transform.localScale = new Vector3(minScale, minScale, minScale);
  227. //Enable/disable light if moving.
  228. if (spotLight != null)
  229. {
  230. SetMovementLight();
  231. }
  232. }
  233. /// <summary>
  234. /// Turns the optional spotLight on or off depending on if the object is moving/translating.
  235. /// Also scales the light to match the object's own scale.
  236. /// </summary>
  237. void SetMovementLight()
  238. {
  239. //Enable/disable Light if the object is moving.
  240. if (!spotLight.enabled && isMoving)
  241. {
  242. spotLight.enabled = true;
  243. }
  244. else if (spotLight.enabled && !isMoving)
  245. {
  246. spotLight.enabled = false;
  247. }
  248. //Scale light with object size.
  249. if (spotLight.enabled && spotLight.type == LightType.Spot)
  250. {
  251. spotLight.spotAngle = transform.localScale.x * 180 * 2;
  252. spotLight.range = transform.localScale.x * 4f;
  253. if (spotLight.range > 2)
  254. spotLight.range = 2;
  255. }
  256. }
  257. /// <summary>
  258. /// Repositions the object to a meter in front of the ZED.
  259. /// Called by ZEDManager.OnZEDReady if repositionAtStart is enabled.
  260. /// </summary>
  261. void RepositionInFrontOfZED()
  262. {
  263. //If the ZEDManager uses Estimate Initial Position and tracking, then the position will change shortly after OnZEDReady.
  264. //We'll make a non-async call to EstimateInitialPosition to determine what the angle will be.
  265. if (zedManager.estimateInitialPosition && zedManager.enableTracking)
  266. {
  267. Vector3 initpos = Vector3.zero;
  268. Quaternion initrot = Quaternion.identity;
  269. zedManager.zedCamera.EstimateInitialPosition(ref initrot, ref initpos);
  270. transform.position = initpos + (initrot * Vector3.forward);
  271. Quaternion newRot = Quaternion.LookRotation(initpos - transform.position, Vector3.up);
  272. transform.eulerAngles = new Vector3(0, newRot.eulerAngles.y + 180, 0);
  273. }
  274. else
  275. {
  276. transform.position = zedManager.OriginPosition + zedManager.OriginRotation * (Vector3.forward);
  277. Quaternion newRot = Quaternion.LookRotation(zedManager.OriginPosition - transform.position, Vector3.up);
  278. transform.eulerAngles = new Vector3(0, newRot.eulerAngles.y + 180, 0);
  279. }
  280. //If we're going to know where the floor is, then make sure the object doesn't spawn in the floor if the user is looking down.
  281. if(zedManager.estimateInitialPosition)
  282. {
  283. if (transform.position.y < 0.5f) transform.position = new Vector3(transform.position.x, 0.5f, transform.position.z);
  284. }
  285. }
  286. IEnumerator RepositionAfterZEDReady()
  287. {
  288. for (int i = 0; i < 50; i++)
  289. {
  290. print(zedManager.GetZedRootTansform().position);
  291. yield return null;
  292. }
  293. }
  294. /// <summary>
  295. /// Options for what movement will be relevant to.
  296. /// </summary>
  297. public enum RelativeMotion
  298. {
  299. Itself, //Relative to its own rotation, eg. moving forward moves where the object is facing.
  300. Camera //Relative to the camera's rotation, eg. moving forward moves where the camera/player is facing.
  301. }
  302. }