Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using System;
- using UnityEngine.EventSystems;
- using HoloToolkit.Unity.InputModule;
- using Random = System.Random;
- using UnityEngine.UI;
- public class USIManipulation : MonoBehaviour, IInputClickHandler
- {
- //Initializations
- public static USIManipulation Instance { get; private set; }
- public object Wait { get; private set; }
- public GameObject FocusedObject;
- public Text changingText;
- /* 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
- and cursor point is used during the rendering of the line to show the point of the position of the cursor in real time*/
- public Vector3 hitInfoPoint, hitInfoPointFirst, hitInfoPointSecond, cursorPoint;
- /* 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
- going to help us determine where's the gaze of the surgeon*/
- private LineRenderer[] lineRenderer = new LineRenderer[2];
- public GameObject[] sphere = new GameObject[4];
- public GameObject InteractiveMeshCursor;
- public RaycastHit hitInfo;
- private int cnt = 0;
- public int orderOfPrimitives = 0;
- int linecount;
- /* Variables that are going to be used to create the line renderer dueing real time rendering*/
- private Vector3? lineStartPoint = null, lineEndPoint = null;
- private bool selected = false;
- public Material lineMaterial;
- GameObject SecondLine;
- /*We use this variables in order to create the taping logic since the counter logic turned out to have a lot of ambiguities
- the start variable is set true once the start button is pressed and it represents that the surgeon whants to start the selection
- of the points. The end variable is set true once the surgeon has ended the selection of the points. The variables first point
- and second point are used as restrictive safety mesurement just to make sure that he has clicked once (first point created), and
- that he clicked twice (second point created). The variables fp abriviated for first point, and sp abriviated as second point are
- used as part of the function LineRendering and represent the starting and ending position of the line. The variable current point
- 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*/
- bool start = false, end = false, firstPoint = false, secondPoint = false, adjust = false, secondSelection=false;
- enum Points { fp = 1, sp = 2 };
- int currentPoint = 0;
- /* This two variables are used to display the poping up menu which is a safety measure in order to avoid sudden (unwanted) clicks*/
- public GameObject menuButton, endSelectionButton, keepPointsButton, adjustPointsButton, startSelectionButton, deletePointsButton, lineLength;
- /*Once the surgeon clicks the start procedure button we set the start variable to true which means the procedure has started,
- and just to be on the safe side we set the end procedure to false */
- public void Start()
- {
- startSelectionButton.SetActive(true);
- //startSelectionButton.GetComponent<Renderer>().material.color = Color.green;
- }
- public void StartProcedure()
- {
- start = true;
- end = false;
- adjust = false;
- startSelectionButton.SetActive(false);
- adjustPointsButton.SetActive(false);
- lineLength.SetActive(true);
- }
- /*Once the surgeon clicks the end procedure button we set the end variable to true which means the procedure has stopped,
- and further instructions on the menu are expected, we set the start, restart our counter that counts the two clicks and the first point
- since there is possibilitiy that he wants to select again*/
- /*public void EndProcedure()
- {
- end = true;
- cnt = 0;
- start = false;
- firstPoint = false;
- selected = true;
- adjust = false;
- endSelectionButton.SetActive(false);
- keepPointsButton.SetActive(true);
- deletePointsButton.SetActive(true);
- lineLength.SetActive(false);
- //keepPointsButton.GetComponent<Renderer>().material.color = Color.green;
- //deletePointsButton.GetComponent<Renderer>().material.color = Color.green;
- }*/
- /*Activate a poping-up menu as soon as the keep points button is pressed*/
- /*public void KeepPoints()
- {
- menuButton2.SetActive(true);
- }
- */
- /*If the user choses yes from the poping menu, then set that the first pair is selected succesfuly and set the variable
- 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
- pop up menu*/
- public void KeepPointsYes()
- {
- currentPoint = 1;
- selected = false;
- start = false;
- secondPoint = false;
- //menuButton2.SetActive(false);
- keepPointsButton.SetActive(false);
- deletePointsButton.SetActive(false);
- startSelectionButton.SetActive(true);
- lineLength.SetActive(false);
- adjustPointsButton.SetActive(true);
- //startSelectionButton.GetComponent<Renderer>().material.color = Color.green;
- }
- public void AdjustPoints()
- {
- adjust = true;
- adjustPointsButton.SetActive(false);
- startSelectionButton.SetActive(true);
- lineLength.SetActive(true);
- //keepPointsButton.GetComponent<Renderer>().material.color = Color.green;
- if(secondSelection)
- { deletePointsButton.SetActive(true); startSelectionButton.SetActive(false); }
- }
- public void PrimitivesConstrain(GameObject gameObject)
- {
- ;
- }
- /*Activate a poping-up menu as soon as the delete points button is pressed*/
- public void DeletePoints()
- {
- menuButton.SetActive(true);
- }
- /*If no is selected then just close the pop up menu*/
- public void DeletePointsNo()
- {
- menuButton.SetActive(false);
- }
- /*Arrays of colors that are going to be used further as materials for our game objects*/
- private Color[] colorCode =
- {
- new Color(1.0f,0.0f,0.0f,1.0f),
- new Color(1.0f,0.5f,0.0f,1.0f),
- new Color(1.0f,1.0f,0.0f,1.0f),
- new Color(0.5f,1.0f,0.0f,1.0f),
- new Color(0.0f,1.0f,0.0f,1.0f),
- new Color(0.0f,1.0f,0.5f,1.0f),
- new Color(0.0f,1.0f,1.0f,1.0f),
- new Color(0.0f,0.5f,1.0f,1.0f),
- new Color(0.0f,0.0f,1.0f,1.0f),
- new Color(0.5f,0.0f,1.0f,1.0f),
- new Color(1.0f,0.0f,1.0f,1.0f),
- new Color(1.0f,0.0f,0.5f,1.0f),
- };
- //Gesture and Gaze Coordination
- public void Update()
- {
- GameObject oldFocusObject;
- var headPosition = Camera.main.transform.position;
- var gazeDirection = Camera.main.transform.forward;
- int layerMask1 = 1 << 10;
- /* We have our US image on a separate layer so if the raycast hits that layer only in that case
- make the necessary changes. If the gaze is on the object and colides with the image take info
- about the point of collision and set it as the current cursor point. If not make the object null (no hit)
- If the object is hit and the user tapped, take that as the first point for further processing.
- If he already tapped create the primitive and start seting the value of the gaze in the second point.*/
- if (Physics.Raycast(headPosition, gazeDirection, out hitInfo, Mathf.Infinity, layerMask1))
- {
- oldFocusObject = hitInfo.collider.gameObject;
- hitInfoPoint = hitInfo.point;
- cursorPoint = InteractiveMeshCursor.transform.position;
- }
- else { oldFocusObject = null; }
- if (oldFocusObject != null && cnt == 0) { hitInfoPointFirst = hitInfo.point; }
- else if (oldFocusObject != null && cnt == 1)
- {
- if (!adjust)
- { GetPoints(cnt); hitInfoPointSecond = hitInfo.point; }
- }
- /* If the coursor is on the right layer and the adjust button is clicked then we check which one of the points
- 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).
- which is encapsulated in two functions down below*/
- if (Physics.Raycast(headPosition, gazeDirection, out hitInfo, Mathf.Infinity, layerMask1) && adjust)
- {
- if ((currentPoint == 0 || currentPoint==1) && sphere[0].GetComponent<HandDraggable>().IsDraggingEnabled)
- {
- AdjustableFirstPoint(0, 0);
- }
- if ((currentPoint == 0 || currentPoint==1) && sphere[1].GetComponent<HandDraggable>().IsDraggingEnabled)
- {
- AdjustableSecondPoint(1, 0);
- }
- if ((secondSelection) && sphere[2].GetComponent<HandDraggable>().IsDraggingEnabled && sphere[2]!=null)
- {
- AdjustableFirstPoint(2, 1);
- }
- if (secondSelection && sphere[3].GetComponent<HandDraggable>().IsDraggingEnabled && sphere[3]!=null)
- {
- AdjustableSecondPoint(3, 1);
- }
- }
- }
- public void AdjustableFirstPoint(int i, int j)
- {
- lineRenderer[j].SetPositions(new Vector3[] { sphere[i].GetComponent<HandDraggable>().HostTransform.position, sphere[i + 1].transform.position });
- float distance = Vector3.Distance(sphere[i].GetComponent<HandDraggable>().HostTransform.position, sphere[i + 1].transform.position);
- changingText.text = distance.ToString();
- }
- public void AdjustableSecondPoint(int i, int j)
- {
- lineRenderer[j].SetPositions(new Vector3[] { sphere[i - 1].transform.position, sphere[i].GetComponent<HandDraggable>().HostTransform.position });
- float distance = Vector3.Distance(sphere[i - 1].transform.position, sphere[i].GetComponent<HandDraggable>().HostTransform.position);
- changingText.text = distance.ToString();
- }
- /* 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)
- for the second line (or so called fixed line) we use second line renderer which we have under the empty object called Second line*/
- public void LineRendering(Vector3 sp, Vector3 ep)
- {
- Random random = new Random();
- int num = random.Next(0, 11);
- if (currentPoint == 0)
- {
- linecount = 0;
- lineRenderer[linecount] = GetComponent<LineRenderer>();
- lineRenderer[linecount].material.color = Color.red;
- }
- else if (currentPoint == 1)
- {
- linecount = 1;
- SecondLine = GameObject.Find("SecondLine"); lineRenderer[linecount] = SecondLine.GetComponent<LineRenderer>();
- lineRenderer[linecount].material.color = Color.green;
- }
- lineRenderer[linecount].SetWidth(.01f, .01f);
- lineRenderer[linecount].SetPositions(new Vector3[] { sp, ep });
- float distance = Vector3.Distance(sp, ep);
- changingText.text = distance.ToString();
- }
- /* 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
- 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
- fixed the secon point so our line has to be fixed between the first and the second point. */
- public void GetPoints(int pointcount)
- {
- switch (pointcount)
- {
- case 1:
- lineStartPoint = hitInfoPointFirst;
- lineEndPoint = cursorPoint;
- LineRendering(lineStartPoint.Value, lineEndPoint.Value);
- break;
- case 2:
- lineStartPoint = hitInfoPointFirst;
- lineEndPoint = hitInfoPointSecond;
- LineRendering(lineStartPoint.Value, lineEndPoint.Value);
- break;
- }
- }
- /* This function incorporates the Hololens function tap. As previously mentioned we only want to select on the certain
- 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)
- 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
- second point. Other than that just wrong clicks (that are not going to be taken into account). */
- public void OnInputClicked(InputClickedEventData eventData)
- {
- int layerMask = 1 << 10;
- if (Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hitInfo, Mathf.Infinity, layerMask))
- {
- if (start && (!firstPoint) && (!end) && !(Convert.ToBoolean(cnt)) && !selected && !adjust)
- {
- cnt++;
- firstPoint = true;
- if (currentPoint == 0) { CreatePrimitiveFP(cnt - 1); }
- else if (currentPoint == 1) { CreatePrimitiveFP(cnt + 1); }
- }
- else if (start && firstPoint && (!end) && !adjust)
- {
- cnt++;
- if (currentPoint == 0) { CreatePrimitiveFP(cnt - 1); GetPoints(cnt); }
- else if (currentPoint == 1) { CreatePrimitiveFP(cnt + 1); GetPoints(cnt); }
- firstPoint = false;
- secondPoint = true;
- end = true;
- cnt = 0;
- start = false;
- firstPoint = false;
- selected = true;
- adjust = false;
- if(currentPoint==1) {secondSelection = true;}
- deletePointsButton.SetActive(true);
- lineLength.SetActive(false);
- keepPointsButton.SetActive(true);
- }
- /*else if ((secondPoint && firstPoint) || (!secondPoint && !firstPoint) || (!start && !end) || (!start && end))
- {
- cnt = 0;
- }*/
- }
- }
- /* 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
- 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"
- to the new created object*/
- public void CreatePrimitiveFP(int primitiveOrder)
- {
- Random random = new Random();
- int num = random.Next(0, 11);
- sphere[primitiveOrder] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
- sphere[primitiveOrder].layer = 10;
- sphere[primitiveOrder].GetComponent<Renderer>().material.color = colorCode[num];
- sphere[primitiveOrder].transform.localScale = new Vector3(0.09f, 0.09f, 0.09f);
- sphere[primitiveOrder].transform.position = hitInfoPoint;
- sphere[primitiveOrder].layer = 10;
- sphere[primitiveOrder].AddComponent<BoxCollider>();
- sphere[primitiveOrder].AddComponent<HandDraggable>();
- }
- /* 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
- turns off the poping menues, and deletes the points, and doesn't delete the line renderer but resets it (because if we destroy it
- we are not able to restore it afterwards).*/
- public void DeleteObjects(bool value)
- {
- for (int i = 0; i < 2; i++)
- {
- if (!value)
- {
- keepPointsButton.SetActive(false);
- startSelectionButton.SetActive(true);
- Destroy(sphere[i]);
- if (i == 0) { lineRenderer[i].SetPosition(0, Vector3.zero); lineRenderer[i].SetPosition(1, Vector3.zero); }
- }
- else if (value)
- {
- keepPointsButton.SetActive(true);
- deletePointsButton.SetActive(true);
- Destroy(sphere[i + 2]);
- if (i == 1)
- {
- lineRenderer[i].SetPosition(0, Vector3.zero); lineRenderer[i].SetPosition(1, Vector3.zero); secondSelection = false; currentPoint = 0;
- }
- }
- }
- }
- public void DestroyPrimitives()
- {
- menuButton.SetActive(false);
- //menuButton2.SetActive(false);
- lineLength.SetActive(false);
- deletePointsButton.SetActive(false);
- firstPoint = false;
- start = false;
- end = true;
- cnt = 0;
- adjust = false;
- selected = false;
- DeleteObjects(secondSelection);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement