补充注释及更多用法。

This commit is contained in:
2026-07-06 17:04:54 +08:00
parent d938aa9929
commit 45944e4539
5 changed files with 406 additions and 134 deletions
+243 -118
View File
@@ -13,7 +13,7 @@ namespace XericLibrary.Runtime.UIGraph
internal static class XericRendererUtils
{
#region 数学计算
/// <summary>
/// 计算线路的总长度
/// </summary>
@@ -54,7 +54,8 @@ namespace XericLibrary.Runtime.UIGraph
/// <param name="center">是否要居中显示</param>
/// <param name="rectSize">整个绘制矩形范围的尺寸</param>
/// <returns></returns>
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);
/// <summary>
/// 获取两个点之间的法线,副法线
@@ -65,19 +66,21 @@ namespace XericLibrary.Runtime.UIGraph
/// <param name="distance">两点间距离</param>
/// <param name="normal">起点到终点的法线</param>
/// <param name="subTangent">垂直与起点到终点的法线(法线左转90)</param>
/// <param name="reverseVector">反转矢量</param>
/// <returns></returns>
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
/// <param name="totalLength">总线路的长度</param>
/// <param name="startUVY">起点处的uv y</param>
/// <param name="endUVY">终点处的uv y</param>
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)
/// <summary>
/// 创建线段的顶点数据
/// 每个线段由 5 个顶点组成:
@@ -124,8 +128,10 @@ namespace XericLibrary.Runtime.UIGraph
/// <param name="color">线条的颜色</param>
/// <param name="startLength">当前线段起点在线路中的累积长度</param>
/// <param name="totalLength">线路的总长度</param>
public static List<UIVertex> GetSingleLineSegmentVerts_DSL5(List<UIVertex> vertices, Vector2 startPoint, Vector2 endPoint,
float thickness, Color color, float startLength, out float distance, float totalLength, Vector3 offset)
public static List<UIVertex> GetSingleLineSegmentVerts_DSL5(List<UIVertex> 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
/// <param name="vh">构建网格对象</param>
/// <param name="segmentPartIndex">该线路片段索引(比如第一段线应该是0)</param>
/// <param name="verts">该片段顶点</param>
public static void AddSingleLineSegmentVertsAndTriangle_DSL5(this VertexHelper vh, int segmentPartIndex, IEnumerable<UIVertex> verts)
public static void AddSingleLineSegmentVertsAndTriangle_DSL5(this VertexHelper vh, int segmentPartIndex,
IEnumerable<UIVertex> 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);
}
}
/// <summary>
/// 推送顶点绘制线路
/// </summary>
@@ -207,56 +208,94 @@ namespace XericLibrary.Runtime.UIGraph
/// <param name="points"></param>
/// <param name="thickness"></param>
/// <param name="cycleLoop"></param>
/// <param name="color"></param>
/// <param name="lineColor"></param>
/// <param name="offset"></param>
public static void PopulateLineByPointsArray_DSL5(this VertexHelper vh, Vector2[] points, float thickness, bool cycleLoop, Color color, Vector3 offset)
/// <param name="enableArrow"></param>
/// <param name="arrowColor"></param>
/// <param name="arrowSize">宽x长y</param>
/// <param name="pointProgress"></param>
/// <param name="arrowPointProgress"></param>
/// <param name="absProgressPoint"></param>
/// <param name="reverseDir"></param>
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<UIVertex>.Get();
var lineVertices = ListPool<UIVertex>.Get();
var arrowVertices = ListPool<UIVertex>.Get();
var arrowindices = ListPool<int>.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<UIVertex>.Release(vertices);
if (enableArrow)
{
vh.AddUIVertexStream(arrowVertices, arrowindices);
}
ListPool<UIVertex>.Release(lineVertices);
ListPool<UIVertex>.Release(arrowVertices);
ListPool<int>.Release(arrowindices);
}
#endregion
#region 圆弧过度的线路绘制
// 在简易线路绘制的基础上,修改了转角处的处理
// 线的顶点还是5,但是转角圆弧处理会更细节,叫它 CFAL (中心对齐的圆弧转角直线,center fanshaped arc Line)
/// <summary>
/// 在网格构建对象上添加这个直线片段
/// </summary>
/// <param name="vh">构建网格对象</param>
/// <param name="segmentPartIndex">该线路片段索引(比如第一段线应该是0)</param>
/// <param name="verts">该片段顶点</param>
public static void AddSingleLineSegmentVertsAndTriangle_CFAL(this VertexHelper vh, int segmentPartIndex, IEnumerable<UIVertex> verts)
public static void AddSingleLineSegmentVertsAndTriangle_CFAL(this VertexHelper vh, int segmentPartIndex,
IEnumerable<UIVertex> 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
/// <param name="innerRadius">内圆弧半径</param>
/// <param name="distance">返回线段的距离</param>
/// <returns>包含线段顶点的列表</returns>
public static List<UIVertex> GetSingleLineSegmentVerts_CFAL(List<UIVertex> 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<UIVertex> GetSingleLineSegmentVerts_CFAL(List<UIVertex> 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
/// <param name="offset">偏移量</param>
/// <param name="chamferSegments">倒角细分数量</param>
/// <param name="innerRadius">内圆弧半径</param>
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<UIVertex>.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<UIVertex>.Release(vertices);
}
#endregion
#region 箭头绘制工具
/// <summary>
/// 绘制一个三角形箭头
/// </summary>
/// <param name="start">起点</param>
/// <param name="end">终点</param>
/// <param name="color">颜色</param>
/// <param name="sizeL">箭头的长度</param>
/// <param name="sizeW">箭头的宽度</param>
/// <param name="pointProgress">箭头所处坐标相对线的进度,使用绝对距离时,进度为世界单位;使用相对距离时,进度为单位距离</param>
/// <param name="arrowPointProgress">箭头的哪部分与所处坐标对齐,0为头部对齐,1为尾部对齐</param>
/// <param name="absProgressPoint">箭头做出坐标是否为绝对距离</param>
/// <param name="reverseDir">反转方向</param>
/// <remarks>
/// 箭头默认在
/// </remarks>
public static List<UIVertex> PopulateTriangleArrowByPointArray(List<UIVertex> 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 带有顶合并的线路绘制方法
/// <summary>
/// 创建线段的顶点数据
/// 每个线段由 5 个顶点组成:
@@ -450,7 +539,9 @@ namespace XericLibrary.Runtime.UIGraph
/// <param name="vh">用于添加顶点的 VertexHelper 对象</param>
/// <param name="startLength">当前线段起点在线路中的累积长度</param>
/// <param name="totalLength">线路的总长度</param>
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<UIVertex> 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);
/// <summary>
/// 添加一个顶点信息
/// </summary>
@@ -547,6 +644,7 @@ namespace XericLibrary.Runtime.UIGraph
uv3 = uv
});
}
/// <summary>
/// 添加一个三角面索引
/// </summary>
@@ -560,7 +658,34 @@ namespace XericLibrary.Runtime.UIGraph
indices.Add(index1);
indices.Add(index2);
}
/// <summary>
/// 向顶点管理器添加顶点列表中的顶点构成的面
/// </summary>
/// <param name="vh"></param>
/// <param name="vertexList"></param>
/// <param name="startVertexIndex">开始连成面的顶点</param>
/// <param name="faceVertexRange">连成面的顶点范围</param>
/// <param name="centerVertexIndex">作为连接面中心的顶点</param>
public static void AddFaceByConsecutiveVertices(this ICollection<int> indices, IList<UIVertex> 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
}
}
+17
View File
@@ -3,6 +3,10 @@ using System.Linq;
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace XericLibrary.Runtime.UIGraph
{
/// <summary>
@@ -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
}
+50 -6
View File
@@ -3,6 +3,10 @@ using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace XericLibrary.Runtime.UIGraph
{
/// <summary>
@@ -23,12 +27,34 @@ namespace XericLibrary.Runtime.UIGraph
public List<Vector2> points = new List<Vector2>();
private Vector2[] _points;
/// <summary>
/// 线路宽度
/// </summary>
public float thickness = 10f;
/// <summary>
/// 居中对齐
/// </summary>
public bool center = true;
/// <summary>
/// 循环线路
/// </summary>
public bool cycleLoop = false;
/// <summary>
/// 启用额外绘制的矢量箭头
/// </summary>
public bool enableVectorArrow = false;
/// <summary>
/// 矢量箭头尺寸(宽长)
/// </summary>
public Vector2 vectorArrowSize = Vector2.one;
public bool absVectorProgress = true;
public float vectorProgress = 15f;
public float vectorArrowProgress = 0.5f;
public bool reverseVector = false;
/// <summary>
/// 是否启用倒角功能
/// 是/否启用倒角功能
/// </summary>
public bool useChamfer = false;
@@ -76,7 +102,7 @@ namespace XericLibrary.Runtime.UIGraph
points.Clear();
Refresh();
}
/// <summary>
/// 生成线条网格
/// </summary>
@@ -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
}
}
}
+17
View File
@@ -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
}
}
+79 -10
View File
@@ -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<int> _indexList = new List<int>();
// 阵列原点
private List<Vector4> _arrayTransformList = new List<Vector4>();
private List<Color32> _arrayColorList = new List<Color32>();
// 中间数据
private List<UIVertex> _temp_vertexList = new List<UIVertex>();
private List<int> _temp_indexList = new List<int>();
@@ -89,14 +91,26 @@ namespace XericLibrary.Runtime.UIGraph
/// </summary>
/// <param name="offset">偏移</param>
/// <param name="angle">角度</param>
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;
}
/// <summary>
/// 设置阵列节点
/// </summary>
/// <param name="trans"></param>
public void SetArrayModifier(IList<Vector4> trans)
{
if (trans == null)
return;
_arrayTransformList.Clear();
_arrayTransformList.AddRange(trans);
}
/// <summary>
/// 清空阵列节点
/// </summary>
@@ -105,15 +119,62 @@ namespace XericLibrary.Runtime.UIGraph
_arrayTransformList.Clear();
Refresh();
}
public bool ModifyArrayModifier(int index, Vector3 offset, float angle)
/// <summary>
/// 修改阵列节点
/// </summary>
/// <param name="index"></param>
/// <param name="offset"></param>
/// <param name="angle"></param>
/// <param name="size"></param>
/// <returns></returns>
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<Vector4> GetArrayModifier() => _arrayTransformList;
/// <summary>
/// 添加颜色
/// </summary>
/// <param name="color"></param>
public void AddColor(Color color) => _arrayColorList.Add(color);
/// <summary>
/// 添加颜色
/// </summary>
/// <param name="color"></param>
public void AddColor(Color32 color) => _arrayColorList.Add(color);
/// <summary>
/// 设置颜色节点
/// </summary>
/// <param name="index"></param>
/// <param name="color"></param>
public void SetColor(int index, Color color) => _arrayColorList.SetAtIndex<Color32>(color, index);
/// <summary>
/// 设置颜色节点
/// </summary>
/// <param name="index"></param>
/// <param name="color"></param>
public void SetColor(int index, Color32 color) => _arrayColorList.SetAtIndex<Color32>(color, index);
/// <summary>
/// 清空颜色
/// </summary>
public void ClearArrayColor() => _arrayColorList.Clear();
/// <summary>
/// 获取颜色列表
/// </summary>
/// <returns></returns>
public IList<Color32> 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,