/// <summary>
 /// This function is called when the behaviour becomes disabled() or inactive.
 /// </summary>
 private void OnDisable()
 {
     // Stop the calibration thread if it is not null.
     if (_calibrationThread != null)
     {
         var result = _calibrationThread.StopThread();
         _calibrationThread = null;
         Debug.Log("Calibration thread stopped: " + (result ? "YES" : "NO"));
     }
 }
        /// <summary>
        /// Calibration coroutine. Drives the calibration thread states.
        /// </summary>
        /// <param name="points">Optional point list. Null means default set.</param>
        /// <param name="resultCallback">A result callback or null for none.</param>
        /// <returns>An enumerator</returns>
        private IEnumerator PerformCalibration(Vector3[] points, System.Action <bool> resultCallback)
        {
            if (points != null)
            {
                _points = points;
            }

            if (_calibrationThread != null)
            {
                _calibrationThread.StopThread();
                _calibrationThread = null;
            }

            // Create and start the calibration thread.
            _calibrationThread = new CalibrationThread(VREyeTracker.Instance.EyeTrackerInterface, screenBased: false);

            // Only continue if the calibration thread is running.
            for (int i = 0; i < 10; i++)
            {
                if (_calibrationThread.Running)
                {
                    break;
                }

                yield return(new WaitForSeconds(0.1f));
            }

            if (!_calibrationThread.Running)
            {
                Debug.LogError("Failed to start calibration thread");
                _calibrationThread.StopThread();
                _calibrationThread     = null;
                _calibrationInProgress = false;
                yield break;
            }

            _point.SetActive(true);

            var enterResult = _calibrationThread.EnterCalibrationMode();

            // Wait for the call to finish
            yield return(StartCoroutine(WaitForResult(enterResult)));

            // Iterate through the calibration points.
            foreach (var pointPosition in _points)
            {
                // Set the local position and start the point animation
                _point.transform.localPosition = pointPosition;
                _pointScript.StartAnim();

                // Wait for animation.
                yield return(new WaitForSeconds(1.4f));

                // As of this writing, adding a point takes about 175 ms. A failing add can take up to 3000 ms.
                var collectResult = _calibrationThread.CollectData(new CalibrationThread.Point(
                                                                       _point.transform.localPosition.x * -1000f,
                                                                       _point.transform.localPosition.y * 1000f,
                                                                       _point.transform.localPosition.z * 1000f));

                // Wait for the call to finish
                yield return(StartCoroutine(WaitForResult(collectResult)));

                // React to the result of adding a point.
                if (collectResult.Status == CalibrationStatus.Failure)
                {
                    Debug.Log("There was an error gathering data for this calibration point: " + _point.transform.localPosition);
                }
            }

            // Compute and apply the result of the calibration. A succesful compute currently takes about 300 ms. A failure may bail out in a few ms.
            var computeResult = _calibrationThread.ComputeAndApply();

            // Wait for the call to finish
            yield return(StartCoroutine(WaitForResult(computeResult)));

            // Leave calibration mode.
            var leaveResult = _calibrationThread.LeaveCalibrationMode();

            // Wait for the call to finish
            yield return(StartCoroutine(WaitForResult(leaveResult)));

            // Stop the thread.
            _calibrationThread.StopThread();
            _calibrationThread = null;

            // Finish up or restart if failure.
            LatestCalibrationSuccessful = computeResult.Status == CalibrationStatus.Success;

            _point.SetActive(false);

            if (resultCallback != null)
            {
                resultCallback(LatestCalibrationSuccessful);
            }

            _calibrationInProgress = false;
        }