From 45944e45394a071cef35476dec89cc91347619f0 Mon Sep 17 00:00:00 2001 From: lrc <571244399@qq.com> Date: Mon, 6 Jul 2026 17:04:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A=E5=8F=8A?= =?UTF-8?q?=E6=9B=B4=E5=A4=9A=E7=94=A8=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Runtime/Core/XericRendererUtils.cs | 361 +++++++++++++++------- Runtime/Pattern/UIAnyPatternRenderer.cs | 17 + Runtime/Pattern/UILineRenderer.cs | 56 +++- Runtime/Pattern/UIPatternRenderer.cs | 17 + Runtime/Pattern/XericRendererComponent.cs | 89 +++++- 5 files changed, 406 insertions(+), 134 deletions(-) diff --git a/Runtime/Core/XericRendererUtils.cs b/Runtime/Core/XericRendererUtils.cs index a615122..f28ecac 100644 --- a/Runtime/Core/XericRendererUtils.cs +++ b/Runtime/Core/XericRendererUtils.cs @@ -13,7 +13,7 @@ namespace XericLibrary.Runtime.UIGraph internal static class XericRendererUtils { #region 数学计算 - + /// /// 计算线路的总长度 /// @@ -54,7 +54,8 @@ namespace XericLibrary.Runtime.UIGraph /// 是否要居中显示 /// 整个绘制矩形范围的尺寸 /// - public static Vector2 SwitchCenterOffset(bool center, Vector2 rectSize) => center ? Vector2.zero : -(rectSize / 2); + public static Vector2 SwitchCenterOffset(bool center, Vector2 rectSize) => + center ? Vector2.zero : -(rectSize / 2); /// /// 获取两个点之间的法线,副法线 @@ -65,19 +66,21 @@ namespace XericLibrary.Runtime.UIGraph /// 两点间距离 /// 起点到终点的法线 /// 垂直与起点到终点的法线(法线左转90) + /// 反转矢量 /// - private static bool GetNormalizedVector(Vector2 startPoint, Vector2 endPoint, - out Vector2 vector, out float distance, out Vector2 normal, out Vector2 subTangent) + private static bool GetNormalizedVector(Vector2 startPoint, Vector2 endPoint, + out Vector2 vector, out float distance, out Vector2 normal, out Vector2 subTangent, + bool reverseVector = false) { - vector = endPoint - startPoint; + vector = reverseVector ? startPoint - endPoint : endPoint - startPoint; distance = vector.magnitude; normal = Vector2.zero; subTangent = Vector2.zero; - + // 距离过小时不绘制 if (distance <= float.Epsilon) return false; - + // 线段的法线和副法线 normal = vector / distance; subTangent = Vector2.Perpendicular(normal); @@ -96,19 +99,20 @@ namespace XericLibrary.Runtime.UIGraph /// 总线路的长度 /// 起点处的uv y /// 终点处的uv y - private static void GetCurrentLengthUVY(float startLength, float currentLength, float totalLength, out float startUVY, out float endUVY) + private static void GetCurrentLengthUVY(float startLength, float currentLength, float totalLength, + out float startUVY, out float endUVY) { startUVY = totalLength > 0 ? startLength / totalLength : 0f; endUVY = totalLength > 0 ? (startLength + currentLength) / totalLength : 0f; } - + #endregion #region 简易线路绘制 - + // 在点与点之间绘制给定宽度(thickness)的方片,转角处用两个三角形链接 // 这样会造成一根线会出现5个顶点,所以叫做 DSL5 (直接简单的5点直线 directly simple line 5) - + /// /// 创建线段的顶点数据 /// 每个线段由 5 个顶点组成: @@ -124,8 +128,10 @@ namespace XericLibrary.Runtime.UIGraph /// 线条的颜色 /// 当前线段起点在线路中的累积长度 /// 线路的总长度 - public static List GetSingleLineSegmentVerts_DSL5(List vertices, Vector2 startPoint, Vector2 endPoint, - float thickness, Color color, float startLength, out float distance, float totalLength, Vector3 offset) + public static List GetSingleLineSegmentVerts_DSL5(List vertices, Vector2 startPoint, + Vector2 endPoint, + float thickness, Color color, Vector2 normal, Vector2 subTangent, float startUVY, float endUVY, + Vector3 offset) { if (vertices == null) throw new Exception("没有指定线段片段顶点容器列表"); @@ -134,35 +140,29 @@ namespace XericLibrary.Runtime.UIGraph UIVertex vertex = UIVertex.simpleVert; vertex.color = color; - if (!GetNormalizedVector(startPoint, endPoint, - out var vector, out distance, out var normal, out var subTangent)) - return vertices; - // 线段单侧宽度 var width = thickness / 2; - - GetCurrentLengthUVY(startLength, distance, totalLength, out var startUVY, out var endUVY); - - vertex.position = (startPoint + - subTangent * width); + + vertex.position = (startPoint + + subTangent * width); vertex.position += offset; vertex.uv0 = new Vector2(0f, startUVY); // 左侧顶点的UV vertices.Add(vertex); - - vertex.position = (startPoint + - subTangent * -width); + + vertex.position = (startPoint + + subTangent * -width); vertex.position += offset; vertex.uv0 = new Vector2(1f, startUVY); // 右侧顶点的UV vertices.Add(vertex); - vertex.position = (endPoint + - subTangent * width); + vertex.position = (endPoint + + subTangent * width); vertex.position += offset; vertex.uv0 = new Vector2(0f, endUVY); // 左侧顶点的UV vertices.Add(vertex); - - vertex.position = (endPoint + - subTangent * -width); + + vertex.position = (endPoint + + subTangent * -width); vertex.position += offset; vertex.uv0 = new Vector2(1f, endUVY); // 右侧顶点的UV vertices.Add(vertex); @@ -181,25 +181,26 @@ namespace XericLibrary.Runtime.UIGraph /// 构建网格对象 /// 该线路片段索引(比如第一段线应该是0) /// 该片段顶点 - public static void AddSingleLineSegmentVertsAndTriangle_DSL5(this VertexHelper vh, int segmentPartIndex, IEnumerable verts) + public static void AddSingleLineSegmentVertsAndTriangle_DSL5(this VertexHelper vh, int segmentPartIndex, + IEnumerable verts) { foreach (var vert in verts) vh.AddVert(vert); int index = segmentPartIndex * 5; - + // 添加线段的两个三角形(构成矩形线段) - vh.AddTriangle(index, index+1, index+3); - vh.AddTriangle(index+3, index+2, index); - + vh.AddTriangle(index, index + 1, index + 3); + vh.AddTriangle(index + 3, index + 2, index); + // 为线段之间添加斜角边缘 // 使用上一个线段的终点和当前线段的起点创建过渡三角形 if (segmentPartIndex != 0) { - vh.AddTriangle(index, index-1, index-3); - vh.AddTriangle(index+1, index-1, index-2); + vh.AddTriangle(index, index - 1, index - 3); + vh.AddTriangle(index + 1, index - 1, index - 2); } } - + /// /// 推送顶点绘制线路 /// @@ -207,56 +208,94 @@ namespace XericLibrary.Runtime.UIGraph /// /// /// - /// + /// /// - public static void PopulateLineByPointsArray_DSL5(this VertexHelper vh, Vector2[] points, float thickness, bool cycleLoop, Color color, Vector3 offset) + /// + /// + /// 宽x长y + /// + /// + /// + /// + public static void PopulateLineByPointsArray_DSL5(this VertexHelper vh, Vector2[] points, + float thickness, bool cycleLoop, Color lineColor, Vector3 offset, + bool enableArrow, + Color arrowColor, Vector2 arrowSize, float pointProgress, float arrowPointProgress, + bool absProgressPoint = true, bool reverseDir = false) { // 至少需要 2 个点才能绘制线条 if (points.Length < 2) return; - + // 计算线路总长度 var totalLength = points.CalculateTotalLength(cycleLoop); var currentLength = 0f; - var vertices = ListPool.Get(); + var lineVertices = ListPool.Get(); + var arrowVertices = ListPool.Get(); + var arrowindices = ListPool.Get(); for (int i = 0; i < points.Length - (cycleLoop ? 0 : 1); i++) { - vh.AddSingleLineSegmentVertsAndTriangle_DSL5(i, - GetSingleLineSegmentVerts_DSL5(vertices, points[i], points[(i + 1) % points.Length], thickness, color, currentLength, out var distance, totalLength, offset)); + var thisPoint = points[i]; + var nextPoint = points[(i + 1) % points.Length]; + + // 先计算线的矢量参数,以及uv。 + if (!GetNormalizedVector(thisPoint, nextPoint, + out var vector, out var distance, out var normal, out var subTangent)) + continue; + GetCurrentLengthUVY(currentLength, distance, totalLength, out var startUvy, out var endUvy); + + vh.AddSingleLineSegmentVertsAndTriangle_DSL5(i, + GetSingleLineSegmentVerts_DSL5(lineVertices, thisPoint, nextPoint, thickness, lineColor, normal, + subTangent, startUvy, endUvy, offset)); + + if (enableArrow) + { + PopulateTriangleArrowByPointArray(arrowVertices, thisPoint, nextPoint, arrowColor, arrowSize.y, + arrowSize.x, pointProgress, arrowPointProgress, absProgressPoint, reverseDir); + arrowindices.AddFaceByConsecutiveVertices(arrowVertices, i * 3, 3, i * 3); + } currentLength += distance; } - ListPool.Release(vertices); + + if (enableArrow) + { + vh.AddUIVertexStream(arrowVertices, arrowindices); + } + ListPool.Release(lineVertices); + ListPool.Release(arrowVertices); + ListPool.Release(arrowindices); } - + #endregion #region 圆弧过度的线路绘制 // 在简易线路绘制的基础上,修改了转角处的处理 // 线的顶点还是5,但是转角圆弧处理会更细节,叫它 CFAL (中心对齐的圆弧转角直线,center fanshaped arc Line) - + /// /// 在网格构建对象上添加这个直线片段 /// /// 构建网格对象 /// 该线路片段索引(比如第一段线应该是0) /// 该片段顶点 - public static void AddSingleLineSegmentVertsAndTriangle_CFAL(this VertexHelper vh, int segmentPartIndex, IEnumerable verts) + public static void AddSingleLineSegmentVertsAndTriangle_CFAL(this VertexHelper vh, int segmentPartIndex, + IEnumerable verts) { foreach (var vert in verts) vh.AddVert(vert); int index = segmentPartIndex * 5; - + // 添加线段的两个三角形(构成矩形线段) - vh.AddTriangle(index, index+1, index+3); - vh.AddTriangle(index+3, index+2, index); - + vh.AddTriangle(index, index + 1, index + 3); + vh.AddTriangle(index + 3, index + 2, index); + // 为线段之间添加斜角边缘 // 使用上一个线段的终点和当前线段的起点创建过渡三角形 if (segmentPartIndex != 0) { - vh.AddTriangle(index, index-1, index-3); - vh.AddTriangle(index+1, index-1, index-2); + vh.AddTriangle(index, index - 1, index - 3); + vh.AddTriangle(index + 1, index - 1, index - 2); } } @@ -278,49 +317,50 @@ namespace XericLibrary.Runtime.UIGraph /// 内圆弧半径 /// 返回线段的距离 /// 包含线段顶点的列表 - public static List GetSingleLineSegmentVerts_CFAL(List vertices, Vector2 startPoint, Vector2 endPoint, Vector2 nextPoint, Vector2 prevPoint, - float thickness, Color color, float startLength, out float distance, float totalLength, Vector3 offset, + public static List GetSingleLineSegmentVerts_CFAL(List vertices, Vector2 startPoint, + Vector2 endPoint, Vector2 nextPoint, Vector2 prevPoint, + float thickness, Color color, float startLength, out float distance, float totalLength, Vector3 offset, int chamferSegments = 0, float innerRadius = 0f) { if (vertices == null) throw new Exception("没有指定线段片段顶点容器列表"); vertices.Clear(); - + // 创建顶点模板,设置颜色为组件的当前颜色 UIVertex vertex = UIVertex.simpleVert; vertex.color = color; - if (!GetNormalizedVector(startPoint, endPoint, + if (!GetNormalizedVector(startPoint, endPoint, out var vector, out distance, out var normal, out var subTangent)) return vertices; - + // 线段单侧宽度 var width = thickness / 2; - + GetCurrentLengthUVY(startLength, distance, totalLength, out var startUVY, out var endUVY); - + // 计算起点和终点的夹角 float startAngle = 0f; float endAngle = 0f; - + if (prevPoint != startPoint) { var prevVector = startPoint - prevPoint; var prevNormal = prevVector.normalized; startAngle = Vector2.Angle(normal, -prevNormal); } - + if (nextPoint != endPoint) { var nextVector = nextPoint - endPoint; var nextNormal = nextVector.normalized; endAngle = Vector2.Angle(-normal, nextNormal); } - + // 计算顶点偏移量 float startOffset = 0f; float endOffset = 0f; - + if (Mathf.Abs(startAngle) > 0.1f) { if (innerRadius > 0f) @@ -332,7 +372,7 @@ namespace XericLibrary.Runtime.UIGraph startOffset = width / Mathf.Sin(startAngle * Mathf.Deg2Rad / 2); } } - + if (Mathf.Abs(endAngle) > 0.1f) { if (innerRadius > 0f) @@ -344,46 +384,46 @@ namespace XericLibrary.Runtime.UIGraph endOffset = width / Mathf.Sin(endAngle * Mathf.Deg2Rad / 2); } } - + // 添加起点的左侧顶点 - vertex.position = (startPoint + - subTangent * width + - normal * startOffset); + vertex.position = (startPoint + + subTangent * width + + normal * startOffset); vertex.position += offset; vertex.uv0 = new Vector2(0f, startUVY); vertices.Add(vertex); - + // 添加起点的右侧顶点 - vertex.position = (startPoint + - subTangent * -width + - normal * startOffset); + vertex.position = (startPoint + + subTangent * -width + + normal * startOffset); vertex.position += offset; vertex.uv0 = new Vector2(1f, startUVY); vertices.Add(vertex); // 添加终点的左侧顶点 - vertex.position = (endPoint + - subTangent * width + - normal * -endOffset); + vertex.position = (endPoint + + subTangent * width + + normal * -endOffset); vertex.position += offset; vertex.uv0 = new Vector2(0f, endUVY); vertices.Add(vertex); - + // 添加终点的右侧顶点 - vertex.position = (endPoint + - subTangent * -width + - normal * -endOffset); + vertex.position = (endPoint + + subTangent * -width + + normal * -endOffset); vertex.position += offset; vertex.uv0 = new Vector2(1f, endUVY); vertices.Add(vertex); // 添加终点的中心点 - vertex.position = (endPoint + - normal * -endOffset); + vertex.position = (endPoint + + normal * -endOffset); vertex.position += offset; vertex.uv0 = new Vector2(0.5f, endUVY); vertices.Add(vertex); - + return vertices; } @@ -398,40 +438,89 @@ namespace XericLibrary.Runtime.UIGraph /// 偏移量 /// 倒角细分数量 /// 内圆弧半径 - public static void PopulateLineByPointsArray_CFAL(this VertexHelper vh, Vector2[] points, float thickness, bool cycleLoop, Color color, Vector3 offset, + public static void PopulateLineByPointsArray_CFAL(this VertexHelper vh, Vector2[] points, float thickness, + bool cycleLoop, Color color, Vector3 offset, int chamferSegments = 0, float innerRadius = 0f) { // 至少需要 2 个点才能绘制线条 if (points.Length < 2) return; - + // 计算线路总长度 var totalLength = points.CalculateTotalLength(cycleLoop); var currentLength = 0f; var vertices = ListPool.Get(); - + for (int i = 0; i < points.Length - (cycleLoop ? 0 : 1); i++) { var startPoint = points[i]; var endPoint = points[(i + 1) % points.Length]; var prevPoint = i > 0 ? points[i - 1] : cycleLoop ? points[^1] : startPoint; var nextPoint = points[(i + 2) % points.Length]; - - vh.AddSingleLineSegmentVertsAndTriangle_CFAL(i, - GetSingleLineSegmentVerts_CFAL(vertices, startPoint, endPoint, nextPoint, prevPoint, - thickness, color, currentLength, out var distance, totalLength, offset, + + vh.AddSingleLineSegmentVertsAndTriangle_CFAL(i, + GetSingleLineSegmentVerts_CFAL(vertices, startPoint, endPoint, nextPoint, prevPoint, + thickness, color, currentLength, out var distance, totalLength, offset, chamferSegments, innerRadius)); currentLength += distance; } - + ListPool.Release(vertices); } - #endregion - + + #region 箭头绘制工具 + + /// + /// 绘制一个三角形箭头 + /// + /// 起点 + /// 终点 + /// 颜色 + /// 箭头的长度 + /// 箭头的宽度 + /// 箭头所处坐标相对线的进度,使用绝对距离时,进度为世界单位;使用相对距离时,进度为单位距离 + /// 箭头的哪部分与所处坐标对齐,0为头部对齐,1为尾部对齐 + /// 箭头做出坐标是否为绝对距离 + /// 反转方向 + /// + /// 箭头默认在 + /// + public static List PopulateTriangleArrowByPointArray(List vertices, Vector2 start, + Vector2 end, Color color, float sizeL, float sizeW, float pointProgress, float arrowPointProgress, + bool absProgressPoint = true, bool reverseDir = false) + { + GetNormalizedVector(start, end, out var vector, out var length, out var normal, out var tangent, + reverseDir); + + var progressPosition = absProgressPoint + ? pointProgress * normal + : pointProgress * vector; + // 加上坐标 + progressPosition += reverseDir ? end : start; + // 加上箭头偏移量 + progressPosition += arrowPointProgress * sizeL * normal; + + // 绘制箭头 + UIVertex vertex = UIVertex.simpleVert; + vertex.color = color; + + vertex.position = progressPosition; + vertices.Add(vertex); + + vertex.position = progressPosition + -sizeL * normal + sizeW * 0.5f * tangent; + vertices.Add(vertex); + vertex.position += (Vector3)(-sizeW * tangent); + vertices.Add(vertex); + + return vertices; + } + + #endregion + #region 带有顶合并的线路绘制方法 - + /// /// 创建线段的顶点数据 /// 每个线段由 5 个顶点组成: @@ -450,7 +539,9 @@ namespace XericLibrary.Runtime.UIGraph /// 用于添加顶点的 VertexHelper 对象 /// 当前线段起点在线路中的累积长度 /// 线路的总长度 - public static void CreateLineSegment_CFAL(this VertexHelper vh, Vector2 startPoint, Vector2 endPoint, float angle0, float angle3, float thickness, bool center, Vector2 rectSize, Color color, float startLength, float totalLength) + public static void CreateLineSegment_CFAL(this VertexHelper vh, Vector2 startPoint, Vector2 endPoint, + float angle0, float angle3, float thickness, bool center, Vector2 rectSize, Color color, float startLength, + float totalLength) { // 计算偏移量:如果需要居中显示,则偏移到组件中心 Vector2 offset = center ? (rectSize / 2) : Vector2.zero; @@ -466,39 +557,44 @@ namespace XericLibrary.Runtime.UIGraph // 线段单侧宽度 var width = thickness / 2; //顶点偏移量,根据夹角计算内侧交点相对坐标点应该退后的距离 - var pointOffset1 = Mathf.Abs(angle0) <= 0.1f ? 0 : width / Mathf.Sin(angle0 * Mathf.Deg2Rad) + (angle0 > 90 ? width : 0); - var pointOffset2 = Mathf.Abs(angle3) <= 0.1f ? 0 : width / Mathf.Sin(angle3 * Mathf.Deg2Rad) + (angle3 > 90 ? width : 0); - Debug.Log($"{angle0} = {Mathf.Sin(angle0 * Mathf.Deg2Rad)} , {angle3} = {Mathf.Sin(angle3 * Mathf.Deg2Rad)}"); + var pointOffset1 = Mathf.Abs(angle0) <= 0.1f + ? 0 + : width / Mathf.Sin(angle0 * Mathf.Deg2Rad) + (angle0 > 90 ? width : 0); + var pointOffset2 = Mathf.Abs(angle3) <= 0.1f + ? 0 + : width / Mathf.Sin(angle3 * Mathf.Deg2Rad) + (angle3 > 90 ? width : 0); + Debug.Log( + $"{angle0} = {Mathf.Sin(angle0 * Mathf.Deg2Rad)} , {angle3} = {Mathf.Sin(angle3 * Mathf.Deg2Rad)}"); // 计算起点和终点的UV坐标Y值 float startUVY = totalLength > 0 ? startLength / totalLength : 0f; float endUVY = totalLength > 0 ? (startLength + distance) / totalLength : 0f; - - vertex.position = (Vector3)(startPoint + - subTangent * width + + + vertex.position = (Vector3)(startPoint + + subTangent * width + normal * pointOffset1) - (Vector3)offset; vertex.uv0 = new Vector2(0f, startUVY); // 左侧顶点的UV vh.AddVert(vertex); - - vertex.position = (Vector3)(startPoint + - subTangent * -width + + + vertex.position = (Vector3)(startPoint + + subTangent * -width + normal * pointOffset1) - (Vector3)offset; vertex.uv0 = new Vector2(1f, startUVY); // 右侧顶点的UV vh.AddVert(vertex); - vertex.position = (Vector3)(endPoint + - subTangent * width + + vertex.position = (Vector3)(endPoint + + subTangent * width + normal * -pointOffset2) - (Vector3)offset; vertex.uv0 = new Vector2(0f, endUVY); // 左侧顶点的UV vh.AddVert(vertex); - - vertex.position = (Vector3)(endPoint + - subTangent * -width + + + vertex.position = (Vector3)(endPoint + + subTangent * -width + normal * -pointOffset2) - (Vector3)offset; vertex.uv0 = new Vector2(1f, endUVY); // 右侧顶点的UV vh.AddVert(vertex); // 添加终点的中心点,用于连接后续线段 - vertex.position = (Vector3)(endPoint + + vertex.position = (Vector3)(endPoint + normal * -pointOffset2) - (Vector3)offset; vertex.uv0 = new Vector2(0.5f, endUVY); // 中心点的UV vh.AddVert(vertex); @@ -513,19 +609,20 @@ namespace XericLibrary.Runtime.UIGraph u = (pos.x - rect.xMin) / rect.width; v = (pos.y - rect.yMin) / rect.height; } - + public static void Get(this IList vertexList, Vector4 uv2) { - } #endregion #region 顶点列表工具 - - private static readonly Color32 s_DefaultColor = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); - private static readonly Vector4 s_DefaultTangent = new Vector4(1f, 0.0f, 0.0f, -1f); - + + private static readonly Color32 s_DefaultColor = + new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); + + private static readonly Vector4 s_DefaultTangent = new Vector4(1f, 0.0f, 0.0f, -1f); + /// /// 添加一个顶点信息 /// @@ -547,6 +644,7 @@ namespace XericLibrary.Runtime.UIGraph uv3 = uv }); } + /// /// 添加一个三角面索引 /// @@ -560,7 +658,34 @@ namespace XericLibrary.Runtime.UIGraph indices.Add(index1); indices.Add(index2); } - + + /// + /// 向顶点管理器添加顶点列表中的顶点构成的面 + /// + /// + /// + /// 开始连成面的顶点 + /// 连成面的顶点范围 + /// 作为连接面中心的顶点 + public static void AddFaceByConsecutiveVertices(this ICollection indices, IList vertexList, + int startVertexIndex, int faceVertexRange, int centerVertexIndex) + { + if (faceVertexRange < 3) + throw new IndexOutOfRangeException("无法创建小于3个点的面"); + var length = startVertexIndex + faceVertexRange - 1; + for (int i = startVertexIndex + 1; i < length; i++) + { + if (i < 0 || i > vertexList.Count) + throw new IndexOutOfRangeException( + $"在向顶点集添加顶点时,从{startVertexIndex}开始的{faceVertexRange}个顶点(以及{centerVertexIndex})可能超出{vertexList.Count}的范围(预定范围{length}),导致构建超出预期"); + var next = startVertexIndex + 1; + + if (next >= vertexList.Count) + return; + indices.AddTriangle(centerVertexIndex, startVertexIndex, startVertexIndex + 1); + } + } + #endregion } } \ No newline at end of file diff --git a/Runtime/Pattern/UIAnyPatternRenderer.cs b/Runtime/Pattern/UIAnyPatternRenderer.cs index 3205802..c99aaa4 100644 --- a/Runtime/Pattern/UIAnyPatternRenderer.cs +++ b/Runtime/Pattern/UIAnyPatternRenderer.cs @@ -3,6 +3,10 @@ using System.Linq; using UnityEngine; using UnityEngine.UI; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace XericLibrary.Runtime.UIGraph { /// @@ -794,6 +798,19 @@ namespace XericLibrary.Runtime.UIGraph base.OnValidate(); isDirty = true; } + + + [MenuItem("GameObject/Xeric Library/UI/UIAnyPatternRenderer", false, 10)] + private static void CreateGameObject() + { + GameObject newObject = new GameObject(nameof(UIAnyPatternRenderer), typeof(UIAnyPatternRenderer)); + + if (Selection.activeGameObject != null) + newObject.transform.SetParent(Selection.activeGameObject.transform); + + Undo.RegisterCreatedObjectUndo(newObject, $"Create {nameof(UIAnyPatternRenderer)}"); + Selection.activeObject = newObject; + } #endif } diff --git a/Runtime/Pattern/UILineRenderer.cs b/Runtime/Pattern/UILineRenderer.cs index 403f25b..98adbfd 100644 --- a/Runtime/Pattern/UILineRenderer.cs +++ b/Runtime/Pattern/UILineRenderer.cs @@ -3,6 +3,10 @@ using UnityEngine; using UnityEngine.Serialization; using UnityEngine.UI; +#if UNITY_EDITOR +using UnityEditor; +#endif + namespace XericLibrary.Runtime.UIGraph { /// @@ -23,12 +27,34 @@ namespace XericLibrary.Runtime.UIGraph public List points = new List(); private Vector2[] _points; + /// + /// 线路宽度 + /// public float thickness = 10f; + /// + /// 居中对齐 + /// public bool center = true; + /// + /// 循环线路 + /// public bool cycleLoop = false; + /// + /// 启用额外绘制的矢量箭头 + /// + public bool enableVectorArrow = false; + /// + /// 矢量箭头尺寸(宽长) + /// + public Vector2 vectorArrowSize = Vector2.one; + + public bool absVectorProgress = true; + public float vectorProgress = 15f; + public float vectorArrowProgress = 0.5f; + public bool reverseVector = false; /// - /// 是否启用倒角功能 + /// 是/否启用倒角功能 /// public bool useChamfer = false; @@ -76,7 +102,7 @@ namespace XericLibrary.Runtime.UIGraph points.Clear(); Refresh(); } - + /// /// 生成线条网格 /// @@ -89,15 +115,18 @@ namespace XericLibrary.Runtime.UIGraph var offset = XericRendererUtils.SwitchCenterOffset(center, rectTransform.sizeDelta); _points = points.ToArray(); + // 切换线路绘制模式 if (useChamfer) { vh.PopulateLineByPointsArray_CFAL(_points, thickness, cycleLoop, color, offset, chamferSegments, innerRadius); } else - { - vh.PopulateLineByPointsArray_DSL5(_points, thickness, cycleLoop, color, offset); - } + { + vh.PopulateLineByPointsArray_DSL5(_points, thickness, cycleLoop, color, offset, + enableVectorArrow, + color, vectorArrowSize, vectorProgress, vectorArrowProgress, absVectorProgress, reverseVector); + } return; @@ -138,5 +167,20 @@ namespace XericLibrary.Runtime.UIGraph } } } + +#if UNITY_EDITOR + + [MenuItem("GameObject/Xeric Library/UI/UILineRenderer", false, 10)] + private static void CreateGameObject() + { + GameObject newObject = new GameObject(nameof(UILineRenderer), typeof(UILineRenderer)); + + if (Selection.activeGameObject != null) + newObject.transform.SetParent(Selection.activeGameObject.transform); + + Undo.RegisterCreatedObjectUndo(newObject, $"Create {nameof(UILineRenderer)}"); + Selection.activeObject = newObject; + } +#endif } -} \ No newline at end of file +} diff --git a/Runtime/Pattern/UIPatternRenderer.cs b/Runtime/Pattern/UIPatternRenderer.cs index c4e3771..4763832 100644 --- a/Runtime/Pattern/UIPatternRenderer.cs +++ b/Runtime/Pattern/UIPatternRenderer.cs @@ -7,6 +7,10 @@ using UnityEngine.Serialization; using UnityEngine.UI; using XericLibrary.Runtime.Debuger; using XericLibrary.Runtime.MacroLibrary; + +#if UNITY_EDITOR +using UnityEditor; +#endif #if ODIN_INSPECTOR using Sirenix.OdinInspector; #endif @@ -315,6 +319,19 @@ namespace XericLibrary.Runtime.UIGraph BorderColorLinear = borderColor2; FillColor = fillColor; } + + + [MenuItem("GameObject/Xeric Library/UI/UIPatternRenderer", false, 10)] + private static void CreateGameObject() + { + GameObject newObject = new GameObject(nameof(UIPatternRenderer), typeof(UIPatternRenderer)); + + if (Selection.activeGameObject != null) + newObject.transform.SetParent(Selection.activeGameObject.transform); + + Undo.RegisterCreatedObjectUndo(newObject, $"Create {nameof(UIPatternRenderer)}"); + Selection.activeObject = newObject; + } #endif } } \ No newline at end of file diff --git a/Runtime/Pattern/XericRendererComponent.cs b/Runtime/Pattern/XericRendererComponent.cs index f31dbb3..cc8ba41 100644 --- a/Runtime/Pattern/XericRendererComponent.cs +++ b/Runtime/Pattern/XericRendererComponent.cs @@ -3,6 +3,7 @@ using System.Linq; using UnityEngine; using UnityEngine.Pool; using UnityEngine.UI; +using XericLibrary.Runtime.MacroLibrary; namespace XericLibrary.Runtime.UIGraph { @@ -21,6 +22,7 @@ namespace XericLibrary.Runtime.UIGraph private readonly List _indexList = new List(); // 阵列原点 private List _arrayTransformList = new List(); + private List _arrayColorList = new List(); // 中间数据 private List _temp_vertexList = new List(); private List _temp_indexList = new List(); @@ -89,14 +91,26 @@ namespace XericLibrary.Runtime.UIGraph /// /// 偏移 /// 角度 - public int AddArrayModifier(Vector3 offset, float angle) + public int AddArrayModifier(Vector2 offset, float angle, float size) { var index = _arrayTransformList.Count; - _arrayTransformList.Add(new Vector4(offset.x, offset.y, offset.z, angle)); + _arrayTransformList.Add(new Vector4(offset.x, offset.y, angle, size)); Refresh(); return index; } + /// + /// 设置阵列节点 + /// + /// + public void SetArrayModifier(IList trans) + { + if (trans == null) + return; + _arrayTransformList.Clear(); + _arrayTransformList.AddRange(trans); + } + /// /// 清空阵列节点 /// @@ -105,15 +119,62 @@ namespace XericLibrary.Runtime.UIGraph _arrayTransformList.Clear(); Refresh(); } - - public bool ModifyArrayModifier(int index, Vector3 offset, float angle) + + /// + /// 修改阵列节点 + /// + /// + /// + /// + /// + /// + public bool ModifyArrayModifier(int index, Vector2 offset, float angle, float size) { if (index < 0 || index >= _arrayTransformList.Count) return false; - _arrayTransformList[index] = new Vector4(offset.x, offset.y, offset.z, angle); + _arrayTransformList[index] = new Vector4(offset.x, offset.y, angle, size); Refresh(); return true; } + + public IList GetArrayModifier() => _arrayTransformList; + + /// + /// 添加颜色 + /// + /// + public void AddColor(Color color) => _arrayColorList.Add(color); + + /// + /// 添加颜色 + /// + /// + public void AddColor(Color32 color) => _arrayColorList.Add(color); + + /// + /// 设置颜色节点 + /// + /// + /// + public void SetColor(int index, Color color) => _arrayColorList.SetAtIndex(color, index); + + /// + /// 设置颜色节点 + /// + /// + /// + public void SetColor(int index, Color32 color) => _arrayColorList.SetAtIndex(color, index); + + /// + /// 清空颜色 + /// + public void ClearArrayColor() => _arrayColorList.Clear(); + + /// + /// 获取颜色列表 + /// + /// + public IList GetArrayColor() => _arrayColorList; #endregion @@ -147,19 +208,27 @@ namespace XericLibrary.Runtime.UIGraph { _temp_vertexList.AddRange(_vertexList.Select(a => { - var newPos = a.position; - if (transform.w != 0) + Vector2 newPos = a.position; + if (transform.z != 0) { - var rot = Quaternion.Euler(0, 0, transform.w); + var rot = Quaternion.Euler(0, 0, transform.z); newPos = rot * newPos; } - newPos += (Vector3)transform; + if (transform.z > 0) + newPos *= transform.w; + newPos += (Vector2)transform; + var newColor = a.color; + if (index < _arrayColorList.Count && !default(Color32).Equals(_arrayColorList[index])) + { + newColor = _arrayColorList[index]; + } + return new UIVertex() { position = newPos, normal = a.normal, tangent = a.tangent, - color = a.color, + color = newColor, uv0 = a.uv0, uv1 = a.uv1, uv2 = a.uv2,