Advertisement
Guest User

Untitled

a guest
May 25th, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.89 KB | None | 0 0
  1. using UnityEngine;
  2. using System;
  3. using UnityEngine.EventSystems;
  4. using HoloToolkit.Unity.InputModule;
  5. using Random = System.Random;
  6. using UnityEngine.UI;
  7.  
  8. public class USIManipulation : MonoBehaviour, IInputClickHandler
  9. {
  10. //Initializations
  11. public static USIManipulation Instance { get; private set; }
  12. public object Wait { get; private set; }
  13. public GameObject FocusedObject;
  14. public Text changingText;
  15. /* The variables are used to store the values of the point where the surgeon is taping, first and second as variables used to create the primitives
  16. and cursor point is used during the rendering of the line to show the point of the position of the cursor in real time*/
  17. public Vector3 hitInfoPoint, hitInfoPointFirst, hitInfoPointSecond, cursorPoint;
  18. /* Creating objects for the line renderer, points that are going to be displayed, cursor(in order to read its position) and raycast variable that is
  19. going to help us determine where's the gaze of the surgeon*/
  20. private LineRenderer[] lineRenderer = new LineRenderer[2];
  21. public GameObject[] sphere = new GameObject[4];
  22. public GameObject InteractiveMeshCursor;
  23. public RaycastHit hitInfo;
  24. private int cnt = 0;
  25. public int orderOfPrimitives = 0;
  26. int linecount;
  27. /* Variables that are going to be used to create the line renderer dueing real time rendering*/
  28. private Vector3? lineStartPoint = null, lineEndPoint = null;
  29. private bool selected = false;
  30. public Material lineMaterial;
  31. GameObject SecondLine;
  32. /*We use this variables in order to create the taping logic since the counter logic turned out to have a lot of ambiguities
  33. the start variable is set true once the start button is pressed and it represents that the surgeon whants to start the selection
  34. of the points. The end variable is set true once the surgeon has ended the selection of the points. The variables first point
  35. and second point are used as restrictive safety mesurement just to make sure that he has clicked once (first point created), and
  36. that he clicked twice (second point created). The variables fp abriviated for first point, and sp abriviated as second point are
  37. used as part of the function LineRendering and represent the starting and ending position of the line. The variable current point
  38. is used as a bool variable that shows us if the surgeon is working with the first pair points or just with the secon pair of points*/
  39. bool start = false, end = false, firstPoint = false, secondPoint = false, adjust = false, secondSelection=false;
  40. enum Points { fp = 1, sp = 2 };
  41. int currentPoint = 0;
  42.  
  43. /* This two variables are used to display the poping up menu which is a safety measure in order to avoid sudden (unwanted) clicks*/
  44. public GameObject menuButton, endSelectionButton, keepPointsButton, adjustPointsButton, startSelectionButton, deletePointsButton, lineLength;
  45. /*Once the surgeon clicks the start procedure button we set the start variable to true which means the procedure has started,
  46. and just to be on the safe side we set the end procedure to false */
  47. public void Start()
  48. {
  49.  
  50. startSelectionButton.SetActive(true);
  51. //startSelectionButton.GetComponent<Renderer>().material.color = Color.green;
  52. }
  53. public void StartProcedure()
  54. {
  55. start = true;
  56. end = false;
  57. adjust = false;
  58.  
  59. startSelectionButton.SetActive(false);
  60. adjustPointsButton.SetActive(false);
  61. lineLength.SetActive(true);
  62. }
  63. /*Once the surgeon clicks the end procedure button we set the end variable to true which means the procedure has stopped,
  64. and further instructions on the menu are expected, we set the start, restart our counter that counts the two clicks and the first point
  65. since there is possibilitiy that he wants to select again*/
  66. /*public void EndProcedure()
  67. {
  68. end = true;
  69. cnt = 0;
  70. start = false;
  71. firstPoint = false;
  72. selected = true;
  73. adjust = false;
  74.  
  75. endSelectionButton.SetActive(false);
  76. keepPointsButton.SetActive(true);
  77. deletePointsButton.SetActive(true);
  78. lineLength.SetActive(false);
  79. //keepPointsButton.GetComponent<Renderer>().material.color = Color.green;
  80. //deletePointsButton.GetComponent<Renderer>().material.color = Color.green;
  81.  
  82. }*/
  83. /*Activate a poping-up menu as soon as the keep points button is pressed*/
  84. /*public void KeepPoints()
  85. {
  86. menuButton2.SetActive(true);
  87. }
  88. */
  89. /*If the user choses yes from the poping menu, then set that the first pair is selected succesfuly and set the variable
  90. current point to 1, start to false, and selected to false in order to enable the surgeon to select another two points (if there is necessatiy for it), close the
  91. pop up menu*/
  92. public void KeepPointsYes()
  93. {
  94. currentPoint = 1;
  95. selected = false;
  96. start = false;
  97. secondPoint = false;
  98. //menuButton2.SetActive(false);
  99. keepPointsButton.SetActive(false);
  100. deletePointsButton.SetActive(false);
  101. startSelectionButton.SetActive(true);
  102. lineLength.SetActive(false);
  103. adjustPointsButton.SetActive(true);
  104. //startSelectionButton.GetComponent<Renderer>().material.color = Color.green;
  105. }
  106. public void AdjustPoints()
  107. {
  108. adjust = true;
  109. adjustPointsButton.SetActive(false);
  110. startSelectionButton.SetActive(true);
  111. lineLength.SetActive(true);
  112. //keepPointsButton.GetComponent<Renderer>().material.color = Color.green;
  113. if(secondSelection)
  114. { deletePointsButton.SetActive(true); startSelectionButton.SetActive(false); }
  115.  
  116. }
  117. public void PrimitivesConstrain(GameObject gameObject)
  118. {
  119. ;
  120. }
  121.  
  122. /*Activate a poping-up menu as soon as the delete points button is pressed*/
  123. public void DeletePoints()
  124. {
  125. menuButton.SetActive(true);
  126. }
  127. /*If no is selected then just close the pop up menu*/
  128. public void DeletePointsNo()
  129. {
  130. menuButton.SetActive(false);
  131. }
  132.  
  133. /*Arrays of colors that are going to be used further as materials for our game objects*/
  134. private Color[] colorCode =
  135. {
  136. new Color(1.0f,0.0f,0.0f,1.0f),
  137. new Color(1.0f,0.5f,0.0f,1.0f),
  138. new Color(1.0f,1.0f,0.0f,1.0f),
  139. new Color(0.5f,1.0f,0.0f,1.0f),
  140. new Color(0.0f,1.0f,0.0f,1.0f),
  141. new Color(0.0f,1.0f,0.5f,1.0f),
  142. new Color(0.0f,1.0f,1.0f,1.0f),
  143. new Color(0.0f,0.5f,1.0f,1.0f),
  144. new Color(0.0f,0.0f,1.0f,1.0f),
  145. new Color(0.5f,0.0f,1.0f,1.0f),
  146. new Color(1.0f,0.0f,1.0f,1.0f),
  147. new Color(1.0f,0.0f,0.5f,1.0f),
  148. };
  149.  
  150. //Gesture and Gaze Coordination
  151. public void Update()
  152. {
  153. GameObject oldFocusObject;
  154. var headPosition = Camera.main.transform.position;
  155. var gazeDirection = Camera.main.transform.forward;
  156. int layerMask1 = 1 << 10;
  157. /* We have our US image on a separate layer so if the raycast hits that layer only in that case
  158. make the necessary changes. If the gaze is on the object and colides with the image take info
  159. about the point of collision and set it as the current cursor point. If not make the object null (no hit)
  160. If the object is hit and the user tapped, take that as the first point for further processing.
  161. If he already tapped create the primitive and start seting the value of the gaze in the second point.*/
  162. if (Physics.Raycast(headPosition, gazeDirection, out hitInfo, Mathf.Infinity, layerMask1))
  163. {
  164. oldFocusObject = hitInfo.collider.gameObject;
  165. hitInfoPoint = hitInfo.point;
  166. cursorPoint = InteractiveMeshCursor.transform.position;
  167. }
  168. else { oldFocusObject = null; }
  169.  
  170. if (oldFocusObject != null && cnt == 0) { hitInfoPointFirst = hitInfo.point; }
  171. else if (oldFocusObject != null && cnt == 1)
  172. {
  173. if (!adjust)
  174. { GetPoints(cnt); hitInfoPointSecond = hitInfo.point; }
  175.  
  176. }
  177. /* If the coursor is on the right layer and the adjust button is clicked then we check which one of the points
  178. is being draged and adjusted. We start re-rendering the line with the new primitive position and also we canghe the text (length of the line).
  179. which is encapsulated in two functions down below*/
  180. if (Physics.Raycast(headPosition, gazeDirection, out hitInfo, Mathf.Infinity, layerMask1) && adjust)
  181. {
  182.  
  183. if ((currentPoint == 0 || currentPoint==1) && sphere[0].GetComponent<HandDraggable>().IsDraggingEnabled)
  184. {
  185. AdjustableFirstPoint(0, 0);
  186. }
  187. if ((currentPoint == 0 || currentPoint==1) && sphere[1].GetComponent<HandDraggable>().IsDraggingEnabled)
  188. {
  189. AdjustableSecondPoint(1, 0);
  190. }
  191. if ((secondSelection) && sphere[2].GetComponent<HandDraggable>().IsDraggingEnabled && sphere[2]!=null)
  192. {
  193. AdjustableFirstPoint(2, 1);
  194. }
  195. if (secondSelection && sphere[3].GetComponent<HandDraggable>().IsDraggingEnabled && sphere[3]!=null)
  196. {
  197. AdjustableSecondPoint(3, 1);
  198. }
  199.  
  200. }
  201. }
  202. public void AdjustableFirstPoint(int i, int j)
  203. {
  204. lineRenderer[j].SetPositions(new Vector3[] { sphere[i].GetComponent<HandDraggable>().HostTransform.position, sphere[i + 1].transform.position });
  205. float distance = Vector3.Distance(sphere[i].GetComponent<HandDraggable>().HostTransform.position, sphere[i + 1].transform.position);
  206. changingText.text = distance.ToString();
  207. }
  208.  
  209. public void AdjustableSecondPoint(int i, int j)
  210. {
  211. lineRenderer[j].SetPositions(new Vector3[] { sphere[i - 1].transform.position, sphere[i].GetComponent<HandDraggable>().HostTransform.position });
  212. float distance = Vector3.Distance(sphere[i - 1].transform.position, sphere[i].GetComponent<HandDraggable>().HostTransform.position);
  213. changingText.text = distance.ToString();
  214. }
  215. /* Line count is a variable that shows if we are doing real time rendering (when it has value zero) or we fix the line (when it has value 1)
  216. for the second line (or so called fixed line) we use second line renderer which we have under the empty object called Second line*/
  217. public void LineRendering(Vector3 sp, Vector3 ep)
  218. {
  219. Random random = new Random();
  220. int num = random.Next(0, 11);
  221. if (currentPoint == 0)
  222. {
  223. linecount = 0;
  224. lineRenderer[linecount] = GetComponent<LineRenderer>();
  225. lineRenderer[linecount].material.color = Color.red;
  226. }
  227. else if (currentPoint == 1)
  228. {
  229. linecount = 1;
  230. SecondLine = GameObject.Find("SecondLine"); lineRenderer[linecount] = SecondLine.GetComponent<LineRenderer>();
  231. lineRenderer[linecount].material.color = Color.green;
  232. }
  233. lineRenderer[linecount].SetWidth(.01f, .01f);
  234. lineRenderer[linecount].SetPositions(new Vector3[] { sp, ep });
  235.  
  236. float distance = Vector3.Distance(sp, ep);
  237. changingText.text = distance.ToString();
  238. }
  239. /* This function deals with the points that are going to be send to the renderer if the value of point count is one it means the user
  240. already fixed the first point and we have to render between that point and the gaze (cursor position). If the count is two it means he already
  241. fixed the secon point so our line has to be fixed between the first and the second point. */
  242. public void GetPoints(int pointcount)
  243. {
  244. switch (pointcount)
  245. {
  246. case 1:
  247. lineStartPoint = hitInfoPointFirst;
  248. lineEndPoint = cursorPoint;
  249. LineRendering(lineStartPoint.Value, lineEndPoint.Value);
  250.  
  251. break;
  252. case 2:
  253. lineStartPoint = hitInfoPointFirst;
  254. lineEndPoint = hitInfoPointSecond;
  255. LineRendering(lineStartPoint.Value, lineEndPoint.Value);
  256. break;
  257.  
  258. }
  259. }
  260.  
  261. /* This function incorporates the Hololens function tap. As previously mentioned we only want to select on the certain
  262. layer and therefore we set the layer 10 where our image is assigned. If start is clicked, we haven't had first point before (as safety measure)
  263. if the counter is zero (no tap on the image) and selected is zero then it means he is going to start the first selection. Similar logic for the
  264. second point. Other than that just wrong clicks (that are not going to be taken into account). */
  265.  
  266. public void OnInputClicked(InputClickedEventData eventData)
  267. {
  268. int layerMask = 1 << 10;
  269. if (Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hitInfo, Mathf.Infinity, layerMask))
  270. {
  271. if (start && (!firstPoint) && (!end) && !(Convert.ToBoolean(cnt)) && !selected && !adjust)
  272. {
  273. cnt++;
  274. firstPoint = true;
  275. if (currentPoint == 0) { CreatePrimitiveFP(cnt - 1); }
  276. else if (currentPoint == 1) { CreatePrimitiveFP(cnt + 1); }
  277. }
  278.  
  279. else if (start && firstPoint && (!end) && !adjust)
  280. {
  281. cnt++;
  282. if (currentPoint == 0) { CreatePrimitiveFP(cnt - 1); GetPoints(cnt); }
  283. else if (currentPoint == 1) { CreatePrimitiveFP(cnt + 1); GetPoints(cnt); }
  284. firstPoint = false;
  285. secondPoint = true;
  286.  
  287. end = true;
  288. cnt = 0;
  289. start = false;
  290. firstPoint = false;
  291. selected = true;
  292. adjust = false;
  293. if(currentPoint==1) {secondSelection = true;}
  294. deletePointsButton.SetActive(true);
  295. lineLength.SetActive(false);
  296. keepPointsButton.SetActive(true);
  297. }
  298. /*else if ((secondPoint && firstPoint) || (!secondPoint && !firstPoint) || (!start && !end) || (!start && end))
  299. {
  300. cnt = 0;
  301. }*/
  302. }
  303. }
  304.  
  305.  
  306. /* This function helps the user create the primitives (points) on the image. Also we assign specific layer (the same one as the US image) in order to be able to
  307. manipulate the primitives when necessary. In order to be able to adjust them once they are created we add box colider component and we add the "Hand Draggable Script"
  308. to the new created object*/
  309.  
  310. public void CreatePrimitiveFP(int primitiveOrder)
  311. {
  312. Random random = new Random();
  313. int num = random.Next(0, 11);
  314. sphere[primitiveOrder] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  315. sphere[primitiveOrder].layer = 10;
  316. sphere[primitiveOrder].GetComponent<Renderer>().material.color = colorCode[num];
  317. sphere[primitiveOrder].transform.localScale = new Vector3(0.09f, 0.09f, 0.09f);
  318. sphere[primitiveOrder].transform.position = hitInfoPoint;
  319. sphere[primitiveOrder].layer = 10;
  320. sphere[primitiveOrder].AddComponent<BoxCollider>();
  321. sphere[primitiveOrder].AddComponent<HandDraggable>();
  322.  
  323. }
  324.  
  325. /* This function is called if YES is pressed on the delete points button, or NO on the keep points button and what it does is
  326. turns off the poping menues, and deletes the points, and doesn't delete the line renderer but resets it (because if we destroy it
  327. we are not able to restore it afterwards).*/
  328. public void DeleteObjects(bool value)
  329. {
  330. for (int i = 0; i < 2; i++)
  331. {
  332. if (!value)
  333. {
  334. keepPointsButton.SetActive(false);
  335. startSelectionButton.SetActive(true);
  336. Destroy(sphere[i]);
  337. if (i == 0) { lineRenderer[i].SetPosition(0, Vector3.zero); lineRenderer[i].SetPosition(1, Vector3.zero); }
  338. }
  339. else if (value)
  340. {
  341. keepPointsButton.SetActive(true);
  342. deletePointsButton.SetActive(true);
  343. Destroy(sphere[i + 2]);
  344. if (i == 1)
  345. {
  346. lineRenderer[i].SetPosition(0, Vector3.zero); lineRenderer[i].SetPosition(1, Vector3.zero); secondSelection = false; currentPoint = 0;
  347. }
  348. }
  349. }
  350. }
  351.  
  352. public void DestroyPrimitives()
  353. {
  354. menuButton.SetActive(false);
  355. //menuButton2.SetActive(false);
  356. lineLength.SetActive(false);
  357. deletePointsButton.SetActive(false);
  358. firstPoint = false;
  359. start = false;
  360. end = true;
  361. cnt = 0;
  362. adjust = false;
  363. selected = false;
  364. DeleteObjects(secondSelection);
  365. }
  366.  
  367. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement