using System; using System.Collections.Generic; using UnityEngine.Pool; namespace UnityEngine.UI { /// /// A utility class that can aid in the generation of meshes for the UI. /// /// /// This class implements IDisposable to aid with memory management. /// /// /// /// /// /// public class VertexHelper : IDisposable { private List m_Positions; private List m_Colors; private List m_Uv0S; private List m_Uv1S; private List m_Uv2S; private List m_Uv3S; private List m_Normals; private List m_Tangents; private List m_Indices; private static readonly Vector4 s_DefaultTangent = new Vector4(1.0f, 0.0f, 0.0f, -1.0f); private static readonly Vector3 s_DefaultNormal = Vector3.back; private bool m_ListsInitalized = false; public VertexHelper() {} public VertexHelper(Mesh m) { InitializeListIfRequired(); m_Positions.AddRange(m.vertices); m_Colors.AddRange(m.colors32); List tempUVList = new List(); m.GetUVs(0, tempUVList); m_Uv0S.AddRange(tempUVList); m.GetUVs(1, tempUVList); m_Uv1S.AddRange(tempUVList); m.GetUVs(2, tempUVList); m_Uv2S.AddRange(tempUVList); m.GetUVs(3, tempUVList); m_Uv3S.AddRange(tempUVList); m_Normals.AddRange(m.normals); m_Tangents.AddRange(m.tangents); m_Indices.AddRange(m.GetIndices(0)); } private void InitializeListIfRequired() { if (!m_ListsInitalized) { m_Positions = ListPool.Get(); m_Colors = ListPool.Get(); m_Uv0S = ListPool.Get(); m_Uv1S = ListPool.Get(); m_Uv2S = ListPool.Get(); m_Uv3S = ListPool.Get(); m_Normals = ListPool.Get(); m_Tangents = ListPool.Get(); m_Indices = ListPool.Get(); m_ListsInitalized = true; } } /// /// Cleanup allocated memory. /// public void Dispose() { if (m_ListsInitalized) { ListPool.Release(m_Positions); ListPool.Release(m_Colors); ListPool.Release(m_Uv0S); ListPool.Release(m_Uv1S); ListPool.Release(m_Uv2S); ListPool.Release(m_Uv3S); ListPool.Release(m_Normals); ListPool.Release(m_Tangents); ListPool.Release(m_Indices); m_Positions = null; m_Colors = null; m_Uv0S = null; m_Uv1S = null; m_Uv2S = null; m_Uv3S = null; m_Normals = null; m_Tangents = null; m_Indices = null; m_ListsInitalized = false; } } /// /// Clear all vertices from the stream. /// public void Clear() { // Only clear if we have our lists created. if (m_ListsInitalized) { m_Positions.Clear(); m_Colors.Clear(); m_Uv0S.Clear(); m_Uv1S.Clear(); m_Uv2S.Clear(); m_Uv3S.Clear(); m_Normals.Clear(); m_Tangents.Clear(); m_Indices.Clear(); } } /// /// Current number of vertices in the buffer. /// public int currentVertCount { get { return m_Positions != null ? m_Positions.Count : 0; } } /// /// Get the number of indices set on the VertexHelper. /// public int currentIndexCount { get { return m_Indices != null ? m_Indices.Count : 0; } } /// /// Fill a UIVertex with data from index i of the stream. /// /// Vertex to populate /// Index to populate. public void PopulateUIVertex(ref UIVertex vertex, int i) { InitializeListIfRequired(); vertex.position = m_Positions[i]; vertex.color = m_Colors[i]; vertex.uv0 = m_Uv0S[i]; vertex.uv1 = m_Uv1S[i]; vertex.uv2 = m_Uv2S[i]; vertex.uv3 = m_Uv3S[i]; vertex.normal = m_Normals[i]; vertex.tangent = m_Tangents[i]; } /// /// Set a UIVertex at the given index. /// /// The vertex to fill /// the position in the current list to fill. public void SetUIVertex(UIVertex vertex, int i) { InitializeListIfRequired(); m_Positions[i] = vertex.position; m_Colors[i] = vertex.color; m_Uv0S[i] = vertex.uv0; m_Uv1S[i] = vertex.uv1; m_Uv2S[i] = vertex.uv2; m_Uv3S[i] = vertex.uv3; m_Normals[i] = vertex.normal; m_Tangents[i] = vertex.tangent; } /// /// Fill the given mesh with the stream data. /// public void FillMesh(Mesh mesh) { InitializeListIfRequired(); mesh.Clear(); if (m_Positions.Count >= 65000) throw new ArgumentException("Mesh can not have more than 65000 vertices"); mesh.SetVertices(m_Positions); mesh.SetColors(m_Colors); mesh.SetUVs(0, m_Uv0S); mesh.SetUVs(1, m_Uv1S); mesh.SetUVs(2, m_Uv2S); mesh.SetUVs(3, m_Uv3S); mesh.SetNormals(m_Normals); mesh.SetTangents(m_Tangents); mesh.SetTriangles(m_Indices, 0); mesh.RecalculateBounds(); } /// /// Add a single vertex to the stream. /// /// Position of the vert /// Color of the vert /// UV of the vert /// UV1 of the vert /// UV2 of the vert /// UV3 of the vert /// Normal of the vert. /// Tangent of the vert public void AddVert(Vector3 position, Color32 color, Vector4 uv0, Vector4 uv1, Vector4 uv2, Vector4 uv3, Vector3 normal, Vector4 tangent) { InitializeListIfRequired(); m_Positions.Add(position); m_Colors.Add(color); m_Uv0S.Add(uv0); m_Uv1S.Add(uv1); m_Uv2S.Add(uv2); m_Uv3S.Add(uv3); m_Normals.Add(normal); m_Tangents.Add(tangent); } /// /// Add a single vertex to the stream. /// /// Position of the vert /// Color of the vert /// UV of the vert /// UV1 of the vert /// Normal of the vert. /// Tangent of the vert public void AddVert(Vector3 position, Color32 color, Vector4 uv0, Vector4 uv1, Vector3 normal, Vector4 tangent) { AddVert(position, color, uv0, uv1, Vector4.zero, Vector4.zero, normal, tangent); } /// /// Add a single vertex to the stream. /// /// Position of the vert /// Color of the vert /// UV of the vert public void AddVert(Vector3 position, Color32 color, Vector4 uv0) { AddVert(position, color, uv0, Vector4.zero, s_DefaultNormal, s_DefaultTangent); } /// /// Add a single vertex to the stream. /// /// The vertex to add public void AddVert(UIVertex v) { AddVert(v.position, v.color, v.uv0, v.uv1, v.uv2, v.uv3, v.normal, v.tangent); } /// /// Add a triangle to the buffer. /// /// index 0 /// index 1 /// index 2 public void AddTriangle(int idx0, int idx1, int idx2) { InitializeListIfRequired(); m_Indices.Add(idx0); m_Indices.Add(idx1); m_Indices.Add(idx2); } /// /// Add a quad to the stream. /// /// 4 Vertices representing the quad. public void AddUIVertexQuad(UIVertex[] verts) { int startIndex = currentVertCount; for (int i = 0; i < 4; i++) AddVert(verts[i].position, verts[i].color, verts[i].uv0, verts[i].uv1, verts[i].normal, verts[i].tangent); AddTriangle(startIndex, startIndex + 1, startIndex + 2); AddTriangle(startIndex + 2, startIndex + 3, startIndex); } /// /// Add a stream of custom UIVertex and corresponding indices. /// /// The custom stream of verts to add to the helpers internal data. /// The custom stream of indices to add to the helpers internal data. public void AddUIVertexStream(List verts, List indices) { InitializeListIfRequired(); if (verts != null) { CanvasRenderer.AddUIVertexStream(verts, m_Positions, m_Colors, m_Uv0S, m_Uv1S, m_Uv2S, m_Uv3S, m_Normals, m_Tangents); } if (indices != null) { m_Indices.AddRange(indices); } } /// /// Add a list of triangles to the stream. /// /// Vertices to add. Length should be divisible by 3. public void AddUIVertexTriangleStream(List verts) { if (verts == null) return; InitializeListIfRequired(); CanvasRenderer.SplitUIVertexStreams(verts, m_Positions, m_Colors, m_Uv0S, m_Uv1S, m_Uv2S, m_Uv3S, m_Normals, m_Tangents, m_Indices); } /// /// Create a stream of UI vertex (in triangles) from the stream. /// public void GetUIVertexStream(List stream) { if (stream == null) return; InitializeListIfRequired(); CanvasRenderer.CreateUIVertexStream(stream, m_Positions, m_Colors, m_Uv0S, m_Uv1S, m_Uv2S, m_Uv3S, m_Normals, m_Tangents, m_Indices); } } }