/**
         * A 2D GUI view position handle.
         * @param id The Handle id.
         * @param position The position in GUI coordinates.
         * @param size How large in pixels to draw this handle.
         */
        public static Vector2 PositionHandle2d(int id, Vector2 position, int size)
        {
            int width = size / 4;
            var evt   = Event.current;

            Rect handleRectUp    = new Rect(position.x - width / 2, position.y - size - HANDLE_PADDING, width, size + HANDLE_PADDING);
            Rect handleRectRight = new Rect(position.x, position.y - width / 2, size, width + HANDLE_PADDING);

            Handles.color = Color.yellow;
            Handles.CircleHandleCap(-1, position, Quaternion.identity, width / 2f, Event.current.type);
            Handles.color = k_HandleColorUp;

            // Y Line
            Handles.DrawLine(position, position - Vector2.up * size);

            // Y Cone
            if (position.y - size > 0f)
            {
                Handles.ConeHandleCap(0, ((Vector3)((position - Vector2.up * size))) - ConeDepth, QuaternionUp, width / 2, evt.type);
            }

            Handles.color = k_HandleColorRight;

            // X Line
            Handles.DrawLine(position, position + Vector2.right * size);

            // X Cap
            if (position.y > 0f)
            {
                Handles.ConeHandleCap(0, ((Vector3)((position + Vector2.right * size))) - ConeDepth, QuaternionRight, width / 2, evt.type);
            }

            // If a Tool already is engaged and it's not this one, bail.
            if (currentId >= 0 && currentId != id)
            {
                return(position);
            }

            Vector2 mousePosition = evt.mousePosition;
            Vector2 newPosition   = position;

            if (currentId == id)
            {
                switch (evt.type)
                {
                case EventType.MouseDrag:
                    newPosition = axisConstraint.Mask(mousePosition + handleOffset) + axisConstraint.InverseMask(position);
                    break;

                case EventType.MouseUp:
                case EventType.Ignore:
                    currentId = -1;
                    break;
                }
            }
            else
            {
                if (evt.type == EventType.MouseDown && ((!limitToLeftButton && evt.button != MIDDLE_MOUSE_BUTTON) || evt.button == LEFT_MOUSE_BUTTON))
                {
                    if (Vector2.Distance(mousePosition, position) < width / 2f)
                    {
                        currentId      = id;
                        handleOffset   = position - mousePosition;
                        axisConstraint = new HandleConstraint2D(1, 1);
                    }
                    else if (handleRectRight.Contains(mousePosition))
                    {
                        currentId      = id;
                        handleOffset   = position - mousePosition;
                        axisConstraint = new HandleConstraint2D(1, 0);
                    }
                    else if (handleRectUp.Contains(mousePosition))
                    {
                        currentId      = id;
                        handleOffset   = position - mousePosition;
                        axisConstraint = new HandleConstraint2D(0, 1);
                    }
                }
            }

            return(newPosition);
        }
        /// <summary>
        /// Scale handle in 2d space.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="position"></param>
        /// <param name="scale"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static Vector2 ScaleHandle2d(int id, Vector2 position, Vector2 scale, int size)
        {
            Event   evt           = Event.current;
            Vector2 mousePosition = evt.mousePosition;
            int     width         = size / 4;

            Handles.color = k_HandleColorUp;
            Handles.DrawLine(position, position - Vector2.up * size * scale.y);

            if (position.y - size > 0f)
            {
                Handles.CubeHandleCap(0, ((Vector3)((position - Vector2.up * scale.y * size))) - Vector3.forward * 16, QuaternionUp, width / 3, evt.type);
            }

            Handles.color = k_HandleColorRight;
            Handles.DrawLine(position, position + Vector2.right * size * scale.x);

            if (position.y > 0f)
            {
                Handles.CubeHandleCap(0,
                                      ((Vector3)((position + Vector2.right * scale.x * size))) - Vector3.forward * 16,
                                      Quaternion.Euler(Vector3.up * 90f),
                                      width / 3f,
                                      evt.type);
            }

            Handles.color = k_HandleColorScale;

            Handles.CubeHandleCap(0,
                                  ((Vector3)position) - Vector3.forward * 16,
                                  QuaternionUp,
                                  width / 2f,
                                  evt.type);

            // If a Tool already is engaged and it's not this one, bail.
            if (currentId >= 0 && currentId != id)
            {
                return(scale);
            }

            Rect handleRectUp     = new Rect(position.x - width / 2f, position.y - size - HANDLE_PADDING, width, size + HANDLE_PADDING);
            Rect handleRectRight  = new Rect(position.x, position.y - width / 2f, size + 8, width);
            Rect handleRectCenter = new Rect(position.x - width / 2f, position.y - width / 2f, width, width);

            if (currentId == id)
            {
                switch (evt.type)
                {
                case EventType.MouseDrag:
                    Vector2 diff = axisConstraint.Mask(mousePosition - initialMousePosition);
                    diff.x += size;
                    diff.y  = -diff.y;      // gui space Y is opposite-world
                    diff.y += size;
                    scale   = diff / size;
                    if (axisConstraint == HandleConstraint2D.None)
                    {
                        scale.x = Mathf.Min(scale.x, scale.y);
                        scale.y = Mathf.Min(scale.x, scale.y);
                    }
                    break;

                case EventType.MouseUp:
                case EventType.Ignore:
                    currentId = -1;
                    break;
                }
            }
            else
            {
                if (evt.type == EventType.MouseDown && ((!limitToLeftButton && evt.button != MIDDLE_MOUSE_BUTTON) || evt.button == LEFT_MOUSE_BUTTON))
                {
                    if (handleRectCenter.Contains(mousePosition))
                    {
                        currentId            = id;
                        handleOffset         = position - mousePosition;
                        initialMousePosition = mousePosition;
                        axisConstraint       = new HandleConstraint2D(1, 1);
                    }
                    else if (handleRectRight.Contains(mousePosition))
                    {
                        currentId            = id;
                        handleOffset         = position - mousePosition;
                        initialMousePosition = mousePosition;
                        axisConstraint       = new HandleConstraint2D(1, 0);
                    }
                    else if (handleRectUp.Contains(mousePosition))
                    {
                        currentId            = id;
                        handleOffset         = position - mousePosition;
                        initialMousePosition = mousePosition;
                        axisConstraint       = new HandleConstraint2D(0, 1);
                    }
                }
            }

            return(scale);
        }