private void reachSpecCalculatorThread_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage >= 0)
            {
                reachSpecProgressBar.Style = ProgressBarStyle.Continuous;
                reachSpecProgressBar.Value = e.ProgressPercentage;
                return;
            }

            if (e.ProgressPercentage == -1)
            {
                progressLabel.Visible = true;
                progressLabel.Text    = (string)e.UserState;
                return;
            }

            //Recalculate reachspec on UI thread, because the shared memory implementation doesn't support background thread updates...
            if (e.ProgressPercentage == -2)
            {
                ReachSpecUpdaterUIThreadOptions o = (ReachSpecUpdaterUIThreadOptions)e.UserState;
                recalculateReachSpec(o.reachSpecExport, o.calculatedProperDistance, o.dirX, o.dirY, o.dirZ);
            }
        }
        private bool calculateReachSpec(IExportEntry reachSpecExport, bool readOnly, IExportEntry startNodeExport = null)
        {
            //Get start and end exports.
            var            properties = reachSpecExport.GetProperties();
            ObjectProperty start      = properties.GetProp <ObjectProperty>("Start");
            StructProperty end        = properties.GetProp <StructProperty>("End");

            ObjectProperty endActorObj = end.GetProp <ObjectProperty>("Actor");

            if (start.Value > 0 && endActorObj.Value > 0)
            {
                //We should capture GUID here

                IExportEntry startNode = reachSpecExport.FileRef.Exports[start.Value - 1];
                IExportEntry endNode   = reachSpecExport.FileRef.Exports[endActorObj.Value - 1];

                if (startNodeExport != null && startNode.Index != startNodeExport.Index)
                {
                    //ERROR!
                    MessageBox.Show(reachSpecExport.Index + " " + reachSpecExport.ObjectName + " start does not match it's containing pathlist reference (" + startNodeExport.Index + " " + startNodeExport.ObjectName + ")");
                }

                float startX = 0, startY = 0, startZ = 0;
                float destX = 0, destY = 0, destZ = 0;

                StructProperty startLocationProp = startNode.GetProperty <StructProperty>("location");
                StructProperty endLocationProp = endNode.GetProperty <StructProperty>("location");

                if (startLocationProp != null && endLocationProp != null)
                {
                    startX = startLocationProp.GetProp <FloatProperty>("X");
                    startY = startLocationProp.GetProp <FloatProperty>("Y");
                    startZ = startLocationProp.GetProp <FloatProperty>("Z");
                    destX  = endLocationProp.GetProp <FloatProperty>("X");
                    destY  = endLocationProp.GetProp <FloatProperty>("Y");
                    destZ  = endLocationProp.GetProp <FloatProperty>("Z");

                    Point3D startPoint = new Point3D(startX, startY, startZ);
                    Point3D destPoint  = new Point3D(destX, destY, destZ);

                    double distance = startPoint.getDistanceToOtherPoint(destPoint);
                    if (distance != 0)
                    {
                        float dirX = (float)((destPoint.X - startPoint.X) / distance);
                        float dirY = (float)((destPoint.Y - startPoint.Y) / distance);
                        float dirZ = (float)((destPoint.Z - startPoint.Z) / distance);


                        //Get Original Values, for comparison.
                        StructProperty specDirection = properties.GetProp <StructProperty>("Direction");
                        float          origX = 0, origY = 0, origZ = 0;
                        if (specDirection != null)
                        {
                            origX = specDirection.GetProp <FloatProperty>("X");
                            origY = specDirection.GetProp <FloatProperty>("Y");
                            origZ = specDirection.GetProp <FloatProperty>("Z");
                            IntProperty origDistanceProp = properties.GetProp <IntProperty>("Distance");
                            if (origDistanceProp != null)
                            {
                                int origDistance             = origDistanceProp.Value;
                                int calculatedProperDistance = RoundDoubleToInt(distance);
                                int distanceDiff             = Math.Abs(origDistance - calculatedProperDistance);
                                ReachSpecUpdaterUIThreadOptions recalcOption = new ReachSpecUpdaterUIThreadOptions(reachSpecExport, calculatedProperDistance, dirX, dirY, dirZ);

                                if (distanceDiff > MAX_DISTANCE_TOLERANCE)
                                {
                                    // Difference.
                                    Debug.WriteLine("Diff Distance is > tolerance: " + distanceDiff + ", should be " + calculatedProperDistance);
                                    if (!readOnly)
                                    {
                                        worker.ReportProgress(-2, recalcOption);
                                    }
                                    return(true);
                                }

                                float diffX = origX - dirX;
                                float diffY = origY - dirY;
                                float diffZ = origZ - dirZ;
                                if (Math.Abs(diffX) > MAX_DIRECTION_TOLERANCE)
                                {
                                    // Difference.
                                    Debug.WriteLine("Diff Direction X is > tolerance: " + diffX + ", should be " + dirX);
                                    if (!readOnly)
                                    {
                                        worker.ReportProgress(-2, recalcOption);
                                    }
                                    return(true);
                                }
                                if (Math.Abs(diffY) > MAX_DIRECTION_TOLERANCE)
                                {
                                    // Difference.
                                    Debug.WriteLine("Diff Direction Y is > tolerance: " + diffY + ", should be " + dirY);
                                    if (!readOnly)
                                    {
                                        worker.ReportProgress(-2, recalcOption);
                                    }
                                    return(true);
                                }
                                if (Math.Abs(diffZ) > MAX_DIRECTION_TOLERANCE)
                                {
                                    // Difference.
                                    Debug.WriteLine("Diff Direction Z is > tolerance: " + diffZ + ", should be " + dirZ);
                                    if (!readOnly)
                                    {
                                        worker.ReportProgress(-2, recalcOption);
                                    }
                                    return(true);
                                }

                                return(false);
                            }
                        }
                    }
                }
            }
            //We really shouldn't reach here, hopefully.
            return(false);
        }