void OnGUI()
        {
            CheckInit();

            size.x = size.y = Mathf.Min(Screen.width, Screen.height);
            GUI.DrawTexture(new Rect(0f, 0f, size.x, size.y), grid);
            DrawHeader();
            CatchEvent();

            for (int i = 0, n = points.Count; i < n; i++)
            {
                if (i == selected)
                {
                    GUI.color = new Color(0.6f, 0.75f, 1f);
                }
                else
                {
                    GUI.color = Color.white;
                }
                var p = points[i];
                GUI.DrawTexture(new Rect(Vector2.Scale(p, size) - new Vector2(unit, unit) * 0.5f, new Vector2(unit, unit)), knob);
            }
            GUI.color = Color.white;

            // GUI.Box(new Rect(new Vector2((size.x - unit) * 0.5f, 0f), new Vector2(unit, unit)), "top");
            // GUI.Box(new Rect(new Vector2((size.x - unit) * 0.5f, size.y - unit), new Vector2(unit, unit)), "bottom");

            if (points.Count >= 2)
            {
                var mirror = PFShape.Mirror(GetControls(points), size.x, size.y);
                Handles.color = Color.black;
                DrawShape(mirror, points.Count);
            }
        }
        void CheckInit()
        {
            var obj = Selection.activeObject;

            if (obj && obj as PFShape)
            {
                var current = obj as PFShape;
                if (current != shape)
                {
                    Load(current);
                }
                shape = current;
            }

            if (grid == null)
            {
                grid = AssetDatabase.LoadAssetAtPath <Texture>(PACKAGE_PATH + "Textures/Grid.jpg");
            }

            if (knob == null)
            {
                knob = AssetDatabase.LoadAssetAtPath <Texture>(PACKAGE_PATH + "Textures/Knob.png");
            }

            if (points == null)
            {
                points = new List <Vector2>();
            }
        }
        void DrawShape(List <Vector3> mirror, int count, int resolution = 5)
        {
            // left side
            var points = new List <Vector3>();

            for (int i = 0; i <= count; i++)
            {
                var edge = PFCatmullRomSpline.GetCatmullRomPositions(
                    resolution,
                    PFShape.GetLoopPoint(mirror, i - 1),
                    PFShape.GetLoopPoint(mirror, i),
                    PFShape.GetLoopPoint(mirror, i + 1),
                    PFShape.GetLoopPoint(mirror, i + 2)
                    );
                if (i != 0)
                {
                    edge.RemoveAt(0);
                }
                points.AddRange(edge);
            }

            for (int i = 0, n = points.Count - 1; i < n; i++)
            {
                var from = points[i];
                var to   = points[i + 1];
                Handles.DrawLine(Translate(from), Translate(to));
            }

            for (int i = 0, n = points.Count - 1; i < n; i++)
            {
                var from = points[i];
                var to   = points[i + 1];
                Handles.DrawLine(Translate(new Vector2(-from.x, from.y)), Translate(new Vector2(-to.x, to.y)));
            }
        }
        void Load(PFShape shp)
        {
            var controls = shp.controls;

            points = controls.Select(c => Convert(c)).ToList();
        }