udpate 0.6.3.3

This commit is contained in:
2026-07-20 11:08:12 +08:00
parent acaa1cd57a
commit 603f5a24c2
71 changed files with 57665 additions and 2183 deletions
@@ -0,0 +1,229 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XericLibrary.Runtime.UIGraph
{
/// <summary>
/// 图元缓存渲染器基类
/// 管理 PrimitiveCacheEntry 列表 + 脏标记范围更新
/// LateUpdate 中只重建脏标记范围内的图元
/// </summary>
[RequireComponent(typeof(CanvasRenderer))]
public abstract class PrimitiveCacheRendererBase : MaskableGraphic
{
#region 默认材质
private static Material s_DefaultMaterial;
private const string DefaultShaderPath = "XericLibrary/UIGraph/UIPattern";
/// <summary>
/// 获取图元渲染器的默认材质(基于 UIPattern.shader)
/// </summary>
public override Material defaultMaterial
{
get
{
if (s_DefaultMaterial == null)
{
var shader = Shader.Find(DefaultShaderPath);
if (shader != null)
s_DefaultMaterial = new Material(shader);
else
s_DefaultMaterial = base.defaultMaterial;
}
return s_DefaultMaterial;
}
}
#endregion
#region 数据缓存
/// <summary>
/// 图元列表
/// </summary>
protected List<PrimitiveCacheEntry> m_Primitives = new List<PrimitiveCacheEntry>();
/// <summary>
/// 模型顶点缓存
/// </summary>
protected List<UIVertex> m_MeshVertexCache = new List<UIVertex>();
/// <summary>
/// 三角形索引缓存
/// </summary>
protected List<int> m_MeshIndexCache = new List<int>();
/// <summary>
/// 脏标记范围起点(图元索引),-1 表示无脏标记
/// </summary>
protected int m_DirtyStartIndex = -1;
/// <summary>
/// 脏标记范围终点(图元索引)
/// </summary>
protected int m_DirtyEndIndex = -1;
#endregion
#region API
/// <summary>
/// 添加一个图元
/// </summary>
/// <returns>图元索引</returns>
public int AddPrimitive(PrimitiveCacheEntry entry)
{
int index = m_Primitives.Count;
m_Primitives.Add(entry);
MarkDirty(index);
return index;
}
/// <summary>
/// 移除指定图元
/// </summary>
public void RemovePrimitive(int index)
{
if (index < 0 || index >= m_Primitives.Count) return;
m_Primitives.RemoveAt(index);
RebuildAll();
}
/// <summary>
/// 标记指定图元为脏
/// </summary>
public void SetPrimitiveDirty(int index)
{
MarkDirty(index);
}
/// <summary>
/// 清空所有图元
/// </summary>
public void ClearAll()
{
m_Primitives.Clear();
m_MeshVertexCache.Clear();
m_MeshIndexCache.Clear();
m_DirtyStartIndex = -1;
m_DirtyEndIndex = -1;
SetVerticesDirty();
}
#endregion
#region 脏标记
protected void MarkDirty(int index)
{
if (m_DirtyStartIndex < 0 || index < m_DirtyStartIndex)
m_DirtyStartIndex = index;
if (m_DirtyEndIndex < 0 || index > m_DirtyEndIndex)
m_DirtyEndIndex = index;
}
/// <summary>
/// 标记所有图元为脏(下次 LateUpdate 全量重绘)
/// 适用于:更新顶点坐标后,不改变元素数量的重绘
/// </summary>
public void RebuildAll()
{
m_DirtyStartIndex = 0;
m_DirtyEndIndex = m_Primitives.Count - 1;
if (m_DirtyEndIndex < 0)
m_DirtyStartIndex = -1;
}
#endregion
#region LateUpdate
protected virtual void LateUpdate()
{
if (m_DirtyStartIndex < 0) return;
// 全量重建策略:从脏范围起点开始,重绘该条目及后续所有条目
// 保证所有条目 startVertexIndex/startIndexIndex 始终正确
int start = m_DirtyStartIndex;
// 统计脏范围前的顶点/索引数(这些条目无需重建)
int preVertexCount = 0;
int preIndexCount = 0;
for (int i = 0; i < start; i++)
{
preVertexCount += m_Primitives[i].vertexCount;
preIndexCount += m_Primitives[i].triangleCount * 3;
}
// 从 start 开始重建所有条目
var tempVerts = new List<UIVertex>();
var tempIndices = new List<int>();
int vAccum = preVertexCount;
int iAccum = preIndexCount;
for (int i = start; i < m_Primitives.Count; i++)
{
var entry = m_Primitives[i];
int vertBefore = tempVerts.Count;
int idxBefore = tempIndices.Count;
PrimitiveMeshGenerator.GeneratePrimitive(entry, tempVerts, tempIndices);
var updated = entry;
updated.startVertexIndex = vAccum;
updated.vertexCount = tempVerts.Count - vertBefore;
updated.startIndexIndex = iAccum;
updated.triangleCount = (tempIndices.Count - idxBefore) / 3;
m_Primitives[i] = updated;
vAccum += updated.vertexCount;
iAccum += updated.triangleCount * 3;
}
// 合并到主缓存
int totalVertices = vAccum;
int totalIndices = iAccum;
while (m_MeshVertexCache.Count < totalVertices)
m_MeshVertexCache.Add(new UIVertex());
while (m_MeshIndexCache.Count < totalIndices)
m_MeshIndexCache.Add(0);
for (int i = 0; i < tempVerts.Count; i++)
m_MeshVertexCache[preVertexCount + i] = tempVerts[i];
for (int i = 0; i < tempIndices.Count; i++)
m_MeshIndexCache[preIndexCount + i] = tempIndices[i] + preVertexCount;
SetVerticesDirty();
m_DirtyStartIndex = -1;
m_DirtyEndIndex = -1;
}
#endregion
#region OnPopulateMesh
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
if (m_MeshVertexCache.Count == 0 || m_MeshIndexCache.Count == 0) return;
vh.AddUIVertexStream(m_MeshVertexCache, m_MeshIndexCache);
}
#endregion
#region 生命周期
protected override void OnEnable()
{
base.OnEnable();
RebuildAll();
}
protected override void OnDestroy()
{
base.OnDestroy();
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28047425f50534b46a5ad5b7a924bd30
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,390 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using XericLibrary.Runtime.MacroLibrary;
namespace XericLibrary.Runtime.UIGraph
{
/// <summary>
/// 图元网格生成器
/// 为多边形/矩形生成 triangle-fan 网格,支持倒角
/// </summary>
public static class PrimitiveMeshGenerator
{
/// <summary>
/// 生成单个图元的网格顶点和索引
/// </summary>
public static void GeneratePrimitive(
in PrimitiveCacheEntry entry,
List<UIVertex> vertexList,
List<int> indexList)
{
// 将归一化 chamferSize [0,1] 映射为实际像素倒角尺寸
float minDim = Mathf.Min(entry.size.x, entry.size.y);
float scaledChamfer = entry.@params.chamferSize * minDim * 0.5f;
PrimitiveParamHelper helper = new PrimitiveParamHelper
{
center = entry.center,
size = entry.size,
sizeMode = entry.sizeMode,
type = entry.type,
sideCount = (int)entry.@params.sideCount,
chamferSize = scaledChamfer,
chamferSegments = entry.@params.chamferSegments,
faceCount = 0
};
// 1. 计算外围顶点
var corners = ComputeCorners(helper);
if (corners.Count < 3) return;
// 应用角度旋转
if (Mathf.Abs(entry.angle) > 0.001f)
{
float rad = entry.angle * Mathf.Deg2Rad;
float cos = Mathf.Cos(rad);
float sin = Mathf.Sin(rad);
for (int i = 0; i < corners.Count; i++)
{
Vector2 rel = corners[i] - entry.center;
corners[i] = entry.center + new Vector2(
rel.x * cos - rel.y * sin,
rel.x * sin + rel.y * cos);
}
}
int baseVertex = vertexList.Count;
int typeIndex = (int)entry.type;
// 颜色打包到法线/副法线
// normal: (bg.r/255, bg.g/255, bg.b/255)
// tangent: (border.r/255, border.g/255, border.b/255, border.a/255)
Color32 bg = entry.@params.bgColor;
Vector3 normalCol = new Vector3(bg.r / 255f, bg.g / 255f, bg.b / 255f);
Color32 bc = entry.@params.borderColor;
Vector4 tangentCol = new Vector4(bc.r / 255f, bc.g / 255f, bc.b / 255f, bc.a / 255f);
// 2. 添加中心点
UIVertex centerVert = new UIVertex
{
position = (Vector3)entry.center,
color = entry.@params.centerColor,
normal = normalCol,
tangent = tangentCol,
uv0 = new Vector2(0.5f, 0.5f),
uv1 = new Vector2(0f, 0f),
};
vertexList.Add(centerVert);
// 3. 添加外围顶点 + 创建三角形扇
for (int i = 0; i < corners.Count; i++)
{
Vector2 pos = corners[i];
float dist = Vector2.Distance(pos, entry.center);
float maxDist = Mathf.Max(entry.size.x, entry.size.y) * 0.5f;
float normalizedDist = maxDist > 0.001f ? Mathf.Clamp01(dist / maxDist) : 0f;
UIVertex vert = new UIVertex
{
position = (Vector3)pos,
color = entry.@params.centerColor,
normal = normalCol,
tangent = tangentCol,
uv0 = new Vector2(
(pos.x - entry.center.x) / entry.size.x + 0.5f,
(pos.y - entry.center.y) / entry.size.y + 0.5f),
uv1 = new Vector2(normalizedDist, 0f),
};
vertexList.Add(vert);
// 三角形扇: (中心, i, i+1)
if (i > 0)
{
indexList.Add(baseVertex); // 中心
indexList.Add(baseVertex + i); // 当前角
indexList.Add(baseVertex + i + 1); // 下一个角
}
}
// 闭合:最后一个角 → 第一个角
if (corners.Count > 2)
{
indexList.Add(baseVertex);
indexList.Add(baseVertex + corners.Count);
indexList.Add(baseVertex + 1);
}
// 4. 生成物理边框 — 复制外围顶点并向外偏移一圈,条带拼接
float borderThickness = entry.@params.borderThickness;
if (borderThickness > 0.001f && corners.Count >= 3)
{
int n = corners.Count;
int borderBase = vertexList.Count;
// 计算每个顶点的向外偏移方向(从中心指向顶点的方向)
var outDirs = new Vector2[n];
for (int i = 0; i < n; i++)
{
Vector2 dir = corners[i] - entry.center;
outDirs[i] = dir.sqrMagnitude > 0.001f ? dir.normalized : Vector2.up;
}
// 添加内圈(原始位置)+ 外圈(偏移位置),isBorder=1
for (int i = 0; i < n; i++)
{
Vector2 pos = corners[i];
Vector2 outPos = pos + outDirs[i] * borderThickness;
// 内圈顶点 (borderProgress=0)
UIVertex inner = new UIVertex
{
position = (Vector3)pos,
color = entry.@params.borderColor,
normal = normalCol,
tangent = tangentCol,
uv0 = new Vector2(
(pos.x - entry.center.x) / entry.size.x + 0.5f,
(pos.y - entry.center.y) / entry.size.y + 0.5f),
uv1 = new Vector2(0f, 1f),
};
vertexList.Add(inner);
// 外圈顶点 (borderProgress=1)
UIVertex outer = new UIVertex
{
position = (Vector3)outPos,
color = entry.@params.borderColor,
normal = normalCol,
tangent = tangentCol,
uv0 = new Vector2(
(outPos.x - entry.center.x) / entry.size.x + 0.5f,
(outPos.y - entry.center.y) / entry.size.y + 0.5f),
uv1 = new Vector2(1f, 1f),
};
vertexList.Add(outer);
}
// 连接条带三角形
for (int i = 0; i < n; i++)
{
int next = (i + 1) % n;
int iI = borderBase + i * 2; // 内圈 i
int oI = borderBase + i * 2 + 1; // 外圈 i
int iN = borderBase + next * 2; // 内圈 next
int oN = borderBase + next * 2 + 1; // 外圈 next
indexList.Add(iI);
indexList.Add(oI);
indexList.Add(iN);
indexList.Add(oI);
indexList.Add(oN);
indexList.Add(iN);
}
}
}
/// <summary>
/// 计算图元的外围顶点列表
/// </summary>
private static List<Vector2> ComputeCorners(in PrimitiveParamHelper helper)
{
if (helper.type == PrimitiveType.Polygon)
return ComputePolygonCorners(helper);
else
return ComputeRectangleCorners(helper);
}
/// <summary>
/// 计算正多边形的外围顶点
/// </summary>
private static List<Vector2> ComputePolygonCorners(in PrimitiveParamHelper helper)
{
int sides = Mathf.Max(3, helper.sideCount);
float angleStep = 360f / sides;
float startAngle = 90f;
// 计算半径
float minSize = Mathf.Min(helper.size.x, helper.size.y);
float radius = minSize * 0.5f;
if (helper.sizeMode == SizeMode.CircumscribedCircle)
{
// 外切圆:半径延伸到各顶点
// 外切圆半径 = minSize/2
// 实际半径需要让多边形的边与外切圆相切
// 对于外切圆,多边形的顶点到中心的距离 = r / cos(π/N)
float apothemAngle = Mathf.PI / sides;
radius = radius / Mathf.Cos(apothemAngle);
}
// InscribedCircle 保持 radius = minSize/2
// 计算基本多边形顶点
var corners = new List<Vector2>(sides);
for (int i = 0; i < sides; i++)
{
float angleDeg = startAngle + i * angleStep;
float angle = angleDeg * Mathf.Deg2Rad;
corners.Add(new Vector2(
helper.center.x + Mathf.Cos(angle) * radius,
helper.center.y + Mathf.Sin(angle) * radius));
}
// 应用 XY 缩放
for (int i = 0; i < corners.Count; i++)
{
Vector2 dir = corners[i] - helper.center;
corners[i] = helper.center + new Vector2(
dir.x * helper.size.x / minSize,
dir.y * helper.size.y / minSize);
}
// 处理倒角
if (helper.chamferSize > 0.001f)
corners = ApplyChamfer(corners, helper.chamferSize, helper.chamferSegments);
return corners;
}
/// <summary>
/// 计算矩形的四个角
/// </summary>
private static List<Vector2> ComputeRectangleCorners(in PrimitiveParamHelper helper)
{
float halfX, halfY;
switch (helper.sizeMode)
{
case SizeMode.InscribedCircle:
{
float minSize = Mathf.Min(helper.size.x, helper.size.y);
halfX = minSize * 0.5f;
halfY = minSize * 0.5f;
break;
}
case SizeMode.CircumscribedCircle:
{
float minSize = Mathf.Min(helper.size.x, helper.size.y);
float radius = minSize * 0.5f;
halfX = radius;
halfY = radius;
break;
}
case SizeMode.InscribedEllipse:
{
halfX = helper.size.x * 0.5f;
halfY = helper.size.y * 0.5f;
break;
}
case SizeMode.CircumscribedRatio:
{
float minSize = Mathf.Min(helper.size.x, helper.size.y);
float radius = minSize * 0.5f;
halfX = radius * (helper.size.x / minSize);
halfY = radius * (helper.size.y / minSize);
break;
}
default:
halfX = helper.size.x * 0.5f;
halfY = helper.size.y * 0.5f;
break;
}
var corners = new List<Vector2>(4)
{
helper.center + new Vector2(-halfX, -halfY),
helper.center + new Vector2( halfX, -halfY),
helper.center + new Vector2( halfX, halfY),
helper.center + new Vector2(-halfX, halfY),
};
if (helper.chamferSize > 0.001f)
corners = ApplyChamfer(corners, helper.chamferSize, helper.chamferSegments);
return corners;
}
/// <summary>
/// 对多边形角应用倒角(Bezier 曲线圆角)
/// </summary>
private static List<Vector2> ApplyChamfer(
List<Vector2> corners, float chamferSize, int segments)
{
int n = corners.Count;
// 计算每条边的长度,取最短边的一半作为倒角上限
float minEdgeHalf = float.MaxValue;
for (int i = 0; i < n; i++)
{
int next = (i + 1) % n;
float edgeLen = Vector2.Distance(corners[i], corners[next]);
minEdgeHalf = Mathf.Min(minEdgeHalf, edgeLen * 0.5f);
}
float clampedChamfer = Mathf.Min(chamferSize, minEdgeHalf);
if (clampedChamfer < 0.001f) return corners;
var result = new List<Vector2>();
for (int i = 0; i < n; i++)
{
int prev = (i - 1 + n) % n;
int curr = i;
int next = (i + 1) % n;
Vector2 pCurr = corners[curr];
Vector2 pPrev = corners[prev];
Vector2 pNext = corners[next];
float edgeLenIn = Vector2.Distance(pPrev, pCurr);
float edgeLenOut = Vector2.Distance(pCurr, pNext);
float clampIn = Mathf.Min(clampedChamfer, edgeLenIn * 0.5f);
float clampOut = Mathf.Min(clampedChamfer, edgeLenOut * 0.5f);
// p0 在入边 (prev→curr) 上,距角 clampIn
// p3 在出边 (curr→next) 上,距角 clampOut
Vector2 dirFromCurrToPrev = (pPrev - pCurr).normalized;
Vector2 dirFromCurrToNext = (pNext - pCurr).normalized;
Vector2 p0 = pCurr + dirFromCurrToPrev * clampIn;
Vector2 p3 = pCurr + dirFromCurrToNext * clampOut;
// 三次 Bezier 控制点:向角的方向内收,使曲线从 p0 平滑过渡到 p3
// 控制点位于 p0→pCorner 和 p3→pCorner 之间
float c = 0.5522847498f; // 四分之一圆的 Bezier 近似常数
float bezierR = Mathf.Min(clampIn, clampOut);
Vector2 p1 = p0 + (pCurr - p0).normalized * bezierR * c;
Vector2 p2 = p3 + (pCurr - p3).normalized * bezierR * c;
// 添加 p0(每条边的起点)
result.Add(p0);
// 插值 Bezier 曲线上的中间点
for (int j = 1; j < segments; j++)
{
float t = (float)j / segments;
MacroCurve.BezierCurve3(p0, p1, p2, p3, t, out Vector2 pos);
result.Add(pos);
}
// 添加 p3(每条边的终点,也是下条边的起点)
result.Add(p3);
}
return result;
}
/// <summary>
/// 内部辅助结构(避免在 ComputeCorners 中传递过多参数)
/// </summary>
private struct PrimitiveParamHelper
{
public Vector2 center;
public Vector2 size;
public SizeMode sizeMode;
public PrimitiveType type;
public int sideCount;
public float chamferSize;
public int chamferSegments;
public int faceCount; // 输出:实际生成的三角形数
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9ae63ff723ba749448c841d5afe21ac2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,80 @@
using UnityEngine;
namespace XericLibrary.Runtime.UIGraph
{
/// <summary>
/// 图元类型
/// </summary>
public enum PrimitiveType : byte
{
/// <summary>正多边形(内切圆/外切圆)</summary>
Polygon,
/// <summary>矩形(内切椭圆/外切圆比例)</summary>
Rectangle,
}
/// <summary>
/// 尺寸模式
/// </summary>
public enum SizeMode : byte
{
/// <summary>内切圆 — 半径延伸到各边中点</summary>
InscribedCircle,
/// <summary>外切圆 — 半径延伸到各顶点</summary>
CircumscribedCircle,
/// <summary>内切椭圆 — XY各自独立的内切半径</summary>
InscribedEllipse,
/// <summary>外切圆比例 — 外切圆半径 + XY比例</summary>
CircumscribedRatio,
}
/// <summary>
/// 图元参数
/// 顶点通道分配:
/// uv0: 面片内归一化坐标 (0~1)
/// uv1: (centerDist, isBorder)
/// normal: (bg.r, bg.g, bg.b) — 0~1
/// tangent: (border.r, border.g, border.b, border.a) — 0~1
/// </summary>
public struct PrimitiveParams
{
public float axisScaleX;
public float axisScaleY;
public float sideCount;
public float chamferSize;
/// <summary>倒角细分段数(仅网格生成使用)</summary>
public int chamferSegments;
public Color32 bgColor;
public Color32 centerColor;
public Color32 borderColor;
public float borderThickness;
}
/// <summary>
/// 图元缓存条目
/// </summary>
public struct PrimitiveCacheEntry
{
/// <summary>在网格顶点缓存中的起始索引</summary>
public int startVertexIndex;
/// <summary>该图元占用的顶点数</summary>
public int vertexCount;
/// <summary>在网格索引缓存中的起始索引</summary>
public int startIndexIndex;
/// <summary>三角形数量</summary>
public int triangleCount;
public PrimitiveType type;
public SizeMode sizeMode;
/// <summary>图元中心(局部坐标)</summary>
public Vector2 center;
/// <summary>图元尺寸</summary>
public Vector2 size;
/// <summary>旋转角度(度数,0 = 正上方)</summary>
public float angle;
/// <summary>图元参数</summary>
public PrimitiveParams @params;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b233b049f5be67e47a89d1f9bee867b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,144 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace XericLibrary.Runtime.UIGraph
{
/// <summary>
/// 图元绘制器组件
/// 支持多边形/矩形的内切圆/外切圆/椭圆等尺寸模式
/// 参数写入 UV2-UV7 通道
/// </summary>
[AddComponentMenu("Xeric Library/UI/UIPrimitiveRenderer", 15)]
public class UIPrimitiveRenderer : PrimitiveCacheRendererBase
{
public PrimitiveType primitiveType = PrimitiveType.Polygon;
public SizeMode sizeMode = SizeMode.InscribedCircle;
public Vector2 size = new Vector2(100f, 100f);
public Vector2 centerOffset = Vector2.zero;
[Range(-180f, 180f)]
public float angle = 0f;
[Range(3, 64)]
public int sideCount = 6;
[Range(0f, 1f)]
public float chamferSize = 0f;
[Range(1, 16)]
public int chamferSegments = 4;
public Color bgColor = Color.gray;
public Color centerColor = Color.white;
public Color borderColor = Color.black;
[Range(0f, 50f)]
public float borderThickness = 2f;
public bool autoRebuild = true;
private PrimitiveCacheEntry? m_CurrentEntry;
protected override void OnEnable()
{
base.OnEnable();
if (autoRebuild) RebuildPrimitive();
}
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
if (sideCount < 3) sideCount = 3;
if (autoRebuild && isActiveAndEnabled)
{
// 使用 EditorApplication.delayCall 避免 OnValidate 中的 SetVerticesDirty 警告
EditorApplication.delayCall += () =>
{
if (this != null && isActiveAndEnabled)
RebuildPrimitive();
};
}
}
#endif
/// <summary>
/// 重建图元
/// </summary>
public void RebuildPrimitive()
{
// 清除旧的图元
ClearAll();
var entry = new PrimitiveCacheEntry
{
type = primitiveType,
sizeMode = sizeMode,
center = centerOffset,
size = size,
angle = angle,
@params = new PrimitiveParams
{
axisScaleX = 1f,
axisScaleY = 1f,
sideCount = sideCount,
chamferSize = chamferSize,
chamferSegments = chamferSegments,
bgColor = bgColor,
centerColor = centerColor,
borderColor = borderColor,
borderThickness = borderThickness,
}
};
AddPrimitive(entry);
m_CurrentEntry = entry;
}
/// <summary>
/// 更新图元参数(不触发完全重建,只标记脏)
/// </summary>
public void UpdateParams(System.Action<PrimitiveCacheEntry> updater)
{
if (m_Primitives.Count == 0) return;
var entry = m_Primitives[0];
updater?.Invoke(entry);
m_Primitives[0] = entry;
SetPrimitiveDirty(0);
}
#region 便捷方法
/// <summary>
/// 快速设置为正多边形
/// </summary>
public void SetPolygon(int sides, float radius, Color? fill = null, Color? border = null)
{
primitiveType = PrimitiveType.Polygon;
sizeMode = SizeMode.InscribedCircle;
size = new Vector2(radius * 2f, radius * 2f);
sideCount = Mathf.Max(3, sides);
if (fill.HasValue) bgColor = fill.Value;
if (border.HasValue) borderColor = border.Value;
RebuildPrimitive();
}
/// <summary>
/// 快速设置为矩形
/// </summary>
public void SetRectangle(float width, float height, Color? fill = null, Color? border = null)
{
primitiveType = PrimitiveType.Rectangle;
sizeMode = SizeMode.InscribedEllipse;
size = new Vector2(width, height);
if (fill.HasValue) bgColor = fill.Value;
if (border.HasValue) borderColor = border.Value;
RebuildPrimitive();
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a7f57f5609d9f3a46aa9d50dc1a47904
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: