InsertPoint() public method

public InsertPoint ( int index ) : TrackBuildRPoint,
index int
return TrackBuildRPoint,
コード例 #1
0
    /// <summary>
    /// unfinished!
    /// </summary>
    /// <param name="track"></param>
    /// <param name="selectedPoint"></param>
    public static void AddTwist(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint   = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);

        float      twistDistance      = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, track.maxJumpLength);
        Vector3    twistDirection     = atPoint.trackDirection;
        Vector3    twistMiddle        = atPoint.worldPosition;
        Vector3    twistUp            = atPoint.trackUp;
        Vector3    twistAxis          = Vector3.Cross(twistDirection, twistUp);
        float      twistRadius        = track.twistRadius;
        Vector3    twistStartPosition = -twistDirection * (twistDistance * 0.33f);
        Vector3    twistEndPosition   = twistDirection * (twistDistance * 0.33f);
        Vector3    twistCentreHeight  = twistUp * twistRadius;
        Quaternion twistAngle         = Quaternion.LookRotation(twistDirection, twistUp);
        Vector3    twistCenter        = atPoint.worldPosition + Vector3.up * twistRadius;
        float      controlPointLength = twistRadius / (Mathf.PI);

        int   numberOfPoints = track.twistPoints;
        float arcPercent     = 1.0f / numberOfPoints;

        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[numberOfPoints + 1];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float   pointArcPercent   = arcPercent * i;
            float   radA              = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3 pointLoopPosition = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius);
            float   smoothI           = pointArcPercent * pointArcPercent * (3.0f - 2.0f * pointArcPercent);
            Vector3 lateral           = Vector3.Lerp(twistStartPosition, twistEndPosition, pointArcPercent + (pointArcPercent - smoothI));
            Vector3 pointPosition     = (pointLoopPosition) + lateral;
            Vector3 pointDirection    = Vector3.Cross(-pointLoopPosition, twistAxis).normalized;

            TrackBuildRPoint newTrackPoint = track.InsertPoint(selectedPoint + 1 + i);
            newTrackPoint.worldPosition       = twistCenter + pointPosition;
            newTrackPoint.trackUpQ            = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength);
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition      += twistStartPosition;
        atPoint.trackUpQ            = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (twistDirection * controlPointLength) - twistAxis;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack       = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength      = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
コード例 #2
0
    public static void AddLoop(TrackBuildRTrack track, int selectedPointIndex)
    {
        TrackBuildRPoint atPoint = track[selectedPointIndex];
        int     atPointIndex     = selectedPointIndex;
        float   loopRadius       = track.loopRadius;
        float   trackWidth       = atPoint.width;
        Vector3 trackDirection   = atPoint.trackDirection.normalized;
        Vector3 trackUp          = atPoint.trackUpQ * Vector3.forward;
        Vector3 trackCross       = atPoint.trackCross;

        Vector3    entryPosition       = atPoint.worldPosition + (trackCross * trackWidth * 0.6f);
        Vector3    loopAxis            = Vector3.Cross(trackDirection, trackUp);
        Vector3    loopCenter          = atPoint.worldPosition + Vector3.up * loopRadius;
        Quaternion loopAngle           = Quaternion.FromToRotation(Vector3.right, trackDirection);
        float      controlPointLength  = loopRadius / (Mathf.PI);
        Vector3    controlPointLateral = -loopAxis;

        int   numberOfPoints = 6;
        float arcPercent     = 1.0f / numberOfPoints;

        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[7];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float            pointArcPercent   = arcPercent * i;
            TrackBuildRPoint newTrackPoint     = track.InsertPoint(atPointIndex + 1);
            float            rad               = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3          pointLoopPosition = loopAngle * ((new Vector3(Mathf.Sin(rad), Mathf.Cos(rad), 0)) * loopRadius);
            Vector3          lateral           = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), pointArcPercent);
            Vector3          pointPosition     = (pointLoopPosition) + lateral;
            Vector3          pointDirection    = Vector3.Cross(-pointLoopPosition, loopAxis).normalized;
            newTrackPoint.worldPosition       = loopCenter + pointPosition;
            newTrackPoint.trackUpQ            = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength) - controlPointLateral;
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition       = entryPosition;
        atPoint.trackUpQ            = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (trackDirection * controlPointLength) + controlPointLateral;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack       = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength      = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
コード例 #3
0
    public static void AddLoop(TrackBuildRTrack track, int selectedPointIndex)
    {
        TrackBuildRPoint atPoint = track[selectedPointIndex];
        int atPointIndex = selectedPointIndex;
        float loopRadius = track.loopRadius;
        float trackWidth = atPoint.width;
        Vector3 trackDirection = atPoint.trackDirection.normalized;
        Vector3 trackUp = atPoint.trackUpQ * Vector3.forward;
        Vector3 trackCross = atPoint.trackCross;

        Vector3 entryPosition = atPoint.worldPosition + (trackCross * trackWidth * 0.6f);
        Vector3 loopAxis = Vector3.Cross(trackDirection, trackUp);
        Vector3 loopCenter = atPoint.worldPosition + Vector3.up * loopRadius;
        Quaternion loopAngle = Quaternion.FromToRotation(Vector3.right, trackDirection);
        float controlPointLength = loopRadius / (Mathf.PI);
        Vector3 controlPointLateral = -loopAxis;

        int numberOfPoints = 6;
        float arcPercent = 1.0f / numberOfPoints;
        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[7];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float pointArcPercent = arcPercent * i;
            TrackBuildRPoint newTrackPoint = track.InsertPoint(atPointIndex + 1);
            float rad = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3 pointLoopPosition = loopAngle * ((new Vector3(Mathf.Sin(rad), Mathf.Cos(rad), 0)) * loopRadius);
            Vector3 lateral = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), pointArcPercent);
            Vector3 pointPosition = (pointLoopPosition) + lateral;
            Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, loopAxis).normalized;
            newTrackPoint.worldPosition = loopCenter + pointPosition;
            newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength) - controlPointLateral;
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition = entryPosition;
        atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (trackDirection * controlPointLength) + controlPointLateral;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
コード例 #4
0
    public static void AddJumpTwist(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint   = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);
        TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1);

        float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
        float jumpDistance      = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength);

        float      trackWidth      = atPoint.width * 0.5f;
        Vector3    startCross      = atPoint.trackCross;
        Vector3    jumpDirection   = atPoint.trackDirection;
        Vector3    jumpMiddle      = atPoint.worldPosition;
        Quaternion atPointUpQ      = atPoint.trackUpQ;
        Quaternion trackUpJump     = Quaternion.AngleAxis(track.twistAngle, -jumpDirection);
        Quaternion trackCrossExit  = trackUpJump * (atPointUpQ);
        Quaternion trackCrossEntry = Quaternion.Inverse(trackUpJump) * (atPointUpQ);
        Vector3    jumpLateral     = startCross * track.twistAngle / 33.3f;

        Vector3 jumpHeight        = atPointUpQ * (Vector3.forward * track.jumpHeight);
        Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f) + jumpHeight - jumpLateral;
        Vector3 jumpEndPosition   = jumpMiddle + jumpDirection * (jumpDistance * 0.33f) + jumpHeight + jumpLateral;

        lastPoint.extrudeTrack       = true;
        lastPoint.extrudeLength      = track.jumpHeight;
        lastPoint.extrudeCurveEnd    = true;
        lastPoint.extrudeTrackBottom = true;

        atPoint.Reset();
        atPoint.worldPosition       = jumpStartPosition;
        atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight;
        atPoint.trackUpQ            = trackCrossExit;
        atPoint.render = false;

        TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1);

        jumpEnd.worldPosition       = jumpEndPosition;
        jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition - jumpHeight;
        jumpEnd.trackUpQ            = trackCrossEntry;
        jumpEnd.extrudeTrack        = true;
        jumpEnd.extrudeLength       = track.jumpHeight;
        jumpEnd.extrudeCurveEnd     = true;
        jumpEnd.extrudeTrackBottom  = true;

        atPoint.RecalculateStoredValues();
        jumpEnd.RecalculateStoredValues();
    }
コード例 #5
0
    public static void AddJump(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint   = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);
        TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1);

        float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
        float jumpDistance      = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength);

        Vector3    jumpDirection = atPoint.trackDirection;
        Vector3    jumpMiddle    = atPoint.worldPosition;
        Vector3    startCross    = atPoint.trackCross;
        float      trackWidth    = atPoint.width * 0.5f;
        Quaternion trackUp       = atPoint.trackUpQ;

        Vector3 jumpHeight        = trackUp * (Vector3.forward * track.jumpHeight);
        Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f);
        Vector3 jumpEndPosition   = jumpMiddle + jumpDirection * (jumpDistance * 0.33f);

        lastPoint.extrudeTrack    = true;
        lastPoint.extrudeLength   = track.jumpHeight;
        lastPoint.extrudeCurveEnd = true;

        atPoint.Reset();
        atPoint.worldPosition       = jumpStartPosition + jumpHeight;
        atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight * 2;
        atPoint.trackUpQ            = trackUp;
        atPoint.render = false;

        TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1);

        jumpEnd.worldPosition       = jumpEndPosition + jumpHeight;
        jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition;
        jumpEnd.trackUpQ            = trackUp;
        jumpEnd.extrudeTrack        = true;
        jumpEnd.extrudeLength       = track.jumpHeight;
        jumpEnd.extrudeCurveEnd     = true;

        atPoint.RecalculateStoredValues();
        jumpEnd.RecalculateStoredValues();
    }
コード例 #6
0
    public static void AddJump(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);
//        TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1);

        float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
        float jumpDistance = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength);

        Vector3 jumpDirection = atPoint.trackDirection;
        Vector3 jumpMiddle = atPoint.worldPosition;
//        Vector3 startCross = atPoint.trackCross;
//        float trackWidth = atPoint.width * 0.5f;
        Quaternion trackUp = atPoint.trackUpQ;

        Vector3 jumpHeight = trackUp * (Vector3.forward * track.jumpHeight);
        Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f);
        Vector3 jumpEndPosition = jumpMiddle + jumpDirection * (jumpDistance * 0.33f);

        lastPoint.extrudeTrack = true;
        lastPoint.extrudeLength = track.jumpHeight;
        lastPoint.extrudeCurveEnd = true;

        atPoint.Reset();
        atPoint.worldPosition = jumpStartPosition + jumpHeight;
        atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight * 2;
        atPoint.trackUpQ = trackUp;
        atPoint.render = false;

        TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1);
        jumpEnd.worldPosition = jumpEndPosition + jumpHeight;
        jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition;
        jumpEnd.trackUpQ = trackUp;
        jumpEnd.extrudeTrack = true;
        jumpEnd.extrudeLength = track.jumpHeight;
        jumpEnd.extrudeCurveEnd = true;

        atPoint.RecalculateStoredValues();
        jumpEnd.RecalculateStoredValues();
    }
コード例 #7
0
    public static void AddJumpTwist(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);
//        TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1);

        float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
        float jumpDistance = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength);

//        float trackWidth = atPoint.width * 0.5f;
        Vector3 startCross = atPoint.trackCross;
        Vector3 jumpDirection = atPoint.trackDirection;
        Vector3 jumpMiddle = atPoint.worldPosition;
        Quaternion atPointUpQ = atPoint.trackUpQ;
        Quaternion trackUpJump = Quaternion.AngleAxis(track.twistAngle, -jumpDirection);
        Quaternion trackCrossExit = trackUpJump * (atPointUpQ);
        Quaternion trackCrossEntry = Quaternion.Inverse(trackUpJump) * (atPointUpQ);
        Vector3 jumpLateral = startCross * track.twistAngle / 33.3f;

        Vector3 jumpHeight = atPointUpQ * (Vector3.forward * track.jumpHeight);
        Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f) + jumpHeight - jumpLateral;
        Vector3 jumpEndPosition = jumpMiddle + jumpDirection * (jumpDistance * 0.33f) + jumpHeight + jumpLateral;

        lastPoint.extrudeTrack = true;
        lastPoint.extrudeLength = track.jumpHeight;
        lastPoint.extrudeCurveEnd = true;
        lastPoint.extrudeTrackBottom = true;

        atPoint.Reset();
        atPoint.worldPosition = jumpStartPosition;
        atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight;
        atPoint.trackUpQ = trackCrossExit;
        atPoint.render = false;

        TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1);
        jumpEnd.worldPosition = jumpEndPosition;
        jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition - jumpHeight;
        jumpEnd.trackUpQ = trackCrossEntry;
        jumpEnd.extrudeTrack = true;
        jumpEnd.extrudeLength = track.jumpHeight;
        jumpEnd.extrudeCurveEnd = true;
        jumpEnd.extrudeTrackBottom = true;

        atPoint.RecalculateStoredValues();
        jumpEnd.RecalculateStoredValues();
    }
コード例 #8
0
    /// <summary>
    /// unfinished!
    /// </summary>
    /// <param name="track"></param>
    /// <param name="selectedPoint"></param>
    public static void AddTwist(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);

        float twistDistance = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, track.maxJumpLength);
        Vector3 twistDirection = atPoint.trackDirection;
//        Vector3 twistMiddle = atPoint.worldPosition;
        Vector3 twistUp = atPoint.trackUp;
        Vector3 twistAxis = Vector3.Cross(twistDirection, twistUp);
        float twistRadius = track.twistRadius;
        Vector3 twistStartPosition = -twistDirection * (twistDistance * 0.33f);
        Vector3 twistEndPosition = twistDirection * (twistDistance * 0.33f);
//        Vector3 twistCentreHeight = twistUp * twistRadius;
        Quaternion twistAngle = Quaternion.LookRotation(twistDirection, twistUp);
        Vector3 twistCenter = atPoint.worldPosition + Vector3.up * twistRadius;
        float controlPointLength = twistRadius / (Mathf.PI);

        int numberOfPoints = track.twistPoints;
        float arcPercent = 1.0f / numberOfPoints;
        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[numberOfPoints+1];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float pointArcPercent = arcPercent * i;
            float radA = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3 pointLoopPosition = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius);
            float smoothI = pointArcPercent * pointArcPercent * (3.0f - 2.0f * pointArcPercent);
            Vector3 lateral = Vector3.Lerp(twistStartPosition, twistEndPosition, pointArcPercent + (pointArcPercent - smoothI));
            Vector3 pointPosition = (pointLoopPosition) + lateral;
            Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, twistAxis).normalized;

            TrackBuildRPoint newTrackPoint = track.InsertPoint(selectedPoint + 1 + i);
            newTrackPoint.worldPosition = twistCenter + pointPosition;
            newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength);
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition += twistStartPosition;
        atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (twistDirection * controlPointLength) - twistAxis;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
コード例 #9
0
    void OnSceneGUI()
    {
        if (_track.drawMode)
        {
            DrawTrack();
            return;
        }

        if (SceneView.focusedWindow != null)
        {
            SceneView.focusedWindow.wantsMouseMove = false;
        }
        Vector3 position    = _trackBuildR.transform.position;
        Camera  sceneCamera = Camera.current;

        _handleSize = HandleUtility.GetHandleSize(_trackBuildR.transform.position) * 0.1f;

        int realNumberOfPoints = _track.realNumberOfPoints;

        Ray        mouseRay           = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
        Quaternion mouseLookDirection = Quaternion.LookRotation(-mouseRay.direction);
        int        numberOfCurves     = _track.numberOfCurves;

        switch (_trackBuildR.mode)
        {
        case TrackBuildR.modes.track:
            Handles.color = TrackBuildRColours.GREEN;
            switch (_trackBuildR.pointMode)
            {
            case TrackBuildR.pointModes.add:

                if (SceneView.focusedWindow != null)
                {
                    SceneView.focusedWindow.wantsMouseMove = true;
                }

                if (Event.current.type == EventType.MouseMove)
                {
                    Repaint();
                }

                Handles.color = TrackBuildRColours.GREY;
                for (int i = 0; i < _track.realNumberOfPoints; i++)
                {
                    Vector3 pointPos   = _track[i].worldPosition;
                    float   handleSize = HandleUtility.GetHandleSize(pointPos);
                    Handles.DotCap(0, pointPos, Quaternion.identity, handleSize * 0.05f);
                }

                Handles.color = TrackBuildRColours.GREEN;
                float   mousePercentage = NearestmMousePercentage();      // _track.GetNearestPoint(mousePlanePoint);
                Vector3 mouseTrackPoint = _track.GetTrackPosition(mousePercentage) + position;
                Handles.Label(mouseTrackPoint, "Add New Track Point");
                float newPointHandleSize = HandleUtility.GetHandleSize(mouseTrackPoint) * HANDLE_SCALE;
                if (Handles.Button(mouseTrackPoint, mouseLookDirection, newPointHandleSize, newPointHandleSize, Handles.DotCap))
                {
                    int newPointIndex         = _track.GetLastPointIndex(mousePercentage);
                    TrackBuildRPoint newPoint = _track.InsertPoint(newPointIndex + 1);
                    newPoint.worldPosition = mouseTrackPoint;
                    newPoint.width         = _track.GetTrackWidth(mousePercentage);
                    newPoint.crownAngle    = _track.GetTrackCrownAngle(mousePercentage);
                    selectedPoint          = newPointIndex + 1;
                    GUI.changed            = true;
                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;
                }
                break;

            case TrackBuildR.pointModes.remove:

                if (SceneView.focusedWindow != null)
                {
                    SceneView.focusedWindow.wantsMouseMove = true;
                }

                Handles.color = TrackBuildRColours.RED;
                for (int i = 0; i < realNumberOfPoints; i++)
                {
                    TrackBuildRPoint point = _track[i];

                    float pointHandleSize = HandleUtility.GetHandleSize(point.worldPosition) * HANDLE_SCALE;
                    Handles.Label(point.worldPosition, "Remove Track Point");
                    if (Handles.Button(point.worldPosition, mouseLookDirection, pointHandleSize, pointHandleSize, Handles.DotCap))
                    {
                        _track.RemovePoint(point);
                        GUI.changed            = true;
                        _trackBuildR.pointMode = TrackBuildR.pointModes.transform;
                    }
                }

                break;

            default:

                SceneGUIPointBased();
                break;
            }

            //draw track outline
            for (int i = 0; i < numberOfCurves; i++)
            {
                TrackBuildRPoint curve = _track[i];
                if (curve == null)
                {
                    continue;
                }
                int curvePoints = curve.storedPointSize;

                float dotPA = Vector3.Dot(sceneCamera.transform.forward, curve.worldPosition - sceneCamera.transform.position);
                float dotPB = Vector3.Dot(sceneCamera.transform.forward, curve.nextPoint.worldPosition - sceneCamera.transform.position);

                if (dotPA < 0 && dotPB < 0)
                {
                    continue;
                }

                float curveDistance = Vector3.Distance(sceneCamera.transform.position, curve.center);
                int   pointJump     = Mathf.Max((int)(curveDistance / 20.0f), 1);
                Color trackOutline  = curve.render ? TrackBuildRColours.GREEN : TrackBuildRColours.RED;
                Color trackOutlineA = trackOutline;
                trackOutlineA.a = 0.5f;
                for (int p = pointJump; p < curvePoints; p += pointJump)
                {
                    int indexA = p - pointJump;
                    int indexB = p;

                    if (p + pointJump > curvePoints - 1)
                    {
                        indexB = curvePoints - 1;
                    }

                    Handles.color = trackOutlineA;
                    Handles.DrawLine(curve.sampledPoints[indexA] + position, curve.sampledPoints[indexB] + position);
                    Handles.color = trackOutline;
                    Vector3 trackCrossWidth = curve.sampledTrackCrosses[indexA] * (curve.sampledWidths[indexA] * 0.5f);
                    Handles.DrawLine(curve.sampledPoints[indexA] + trackCrossWidth + position, curve.sampledPoints[indexB] + trackCrossWidth + position);
                    Handles.DrawLine(curve.sampledPoints[indexA] - trackCrossWidth + position, curve.sampledPoints[indexB] - trackCrossWidth + position);
                }
            }
            break;

        case TrackBuildR.modes.boundary:

            //draw boundary outline
            for (int i = 0; i < numberOfCurves; i++)
            {
                TrackBuildRPoint curve = _track[i];
                int curvePoints        = curve.storedPointSize;

                float dotPA = Vector3.Dot(sceneCamera.transform.forward, curve.worldPosition - sceneCamera.transform.position);
                float dotPB = Vector3.Dot(sceneCamera.transform.forward, curve.nextPoint.worldPosition - sceneCamera.transform.position);

                if (dotPA < 0 && dotPB < 0)
                {
                    continue;
                }

                float curveDistance = Vector3.Distance(sceneCamera.transform.position, curve.center);
                int   pointJump     = Mathf.Max((int)(curveDistance / 20.0f), 1);
                for (int p = pointJump; p < curvePoints; p += pointJump)
                {
                    int indexA = p - pointJump;
                    int indexB = p;

                    if (p + pointJump > curvePoints - 1)
                    {
                        indexB = curvePoints - 1;
                    }

                    if (_track.disconnectBoundary)
                    {
                        Handles.color = TrackBuildRColours.BLUE;
                        Handles.DrawLine(curve.sampledLeftBoundaryPoints[indexA] + position, curve.sampledLeftBoundaryPoints[indexB] + position);
                        Handles.color = TrackBuildRColours.RED;
                        Handles.DrawLine(curve.sampledRightBoundaryPoints[indexA] + position, curve.sampledRightBoundaryPoints[indexB] + position);
                    }
                    else
                    {
                        Vector3 trackCrossWidth = curve.sampledTrackCrosses[indexA] * (curve.sampledWidths[indexA] * 0.5f);
                        Handles.color = TrackBuildRColours.BLUE;
                        Handles.DrawLine(curve.sampledPoints[indexA] + trackCrossWidth + position, curve.sampledPoints[indexB] + trackCrossWidth + position);
                        Handles.color = TrackBuildRColours.RED;
                        Handles.DrawLine(curve.sampledPoints[indexA] - trackCrossWidth + position, curve.sampledPoints[indexB] - trackCrossWidth + position);
                    }
                }
            }
            SceneGUIPointBased();
            break;

        case TrackBuildR.modes.textures:

            for (int i = 0; i < numberOfCurves; i++)
            {
                TrackBuildRPoint thisCurve = _track[i];

                float pointHandleSize = HandleUtility.GetHandleSize(thisCurve.center) * HANDLE_SCALE;
                Handles.color = (i == selectedCurveIndex) ? TrackBuildRColours.RED : TrackBuildRColours.BLUE;
                if (Handles.Button(thisCurve.center, Quaternion.identity, pointHandleSize, pointHandleSize, Handles.DotCap))
                {
                    selectedCurveIndex         = i;
                    GUIUtility.hotControl      = 0;
                    GUIUtility.keyboardControl = 0;
                    GUI.changed = true;
                }
            }


            Handles.color = TrackBuildRColours.RED;
            TrackBuildRPoint selectedCurve  = _track[selectedCurveIndex];
            int numberOfSelectedCurvePoints = selectedCurve.storedPointSize;
            for (int i = 0; i < numberOfSelectedCurvePoints - 1; i++)
            {
                Vector3 leftPointA  = selectedCurve.sampledLeftBoundaryPoints[i];
                Vector3 leftPointB  = selectedCurve.sampledLeftBoundaryPoints[i + 1];
                Vector3 rightPointA = selectedCurve.sampledRightBoundaryPoints[i];
                Vector3 rightPointB = selectedCurve.sampledRightBoundaryPoints[i + 1];

                Handles.DrawLine(leftPointA, leftPointB);
                Handles.DrawLine(rightPointA, rightPointB);

                if (i == 0)
                {
                    Handles.DrawLine(leftPointA, rightPointA);
                }
                if (i == numberOfSelectedCurvePoints - 2)
                {
                    Handles.DrawLine(leftPointB, rightPointB);
                }
            }

            break;

        case TrackBuildR.modes.terrain:

            //nothing

            break;

        case TrackBuildR.modes.stunt:

            SceneGUIPointBased();

            TrackBuildRPoint atPoint   = _track[selectedPoint];
            TrackBuildRPoint lastPoint = _track.GetPoint(selectedPoint - 1);
            TrackBuildRPoint nextPoint = _track.GetPoint(selectedPoint + 1);
            float            trackWidth;
            Vector3          startCross;
            Vector3          p0, p1, p2, p3, p4, p5, p6, p7;
            switch (_trackBuildR.stuntMode)
            {
            case TrackBuildR.stuntModes.loop:

                atPoint    = _track[selectedPoint];
                trackWidth = atPoint.width;

                float      loopRadius       = _track.loopRadius;
                Vector3    loopPosition     = atPoint.worldPosition;
                Vector3    trackDirection   = atPoint.trackDirection.normalized;
                Vector3    trackup          = atPoint.trackUpQ * Vector3.forward;
                Vector3    trackCross       = atPoint.trackCross;
                Vector3    loopCentreHeight = loopRadius * trackup;
                Quaternion loopAngle        = Quaternion.FromToRotation(Vector3.right, trackDirection);
                for (float i = 0; i < 0.99f; i += 0.01f)
                {
                    float   radA = Mathf.PI * 2 * (i + 0.5f);
                    float   radB = Mathf.PI * 2 * (i + 0.51f);
                    Vector3 pointLoopPositionA = loopAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * loopRadius);
                    Vector3 pointLoopPositionB = loopAngle * ((new Vector3(Mathf.Sin(radB), Mathf.Cos(radB), 0)) * loopRadius);
                    Vector3 lateral            = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), i);
                    Vector3 pointPositionA     = (pointLoopPositionA) + lateral + loopPosition + loopCentreHeight;
                    Vector3 pointPositionB     = (pointLoopPositionB) + lateral + loopPosition + loopCentreHeight;
                    Handles.DrawLine(pointPositionA, pointPositionB);
                }
                break;

            case TrackBuildR.stuntModes.jump:

                atPoint   = _track[selectedPoint];
                lastPoint = _track.GetPoint(selectedPoint - 1);
                nextPoint = _track.GetPoint(selectedPoint + 1);

                float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
                float jumpDistance      = Mathf.Min(trackPartDistance * 0.333f, _track.maxJumpLength);

                Vector3 jumpDirection = atPoint.trackDirection;
                Vector3 jumpMiddle    = atPoint.worldPosition;
                startCross = atPoint.trackCross;
                trackWidth = atPoint.width * 0.5f;
                Quaternion trackUp = atPoint.trackUpQ;

                Vector3 jumpHeight        = trackUp * (Vector3.forward * _track.jumpHeight);
                Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f);
                Vector3 jumpEndPosition   = jumpMiddle + jumpDirection * (jumpDistance * 0.33f);

                p0 = lastPoint.worldPosition + trackWidth * startCross;
                p1 = lastPoint.worldPosition - trackWidth * startCross;
                p2 = jumpStartPosition + trackWidth * startCross + jumpHeight;
                p3 = jumpStartPosition - trackWidth * startCross + jumpHeight;

                p4 = jumpEndPosition + trackWidth * startCross + jumpHeight;
                p5 = jumpEndPosition - trackWidth * startCross + jumpHeight;
                p6 = nextPoint.worldPosition + trackWidth * startCross;
                p7 = nextPoint.worldPosition - trackWidth * startCross;

                Handles.DrawLine(p0, p2);
                Handles.DrawLine(p1, p3);
                Handles.DrawLine(p0, p1);
                Handles.DrawLine(p2, p3);
                Handles.DrawLine(p2, p2 - jumpHeight);
                Handles.DrawLine(p3, p3 - jumpHeight);
                Handles.DrawLine(p0, p2 - jumpHeight);
                Handles.DrawLine(p1, p3 - jumpHeight);

                Handles.DrawLine(p4, p6);
                Handles.DrawLine(p5, p7);
                Handles.DrawLine(p4, p5);
                Handles.DrawLine(p6, p7);
                Handles.DrawLine(p4, p4 - jumpHeight);
                Handles.DrawLine(p5, p5 - jumpHeight);
                Handles.DrawLine(p6, p4 - jumpHeight);
                Handles.DrawLine(p7, p5 - jumpHeight);

                break;

//                        case TrackBuildR.stuntModes.twist:
//
//                        atPoint = _track[selectedPoint];
//                        lastPoint = _track.GetPoint(selectedPoint - 1);
//
//                        float twistDistance = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, _track.maxJumpLength);
//
//                        Vector3 twistDirection = atPoint.trackDirection;
//                        Vector3 twistMiddle = atPoint.worldPosition;
//                        Vector3 twistUp = atPoint.trackUp;
//                        float twistRadius = _track.twistRadius;
//                        Vector3 twistStartPosition = twistMiddle - twistDirection * (twistDistance * 0.33f);
//                        Vector3 twistEndPosition = twistMiddle + twistDirection * (twistDistance * 0.33f);
//                        Vector3 twistCentreHeight = twistUp * twistRadius;
//                        Quaternion twistAngle = Quaternion.LookRotation(twistDirection, twistUp);
//                        for(float i = 0; i < 0.99f; i += 0.01f )
//                        {
//                            float radA = Mathf.PI * 2 * (i+0.5f);
//                            float radB = Mathf.PI * 2 * (i+0.51f);
//                            Vector3 pointLoopPositionA = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius);
//                            Vector3 pointLoopPositionB = twistAngle * ((new Vector3(Mathf.Sin(radB), Mathf.Cos(radB), 0)) * twistRadius);
//                            float smoothI = i * i * (3.0f - 2.0f * i);
//                            Vector3 lateral = Vector3.Lerp(twistStartPosition, twistEndPosition, i + (i-smoothI));
//                            Vector3 pointPositionA = (pointLoopPositionA) + lateral + twistCentreHeight;
//                            Vector3 pointPositionB = (pointLoopPositionB) + lateral + twistCentreHeight;
//                            Handles.DrawLine(pointPositionA, pointPositionB);
//                        }
//
//                        break;

            case TrackBuildR.stuntModes.jumptwist:

                atPoint   = _track[selectedPoint];
                lastPoint = _track.GetPoint(selectedPoint - 1);
                nextPoint = _track.GetPoint(selectedPoint + 1);

                float trackTPartDistance = lastPoint.arcLength + atPoint.arcLength;
                float jumpTDistance      = Mathf.Min(trackTPartDistance * 0.333f, _track.maxJumpLength);

                trackWidth = atPoint.width * 0.5f;
                startCross = atPoint.trackCross;
                Vector3    jumpTDirection  = atPoint.trackDirection;
                Vector3    jumpTMiddle     = atPoint.worldPosition;
                Quaternion atPointUpQ      = atPoint.trackUpQ;
                Quaternion trackUpJump     = Quaternion.AngleAxis(_track.twistAngle, -jumpTDirection);
                Vector3    trackCrossExit  = trackUpJump * startCross;
                Vector3    trackCrossEntry = Quaternion.Inverse(trackUpJump) * startCross;
                Vector3    jumpLateral     = startCross * _track.twistAngle / 33.3f;

                Vector3 jumpTHeight        = atPointUpQ * (Vector3.forward * _track.jumpHeight);
                Vector3 jumpTStartPosition = jumpTMiddle - jumpTDirection * (jumpTDistance * 0.33f) + jumpTHeight - jumpLateral;
                Vector3 jumpTEndPosition   = jumpTMiddle + jumpTDirection * (jumpTDistance * 0.33f) + jumpTHeight + jumpLateral;

                p0 = lastPoint.worldPosition + trackWidth * startCross;
                p1 = lastPoint.worldPosition - trackWidth * startCross;
                p2 = jumpTStartPosition + trackWidth * trackCrossExit;
                p3 = jumpTStartPosition - trackWidth * trackCrossExit;

                p4 = jumpTEndPosition + trackWidth * trackCrossEntry;
                p5 = jumpTEndPosition - trackWidth * trackCrossEntry;
                p6 = nextPoint.worldPosition + trackWidth * startCross;
                p7 = nextPoint.worldPosition - trackWidth * startCross;

                Handles.DrawLine(p0, p2);
                Handles.DrawLine(p1, p3);
                Handles.DrawLine(p0, p1);
                Handles.DrawLine(p2, p3);
//                        Handles.DrawLine(p2, p2 - jumpTHeight);
//                        Handles.DrawLine(p3, p3 - jumpTHeight);
//                        Handles.DrawLine(p0, p2 - jumpTHeight);
//                        Handles.DrawLine(p1, p3 - jumpTHeight);

                Handles.DrawLine(p4, p6);
                Handles.DrawLine(p5, p7);
                Handles.DrawLine(p4, p5);
                Handles.DrawLine(p6, p7);
//                        Handles.DrawLine(p4, p4 - jumpTHeight);
//                        Handles.DrawLine(p5, p5 - jumpTHeight);
//                        Handles.DrawLine(p6, p4 - jumpTHeight);
//                        Handles.DrawLine(p7, p5 - jumpTHeight);

                break;
            }

            break;

        case TrackBuildR.modes.diagram:
            if (SceneView.focusedWindow != null)
            {
                SceneView.focusedWindow.wantsMouseMove = true;
            }
            if (!_track.showDiagram)
            {
                break;
            }
            Plane diagramPlane = new Plane(Vector3.up, position);
            float diagramDistance;
            float crossSize = _handleSize * 10;

            switch (_trackBuildR.track.assignedPoints)
            {
            case 0:        //display the diagram scale points

                Vector3 diagramPointA = _track.scalePointA;
                Vector3 diagramPointB = _track.scalePointB;

                if (diagramPointA != Vector3.zero || diagramPointB != Vector3.zero)
                {
                    Handles.color = TrackBuildRColours.BLUE;
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.back * crossSize);

                    Handles.color = TrackBuildRColours.GREEN;
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.back * crossSize);

                    Handles.color = TrackBuildRColours.RED;
                    Handles.DrawLine(diagramPointA, diagramPointB);
                }
                break;

            case 1:        //place the first of two scale points to define the diagram scale size

                Ray diagramRay = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
                if (diagramPlane.Raycast(diagramRay, out diagramDistance))
                {
                    Vector3 diagramPlanePoint = diagramRay.GetPoint(diagramDistance);

                    Handles.color = TrackBuildRColours.BLUE;
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.back * crossSize);

                    Handles.color = new Color(0, 0, 0, 0);
                    if (Handles.Button(diagramPlanePoint, Quaternion.identity, crossSize, crossSize, Handles.DotCap))
                    {
                        _track.scalePointA    = diagramPlanePoint;
                        _track.assignedPoints = 2;
                    }
                }

                break;

            case 2:        //place the second of two scale points to define the diagram scale

                Vector3 diagramPoint1 = _track.scalePointA;
                Handles.color = TrackBuildRColours.BLUE;
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.left * crossSize);
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.right * crossSize);
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.forward * crossSize);
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.back * crossSize);

                Ray diagramRayB = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
                if (diagramPlane.Raycast(diagramRayB, out diagramDistance))
                {
                    Vector3 diagramPlanePoint = diagramRayB.GetPoint(diagramDistance);

                    Handles.color = TrackBuildRColours.RED;
                    Handles.DrawLine(diagramPlanePoint, diagramPoint1);

                    Handles.color = TrackBuildRColours.GREEN;
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.back * crossSize);

                    Handles.color = new Color(0, 0, 0, 0);
                    if (Handles.Button(diagramPlanePoint, Quaternion.identity, crossSize, crossSize, Handles.DotCap))
                    {
                        _track.scalePointB    = diagramPlanePoint;
                        _track.assignedPoints = 0;
                        //wUpdateDiagram();
                    }
                }
                break;
            }
            break;
        }


        if (Event.current.type == EventType.ValidateCommand)
        {
            switch (Event.current.commandName)
            {
            case "UndoRedoPerformed":
                //                    Debug.Log("UndoRedoPerformed");
                _trackBuildR.ForceFullRecalculation();
                GUI.changed = true;
                return;
            }
        }

        if (GUI.changed)
        {
            UpdateGui();
        }
    }