private void Draw()
    {
        var worldBezier = targetPath.WorldSpaceBezier;
        var vertexCount = DynamicBezier.GoodNumMidPoints * worldBezier.Knots.Count;

        vertexCount /= 2;
        var cPointCache = new EvaluationCache(worldBezier, vertexCount).Values;

        // draw bezier
        PathEditorUtility.DrawSplineInScene(cPointCache);

        // draw direction cone cap
        if (!settings.HideDirectionCones &&
            targetScript.transform.lossyScale != Vector3.zero &&
            targetPath.LocalBezier.Knots.Count > 1)     // also hide cones if virtually a dot
        {
            float startConeSize = PathEditorUtility.Nice3DHandleSize(worldBezier.Evaluate(0f));
            float endConeSize   = PathEditorUtility.Nice3DHandleSize(worldBezier.Evaluate(1f));

            Handles.color = Color.yellow;
            Handles.ConeCap(0, worldBezier.Evaluate(0f), Quaternion.LookRotation(worldBezier.Evaluate(0.01f) - worldBezier.Evaluate(0f)), startConeSize);
            Handles.color = Color.magenta;
            Handles.ConeCap(0, worldBezier.Evaluate(1f), Quaternion.LookRotation(worldBezier.Evaluate(1f) - worldBezier.Evaluate(1f - 0.01f)), endConeSize);
        }

        // draw tangent lines
        if (!settings.HideTangentLines)
        {
            Handles.color = Color.cyan;
            for (int i = 0; i < worldBezier.Knots.Count - 1; i++)
            {
                Handles.DrawDottedLine(worldBezier.Knots[i], worldBezier.Knots[i + 1], 7.5f);
            }
        }

        // Draw knot labels
        var knotLabelStyle = new GUIStyle();

        knotLabelStyle.fontStyle     = FontStyle.Bold;
        knotLabelStyle.fontSize      = 17;
        knotLabelStyle.alignment     = TextAnchor.UpperRight;
        knotLabelStyle.contentOffset = new Vector2(25f, -50f);

        for (int i = 0; i < worldBezier.Knots.Count; i++)
        {
            knotLabelStyle.normal.textColor = PathEditorUtility.GetTColor((float)i / worldBezier.Knots.Count);
            Handles.Label(worldBezier.Knots[i], i.ToString(), knotLabelStyle);
        }

        // test t
        if (settings.TestInterpolate)
        {
            PathEditorUtility.DrawTestInterpolate(worldBezier, settings.EditorData.T);
        }

        // draw GUI
        InterpolateSceneGUI();
        ToolShelf();
    }
Ejemplo n.º 2
0
    private void MoveToolSceneGUI()
    {
        // Undo world transformation before writing values to Path's bezier curve
        Func <Vector3, Vector3> handleToLocal = (handlePoint) =>
        { return(PathEditorUtility.HandleToLocalPosition(handlePoint, cubicBezierPath.LocalSpaceTransform)); };

        Vector3 newLocalStartPosition = handleToLocal(cubicBezierPath.StartPosition);
        Vector3 newLocalStartTangent  = handleToLocal(cubicBezierPath.StartTangent);
        Vector3 newLocalEndPosition   = handleToLocal(cubicBezierPath.EndPosition);
        Vector3 newLocalEndTangent    = handleToLocal(cubicBezierPath.EndTangent);

        // Write values to Path's bezier curve
        if (newLocalStartPosition != cubicBezierPath.LocalBezier.StartPosition ||
            newLocalStartTangent != cubicBezierPath.LocalBezier.StartTangent ||
            newLocalEndPosition != cubicBezierPath.LocalBezier.EndPosition ||
            newLocalEndTangent != cubicBezierPath.LocalBezier.EndTangent)
        {
            Undo.RecordObject(target, "Edit Cubic Bezier");

            //~ Before storing new values, prevent lossyScale from deleting values
            Vector3 finalStartPosition = cubicBezierPath.LocalBezier.StartPosition;
            Vector3 finalStartTangent  = cubicBezierPath.LocalBezier.StartTangent;
            Vector3 finalEndPosition   = cubicBezierPath.LocalBezier.EndPosition;
            Vector3 finalEndTangent    = cubicBezierPath.LocalBezier.EndTangent;
            bool    guardX             = Mathf.Approximately(targetScript.transform.lossyScale.x, 0.0f);
            bool    guardY             = Mathf.Approximately(targetScript.transform.lossyScale.y, 0.0f);
            bool    guardZ             = Mathf.Approximately(targetScript.transform.lossyScale.z, 0.0f);

            if (!guardX)
            {
                finalStartPosition.x = newLocalStartPosition.x;
                finalStartTangent.x  = newLocalStartTangent.x;
                finalEndPosition.x   = newLocalEndPosition.x;
                finalEndTangent.x    = newLocalEndTangent.x;
            }
            if (!guardY)
            {
                finalStartPosition.y = newLocalStartPosition.y;
                finalStartTangent.y  = newLocalStartTangent.y;
                finalEndPosition.y   = newLocalEndPosition.y;
                finalEndTangent.y    = newLocalEndTangent.y;
            }
            if (!guardZ)
            {
                finalStartPosition.z = newLocalStartPosition.z;
                finalStartTangent.z  = newLocalStartTangent.z;
                finalEndPosition.z   = newLocalEndPosition.z;
                finalEndTangent.z    = newLocalEndTangent.z;
            }

            cubicBezierPath.LocalBezier.StartPosition = finalStartPosition;
            cubicBezierPath.LocalBezier.StartTangent  = finalStartTangent;
            cubicBezierPath.LocalBezier.EndPosition   = finalEndPosition;
            cubicBezierPath.LocalBezier.EndTangent    = finalEndTangent;

            EditorUtility.SetDirty(target);
        }
    }
    private void OnSceneGUI()
    {
        if (!Safety())
        {
            if (warnedTransform == false)
            {
                Debug.Log("[" + targetScript.name + "]\t" + PathEditorUtility.EditorUnavailable);
                warnedTransform = true;
            }
            return;
        }

        if (settings.HideHandles || Tools.current == Tool.View)
        {
            goto Draw;
        }

        if (Tools.current == Tool.Move)
        {
            Vector3 newLocalStartPosition = PathEditorUtility.HandleToLocalPosition(linePath.StartPosition, linePath.LocalSpaceTransform);
            Vector3 newLocalEndPosition   = PathEditorUtility.HandleToLocalPosition(linePath.EndPosition, linePath.LocalSpaceTransform);

            bool guardX = Mathf.Approximately(linePath.LocalSpaceTransform.lossyScale.x, 0f);
            bool guardY = Mathf.Approximately(linePath.LocalSpaceTransform.lossyScale.y, 0f);
            bool guardZ = Mathf.Approximately(linePath.LocalSpaceTransform.lossyScale.z, 0f);

            if (newLocalStartPosition != linePath.LocalStartPosition ||
                newLocalEndPosition != linePath.LocalEndPosition)
            {
                Undo.RecordObject(target, "Edit Line");
                if (!guardX)
                {
                    linePath.LocalStartPosition.x = newLocalStartPosition.x;
                    linePath.LocalEndPosition.x   = newLocalEndPosition.x;
                }
                if (!guardY)
                {
                    linePath.LocalStartPosition.y = newLocalStartPosition.y;
                    linePath.LocalEndPosition.y   = newLocalEndPosition.y;
                }
                if (!guardZ)
                {
                    linePath.LocalStartPosition.z = newLocalStartPosition.z;
                    linePath.LocalEndPosition.z   = newLocalEndPosition.z;
                }
                EditorUtility.SetDirty(target);
            }
        }

Draw:
        Draw();
    }
Ejemplo n.º 4
0
    private void Draw()
    {
        CubicBezier worldBezier = cubicBezierPath.WorldSpaceBezier;

        // draw bezier
        Vector3[] cPointCache = new EvaluationCache(worldBezier, CubicBezier.GoodNumMidPoints).Values;

        /*Handles.color = Color.yellow;
         * Handles.DrawAAPolyLine(cPointCache);
         */
        for (int i = 0; i < cPointCache.Length - 1; i++)
        {
            Handles.color = Color.Lerp(Color.yellow, Color.magenta, (float)i / cPointCache.Length);
            var lineSegment = new Vector3[2];
            lineSegment[0] = cPointCache[i];
            lineSegment[1] = cPointCache[i + 1];
            Handles.DrawAAPolyLine(lineSegment);
        }

        // draw direction cone cap
        if (!settings.HideDirectionCones && targetScript.transform.lossyScale != Vector3.zero) //check for zero vector, since LookRotation logs messages
        {
            float startConeSize = PathEditorUtility.Nice3DHandleSize(worldBezier.Evaluate(0f));
            float endConeSize   = PathEditorUtility.Nice3DHandleSize(worldBezier.Evaluate(1f));

            Handles.color = Color.yellow;
            Handles.ConeCap(0, worldBezier.Evaluate(0f), Quaternion.LookRotation(worldBezier.Tangent(0f)), startConeSize);
            Handles.color = Color.magenta;
            Handles.ConeCap(0, worldBezier.Evaluate(1f), Quaternion.LookRotation(worldBezier.Tangent(1f)), endConeSize);
        }

        // draw tangent lines
        if (!settings.HideTangentLines)
        {
            Handles.color = Color.cyan;
            Handles.DrawDottedLine(worldBezier.StartPosition, worldBezier.StartTangent, 7.5f);
            Handles.DrawDottedLine(worldBezier.EndPosition, worldBezier.EndTangent, 7.5f);
        }

        // test t
        if (settings.TestInterpolate)
        {
            PathEditorUtility.DrawTestInterpolate(worldBezier, settings.EditorData.T);
        }

        // draw GUI
        InterpolateSceneGUI();
        ToolShelf();
    }
    private void Draw()
    {
        Vector3 startPoint = linePath.Evaluate(0f);
        Vector3 endPoint   = linePath.Evaluate(1f);

        // draw line
        var cPointCache = new Vector3[32];

        for (int i = 0; i < cPointCache.Length; i++)
        {
            cPointCache[i] = Vector3.Lerp(startPoint, endPoint, (float)i / (cPointCache.Length - 1));
        }

        for (int i = 0; i < cPointCache.Length - 1; i++)
        {
            Handles.color = Color.Lerp(Color.yellow, Color.magenta, (float)i / cPointCache.Length);
            var lineSegment = new Vector3[2];
            lineSegment[0] = cPointCache[i];
            lineSegment[1] = cPointCache[i + 1];
            Handles.DrawAAPolyLine(lineSegment);
        }

        // draw direction cone cap
        if (!settings.HideDirectionCones &&
            linePath.LocalSpaceTransform.lossyScale != Vector3.zero &&
            linePath.StartPosition != linePath.EndPosition)    // also hide cones if virtually a dot
        {
            float startConeSize = PathEditorUtility.Nice3DHandleSize(startPoint);
            float endConeSize   = PathEditorUtility.Nice3DHandleSize(endPoint);

            Handles.color = Color.yellow;
            Handles.ConeCap(0, startPoint, Quaternion.LookRotation(linePath.Tangent()), startConeSize);
            Handles.color = Color.magenta;
            Handles.ConeCap(0, endPoint, Quaternion.LookRotation(linePath.Tangent()), endConeSize);
        }

        // test t
        Handles.color = PathEditorUtility.GetTColor(settings.EditorData.T);
        if (settings.TestInterpolate)
        {
            Vector3 targetPoint = linePath.Evaluate(settings.EditorData.T);
            float   sphereSize  = PathEditorUtility.Nice3DHandleSize(targetPoint);
            Handles.SphereCap(0, targetPoint, Quaternion.identity, sphereSize);
        }

        // draw GUI
        InterpolateSceneGUI();
        ToolShelf();
    }
    private void MoveToolSceneGUI()
    {
        for (int i = 0; i < targetPath.LocalBezier.Knots.Count; i++)
        {
            // Undo world transformation before writing values to Path's bezier curve
            Vector3 newLocalPosition;
            {
                var handlePosition = targetPath.WorldSpaceBezier.Knots[i];
                newLocalPosition = PathEditorUtility.HandleToLocalPosition(
                    handlePosition, targetPath.LocalSpaceTransform);
            }

            // Write value to Path's bezier curve
            //if (newLocalPosition != dynamicBezierPath.LocalBezier.Knots[i])
            if (PathEditorUtility.VectorNotApproximately(newLocalPosition, targetPath.LocalBezier.Knots[i]))
            {
                Undo.RecordObject(target, "Edit Dynamic Bezier");

                //~ Before storing new values, prevent lossyScale from deleting values
                var  finalPosition = targetPath.LocalBezier.Knots[i];
                bool guardX        = Mathf.Approximately(targetScript.transform.lossyScale.x, 0.0f);
                bool guardY        = Mathf.Approximately(targetScript.transform.lossyScale.y, 0.0f);
                bool guardZ        = Mathf.Approximately(targetScript.transform.lossyScale.z, 0.0f);

                if (!guardX)
                {
                    finalPosition.x = newLocalPosition.x;
                }
                if (!guardY)
                {
                    finalPosition.y = newLocalPosition.y;
                }
                if (!guardZ)
                {
                    finalPosition.z = newLocalPosition.z;
                }

                targetPath.LocalBezier.Knots[i] = finalPosition;

                EditorUtility.SetDirty(target);
            }
        }
    }
    private void Draw()
    {
        QuadraticBezier worldBezier = qdrBezierPath.WorldSpaceBezier;
        var             cPointCache = new EvaluationCache(worldBezier, QuadraticBezier.GoodNumMidPoints).Values;

        // draw bezier
        PathEditorUtility.DrawSplineInScene(cPointCache);

        // draw direction cone cap
        if (!settings.HideDirectionCones &&
            targetScript.transform.lossyScale != Vector3.zero)         // also hide cones if virtually a dot
        {
            float startConeSize = PathEditorUtility.Nice3DHandleSize(worldBezier.Evaluate(0f));
            float endConeSize   = PathEditorUtility.Nice3DHandleSize(worldBezier.Evaluate(1f));

            Handles.color = Color.yellow;
            Handles.ConeCap(0, worldBezier.Evaluate(0f), Quaternion.LookRotation(worldBezier.Evaluate(0.01f) - worldBezier.Evaluate(0f)), startConeSize);
            Handles.color = Color.magenta;
            Handles.ConeCap(0, worldBezier.Evaluate(1f), Quaternion.LookRotation(worldBezier.Evaluate(1f) - worldBezier.Evaluate(1f - 0.01f)), endConeSize);
        }

        // draw tangent lines
        if (!settings.HideTangentLines)
        {
            Handles.color = Color.cyan;
            Handles.DrawDottedLine(worldBezier.StartPosition, worldBezier.MidTangent, 7.5f);
            Handles.DrawDottedLine(worldBezier.MidTangent, worldBezier.EndPosition, 7.5f);
        }

        // test t
        if (settings.TestInterpolate)
        {
            PathEditorUtility.DrawTestInterpolate(worldBezier, settings.EditorData.T);
        }

        // draw GUI
        InterpolateSceneGUI();
        ToolShelf();
    }
Ejemplo n.º 8
0
    public override void OnInspectorGUI()
    {
        //base.OnInspectorGUI();
        Safety();

        var newStartPosition = cubicBezierPath.LocalBezier.StartPosition;
        var newStartTangent  = cubicBezierPath.LocalBezier.StartTangent;
        var newEndPosition   = cubicBezierPath.LocalBezier.EndPosition;
        var newEndTangent    = cubicBezierPath.LocalBezier.EndTangent;

        #region Path Inspector

        settings.PathFoldout =
            EditorGUILayout.Foldout(settings.PathFoldout, "Path");
        if (settings.PathFoldout)
        {
            EditorGUI.indentLevel++;

            //~ Knots
            //cubicBezierPath.LocalBezier.StartPosition = EditorGUILayout.Vector3Field("Start Position", cubicBezierPath.LocalBezier.StartPosition);
            //cubicBezierPath.LocalBezier.StartTangent = EditorGUILayout.Vector3Field("Start Tangent", cubicBezierPath.LocalBezier.StartTangent);
            //cubicBezierPath.LocalBezier.EndPosition = EditorGUILayout.Vector3Field("End Position", cubicBezierPath.LocalBezier.EndPosition);
            //cubicBezierPath.LocalBezier.EndTangent = EditorGUILayout.Vector3Field("End Tangent", cubicBezierPath.LocalBezier.EndTangent);

            newStartPosition = EditorGUILayout.Vector3Field("Start Position", cubicBezierPath.LocalBezier.StartPosition);
            newStartTangent  = EditorGUILayout.Vector3Field("Start Tangent", cubicBezierPath.LocalBezier.StartTangent);
            newEndPosition   = EditorGUILayout.Vector3Field("End Position", cubicBezierPath.LocalBezier.EndPosition);
            newEndTangent    = EditorGUILayout.Vector3Field("End Tangent", cubicBezierPath.LocalBezier.EndTangent);

            EditorGUI.indentLevel--;
        }

        #endregion Path Inspector

        #region Tool Settings Inspector

        PathEditorUtility.Inspector(settings, 1);

        #endregion Tool Settings Inspector

        #region Advanced

        settings.AdvancedFoldout = EditorGUILayout.Foldout(settings.AdvancedFoldout, "Advanced");
        if (settings.AdvancedFoldout)
        {
            //~ LocalSpaceTransform field
            cubicBezierPath.LocalSpaceTransform =
                (Transform)EditorGUILayout.ObjectField(
                    "Local Space Transform",
                    cubicBezierPath.LocalSpaceTransform,
                    typeof(Transform),
                    allowSceneObjects: true
                    );
        }

        #endregion Advanced

        #region Undo

        if (newStartPosition != cubicBezierPath.LocalBezier.StartPosition ||
            newStartTangent != cubicBezierPath.LocalBezier.StartTangent ||
            newEndPosition != cubicBezierPath.LocalBezier.EndPosition ||
            newEndTangent != cubicBezierPath.LocalBezier.EndTangent)
        {
            Undo.RecordObject(target, "Edit Cubic Bezier");
            cubicBezierPath.LocalBezier.StartPosition = newStartPosition;
            cubicBezierPath.LocalBezier.StartTangent  = newStartTangent;
            cubicBezierPath.LocalBezier.EndPosition   = newEndPosition;
            cubicBezierPath.LocalBezier.EndTangent    = newEndTangent;
            EditorUtility.SetDirty(target);
        }

        #endregion Undo

        SceneView.RepaintAll();
    }
    public override void OnInspectorGUI()
    {
        //base.OnInspectorGUI();
        Safety();

        var newKnots = new List <Vector3>(targetPath.LocalBezier.Knots);

        #region Path Inspector

        settings.PathFoldout = EditorGUILayout.Foldout(settings.PathFoldout, "Path");
        if (settings.PathFoldout)
        {
            // EditorGUI.indentLevel++;

            if (newKnots.Count <= 0)
            {
                if (GUILayout.Button("+"))
                {
                    newKnots.Add(Vector3.right);
                    goto UndoHistory;
                }
            }

            for (int i = 0; i < newKnots.Count; i++)
            {
                newKnots[i] =
                    EditorGUILayout.Vector3Field(i.ToString(), newKnots[i]);

                EditorGUILayout.BeginHorizontal(EditorStyles.inspectorDefaultMargins);
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("-", GUILayout.Width(25f)))
                {
                    newKnots.RemoveAt(i);
                    goto UndoHistory;
                }

                if (GUILayout.Button("+", GUILayout.Width(25f)))
                {
                    Vector3 newKnot;
                    var     currentKnot = newKnots[i];

                    if (i == newKnots.Count - 1) // last knot
                    {
                        if (newKnots.Count == 1) // this is the only knot
                        {
                            newKnot = newKnots[0] + Vector3.right;
                        }
                        else
                        {
                            var previousKnot = newKnots[i - 1];
                            newKnot = currentKnot + (currentKnot - previousKnot);
                        }
                    }
                    else
                    {
                        var nextKnot = newKnots[i + 1];
                        newKnot = Vector3.Lerp(currentKnot, nextKnot, 0.5f);
                    }

                    newKnots.Insert(i + 1, newKnot);
                    goto UndoHistory;
                }
                EditorGUILayout.EndHorizontal();
            }

            //EditorGUI.indentLevel--;
        }

        #endregion Path Inspector

        #region Tool Settings Inspector

        PathEditorUtility.Inspector(settings, 1);

        #endregion Tool Settings Inspector

        #region Advanced

        settings.AdvancedFoldout = EditorGUILayout.Foldout(settings.AdvancedFoldout, "Advanced");
        if (settings.AdvancedFoldout)
        {
            //~ LocalSpaceTransform field
            targetPath.LocalSpaceTransform =
                (Transform)EditorGUILayout.ObjectField(
                    "Local Space Transform",
                    targetPath.LocalSpaceTransform,
                    typeof(Transform),
                    allowSceneObjects: true
                    );
        }

        #endregion Advanced

        #region Undo

UndoHistory:

        if (!targetPath.LocalBezier.Knots.SequenceEqual(newKnots) || targetPath.LocalBezier.Knots.Count != newKnots.Count)
        {
            Undo.RecordObject(target, "Edit Dynamic Bezier");
            targetPath.LocalBezier.Knots = newKnots;
            EditorUtility.SetDirty(target);
        }

        SceneView.RepaintAll();

        #endregion Undo
    }
Ejemplo n.º 10
0
    public override void OnInspectorGUI()
    {
        //base.OnInspectorGUI();
        Safety();

        var newCenter   = circlePath.LocalCircle.Center;
        var newRadius   = circlePath.LocalCircle.Radius;
        var newMaxAngle = circlePath.MaxAngle;

        #region Path Inspector

        settings.PathFoldout
            = EditorGUILayout.Foldout(settings.PathFoldout, "Path");
        if (settings.PathFoldout)
        {
            EditorGUI.indentLevel++;

            //~ Fields
            newCenter   = EditorGUILayout.Vector3Field("Local Center", circlePath.LocalCircle.Center);
            newRadius   = EditorGUILayout.FloatField("Radius", circlePath.LocalCircle.Radius);
            newMaxAngle = EditorGUILayout.FloatField("Max Angle (Degrees)", circlePath.MaxAngle * Mathf.Rad2Deg) * Mathf.Deg2Rad;

            EditorGUI.indentLevel--;
        }

        #endregion Path Inspector

        #region Tool Settings Inspector

        PathEditorUtility.Inspector(settings);

        #endregion Tool Settings Inspector

        #region Advanced

        settings.AdvancedFoldout = EditorGUILayout.Foldout(settings.AdvancedFoldout, "Advanced");
        if (settings.AdvancedFoldout)
        {
            //~ LocalSpaceTransform field
            circlePath.LocalSpaceTransform
                = (Transform)EditorGUILayout.ObjectField(
                      "Local Space Transform",
                      circlePath.LocalSpaceTransform,
                      typeof(Transform),
                      allowSceneObjects: true
                      );
        }

        #endregion Advanced

        #region Undo

        if (newCenter != circlePath.LocalCircle.Center ||
            newRadius != circlePath.LocalCircle.Radius ||
            newMaxAngle != circlePath.MaxAngle)
        {
            Undo.RecordObject(target, "Edit Circle");
            circlePath.LocalCircle.Center = newCenter;
            circlePath.LocalCircle.Radius = newRadius;
            circlePath.MaxAngle           = newMaxAngle;
            EditorUtility.SetDirty(target);
        }

        #endregion Undo

        SceneView.RepaintAll();
    }
Ejemplo n.º 11
0
    private void Draw()
    {
        Vector3    startPoint        = circlePath.Evaluate(0f);
        Vector3    endPoint          = circlePath.Evaluate(1f);
        CirclePath reducedCirclePath = new CirclePath(
            circlePath.LocalSpaceTransform,
            new Circle(circlePath.LocalCircle.Center, circlePath.LocalCircle.Radius),
            circlePath.MaxAngle % Circle.TwoPI // remove loops
            );

        if (circlePath.MaxAngle >= Circle.TwoPI) // add back a single loop if it loops
        {
            reducedCirclePath.MaxAngle += Circle.TwoPI;
        }
        else if (Mathf.Abs(circlePath.MaxAngle) >= Circle.TwoPI) // if negative maxAngle and is still at least one loop
        {
            reducedCirclePath.MaxAngle -= Circle.TwoPI;
        }

        // draw circle
        var cPointCache = new EvaluationCache(reducedCirclePath, 128).Values;

        /*Handles.color = Color.yellow;
         * Handles.DrawAAPolyLine(cPointCache);
         */
        for (int i = 0; i < cPointCache.Length - 1; i++)
        {
            Handles.color = Color.Lerp(Color.yellow, Color.magenta, (float)i / cPointCache.Length);
            var lineSegment = new Vector3[2];
            lineSegment[0] = cPointCache[i];
            lineSegment[1] = cPointCache[i + 1];
            Handles.DrawAAPolyLine(lineSegment);
        }

        // draw direction cone cap
        if (!settings.HideDirectionCones &&
            circlePath.LocalSpaceTransform.lossyScale != Vector3.zero &&
            circlePath.LocalCircle.Radius != 0f &&
            Mathf.Abs(reducedCirclePath.MaxAngle * Mathf.Rad2Deg) > 10.0f)    // also hide cones if virtually a dot
        {
            float startConeSize = PathEditorUtility.Nice3DHandleSize(startPoint);
            float endConeSize   = PathEditorUtility.Nice3DHandleSize(endPoint);

            Handles.color = Color.yellow;
            Handles.ConeCap(0, startPoint, Quaternion.LookRotation(circlePath.Tangent(0f)), startConeSize);
            Handles.color = Color.magenta;
            Handles.ConeCap(0, endPoint, Quaternion.LookRotation(circlePath.Tangent(1f)), endConeSize);
        }

        // test t
        if (settings.TestInterpolate)
        {
            PathEditorUtility.DrawTestInterpolate(circlePath, settings.EditorData.T);
        }

        #region Scene View GUI

        Handles.BeginGUI(); //Note: GUILayout.BeginArea() deprecates Handles, however it behaves incorrectly (debug lines offset)
        {
            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width));
            {
                GUILayout.Space(20.0f);
                targetScript.EditorOnlyToolSettings.TestInterpolate
                    = GUILayout.Toggle(targetScript.EditorOnlyToolSettings.TestInterpolate, "Test Interpolate", GUILayout.ExpandWidth(false));
                if (targetScript.EditorOnlyToolSettings.TestInterpolate)
                {
                    settings.EditorData.T
                        = GUILayout.HorizontalSlider(settings.EditorData.T, 0f, 1.0f, GUILayout.Width(100.0f));
                    GUILayout.Label(settings.EditorData.T.ToString(), GUILayout.Width(75.0f));
                    GUILayout.Label("Custom: ", GUILayout.Width(60.0f));
                    settings.EditorData.CustomT
                        = GUILayout.TextField(settings.EditorData.CustomT, GUILayout.Width(100.0f));
                    if (Event.current.keyCode == KeyCode.Return)
                    {
                        float tempT;
                        if (System.Single.TryParse(settings.EditorData.CustomT, out tempT))
                        {
                            settings.EditorData.T = tempT;
                        }
                    }
                }
            }
            GUILayout.EndHorizontal();
        }

        Handles.EndGUI();

        #endregion Scene View GUI

        ToolShelf();
    }