public void AddPoint()
    {
        GameObject newObj = new GameObject();

        newObj.transform.parent = transform;
        newObj.name             = "Point" + pointCount;
        Jun_BezierPoint newPoint = newObj.AddComponent <Jun_BezierPoint>();

        if (pointCount == 0)
        {
            newPoint.transform.localPosition = Vector3.zero;
        }
        if (pointCount == 1)
        {
            newPoint.transform.localPosition = Vector3.up;
        }

        if (pointCount > 1)
        {
            Vector3 lastPoint = GetPoint(pointCount - 1).transform.localPosition;
            newPoint.transform.localPosition = lastPoint - GetPoint(pointCount - 2).transform.localPosition + lastPoint;
        }

        m_bezierPoints.Add(newPoint);

        IsChange();
    }
    public override void OnInspectorGUI()
    {
        Jun_BezierCurve tar = (Jun_BezierCurve)target;

        GUILayout.BeginVertical();

        tar.isAuto  = EditorGUILayout.Toggle("Auto", tar.isAuto);
        tar.isClose = EditorGUILayout.Toggle("Close:", tar.isClose);
        if (GUILayout.Button("AddPoint", EditorStyles.miniButton))
        {
            tar.AddPoint();
        }

        for (int i = 0; i < tar.pointCount; i++)
        {
            Jun_BezierPoint thisPoint = tar.GetPoint(i);
            if (thisPoint == null)
            {
                break;
            }
            GUILayout.BeginHorizontal();
            GUILayout.Label("Point:" + i, GUILayout.Width(40));
            thisPoint.transform.position = EditorGUILayout.Vector3Field("", thisPoint.transform.position);
            GUILayout.EndHorizontal();
        }
        GUILayout.EndVertical();
    }
    private void OnSceneGUI()
    {
        Jun_BezierPoint tar = (Jun_BezierPoint)target;

        Jun_BezierCurveEditor.DrawCurve(tar.curve);
        if (tar.transform.parent != tar.curve)
        {
            tar.transform.parent = tar.curve.transform;
        }
    }
    Vector3 GetPoint(Jun_BezierPoint point01, Jun_BezierPoint point02, float t)
    {
        if (point01 == null || point02 == null)
        {
            return(transform.position);
        }

        Vector3 p1 = point01.transform.position;
        Vector3 p2 = point01.worldHandles02;
        Vector3 p3 = point02.worldHandles01;
        Vector3 p4 = point02.transform.position;

        return(Jun_BezierCurveTools.GetBezierCurvePoint(p1, p2, p3, p4, t));
    }
    void ApproximateLenght()
    {
        if (pointCount < 2)
        {
            return;
        }

        m_lenght = 0;
        for (int i = 0; i < pointCount - 1; i++)
        {
            Jun_BezierPoint thisPoint = GetPoint(i);
            Jun_BezierPoint nextPoint = GetPoint(i + 1);
            m_lenght += GetCurveLenght(thisPoint, nextPoint);
        }

        if (isClose)
        {
            m_lenght += GetCurveLenght(GetPoint(pointCount - 1), GetPoint(0));
        }
    }
    float GetCurveLenght(Jun_BezierPoint point01, Jun_BezierPoint point02)
    {
        if (point01 == null || point02 == null)
        {
            return(0);
        }

        Vector3 p1 = point01.transform.position;
        Vector3 p2 = point01.worldHandles02;
        Vector3 p3 = point02.worldHandles01;
        Vector3 p4 = point02.transform.position;

        Vector3 lastPosition = p1;
        float   thisLenght   = 0;

        for (int j = 0; j <= sample; j++)
        {
            float   t       = j * 1.0f / sample;
            Vector3 thisPos = Jun_BezierCurveTools.GetBezierCurvePoint(p1, p2, p3, p4, t);
            thisLenght  += Vector3.Distance(thisPos, lastPosition);
            lastPosition = thisPos;
        }
        return(thisLenght);
    }
    public Vector3 GetPointInCurve(float timeValue)
    {
        if (isClose)
        {
            if (timeValue > 1)
            {
                timeValue = timeValue - (int)timeValue;
            }

            if (timeValue < 0)
            {
                timeValue = 1 + timeValue - (int)timeValue;
            }
        }

        if (pointCount < 2)
        {
            return(transform.position);
        }
        if (timeValue <= 0)
        {
            return(GetPoint(0).transform.position);
        }
        if (timeValue >= 1)
        {
            return(isClose? GetPoint(0).transform.position: GetPoint(pointCount - 1).transform.position);
        }

        float lenght = curveLenght;

        float preLenght = 0;

        int count = pointCount - 1;

        if (isClose)
        {
            count = pointCount;
        }
        for (int i = 0; i < count; i++)
        {
            Jun_BezierPoint thisPoint = GetPoint(i);
            Jun_BezierPoint nextPoint = GetPoint(i + 1);

            if (isClose && i == count - 1)
            {
                nextPoint = GetPoint(0);
            }

            if (thisPoint == null || nextPoint == null)
            {
                break;
            }

            Vector3 prePosition = thisPoint.transform.position;
            float   thisLenght  = GetCurveLenght(thisPoint, nextPoint);

            float thisV = thisLenght * 1.0f / lenght;

            if (timeValue >= preLenght && timeValue <= preLenght + thisV)
            {
                Vector3 pos = GetPoint(thisPoint, nextPoint, (timeValue - preLenght) / thisV);
                return(pos);
            }

            preLenght += thisV;
        }

        return(transform.position);
    }
    public static void DrawCurve(Jun_BezierCurve tar)
    {
        for (int i = 0; i < tar.pointCount; i++)
        {
            Jun_BezierPoint thisPoint = tar.GetPoint(i);
            if (thisPoint == null)
            {
                tar.RemovePointAt(i);
                break;
            }

            float handleSize = HandleUtility.GetHandleSize(thisPoint.transform.position) * 0.1f;

            Vector3 pointPos = Handles.FreeMoveHandle(thisPoint.transform.position, Quaternion.identity, handleSize, Vector3.zero, Handles.SphereHandleCap);
            if (thisPoint.transform.position != pointPos)
            {
                thisPoint.transform.position = pointPos;
                tar.IsChange();
            }

            if (!tar.isAuto)
            {
                if (thisPoint.type != Jun_BezierPoint.PointType.None)
                {
                    Vector3 handle01Pos = Handles.FreeMoveHandle(thisPoint.worldHandles01, Quaternion.identity, handleSize, Vector3.zero, Handles.CubeHandleCap);

                    if (thisPoint.worldHandles01 != handle01Pos)
                    {
                        thisPoint.worldHandles01 = handle01Pos;
                        if (thisPoint.type == Jun_BezierPoint.PointType.Smooth)
                        {
                            thisPoint.worldHandles02 = -(handle01Pos - pointPos) + pointPos;
                        }
                    }

                    Vector3 handle02Pos = Handles.FreeMoveHandle(thisPoint.worldHandles02, Quaternion.identity, handleSize, Vector3.zero, Handles.CubeHandleCap);
                    if (thisPoint.worldHandles02 != handle02Pos)
                    {
                        thisPoint.worldHandles02 = handle02Pos;
                        if (thisPoint.type == Jun_BezierPoint.PointType.Smooth)
                        {
                            thisPoint.worldHandles01 = -(handle02Pos - pointPos) + pointPos;
                        }
                    }

                    Handles.DrawLine(pointPos, handle01Pos);
                    Handles.DrawLine(pointPos, handle02Pos);
                }
            }
            else
            {
                Jun_BezierPoint currentPoint = tar.GetPoint(i);
                Jun_BezierPoint prePoint     = tar.GetPrePoint(i);
                Jun_BezierPoint nextPoint    = tar.GetNextPoint(i);

                if (prePoint == null || nextPoint == null || currentPoint == null)
                {
                    currentPoint.type = Jun_BezierPoint.PointType.None;
                }
                else
                {
                    //Vector3 pos01 = prePoint.transform.position - currentPoint.transform.position;
                    //Vector3 pos02 = nextPoint.transform.position - currentPoint.transform.position;

                    //Vector3 nPos = Vector3.Cross(pos01, pos02);

                    //float angle = (180 - Vector3.Angle(pos01, pos02))*0.5f * Mathf.Deg2Rad;
                    //Vector3 pos;
                    //Vector3 a = prePoint.transform.position - pos;
                    //Vector3 b = pos - currentPoint.transform.position;

                    //Vector3 curPPos = currentPoint.transform.position;

                    //(pos.x - curPPos.x)*(pos.x - curPPos.x)

                    //Mathf.Cos(angle) * pos01.magnitude;
                }
            }
        }
    }