private float ShowMidpointControls(Ferr2DPath aPath, int i, PathEditorUtil.Selection aSelection, Matrix4x4 aTransform, SerializedProperty aPathProp, float aCurrDistance)
    {
        EventType eType = Event.current.type;

        // calculate distance data for finding the midpoint
        float segmentDistance = aPath.GetDistanceBetween(i, PathUtil.WrapIndex(i + 1, aPath.Count, aPath.Closed));
        float nextDistance    = aCurrDistance + segmentDistance;
        float midDist         = aCurrDistance + (segmentDistance) / 2;

        // if we have no segment on the control vert, skip this midpoint
        if (aPath.Count <= 1 || (i == aPath.Count - 1 && !aPath.Closed))
        {
            return(nextDistance);
        }

        // find the midpoint of this line
        Vector2 midPoint       = aPath.GetPointAtDistance(midDist);
        Vector2 midNormal      = aPath.GetNormalAtDistance(midDist);
        Vector3 midWorldPoint  = aTransform.MultiplyPoint(midPoint);
        Vector3 midWorldNormal = aTransform.MultiplyVector(midNormal);
        float   midSize        = eType == EventType.Layout || eType == EventType.Repaint ? HandleUtility.GetHandleSize(midWorldPoint) : 0;

        // edge override button
        int direction = aPath.GetData(i).directionOverride;

        if (terrain.EdgeMode != Ferr2D_SectionMode.None && (i == activeSegment || aSelection.IsSegmentSelected(i, aPath.Count, aPath.Closed) || direction != (int)Ferr2DT_TerrainDirection.None))
        {
            if (Event.current.alt)
            {
                if (direction != (int)Ferr2DT_TerrainDirection.None && Handles.Button(midWorldPoint + midWorldNormal * midSize * sizeLargeHandle * 2, Quaternion.identity, midSize * sizeSmallHandle, midSize * sizeSmallHandle, Ferr2DT_Caps.CapDotReset))
                {
                    aSelection.EachSegment(i, aPath.Count, aPath.Closed, id => {
                        SerializedProperty overrideProp = aPathProp.FindPropertyRelative("_data").GetArrayElementAtIndex(id).FindPropertyRelative("directionOverride");
                        overrideProp.intValue           = (int)Ferr2DT_TerrainDirection.None;
                    });
                }
            }
            else
            {
                if (Handles.Button(midWorldPoint + midWorldNormal * midSize * sizeLargeHandle * 2, Quaternion.identity, midSize * sizeSmallHandle, midSize * sizeSmallHandle, Ferr2DT_Caps.GetEdgeCap(direction)))
                {
                    CycleEdgeOverride(aPathProp, i);
                    SerializedProperty cycledOverride = aPathProp.FindPropertyRelative("_data").GetArrayElementAtIndex(i).FindPropertyRelative("directionOverride");
                    aSelection.EachSegment(i, aPath.Count, aPath.Closed, id => {
                        SerializedProperty overrideProp = aPathProp.FindPropertyRelative("_data").GetArrayElementAtIndex(id).FindPropertyRelative("directionOverride");
                        overrideProp.intValue           = cycledOverride.intValue;
                    });
                }
            }
        }

        // new point button
        if (!Event.current.alt && i == activeSegment && Handles.Button(midWorldPoint, Quaternion.identity, midSize * sizeLargeHandle, midSize * sizeLargeHandle, Ferr2DT_Caps.CapDotPlus))
        {
            PathEditorUtil.AddPoint(aPathProp, midPoint, i + 1);
            ProcessNewPoint(aPathProp, i + 1);
        }

        return(nextDistance);
    }
    private void  ShowTexSegmentSelect(Ferr2DPath aPath, SerializedProperty aPathProp, Matrix4x4 aTransform)
    {
        // calculate segment information for displaying the handles correctly
        List <Ferr2DT_PathTerrain.EdgeSegment> segments = Ferr2DT_PathTerrain.EdgeSegment.CreateEdgeSegments(aPath, terrain.splitCorners);
        bool    invert = terrain.EdgeMode == Ferr2D_SectionMode.Invert;
        Vector2 upUV   = terrain.UnitsPerUV;

        for (int i = 0; i < segments.Count; i++)
        {
            // get our segment data, and see if we have any data to override with
            var edgeSegment = segments[i];
            edgeSegment.direction = invert ? Ferr2DT_PathTerrain.Invert(edgeSegment.direction) : edgeSegment.direction;
            var edgeData = terrain.TerrainMaterial.GetDescriptor(edgeSegment.direction);
            if (edgeData.BodyCount < 2)
            {
                continue;
            }

            bool  rightInner = edgeSegment.path.GetInteriorAngle(edgeSegment.start) > 180;
            float rightOff   = edgeData.GetRightCapOffset(invert? !rightInner:rightInner, upUV);

            // calculate all the texture segments present
            List <int> texSources  = new List <int>();
            float      scale       = 0;
            List <int> texSegments = terrain.CreateLineList(edgeSegment, out scale, texSources);

            // now go and add handles for all the texture segments
            for (int t = 0; t < texSegments.Count; t++)
            {
                // find handle location
                float   segDist = TexDistAtSegment(edgeSegment, edgeData, texSegments, t) * scale;
                Vector3 pt      = aTransform.MultiplyPoint(aPath.GetPointAtDistance(edgeSegment.startDistance - rightOff + segDist));
                float   size    = HandleUtility.GetHandleSize(pt);

                // figure out what our data says about this segment, if anything
                int cutPointId   = texSources[t * 2];
                int cutId        = texSources[t * 2 + 1];
                int cutValue     = 0;
                var cutOverrides = aPath.GetData(cutPointId).cutOverrides;
                if (cutOverrides != null && cutOverrides.Count > cutId)
                {
                    cutValue = cutOverrides[cutId];
                }

                // and execute the handles
                if (Event.current.alt)
                {
                    if (cutValue != 0 && Handles.Button(pt, Quaternion.identity, size * sizeSmallHandle, size * sizeSmallHandle, Ferr2DT_Caps.CapDotReset))
                    {
                        SerializedProperty cutProp        = aPathProp.FindPropertyRelative("_data").GetArrayElementAtIndex(cutPointId).FindPropertyRelative("cutOverrides");
                        SerializedProperty segCutProperty = cutProp.GetArrayElementAtIndex(cutId);
                        segCutProperty.intValue = 0;
                    }
                }
                else
                {
                    if (Handles.Button(pt, Quaternion.identity, size * sizeSmallHandle, size * sizeSmallHandle, Ferr2DT_Caps.GetNumberCap(cutValue)))
                    {
                        SerializedProperty cutProp = aPathProp.FindPropertyRelative("_data").GetArrayElementAtIndex(cutPointId).FindPropertyRelative("cutOverrides");
                        while (cutProp.arraySize <= cutId)
                        {
                            cutProp.arraySize += 1;
                            cutProp.GetArrayElementAtIndex(cutProp.arraySize - 1).intValue = 0;
                        }
                        while (cutProp.arraySize > texSegments.Count)
                        {
                            cutProp.arraySize--;
                        }
                        SerializedProperty segCutProperty = cutProp.GetArrayElementAtIndex(cutId);
                        segCutProperty.intValue = (segCutProperty.intValue + 1) % (edgeData.BodyCount + 1);
                    }
                }
            }
        }
    }