void Update() { if (Input.touchCount == 0) { if (currentTouchOperation == TouchOperation.SELECT) { voxelArray.TouchUp(); } if (currentTouchOperation == TouchOperation.MOVE) { movingAxis.TouchUp(); } currentTouchOperation = TouchOperation.NONE; } else if (Input.touchCount == 1) { Touch touch = Input.GetTouch(0); RaycastHit hit; if (currentTouchOperation != TouchOperation.SELECT) { selectingXRay = true; } bool rayHitSomething = Physics.Raycast(cam.ScreenPointToRay(Input.GetTouch(0).position), out hit, Mathf.Infinity, selectingXRay ? Physics.DefaultRaycastLayers : NO_XRAY_MASK); Voxel hitVoxel = null; int hitFaceI = -1; TransformAxis hitTransformAxis = null; ObjectMarker hitMarker = null; if (rayHitSomething) { GameObject hitObject = hit.transform.gameObject; if (hitObject.tag == "Voxel") { hitVoxel = hitObject.GetComponent <Voxel>(); hitFaceI = Voxel.FaceIForDirection(hit.normal); if (hitFaceI == -1) { hitVoxel = null; } } else if (hitObject.tag == "ObjectMarker") { hitMarker = hitObject.GetComponent <ObjectMarker>(); } else if (hitObject.tag == "MoveAxis") { hitTransformAxis = hitObject.GetComponent <TransformAxis>(); } if ((hitVoxel != null && hitVoxel.substance != null && hitVoxel.substance.xRay) || (hitMarker != null && (hitMarker.gameObject.layer == 8 || hitMarker.gameObject.layer == 10))) // xray or SelectedObject layer { // allow moving axes through xray substances RaycastHit newHit; if (Physics.Raycast(cam.ScreenPointToRay(Input.GetTouch(0).position), out newHit, Mathf.Infinity, NO_TRANSPARENT_MASK)) { if (newHit.transform.tag == "MoveAxis") { hitVoxel = null; hitFaceI = -1; hitMarker = null; hitTransformAxis = newHit.transform.GetComponent <TransformAxis>(); } } } } if (hitVoxel != null) { lastHitVoxel = hitVoxel; lastHitFaceI = hitFaceI; } else if (hitMarker != null) { lastHitVoxel = null; lastHitFaceI = -1; } if (touch.phase == TouchPhase.Began) { if (currentTouchOperation == TouchOperation.SELECT) { voxelArray.TouchUp(); } // this seems to improve the reliability of double-taps when things are running slowly. // I think it's because there's not always a long enough gap between taps // for the touch operation to be cleared. currentTouchOperation = TouchOperation.NONE; } if (currentTouchOperation == TouchOperation.NONE) { if (GUIPanel.PanelContainingPoint(touch.position) != null) { currentTouchOperation = TouchOperation.GUI; } else if (touch.phase != TouchPhase.Moved && touch.phase != TouchPhase.Ended && touch.tapCount == 1) { } // wait until moved or released, in case a multitouch operation is about to begin else if (!rayHitSomething) { voxelArray.TouchDown(null); } else if (hitVoxel != null) { if (touch.tapCount == 1) { currentTouchOperation = TouchOperation.SELECT; voxelArray.TouchDown(hitVoxel, hitFaceI); selectingXRay = hitVoxel.substance != null && hitVoxel.substance.xRay; } else if (touch.tapCount == 2) { voxelArray.DoubleTouch(hitVoxel, hitFaceI); } else if (touch.tapCount == 3) { voxelArray.TripleTouch(hitVoxel, hitFaceI); } UpdateZoomDepth(); } else if (hitMarker != null) { currentTouchOperation = TouchOperation.SELECT; voxelArray.TouchDown(hitMarker); selectingXRay = hitMarker.objectEntity.xRay; UpdateZoomDepth(); } else if (hitTransformAxis != null) { if (touch.tapCount == 1) { currentTouchOperation = TouchOperation.MOVE; movingAxis = hitTransformAxis; movingAxis.TouchDown(touch); } else if (touch.tapCount == 2 && lastHitVoxel != null) { voxelArray.DoubleTouch(lastHitVoxel, lastHitFaceI); } else if (touch.tapCount == 3 && lastHitVoxel != null) { voxelArray.TripleTouch(lastHitVoxel, lastHitFaceI); } UpdateZoomDepth(); } } // end if currentTouchOperation == NONE else if (currentTouchOperation == TouchOperation.SELECT) { if (hitVoxel != null) { voxelArray.TouchDrag(hitVoxel, hitFaceI); } if (hitMarker != null) { voxelArray.TouchDrag(hitMarker); } } else if (currentTouchOperation == TouchOperation.MOVE) { movingAxis.TouchDrag(touch); } } // end if touch count is 1 else if (Input.touchCount == 2) { if (currentTouchOperation == TouchOperation.NONE) { currentTouchOperation = TouchOperation.CAMERA; UpdateZoomDepth(); } if (currentTouchOperation != TouchOperation.CAMERA) { return; } Touch touchZero = Input.GetTouch(0); Touch touchOne = Input.GetTouch(1); Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition; Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition; float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude; float touchDeltaMag = (touchZero.position - touchOne.position).magnitude; float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag; float scaleFactor = Mathf.Pow(1.005f, deltaMagnitudeDiff / cam.pixelHeight * 700f); if (scaleFactor != 1) { pivot.localScale *= scaleFactor; if (pivot.localScale.x > MAX_ZOOM) { pivot.localScale = new Vector3(MAX_ZOOM, MAX_ZOOM, MAX_ZOOM); } if (pivot.localScale.x < MIN_ZOOM) { pivot.localScale = new Vector3(MIN_ZOOM, MIN_ZOOM, MIN_ZOOM); } } Vector3 move = (touchZero.deltaPosition + touchOne.deltaPosition) / 2; move *= 300f; move /= cam.pixelHeight; Vector3 pivotRotationEuler = pivot.rotation.eulerAngles; pivotRotationEuler.y += move.x; pivotRotationEuler.x -= move.y; if (pivotRotationEuler.x > 90 && pivotRotationEuler.x < 180) { pivotRotationEuler.x = 90; } if (pivotRotationEuler.x < -90 || (pivotRotationEuler.x > 180 && pivotRotationEuler.x < 270)) { pivotRotationEuler.x = -90; } pivot.rotation = Quaternion.Euler(pivotRotationEuler); } else if (Input.touchCount == 3) { if (currentTouchOperation == TouchOperation.NONE) { currentTouchOperation = TouchOperation.CAMERA; UpdateZoomDepth(); } if (currentTouchOperation != TouchOperation.CAMERA) { return; } Vector2 move = new Vector2(0, 0); for (int i = 0; i < 3; i++) { move += Input.GetTouch(i).deltaPosition; } move *= 4.0f; move /= cam.pixelHeight; pivot.position -= move.x * pivot.right * pivot.localScale.z; pivot.position -= move.y * pivot.up * pivot.localScale.z; } }