/// <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 }