/// <summary>
        /// 求矩形B在当前矩形上的投影填充点
        /// </summary>
        /// <param name="_b">矩形B</param>
        /// <returns>填充点</returns>
        public List <Vector3> IntersectionFill(GraphicRect2D _b)
        {
            List <Vector3> vertexs = new List <Vector3>();

            if (index != _b.index)
            {
                Vector3 va  = Vector3.zero;
                Vector3 vb  = Vector3.zero;
                Vector3 vp  = Vector3.zero;
                Vector3 ab  = Vector3.zero;
                Vector3 ap  = Vector3.zero;
                Vector3 pab = Vector3.zero;
                for (int i = 0; i < corners.Length; i++)
                {
                    va = corners[i];
                    vertexs.Add(va);
                    if (i >= corners.Length - 1)
                    {
                        vb = corners[0];
                    }
                    else
                    {
                        vb = corners[i + 1];
                    }
                    for (int p = 0; p < _b.corners.Length; p++)
                    {
                        vp = _b.corners[p];
                        ab = vb - va;
                        ap = vp - va;
                        //P点在AB上的投影点pab
                        pab = Vector3.Project(ap, ab);
                        //如果投影点的方向与ab方向一致,并且ab的长度大于ap的长度,则投影点在ab边上,为矩形交点
                        if (Vector3.Dot(ab, pab) >= 0 && ab.magnitude >= ap.magnitude)
                        {
                            vertexs.Add(va + pab);
                        }
                    }
                }
            }
            return(vertexs);
        }
    /// <summary>
    /// 仅填充遮罩
    /// </summary>
    /// <param name="_vh">顶点Helper</param>
    /// <param name="_masks">绘制组</param>
    protected virtual void OnFillMask(VertexHelper _vh, List <AbsUIGuideGraphic> _masks)
    {
        _vh.Clear();
        List <UIVertex> vertexs = new List <UIVertex>();

        Vector3[]     fourCorners = null;
        GraphicRect2D sceneRect   = new GraphicRect2D(-1, this);
        Vector4       uv          = (sprite != null) ? UnityEngine.Sprites.DataUtility.GetOuterUV(sprite) : Vector4.zero;

        foreach (AbsUIGuideGraphic g in _masks)
        {
            g.graphic.GraphicLocalCornersForVertexHelper(out fourCorners);
            vertexs = new List <UIVertex>();
            switch (graphicSpriteFillClassify)
            {
            case enGraphicSpriteFillClassify.SceneRatioFill:
                fourCorners[0].x = Mathf.Clamp(fourCorners[0].x, sceneRect.rect.xMin, sceneRect.rect.xMax);
                fourCorners[0].y = Mathf.Clamp(fourCorners[0].y, sceneRect.rect.yMin, sceneRect.rect.yMax);
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[0], color = color, uv0 = Rect.PointToNormalized(sceneRect.rect, fourCorners[0])
                });

                fourCorners[1].x = Mathf.Clamp(fourCorners[1].x, sceneRect.rect.xMin, sceneRect.rect.xMax);
                fourCorners[1].y = Mathf.Clamp(fourCorners[1].y, sceneRect.rect.yMin, sceneRect.rect.yMax);
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[1], color = color, uv0 = Rect.PointToNormalized(sceneRect.rect, fourCorners[1])
                });

                fourCorners[2].x = Mathf.Clamp(fourCorners[2].x, sceneRect.rect.xMin, sceneRect.rect.xMax);
                fourCorners[2].y = Mathf.Clamp(fourCorners[2].y, sceneRect.rect.yMin, sceneRect.rect.yMax);
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[2], color = color, uv0 = Rect.PointToNormalized(sceneRect.rect, fourCorners[2])
                });

                fourCorners[3].x = Mathf.Clamp(fourCorners[3].x, sceneRect.rect.xMin, sceneRect.rect.xMax);
                fourCorners[3].y = Mathf.Clamp(fourCorners[3].y, sceneRect.rect.yMin, sceneRect.rect.yMax);
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[3], color = color, uv0 = Rect.PointToNormalized(sceneRect.rect, fourCorners[3])
                });
                break;

            case enGraphicSpriteFillClassify.MaskAloneFill:
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[0], color = color, uv0 = new Vector2(uv.x, uv.y)
                });
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[1], color = color, uv0 = new Vector2(uv.x, uv.w)
                });
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[2], color = color, uv0 = new Vector2(uv.z, uv.w)
                });
                vertexs.Add(new UIVertex()
                {
                    position = fourCorners[3], color = color, uv0 = new Vector2(uv.z, uv.y)
                });
                break;
            }
            _vh.AddUIVertexQuad(vertexs.ToArray());
        }
    }
    /// <summary>
    /// 除遮罩之外都填充
    /// </summary>
    /// <param name="_vh">顶点Helper</param>
    /// <param name="_masks">绘制组</param>
    protected virtual void OnFillExceptMask(VertexHelper _vh, List <AbsUIGuideGraphic> _masks)
    {
        #region 屏幕矩形
        GraphicRect2D sceneRect = new GraphicRect2D(-1, this);
        #endregion

        #region 遮罩矩形
        List <GraphicRect2D> maskRect = new List <GraphicRect2D>();
        GraphicRect2D        rect;
        for (int i = 0; i < _masks.Count; i++)
        {
            rect = new GraphicRect2D(i, _masks[i].graphic);
            maskRect.Add(rect);
        }

        //求两矩形填充点和矩形在屏幕上的填充点
        List <Vector3> useVertexs      = new List <Vector3>();
        List <Vector3> tempVertexs     = new List <Vector3>();
        List <Vector3> validateVertexs = new List <Vector3>();
        if (maskRect.Count <= 1)
        {
            tempVertexs = maskRect[0].IntersectionFill(sceneRect);
            if (tempVertexs.Count > 0)
            {
                validateVertexs.AddRange(tempVertexs);
            }
        }
        else
        {
            foreach (GraphicRect2D a in maskRect)
            {
                foreach (GraphicRect2D b in maskRect)
                {
                    tempVertexs = a.IntersectionFill(b);
                    if (tempVertexs.Count > 0)
                    {
                        validateVertexs.AddRange(tempVertexs);
                    }
                }
            }
        }
        #endregion

        validateVertexs.InsertRange(0, sceneRect.corners);

        #region 清理重复的点
        List <int> hasPoint = new List <int>();
        int        pk       = 0;
        Vector3    tp       = Vector3.zero;
        foreach (Vector3 cv in validateVertexs)
        {
            //顶点不超过屏幕
            tp.x = cv.x;
            tp.x = Mathf.Max(tp.x, sceneRect.rect.xMin);
            tp.x = Mathf.Min(tp.x, sceneRect.rect.xMax);
            tp.y = cv.y;
            tp.y = Mathf.Max(tp.y, sceneRect.rect.yMin);
            tp.y = Mathf.Min(tp.y, sceneRect.rect.yMax);
            //过滤重复点
            pk = (tp.x.ToString() + tp.y.ToString()).UniqueHashCode();
            if (!hasPoint.Contains(pk))
            {
                hasPoint.Add(pk);
                useVertexs.Add(tp);
            }
        }
        #endregion

        mDelaunayResult = Polygon2DUtility.BuilderDelaunay2D(useVertexs, new List <int>()
        {
            0, 1, 2, 3
        });

        #region 绘制三角面
        _vh.Clear();
        Vector4    uv           = (sprite != null) ? UnityEngine.Sprites.DataUtility.GetOuterUV(sprite) : Vector4.zero;
        UIVertex[] vertexs      = new UIVertex[mDelaunayResult.vertexs.Count];
        List <int> vertexIndexs = new List <int>();
        foreach (PolygonPoint2D p in mDelaunayResult.vertexs)
        {
            vertexs[p.index] = new UIVertex()
            {
                position = p.position, color = color, uv0 = Rect.PointToNormalized(sceneRect.rect, p.position)
            };
        }

        bool isInAnyRect = false;
        foreach (PolygonTriangle2D tri in mDelaunayResult.delaunayTriangle)
        {
            foreach (GraphicRect2D r in maskRect)
            {
                isInAnyRect =
                    Geometry2DUtility.IsPointInRect(tri.vertexs[0].position, r.rect) &&
                    Geometry2DUtility.IsPointInRect(tri.vertexs[1].position, r.rect) &&
                    Geometry2DUtility.IsPointInRect(tri.vertexs[2].position, r.rect);
                if (isInAnyRect)
                {
                    break;
                }
            }
            if (!isInAnyRect)
            {
                vertexIndexs.Add(tri.vertexs[0].index);
                vertexIndexs.Add(tri.vertexs[1].index);
                vertexIndexs.Add(tri.vertexs[2].index);
            }
        }
        _vh.AddUIVertexStream(new List <UIVertex>(vertexs), vertexIndexs);
        #endregion
    }