private static void LayoutSelectionHandles(PathMovementProxy path)
    {
        for (int i = 0; i < path.NumPoints; ++i)
        {
            PathMovementProxy.Point p = path[i];

            if (!p.makeSmoothTangent)
            {
                Handles.CubeHandleCap(
                    p.controlId,
                    p.position,
                    Quaternion.identity,
                    .3f,
                    EventType.Layout);
            }
            else
            {
                Handles.SphereHandleCap(
                    p.controlId,
                    p.position,
                    Quaternion.identity,
                    .3f,
                    EventType.Layout);
            }
        }
    }
    private static void DrawSelectionHandles(PathMovementProxy path)
    {
        for (int i = 0; i < path.NumPoints; ++i)
        {
            PathMovementProxy.Point p = path[i];

            Handles.color = p.isSelected ? Color.blue : Color.white;

            if (!p.makeSmoothTangent)
            {
                Handles.CubeHandleCap(
                    p.controlId,
                    p.position,
                    Quaternion.identity,
                    .3f,
                    EventType.Repaint);
            }
            else
            {
                Handles.SphereHandleCap(
                    p.controlId,
                    p.position,
                    Quaternion.identity,
                    .3f,
                    EventType.Repaint);
            }
        }
    }
 private static void MovePoint(PathMovementProxy.Point pt, Vector3 offset)
 {
     pt.position   += offset;
     pt.inTangent  += offset;
     pt.outTangent += offset;
 }
    private static void UpdatePoint(PathMovementProxy path, int idx, bool lockTangentLength)
    {
        PathMovementProxy.Point p = path[idx];
        Vector3 newPoint;

        // update inTangent
        if ((path.HasLoop && path.loopIndex == 0) || idx > 0)
        {
            EditorGUI.BeginChangeCheck();
            newPoint = Handles.PositionHandle(p.inTangent, Quaternion.identity);
            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(path, "Move In Tangent " + idx);
                EditorUtility.SetDirty(path);
                if (!lockTangentLength)
                {
                    p.inTangent = newPoint;
                }
                // lock distance
                else
                {
                    Vector3 direction = (newPoint - p.position);
                    direction.Normalize();
                    direction  *= (p.inTangent - p.position).magnitude;
                    p.inTangent = p.position + direction;
                }

                // make all 3 points colinear
                if (p.makeSmoothTangent)
                {
                    p.outTangent = AlignPoints(p.inTangent,
                                               p.position, p.outTangent);
                }
            }
        }

        // update outTangent
        if (path.HasLoop || idx < path.points.Count - 1)
        {
            EditorGUI.BeginChangeCheck();
            newPoint = Handles.PositionHandle(p.outTangent, Quaternion.identity);
            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(path, "Move Out Tangent " + idx);
                EditorUtility.SetDirty(path);
                if (!lockTangentLength)
                {
                    p.outTangent = newPoint;
                }
                // lock distance
                else
                {
                    Vector3 direction = (newPoint - p.position);
                    direction.Normalize();
                    direction   *= (p.outTangent - p.position).magnitude;
                    p.outTangent = p.position + direction;
                }

                // make all 3 points colinear
                if (p.makeSmoothTangent)
                {
                    p.inTangent = AlignPoints(p.outTangent,
                                              p.position, p.inTangent);
                }
            }
        }

        // update position
        EditorGUI.BeginChangeCheck();
        newPoint = Handles.PositionHandle(p.position, Quaternion.identity);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(path, "Move Point " + idx);
            EditorUtility.SetDirty(path);

            // move all selected points
            Vector3 diff = newPoint - p.position;
            foreach (PathMovementProxy.Point point in path.points)
            {
                if (point.isSelected)
                {
                    MovePoint(point, diff);
                }
            }
        }
    }