AutoCalibBall.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /// <summary>
  5. /// Handles the clickable ball objects spawned by AutoCalibrationManager, which lets the user set reference points.
  6. /// Should be assigned to a prefab and instantiated with it.
  7. /// Also draws the current primary controller model in its center, facing the camera.
  8. /// </summary>
  9. [RequireComponent(typeof(Collider))]
  10. public class AutoCalibBall : MonoBehaviour, IXRHoverable, IXRClickable
  11. {
  12. /// <summary>
  13. /// Reference to the manager that spawned this ball. Used for reporting its real and virtual positions when assigned.
  14. /// </summary>
  15. [Tooltip("Reference to the manager that spawned this ball. Used for reporting its real and virtual positions when assigned.")]
  16. public AutoCalibrationManager autoCalib;
  17. /// <summary>
  18. /// Material used to draw the controller object each frame.
  19. /// </summary>
  20. [Space(5)]
  21. [Tooltip("Material used to draw the controller object each frame. ")]
  22. public Material controllerDrawMat;
  23. /// <summary>
  24. /// Reference to the object that's enabled when this ball has been used to add a reference point. Checkmark by default.
  25. /// </summary>
  26. [Space(5)]
  27. [Tooltip("Reference to the object that's enabled when this ball has been used to add a reference point. Checkmark by default. ")]
  28. public GameObject checkmarkDisplay;
  29. /// <summary>
  30. /// Reference to the object that's enabled before this ball has been used to add a reference point. Cross by default.
  31. /// </summary>
  32. [Tooltip("Reference to the object that's enabled before this ball has been used to add a reference point. Cross by default. ")]
  33. public GameObject crossDisplay;
  34. private DisplayState currentStage = DisplayState.Cross;
  35. private Vector3 virtualPos;
  36. private Vector3 realPos;
  37. /// <summary>
  38. /// Whether or not the user has assigned a reference using this ball. Used for display purposes.
  39. /// </summary>
  40. private bool hasBeenSet = false;
  41. /// <summary>
  42. /// Unique index of the ball, to be used to set the real and virtual positions to the proper index within AutoCalibrationManager.
  43. /// </summary>
  44. private int ballIndex;
  45. /// <summary>
  46. /// Whether or not AutoCalibrationManager has called Setup() on this object. Necessary before it can be used.
  47. /// </summary>
  48. private bool isSetup = false;
  49. private Collider col;
  50. private ZEDManager zedManager
  51. {
  52. get
  53. {
  54. return autoCalib.zedManager;
  55. }
  56. }
  57. /// <summary>
  58. /// Material applied to the outside ball when hovered over by ZEDXRGrabber. Loads one from the Resources folder if not set manually.
  59. /// </summary>
  60. [Space(5)]
  61. [Tooltip("Material applied to the outside ball when hovered over by ZEDXRGrabber. Loads one from the Resources folder if not set manually. ")]
  62. public Material hoverMaterial;
  63. private Dictionary<Renderer, Material> baseMaterials = new Dictionary<Renderer, Material>();
  64. public void Awake()
  65. {
  66. if(!hoverMaterial)
  67. {
  68. hoverMaterial = Resources.Load<Material>("HoverMatAlpha");
  69. }
  70. col = GetComponent<Collider>();
  71. col.isTrigger = true;
  72. //Make the proper overhead display appear (the checkmark or cross)
  73. SetBallStateDisplay(currentStage); //Should be NotSet.
  74. }
  75. /// <summary>
  76. /// Assigns the manager and index for this ball, both necessary before it can be used to set a reference point.
  77. /// </summary>
  78. public void Setup(AutoCalibrationManager calibmanager, int ballindex)
  79. {
  80. autoCalib = calibmanager;
  81. ballIndex = ballindex;
  82. isSetup = true;
  83. }
  84. public void Update()
  85. {
  86. //Draw the primary hand controller on the inside.
  87. SetControllerSkin skin = PrimaryHandSwitcher.primaryHandObject.GetComponentInChildren<SetControllerSkin>();
  88. if(skin != null)
  89. {
  90. Mesh mesh = skin.GetFirstControllerMesh();
  91. if (mesh)
  92. {
  93. Quaternion drawrot = Quaternion.LookRotation(zedManager.transform.position - transform.position, Vector3.up);
  94. Vector3 drawpos = transform.position - drawrot * mesh.bounds.center;
  95. controllerDrawMat.SetPass(0);
  96. Graphics.DrawMesh(mesh, drawpos, drawrot, controllerDrawMat, CameraAnchor.HIDE_FROM_ZED_LAYER);
  97. }
  98. }
  99. }
  100. public Transform GetTransform()
  101. {
  102. return transform;
  103. }
  104. /// <summary>
  105. /// Starts the process of adding a virtual and real reference point. Only called when first activated, as the collider is disabled afterward.
  106. /// </summary>
  107. /// <param name="clicker"></param>
  108. void IXRClickable.OnClick(ZEDXRGrabber clicker)
  109. {
  110. //TODO: Graphics stuff.
  111. StartCoroutine(PlacingBall(clicker));
  112. }
  113. /// <summary>
  114. /// Applies the hover material to the outside ball and temporarily hides the overhead checkmark/cross.
  115. /// </summary>
  116. void IXRHoverable.OnHoverStart()
  117. {
  118. SetBallStateDisplay(hasBeenSet ? DisplayState.Checkmark : DisplayState.Nothing);
  119. foreach (Renderer rend in GetComponentsInChildren<Renderer>()) //TODO: Lots of code repetition here. Make a static utility somewhere.
  120. {
  121. if (!baseMaterials.ContainsKey(rend))
  122. {
  123. baseMaterials.Add(rend, rend.material);
  124. }
  125. rend.material = hoverMaterial;
  126. }
  127. }
  128. /// <summary>
  129. /// Removes the hover material from the outside ball and re-enables the checkmark or cross, depending on whether it's been set up.
  130. /// </summary>
  131. void IXRHoverable.OnHoverEnd()
  132. {
  133. if (col.enabled == true)
  134. {
  135. SetBallStateDisplay(hasBeenSet ? DisplayState.Checkmark : DisplayState.Cross);
  136. }
  137. foreach (Renderer rend in GetComponentsInChildren<Renderer>())
  138. {
  139. if (baseMaterials.ContainsKey(rend))
  140. {
  141. rend.material = baseMaterials[rend];
  142. }
  143. else Debug.LogError("Starting material for " + rend.gameObject + " wasn't cached before hover started.");
  144. }
  145. }
  146. /// <summary>
  147. /// Handles the process of adding a reference point. First logs the starting point as the "virtual" point, and freezes the
  148. /// 2D video so the user can align the virtual controller with the real-world image. When they click again, this adds
  149. /// the "real" point and sends it to the AutoCalibrationManager.
  150. /// </summary>
  151. private IEnumerator PlacingBall(ZEDXRGrabber clicker)
  152. {
  153. if(!isSetup)
  154. {
  155. throw new System.Exception("Tried to use AutoCalibBall to calibrate before Setup was called on it.");
  156. }
  157. col.enabled = false;
  158. SetBallStateDisplay(DisplayState.Nothing);
  159. //Display new message.
  160. MessageDisplay.DisplayMessageAll("AUTOMATIC MODE\r\nLine up the virtual controller with its real-world counterpart. Then click again.");
  161. virtualPos = zedManager.transform.InverseTransformPoint(clicker.transform.position);
  162. //DrawOutputToPlane.pauseTextureUpdate = true; //Pause the video
  163. zedManager.pauseLiveReading = true;
  164. //TODO: Graphics stuff.
  165. //TODO: Hide all other calibration balls.
  166. //print("Paused - " + ballIndex);
  167. //First wait to make sure the click key is no longer held, so we can click it a second time separately.
  168. while (clicker.zedController.CheckClickButton(ControllerButtonState.Down))
  169. {
  170. yield return null;
  171. }
  172. //Now wait for it to go down again.
  173. while (!clicker.zedController.CheckClickButton(ControllerButtonState.Down))
  174. {
  175. yield return null;
  176. }
  177. realPos = zedManager.transform.InverseTransformPoint(clicker.transform.position);
  178. autoCalib.AddNewPositions(ballIndex, virtualPos, realPos);
  179. zedManager.pauseLiveReading = false;
  180. col.enabled = true;
  181. MessageDisplay.DisplayMessageAll("AUTOMATIC MODE\r\nRepeat this process with the rest of the balls, or stop when you're satisfied.");
  182. hasBeenSet = true;
  183. SetBallStateDisplay(DisplayState.Checkmark);
  184. }
  185. /// <summary>
  186. /// Enables/disables the overhead checkmark or cross, depending on the provided ball stage.
  187. /// </summary>
  188. /// <param name="newstage"></param>
  189. private void SetBallStateDisplay(DisplayState newstage)
  190. {
  191. switch(newstage)
  192. {
  193. case DisplayState.Cross:
  194. if (checkmarkDisplay) checkmarkDisplay.SetActive(false);
  195. if (crossDisplay) crossDisplay.SetActive(true);
  196. break;
  197. default:
  198. case DisplayState.Nothing:
  199. if (checkmarkDisplay) checkmarkDisplay.SetActive(false);
  200. if (crossDisplay) crossDisplay.SetActive(false);
  201. break;
  202. case DisplayState.Checkmark:
  203. if (checkmarkDisplay) checkmarkDisplay.SetActive(true);
  204. if (crossDisplay) crossDisplay.SetActive(false);
  205. break;
  206. }
  207. currentStage = newstage;
  208. }
  209. private void OnDestroy()
  210. {
  211. StopAllCoroutines(); //Prevents weird stuff from happening if you leave Automatic mode while adding a reference point.
  212. }
  213. /// <summary>
  214. /// Options for what to display overhead. Used by SetBallStateDisplay.
  215. /// </summary>
  216. private enum DisplayState
  217. {
  218. Nothing,
  219. Cross,
  220. Checkmark
  221. }
  222. }