示例#1
0
        private static BGCurvePoint CreatePointBetween(BGCurve curve, BGCurvePointI previousPoint, BGCurvePointI nextPoint, int parts, BGCurvePoint.ControlTypeEnum controlType)
        {
            var newPos  = BGEditorUtility.CalculatePosition(previousPoint, nextPoint, .5f);
            var tangent = BGEditorUtility.CalculateTangent(previousPoint, nextPoint, .5f);

            return(CreatePointBetween(curve, previousPoint, nextPoint, parts, controlType, newPos, tangent));
        }
示例#2
0
        /// <summary>find referenced point, attached to target gameobject </summary>
        public static BGCurveReferenceToPoint GetReferenceToPoint(BGCurvePointI point)
        {
            if (point.PointTransform == null)
            {
                return(null);
            }
            var referencesToPoints = point.PointTransform.GetComponents <BGCurveReferenceToPoint>();

            if (referencesToPoints.Length == 0)
            {
                return(null);
            }


            var length = referencesToPoints.Length;

            for (var i = 0; i < length; i++)
            {
                var referencesToPoint = referencesToPoints[i];
                if (referencesToPoint.Point == point)
                {
                    return(referencesToPoint);
                }
            }
            return(null);
        }
示例#3
0
    void ReversePoint(BGCurvePointI p)
    {
        var temp = p.ControlFirstLocal;

        p.ControlFirstLocal  = p.ControlSecondLocal;
        p.ControlSecondLocal = temp;
    }
 private static void ShowFields(BGCurvePointI point)
 {
     foreach (var field in point.Curve.Fields.Where(BGPrivateField.GetShowInPointsMenu))
     {
         ShowField(point, field);
     }
 }
示例#5
0
        public static BGCurvePoint CreatePointBetween(BGCurve curve, BGCurvePointI previousPoint, BGCurvePointI nextPoint, int parts, BGCurvePoint.ControlTypeEnum controlType,
                                                      Vector3 position, Vector3 tangent)
        {
            var scaledTangent = tangent * DistanceToTangentMultiplier * BGEditorUtility.CalculateDistance(previousPoint, nextPoint, parts);

            return(curve.CreatePointFromLocalPosition(curve.ToLocal(position), controlType, curve.ToLocalDirection(-scaledTangent), curve.ToLocalDirection(scaledTangent)));
        }
 /// <summary>Init and get event instance</summary>
 public static BGCurveChangedArgs GetInstance(BGCurve curve, BGCurvePointI point, string changesInTransaction)
 {
     Instance.curve      = curve;
     Instance.changeType = ChangeTypeEnum.Point;
     Instance.message    = BGCurve.EventTransaction;
     Instance.point      = point;
     return(Instance);
 }
示例#7
0
        private static BGCurvePoint CreatePointBetween(BGCurve curve, BGCurvePointI previousPoint, BGCurvePointI nextPoint, int parts, BGCurvePoint.ControlTypeEnum controlType)
        {
            var newPos  = BGEditorUtility.CalculatePosition(previousPoint, nextPoint, .5f);
            var tangent = BGEditorUtility.CalculateTangent(previousPoint, nextPoint, .5f);

            var scaledTangent = tangent * DistanceToTangentMultiplier * BGEditorUtility.CalculateDistance(previousPoint, nextPoint, parts);

            return(curve.CreatePointFromLocalPosition(curve.ToLocal(newPos), controlType, curve.ToLocalDirection(-scaledTangent), curve.ToLocalDirection(scaledTangent)));
        }
        private void PointButtons(BGCurvePointI point, int index, BGCurveSettings settings)
        {
            if (!settings.ShowPointMenu)
            {
                return;
            }

            var curve = point.Curve;

            //================== Copy
            if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGCopy123, PointCopyPaste.Instance.CopyTooltip))
            {
                PointCopyPaste.Instance.Copy(point);
            }
            GUILayout.Space(2);

            //================== Paste
            if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGPaste123, PointCopyPaste.Instance.PasteTooltip))
            {
                PointCopyPaste.Instance.Paste(point);
            }
            GUILayout.Space(2);

            //================== Add before
            if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGAdd123, "Insert a point before this point"))
            {
                BGCurveEditor.AddPoint(curve, BGNewPointPositionManager.InsertBefore(curve, index, settings.ControlType, settings.Sections), index);
            }
            GUILayout.Space(2);


            //=========================== Move Up
            if (index > 0 && BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGMoveUp123, "Move the point up"))
            {
                curve.Swap(index - 1, index);
            }
            GUILayout.Space(2);

            //=========================== Move Down
            if (index < curve.PointsCount - 1 && BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGMoveDown123, "Move the point down"))
            {
                curve.Swap(index, index + 1);
            }
            GUILayout.Space(2);


            //=========================== Delete
            if (BGEditorUtility.ButtonWithIcon(BGBinaryResources.BGDelete123, "Delete the point"))
            {
                BGCurveEditor.DeletePoint(curve, index);
                if (editorSelection != null)
                {
                    editorSelection.Remove(point);
                }
                GUIUtility.ExitGUI();
            }
        }
            public void On(BGCurvePointI point, int index)
            {
                PointIndex = index;
                this.point = point;
                On(point.PositionWorld);

                Get(0).Current = point.ControlType == BGCurvePoint.ControlTypeEnum.Absent;
                Get(1).Current = point.ControlType == BGCurvePoint.ControlTypeEnum.BezierSymmetrical;
                Get(2).Current = point.ControlType == BGCurvePoint.ControlTypeEnum.BezierIndependant;
            }
            public void Copy(BGCurvePointI point)
            {
                controlType              = point.ControlType;
                positionLocal            = point.PositionLocal;
                control1LocalTransformed = point.ControlFirstLocalTransformed;
                control2LocalTransformed = point.ControlSecondLocalTransformed;
                pointTransform           = point.PointTransform;

                InitPasteTooltip();
            }
示例#11
0
 public bool Remove(BGCurvePointI point)
 {
     if (!Contains(point))
     {
         return(false);
     }
     Changed = true;
     points.Remove(point);
     return(true);
 }
示例#12
0
    void CreateSpline()
    {
        var splineObject    = new GameObject("MultipathSpline");
        var splineTransform = splineObject.transform;

        splineTransform.SetParent(transform);

        CreateSplineComponents(splineObject);

        BGCurvePointI firstPoint = null, lastPoint = null;
        var           segment = startingSegment;

        while (segment != null)
        {
            var isFirstSegment = (segment == startingSegment);
            var isLastSegment  = (segment.nextSegment == startingSegment || segment.nextSegment == null);
            var isClosed       = isLastSegment && (segment.nextSegment == startingSegment);

            var s = segment.spline;
            if (!segment.inversed)
            {
                for (var i = 0; i < s.PointsCount; i++)
                {
                    var p = s.Points[i];

                    var isFirstPoint = (i == 0);
                    var isLastPoint  = (i == s.PointsCount - 1);

                    CopyPointToSpline(p, isFirstPoint, isLastPoint, isFirstSegment, isLastSegment, isClosed, segment.inversed, s, ref firstPoint, ref lastPoint);
                }
            }
            else
            {
                for (var i = s.PointsCount - 1; i >= 0; i--)
                {
                    var p = s.Points[i];

                    var isFirstPoint = (i == s.PointsCount - 1);
                    var isLastPoint  = (i == 0);

                    CopyPointToSpline(p, isFirstPoint, isLastPoint, isFirstSegment, isLastSegment, isClosed, segment.inversed, s, ref firstPoint, ref lastPoint);
                }
            }

            Destroy(segment.spline.gameObject);
            segment.processed = true;
            segment           = segment.nextSegment;

            if (isClosed)
            {
                spline.Closed = true;
                return;
            }
        }
    }
 public void Paste(BGCurvePointI point)
 {
     point.Curve.Transaction(() =>
     {
         point.ControlType   = controlType;
         point.PositionLocal = positionLocal;
         point.ControlFirstLocalTransformed  = control1LocalTransformed;
         point.ControlSecondLocalTransformed = control2LocalTransformed;
         point.PointTransform = pointTransform;
     });
 }
示例#14
0
        public bool Add(BGCurvePointI point)
        {
            if (Contains(point))
            {
                return(false);
            }

            Changed = true;
            points.Add(point);
            return(true);
        }
示例#15
0
 //if we selecting or removing selection
 public void GroupSelection(BGCurvePointI point)
 {
     if (groupSelectionIsSelecting)
     {
         Add(point);
     }
     else
     {
         Remove(point);
     }
 }
示例#16
0
        private void FillInterpolationInfo(ref int sectionIndex, out BGCurvePointI fromPoint, out BGCurvePointI toPoint, out float ratio)
        {
            if (sectionIndex == -1)
            {
                sectionIndex = CalculateSectionIndex();
            }

            fromPoint = Curve[sectionIndex];
            toPoint   = sectionIndex == Curve.PointsCount - 1 ? Curve[0] : Curve[sectionIndex + 1];
            var sectionInfo = Math[sectionIndex];

            ratio = (Distance - sectionInfo.DistanceFromStartToOrigin) / (sectionInfo.DistanceFromEndToOrigin - sectionInfo.DistanceFromStartToOrigin);
        }
        private void PositionField(string name, BGCurvePointI point, BGCurve.Mode2DEnum mode2D, int index)
        {
            var math = mathProvider();

            Vector3          pos;
            Action <Vector3> newValueAction;
            string           tooltipDetails;
            string           details;

            switch ((BGCurveSettingsForEditor.CoordinateSpaceEnum)BGCurveSettingsForEditor.I.Get <int>(BGCurveSettingsForEditor.InspectorPointsCoordinatesKey))
            {
            case BGCurveSettingsForEditor.CoordinateSpaceEnum.World:
                pos            = math == null ? point.PositionWorld : math.GetPosition(index);
                newValueAction = vector3 => point.PositionWorld = vector3;
                tooltipDetails = "world";
                details        = "W";
                break;

            case BGCurveSettingsForEditor.CoordinateSpaceEnum.LocalTransformed:
                pos            = point.PositionLocalTransformed;
                newValueAction = vector3 => point.PositionLocalTransformed = vector3;
                tooltipDetails = "local transformed";
                details        = "LT";
                break;

            case BGCurveSettingsForEditor.CoordinateSpaceEnum.Local:
                pos            = point.PositionLocal;
                newValueAction = vector3 => point.PositionLocal = vector3;
                tooltipDetails = "local";
                details        = "L";
                break;

            default:
                throw new ArgumentOutOfRangeException("BGCurveSettingsForEditor.InspectorPointCoordinates");
            }

            BGEditorUtility.SwapLabelWidth(80, () =>
            {
                var label   = name + "(" + details + ")";
                var tooltip = "Point's position in " + tooltipDetails + " space. You can change points space in BGCurve Editor settings (gear icon)";

                if (mode2D == BGCurve.Mode2DEnum.Off)
                {
                    BGEditorUtility.Vector3Field(label, tooltip, pos, newValueAction);
                }
                else
                {
                    Vector2Field(label, tooltip, pos, mode2D, newValueAction);
                }
            });
        }
        protected virtual void OnEnable()
        {
            point = Point;

            pointEditor = new BGCurveEditorPoint(() => null, null);

            if (curveEditor != null)
            {
                curveEditor.OnDestroy();
            }

            curveEditor = (BGCurveEditor)CreateEditor(point.Curve);

            PointSelected = true;
        }
示例#19
0
    void Start()
    {
        rightView = true;

        math      = Curve.GetComponent <BGCcMath>();
        headPoint = Curve.Points[0];
        midPoint  = Curve.Points[1];
        tailPoint = Curve.Points[2];

        Length      = math.GetDistance();
        minDistance = Length * 0.5f;
        prevLength  = Length;

        //UpdateBones();
    }
示例#20
0
        private IEnumerator MoveHandleTo(BGCurvePointI point, Vector3 pos1, Vector3 pos2)
        {
            Vector3 currentPos1 = point.ControlFirstWorld;
            Vector3 currentPos2 = point.ControlSecondWorld;

            float duration  = 2f;
            float startTime = Time.time;

            while (Time.time - startTime < duration)
            {
                point.ControlFirstWorld  = currentPos1 + (pos1 - currentPos1) * ((Time.time - startTime) / duration);
                point.ControlSecondWorld = currentPos2 + (pos2 - currentPos2) * ((Time.time - startTime) / duration);
                yield return(null);
            }
        }
示例#21
0
        //draw interactible selection icon control
        public void InspectorSelectionRect(BGCurvePointI point)
        {
            var currentEvent = Event.current;
            var rect         = GUILayoutUtility.GetRect(24, 24, 24, 24, new GUIStyle {
                fixedWidth = 24, fixedHeight = 24, stretchWidth = false, stretchHeight = false
            });

            if (currentEvent.isMouse)
            {
                if (currentEvent.type == EventType.mouseDown)
                {
                    if (rect.Contains(currentEvent.mousePosition))
                    {
                        groupSelectionStarted     = true;
                        groupSelectionIsSelecting = !Contains(point);
                        GroupSelection(point);
                    }
                }
                else if (groupSelectionStarted)
                {
                    switch (currentEvent.type)
                    {
                    case EventType.MouseUp:
                        groupSelectionStarted = false;
                        break;

                    case EventType.MouseDrag:
                        if (rect.Contains(currentEvent.mousePosition))
                        {
                            GroupSelection(point);
                        }
                        break;
                    }
                }
            }

            var selected        = Contains(point);
            var selectedTexture = selected ? tickYesTexture : tickNoTexture;
            var labelStyle      = selected ? new GUIStyle("Label")
            {
                normal = new GUIStyleState {
                    textColor = settings.LabelColorSelected
                }
            } : EditorStyles.label;

            EditorGUI.LabelField(rect, new GUIContent(selectedTexture, "Click to (de)select a point, or click and drag to (de)select multiple points. " +
                                                      "Hold shift to use rectangular selection"), labelStyle);
        }
示例#22
0
    void CopyPointToSpline(
        BGCurvePointI p,
        bool isFirstPoint, bool isLastPoint,
        bool isFirstSegment, bool isLastSegment,
        bool isClosed,
        bool inversed,
        BGCurve originalCurve,
        ref BGCurvePointI firstPoint,
        ref BGCurvePointI lastPoint
        )
    {
        if (isFirstSegment)
        {
            AddSplinePoint(p, originalCurve, ref lastPoint);

            if (isFirstPoint)
            {
                firstPoint = lastPoint;
            }

            return;
        }

        if (isFirstPoint && !isFirstSegment)
        {
            lastPoint.ControlSecondWorld = inversed ? p.ControlFirstWorld : p.ControlSecondWorld;

            return;
        }

        if (isLastPoint && inversed)
        {
            ReversePoint(p);
        }

        if (isLastSegment && isLastPoint)
        {
            firstPoint.ControlFirstWorld = p.ControlFirstWorld;

            if (isClosed)
            {
                return;
            }
        }

        AddSplinePoint(p, originalCurve, ref lastPoint);
    }
示例#23
0
    void AddSplinePoint(BGCurvePointI p, BGCurve originalCurve, ref BGCurvePointI point)
    {
        point = spline.AddPoint(
            new BGCurvePoint(
                spline,
                p.PositionWorld,
                BGCurvePoint.ControlTypeEnum.BezierIndependant,
                p.ControlFirstWorld,
                p.ControlSecondWorld,
                true
                )
            );

        var normal = originalCurve.transform.rotation * p.GetVector3(Keys.NORMAL_FIELD);

        point.SetVector3(Keys.NORMAL_FIELD, normal);
    }
        protected virtual void OnEnable()
        {
            point = Point;

            pointEditor = new BGCurveEditorPoint(() => null, null);

            if (curveEditor != null)
            {
                curveEditor.OnDestroy();
            }

            curveEditor = (BGCurveEditor)CreateEditor(point.Curve);

            pointSelectedTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPointSelected123);

            PointSelected = true;
        }
        private void ControlField(BGCurvePointI point, BGCurve.Mode2DEnum mode2D, int index)
        {
            Vector3          pos;
            string           tooltipDetails, details;
            Action <Vector3> newValueAction;

            switch ((BGCurveSettingsForEditor.CoordinateSpaceEnum)BGCurveSettingsForEditor.I.Get <int>(BGCurveSettingsForEditor.InspectorControlsCoordinatesKey))
            {
            case BGCurveSettingsForEditor.CoordinateSpaceEnum.Local:
                tooltipDetails = "local";
                details        = "L";
                if (index == 1)
                {
                    pos            = point.ControlFirstLocal;
                    newValueAction = vector3 => point.ControlFirstLocal = vector3;
                }
                else
                {
                    pos            = point.ControlSecondLocal;
                    newValueAction = vector3 => point.ControlSecondLocal = vector3;
                }
                break;

            case BGCurveSettingsForEditor.CoordinateSpaceEnum.LocalTransformed:
                tooltipDetails = "local transformed";
                details        = "LT";

                if (index == 1)
                {
                    pos            = point.ControlFirstLocalTransformed;
                    newValueAction = vector3 => point.ControlFirstLocalTransformed = vector3;
                }
                else
                {
                    pos            = point.ControlSecondLocalTransformed;
                    newValueAction = vector3 => point.ControlSecondLocalTransformed = vector3;
                }
                break;

            case BGCurveSettingsForEditor.CoordinateSpaceEnum.World:
                tooltipDetails = "world";
                details        = "W";

                if (index == 1)
                {
                    pos            = point.ControlFirstWorld;
                    newValueAction = vector3 => point.ControlFirstWorld = vector3;
                }
                else
                {
                    pos            = point.ControlSecondWorld;
                    newValueAction = vector3 => point.ControlSecondWorld = vector3;
                }
                break;

            default:
                throw new ArgumentOutOfRangeException("BGCurveSettingsForEditor.InspectorPointControlsCoordinates");
            }

            var label   = "Control " + index + " (" + details + ")";
            var tooltip = "Point " + (index == 0 ? "1st" : "2nd") + " control position in " + tooltipDetails + " space. You can change points space in BGCurve Editor settings (gear icon)";



            if (mode2D == BGCurve.Mode2DEnum.Off)
            {
                BGEditorUtility.Vector3Field(label, tooltip, pos, newValueAction);
            }
            else
            {
                Vector2Field(label, tooltip, pos, mode2D, newValueAction);
            }
        }
        public void OnSceneGUI(BGCurvePointI point, int index, BGCurveSettings settings, Quaternion rotation, Plane[] frustum)
        {
            var math          = mathProvider();
            var positionWorld = math == null ? point.Curve[index].PositionWorld : math.GetPosition(index);

            //adjust rotation
            if (point.PointTransform != null)
            {
                rotation = BGCurveEditorPoints.GetRotation(point.PointTransform);
            }
            else if (point.Curve.PointsMode == BGCurve.PointsModeEnum.GameObjectsTransform)
            {
                rotation = BGCurveEditorPoints.GetRotation(((BGCurvePointGO)point).transform);
            }

            var isShowingGizmoz = settings.RestrictGizmozSettings.IsShowing(index);

            if (settings.ShowControlHandles && settings.ShowCurve && (editorSelection == null || !editorSelection.HasSelected() || editorSelection.SingleSelected(point)))
            {
                // ============================================== Controls Handles
                if (point.ControlType != BGCurvePoint.ControlTypeEnum.Absent)
                {
                    if (isShowingGizmoz)
                    {
                        var controlFirstWorld  = math == null ? point.Curve[index].ControlFirstWorld : math.GetControlFirst(index);
                        var controlSecondWorld = math == null ? point.Curve[index].ControlSecondWorld : math.GetControlSecond(index);

                        BGEditorUtility.SwapHandlesColor(settings.ControlHandlesColor, () =>
                        {
                            Handles.DrawLine(positionWorld, controlFirstWorld);
                            Handles.DrawLine(positionWorld, controlSecondWorld);

                            if (ShowingHandles)
                            {
                                // control handles different types
                                var newPositionFirst  = BGEditorUtility.Handle(GetUniqueNumber(index) - 1, settings.ControlHandlesType, controlFirstWorld, rotation, settings.ControlHandlesSettings);
                                var newPositionSecond = BGEditorUtility.Handle(GetUniqueNumber(index) - 2, settings.ControlHandlesType, controlSecondWorld, rotation, settings.ControlHandlesSettings);

                                if (BGEditorUtility.AnyChange(controlFirstWorld, newPositionFirst))
                                {
                                    point.ControlFirstWorld = newPositionFirst;
                                }
                                if (BGEditorUtility.AnyChange(controlSecondWorld, newPositionSecond))
                                {
                                    point.ControlSecondWorld = newPositionSecond;
                                }
                            }
                        });

                        if (settings.ShowControlLabels)
                        {
                            ShowControlLabel(settings, frustum, controlFirstWorld, point.ControlFirstLocal, "1");
                            ShowControlLabel(settings, frustum, controlSecondWorld, point.ControlSecondLocal, "2");
                        }
                    }
                }
            }

            //if only one point is selected and this is the selected point- do not print anything further
            if (editorSelection != null && editorSelection.HasSelected() && editorSelection.SingleSelected(point))
            {
                return;
            }

            // ============================================== Move Handles
            if ((editorSelection == null || !editorSelection.HasSelected()) && settings.ShowCurve && settings.ShowHandles && ShowingHandles && isShowingGizmoz)
            {
                var newPos = BGEditorUtility.Handle(GetUniqueNumber(index), settings.HandlesType, positionWorld, rotation, settings.HandlesSettings);

                if (BGEditorUtility.AnyChange(positionWorld, newPos))
                {
                    point.PositionWorld = newPos;
                }
            }
        }
 //Reset pooled section with new data and recalculates if needed
 protected override bool Reset(SectionInfo section, BGCurvePointI @from, BGCurvePointI to, int pointsCount)
 {
     return(section.Reset(@from, to, section.PointsCount, ignoreSectionChangedCheck || ignoreSectionChangedCheckOverride));
 }
        public static void ShowField(BGCurvePointI point, BGCurvePointField field, Action <string, AnimationCurve> animationCurveCallback = null)
        {
            var name = point.Curve.IndexOf(field) + ") " + field.FieldName;

            switch (field.Type)
            {
            case BGCurvePointField.TypeEnum.Bool:
                BGEditorUtility.BoolField(name, point.GetField <bool>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.Int:
                BGEditorUtility.IntField(name, point.GetField <int>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.Float:
                BGEditorUtility.FloatField(name, point.GetField <float>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.Vector3:
                BGEditorUtility.Vector3Field(name, null, point.GetField <Vector3>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.Bounds:
                BGEditorUtility.BoundsField(name, point.GetField <Bounds>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.Color:
                BGEditorUtility.ColorField(name, point.GetField <Color>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.String:
                BGEditorUtility.TextField(name, point.GetField <string>(field.FieldName), v => point.SetField(field.FieldName, v), false);
                break;

            case BGCurvePointField.TypeEnum.AnimationCurve:
                BGEditorUtility.Horizontal(() =>
                {
                    BGEditorUtility.AnimationCurveField(name, point.GetField <AnimationCurve>(field.FieldName), v => point.SetField(field.FieldName, v));

                    if (animationCurveCallback != null && GUILayout.Button("Set", GUILayout.Width(40)))
                    {
                        animationCurveCallback(field.FieldName, point.GetField <AnimationCurve>(field.FieldName));
                    }
                });

                break;

            case BGCurvePointField.TypeEnum.Quaternion:
                BGEditorUtility.QuaternionField(name, point.GetField <Quaternion>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.GameObject:
                BGEditorUtility.GameObjectField(name, point.GetField <GameObject>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.Component:
                BGEditorUtility.ComponentChoosableField(name, point.GetField <Component>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.BGCurve:
                BGEditorUtility.BGCurveField(name, point.GetField <BGCurve>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;

            case BGCurvePointField.TypeEnum.BGCurvePointComponent:
                BGEditorUtility.Horizontal(() =>
                {
                    BGEditorUtility.BGCurvePointComponentField(name, point.GetField <BGCurvePointComponent>(field.FieldName), v => point.SetField(field.FieldName, v));
                    var currentPoint = point.GetField <BGCurvePointComponent>(field.FieldName);

                    if (currentPoint == null || currentPoint.Curve.PointsCount < 2)
                    {
                        return;
                    }

                    var indexOfField = currentPoint.Curve.IndexOf(currentPoint);

                    if (GUILayout.Button("" + indexOfField, GUILayout.Width(40)))
                    {
                        BGCurveChosePointWindow.Open(indexOfField, currentPoint.Curve, c => point.SetField(field.FieldName, c));
                    }
                });
                break;

            case BGCurvePointField.TypeEnum.BGCurvePointGO:
                BGEditorUtility.BGCurvePointGOField(name, point.GetField <BGCurvePointGO>(field.FieldName), v => point.SetField(field.FieldName, v));
                break;
            }
        }
        internal void OnInspectorGui(BGCurvePointI point, int index, BGCurveSettings settings)
        {
            var mode2D = point.Curve.Mode2D;


            //point transform
            if (point.Curve.PointsMode != BGCurve.PointsModeEnum.Inlined && point.PointTransform != null)
            {
                var referenceToPoint = BGCurveReferenceToPoint.GetReferenceToPoint(point);
                if (referenceToPoint == null)
                {
                    point.PointTransform.gameObject.AddComponent <BGCurveReferenceToPoint>().Point = point;
                }
            }

            BGEditorUtility.HorizontalBox(() =>
            {
                if (editorSelection != null)
                {
                    editorSelection.InspectorSelectionRect(point);
                }

                BGEditorUtility.VerticalBox(() =>
                {
                    BGEditorUtility.SwapLabelWidth(60, () =>
                    {
                        if (!settings.ShowPointPosition && !settings.ShowPointControlType)
                        {
                            BGEditorUtility.Horizontal(() =>
                            {
                                //nothing to show- only label
                                EditorGUILayout.LabelField("Point " + index);
                                PointButtons(point, index, settings);
                            });
                            BGEditorUtility.StartIndent(1);
                        }
                        else
                        {
                            //control type
                            if (settings.ShowPointControlType)
                            {
                                BGEditorUtility.Horizontal(() =>
                                {
                                    point.ControlType = (BGCurvePoint.ControlTypeEnum)EditorGUILayout.EnumPopup("Point " + index, point.ControlType);
                                    PointButtons(point, index, settings);
                                });
                                BGEditorUtility.StartIndent(1);
                            }

                            //position
                            if (settings.ShowPointPosition)
                            {
                                if (!settings.ShowPointControlType)
                                {
                                    BGEditorUtility.Horizontal(() =>
                                    {
                                        PositionField("Point " + index, point, mode2D, index);
                                        PointButtons(point, index, settings);
                                    });
                                    BGEditorUtility.StartIndent(1);
                                }
                                else
                                {
                                    PositionField("Pos", point, mode2D, index);
                                }
                            }
                        }
                    });

                    // control positions
                    if (point.ControlType != BGCurvePoint.ControlTypeEnum.Absent && settings.ShowPointControlPositions)
                    {
                        // 1st
                        ControlField(point, mode2D, 1);

                        // 2nd
                        ControlField(point, mode2D, 2);
                    }

                    //transform
                    if (settings.ShowTransformField)
                    {
                        BGEditorUtility.ComponentField("Transform", point.PointTransform, transform =>
                        {
                            if (transform != null)
                            {
                                Undo.RecordObject(transform, "Object moved");

                                if (point.Curve.PointsMode != BGCurve.PointsModeEnum.Inlined)
                                {
                                    Undo.AddComponent <BGCurveReferenceToPoint>(transform.gameObject).Point = point;
                                }
                            }

                            if (point.PointTransform != null)
                            {
                                var referenceToPoint = BGCurveReferenceToPoint.GetReferenceToPoint(point);
                                if (referenceToPoint != null)
                                {
                                    Undo.DestroyObjectImmediate(referenceToPoint);
                                }
                            }

                            point.PointTransform = transform;
                        });
                    }


                    //fields
                    if (point.Curve.FieldsCount > 0)
                    {
                        ShowFields(point);
                    }

                    BGEditorUtility.EndIndent(1);
                });
            });
        }
        //approximate split section
        //this method contains some intentional copy/paste
        protected override void CalculateSplitSection(SectionInfo section, BGCurvePointI @from, BGCurvePointI to)
        {
            //if set to true, tangent formula will be used to calc tangents
            var calcTangents = cacheTangent && !config.UsePointPositionsToCalcTangents;


            var points = section.points;
            var count  = points.Count;

            //move all existing points to the pool (the number of points depends on the curvature)
            for (var i = 0; i < count; i++)
            {
                poolPointInfos.Add(points[i]);
            }
            points.Clear();

            //original points and control types
            var p0 = section.OriginalFrom;
            var p1 = section.OriginalFromControl;
            var p2 = section.OriginalToControl;
            var p3 = section.OriginalTo;

            //type of the curve (0-absent,3-both Bezier, 1 or 2 - one of the points has Bezier controls)
            var type = (section.OriginalFromControlType != BGCurvePoint.ControlTypeEnum.Absent ? 2 : 0) + (section.OriginalToControlType != BGCurvePoint.ControlTypeEnum.Absent ? 1 : 0);

            //=====================================   first point
            SectionPointInfo firstPoint;
            var poolCursor = poolPointInfos.Count - 1;

            if (poolCursor >= 0)
            {
                firstPoint = poolPointInfos[poolCursor];
                poolPointInfos.RemoveAt(poolCursor);
            }
            else
            {
                firstPoint = new SectionPointInfo();
            }
            firstPoint.Position = p0;
            firstPoint.DistanceToSectionStart = 0;
            points.Add(firstPoint);

            //====================================   split recursively
            switch (type)
            {
            case 3:
                RecursiveCubicSplit(section, p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, 0, calcTangents, 0, 1);
                break;

            case 2:
                RecursiveQuadraticSplit(section, p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, p3.x, p3.y, p3.z, 0, false, calcTangents, 0, 1);
                break;

            case 1:
                RecursiveQuadraticSplit(section, p0.x, p0.y, p0.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, 0, true, calcTangents, 0, 1);
                break;
            }

            //=====================================   last point
            SectionPointInfo lastPoint;

            poolCursor = poolPointInfos.Count - 1;
            if (poolCursor >= 0)
            {
                lastPoint = poolPointInfos[poolCursor];
                poolPointInfos.RemoveAt(poolCursor);
            }
            else
            {
                lastPoint = new SectionPointInfo();
            }
            lastPoint.Position = p3;
            points.Add(lastPoint);


            //calculate distances (and optionally tangents)
            //if set to true, points positions will be used to calculate tangents
            calcTangents = cacheTangent && config.UsePointPositionsToCalcTangents;
            var prevPoint = points[0];

            for (var i = 1; i < points.Count; i++)
            {
                var point = points[i];

                var pos     = point.Position;
                var prevPos = prevPoint.Position;

                var dX = (double)pos.x - prevPos.x;
                var dY = (double)pos.y - prevPos.y;
                var dZ = (double)pos.z - prevPos.z;

                //distance
                point.DistanceToSectionStart = prevPoint.DistanceToSectionStart + ((float)Math.Sqrt(dX * dX + dY * dY + dZ * dZ));

                //tangents
                if (calcTangents)
                {
                    point.Tangent = Vector3.Normalize(pos - prevPos);
                }

                prevPoint = point;
            }

            //set first and last points tangents (cause they was omitted during recursive split)
            if (cacheTangent)
            {
                if (config.UsePointPositionsToCalcTangents)
                {
                    firstPoint.Tangent = (points[1].Position - firstPoint.Position).normalized;
                    lastPoint.Tangent  = points[points.Count - 2].Tangent;
                }
                else
                {
                    switch (type)
                    {
                    case 0:
                        firstPoint.Tangent = lastPoint.Tangent = (lastPoint.Position - firstPoint.Position).normalized;
                        break;

                    case 1:
                        firstPoint.Tangent = Vector3.Normalize(section.OriginalToControl - section.OriginalFrom);
                        lastPoint.Tangent  = Vector3.Normalize(section.OriginalTo - section.OriginalToControl);
                        break;

                    case 2:
                        firstPoint.Tangent = Vector3.Normalize(section.OriginalFromControl - section.OriginalFrom);
                        lastPoint.Tangent  = Vector3.Normalize(section.OriginalTo - section.OriginalFromControl);
                        break;

                    case 3:
                        firstPoint.Tangent = Vector3.Normalize(section.OriginalFromControl - section.OriginalFrom);
                        lastPoint.Tangent  = Vector3.Normalize(section.OriginalTo - section.OriginalToControl);
                        break;
                    }
                }
            }
        }