diff --git a/Runtime/Internal/Extensions/MeshExtensions.cs b/Runtime/Internal/Extensions/MeshExtensions.cs new file mode 100644 index 0000000..4a8d132 --- /dev/null +++ b/Runtime/Internal/Extensions/MeshExtensions.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace Coffee.UIParticleInternal +{ + internal static class MeshExtensions + { + internal static readonly InternalObjectPool s_MeshPool = new InternalObjectPool( + () => + { + var mesh = new Mesh + { + hideFlags = HideFlags.DontSave | HideFlags.NotEditable + }; + mesh.MarkDynamic(); + return mesh; + }, + mesh => mesh, + mesh => + { + if (mesh != null) + { + mesh.Clear(); + } + }); + + public static Mesh Rent() + { + return s_MeshPool.Rent(); + } + + public static void Return(ref Mesh mesh) + { + s_MeshPool.Return(ref mesh); + } + + public static void CopyTo(this Mesh self, Mesh dst) + { + if (self == null || dst == null) return; + + var vector3List = InternalListPool.Rent(); + var vector4List = InternalListPool.Rent(); + var color32List = InternalListPool.Rent(); + var intList = InternalListPool.Rent(); + + dst.Clear(false); + + self.GetVertices(vector3List); + dst.SetVertices(vector3List); + + self.GetTriangles(intList, 0); + dst.SetTriangles(intList, 0); + + self.GetNormals(vector3List); + dst.SetNormals(vector3List); + + self.GetTangents(vector4List); + dst.SetTangents(vector4List); + + self.GetColors(color32List); + dst.SetColors(color32List); + + self.GetUVs(0, vector4List); + dst.SetUVs(0, vector4List); + + self.GetUVs(1, vector4List); + dst.SetUVs(1, vector4List); + + self.GetUVs(2, vector4List); + dst.SetUVs(2, vector4List); + + self.GetUVs(3, vector4List); + dst.SetUVs(3, vector4List); + + dst.RecalculateBounds(); + InternalListPool.Return(ref vector3List); + InternalListPool.Return(ref vector4List); + InternalListPool.Return(ref color32List); + InternalListPool.Return(ref intList); + } + + public static void CopyTo(this VertexHelper self, Mesh dst) + { + if (self == null || dst == null) return; + + self.FillMesh(dst); + } + + public static void CopyTo(this Mesh self, VertexHelper dst) + { + if (self == null || dst == null) return; + + var vertexCount = self.vertexCount; + var indexCount = self.triangles.Length; + self.CopyTo(dst, vertexCount, indexCount); + } + + public static void CopyTo(this Mesh self, VertexHelper dst, int vertexCount, int indexCount) + { + if (self == null || dst == null) return; + + var positions = InternalListPool.Rent(); + var normals = InternalListPool.Rent(); + var uv0 = InternalListPool.Rent(); + var uv1 = InternalListPool.Rent(); + var uv2 = InternalListPool.Rent(); + var uv3 = InternalListPool.Rent(); + var tangents = InternalListPool.Rent(); + var colors = InternalListPool.Rent(); + var indices = InternalListPool.Rent(); + self.GetVertices(positions); + self.GetColors(colors); + self.GetUVs(0, uv0); + self.GetUVs(1, uv1); + self.GetUVs(2, uv1); + self.GetUVs(3, uv1); + self.GetNormals(normals); + self.GetTangents(tangents); + self.GetIndices(indices, 0); + + dst.Clear(); + for (var i = 0; i < vertexCount; i++) + { + dst.AddVert(positions.GetOrDefault(i), colors.GetOrDefault(i), uv0.GetOrDefault(i), uv1.GetOrDefault(i), + uv2.GetOrDefault(i), uv3.GetOrDefault(i), normals.GetOrDefault(i), tangents.GetOrDefault(i)); + } + + var count = Mathf.Clamp(indexCount, 0, indices.Count); + for (var i = 0; i < count - 2; i += 3) + { + dst.AddTriangle(indices[i], indices[i + 1], indices[i + 2]); + } + + InternalListPool.Return(ref positions); + InternalListPool.Return(ref normals); + InternalListPool.Return(ref uv0); + InternalListPool.Return(ref uv1); + InternalListPool.Return(ref uv2); + InternalListPool.Return(ref uv3); + InternalListPool.Return(ref tangents); + InternalListPool.Return(ref colors); + InternalListPool.Return(ref indices); + } + + private static T GetOrDefault(this List self, int index) + { + return 0 <= index && index < self.Count + ? self[index] + : default; + } + } +} diff --git a/Runtime/Internal/Extensions/MeshExtensions.cs.meta b/Runtime/Internal/Extensions/MeshExtensions.cs.meta new file mode 100644 index 0000000..0902e29 --- /dev/null +++ b/Runtime/Internal/Extensions/MeshExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c949d47f5c6d4d22bd7baebc60d48f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/UIParticleRenderer.cs b/Runtime/UIParticleRenderer.cs index a26c562..3dd3789 100644 --- a/Runtime/UIParticleRenderer.cs +++ b/Runtime/UIParticleRenderer.cs @@ -26,6 +26,7 @@ namespace Coffee.UIExtensions private static readonly List s_Materials = new List(2); private static MaterialPropertyBlock s_Mpb; private static readonly Vector3[] s_Corners = new Vector3[4]; + private static readonly VertexHelper s_VertexHelper = new VertexHelper(); private bool _delay; private int _index; private bool _isPrevStored; @@ -451,11 +452,15 @@ namespace Coffee.UIExtensions var components = InternalListPool.Rent(); GetComponents(typeof(IMeshModifier), components); - for (var i = 0; i < components.Count; i++) + if (0 < components.Count) { -#pragma warning disable CS0618 // Type or member is obsolete - ((IMeshModifier)components[i]).ModifyMesh(workerMesh); -#pragma warning restore CS0618 // Type or member is obsolete + workerMesh.CopyTo(s_VertexHelper); + for (var i = 0; i < components.Count; i++) + { + ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper); + } + + s_VertexHelper.FillMesh(workerMesh); } InternalListPool.Return(ref components);