using UnityEngine; using System; using System.Collections; using System.Collections.Generic; namespace TMPro { /// /// Class which contains information about every element contained within the text object. /// [Serializable] public class TMP_TextInfo { internal static readonly Vector2 k_InfinityVectorPositive = new Vector2(32767, 32767); internal static readonly Vector2 k_InfinityVectorNegative = new Vector2(-32767, -32767); public TMP_Text textComponent; public int characterCount; public int spriteCount; public int spaceCount; public int wordCount; public int linkCount; public int lineCount; public int pageCount; public int materialCount; [NonSerialized] public TMP_CharacterInfo[] characterInfo; [NonSerialized] public TMP_WordInfo[] wordInfo; [NonSerialized] public TMP_LinkInfo[] linkInfo; [NonSerialized] public TMP_LineInfo[] lineInfo; [NonSerialized] public TMP_PageInfo[] pageInfo; [NonSerialized] public TMP_MeshInfo[] meshInfo; private TMP_MeshInfo[] m_CachedMeshInfo; // Default Constructor public TMP_TextInfo() { characterInfo = new TMP_CharacterInfo[8]; wordInfo = new TMP_WordInfo[16]; linkInfo = new TMP_LinkInfo[0]; lineInfo = new TMP_LineInfo[2]; pageInfo = new TMP_PageInfo[4]; meshInfo = new TMP_MeshInfo[1]; } internal TMP_TextInfo(int characterCount) { characterInfo = new TMP_CharacterInfo[characterCount]; wordInfo = new TMP_WordInfo[16]; linkInfo = new TMP_LinkInfo[0]; lineInfo = new TMP_LineInfo[2]; pageInfo = new TMP_PageInfo[4]; meshInfo = new TMP_MeshInfo[1]; } public TMP_TextInfo(TMP_Text textComponent) { this.textComponent = textComponent; characterInfo = new TMP_CharacterInfo[8]; wordInfo = new TMP_WordInfo[4]; linkInfo = new TMP_LinkInfo[0]; lineInfo = new TMP_LineInfo[2]; pageInfo = new TMP_PageInfo[4]; meshInfo = new TMP_MeshInfo[1]; meshInfo[0].mesh = textComponent.mesh; materialCount = 1; } /// /// Function to clear the counters of the text object. /// internal void Clear() { characterCount = 0; spaceCount = 0; wordCount = 0; linkCount = 0; lineCount = 0; pageCount = 0; spriteCount = 0; for (int i = 0; i < this.meshInfo.Length; i++) { this.meshInfo[i].vertexCount = 0; } } /// /// /// internal void ClearAllData() { characterCount = 0; spaceCount = 0; wordCount = 0; linkCount = 0; lineCount = 0; pageCount = 0; spriteCount = 0; this.characterInfo = new TMP_CharacterInfo[4]; this.wordInfo = new TMP_WordInfo[1]; this.lineInfo = new TMP_LineInfo[1]; this.pageInfo = new TMP_PageInfo[1]; this.linkInfo = new TMP_LinkInfo[0]; materialCount = 0; this.meshInfo = new TMP_MeshInfo[1]; } /// /// Function to clear the content of the MeshInfo array while preserving the Triangles, Normals and Tangents. /// public void ClearMeshInfo(bool updateMesh) { for (int i = 0; i < this.meshInfo.Length; i++) this.meshInfo[i].Clear(updateMesh); } /// /// Function to clear the content of all the MeshInfo arrays while preserving their Triangles, Normals and Tangents. /// public void ClearAllMeshInfo() { for (int i = 0; i < this.meshInfo.Length; i++) this.meshInfo[i].Clear(true); } /// /// Clears all mesh data and reconfigures the vertex structures to support either standard quads or volumetric (3D) character geometry. /// /// When true, subsequent mesh growth uses eight vertices per glyph; otherwise four vertices per glyph. /// /// Resizes each entry in to zero vertices using , /// so subsequent text generation allocates buffers for either billboard quads or extruded volumetric glyphs as required. /// public void ResetVertexLayout(bool isVolumetric) { for (int i = 0; i < this.meshInfo.Length; i++) this.meshInfo[i].ResizeMeshInfo(0, isVolumetric); } /// /// Marks unused vertices as degenerate. /// /// Parallel material references for each sub-mesh entry; reserved for per-material vertex ranges when clearing unused vertices. /// /// Iterates and calls from the computed start index so trailing vertices /// in each buffer can be cleared without reallocating the mesh. /// public void ClearUnusedVertices(MaterialReference[] materials) { for (int i = 0; i < meshInfo.Length; i++) { int start = 0; // materials[i].referenceCount * 4; meshInfo[i].ClearUnusedVertices(start); } } /// /// Function to clear and initialize the lineInfo array. /// internal void ClearLineInfo() { if (this.lineInfo == null) this.lineInfo = new TMP_LineInfo[1]; int length = this.lineInfo.Length; for (int i = 0; i < length; i++) { this.lineInfo[i].characterCount = 0; this.lineInfo[i].spaceCount = 0; this.lineInfo[i].wordCount = 0; this.lineInfo[i].controlCharacterCount = 0; this.lineInfo[i].visibleCharacterCount = 0; this.lineInfo[i].visibleSpaceCount = 0; this.lineInfo[i].ascender = k_InfinityVectorNegative.x; this.lineInfo[i].baseline = 0; this.lineInfo[i].descender = k_InfinityVectorPositive.x; this.lineInfo[i].maxAdvance = 0; this.lineInfo[i].marginLeft = 0; this.lineInfo[i].marginRight = 0; this.lineInfo[i].lineExtents.min = k_InfinityVectorPositive; this.lineInfo[i].lineExtents.max = k_InfinityVectorNegative; this.lineInfo[i].width = 0; } } internal void ClearPageInfo() { if (this.pageInfo == null) this.pageInfo = new TMP_PageInfo[2]; int length = this.pageInfo.Length; for (int i = 0; i < length; i++) { this.pageInfo[i].firstCharacterIndex = 0; this.pageInfo[i].lastCharacterIndex = 0; this.pageInfo[i].ascender = -32767; this.pageInfo[i].baseLine = 0; this.pageInfo[i].descender = 32767; } } /// /// Function to copy the MeshInfo Arrays and their primary vertex data content. /// /// A copy of the MeshInfo[] public TMP_MeshInfo[] CopyMeshInfoVertexData() { if (m_CachedMeshInfo == null || m_CachedMeshInfo.Length != meshInfo.Length) { m_CachedMeshInfo = new TMP_MeshInfo[meshInfo.Length]; // Initialize all the vertex data arrays for (int i = 0; i < m_CachedMeshInfo.Length; i++) { int length = meshInfo[i].vertices.Length; m_CachedMeshInfo[i].vertices = new Vector3[length]; m_CachedMeshInfo[i].uvs0 = new Vector4[length]; m_CachedMeshInfo[i].uvs2 = new Vector2[length]; m_CachedMeshInfo[i].colors32 = new Color32[length]; //m_CachedMeshInfo[i].normals = new Vector3[length]; //m_CachedMeshInfo[i].tangents = new Vector4[length]; //m_CachedMeshInfo[i].triangles = new int[meshInfo[i].triangles.Length]; } } for (int i = 0; i < m_CachedMeshInfo.Length; i++) { int length = meshInfo[i].vertices.Length; if (m_CachedMeshInfo[i].vertices.Length != length) { m_CachedMeshInfo[i].vertices = new Vector3[length]; m_CachedMeshInfo[i].uvs0 = new Vector4[length]; m_CachedMeshInfo[i].uvs2 = new Vector2[length]; m_CachedMeshInfo[i].colors32 = new Color32[length]; //m_CachedMeshInfo[i].normals = new Vector3[length]; //m_CachedMeshInfo[i].tangents = new Vector4[length]; //m_CachedMeshInfo[i].triangles = new int[meshInfo[i].triangles.Length]; } // Only copy the primary vertex data Array.Copy(meshInfo[i].vertices, m_CachedMeshInfo[i].vertices, length); Array.Copy(meshInfo[i].uvs0, m_CachedMeshInfo[i].uvs0, length); Array.Copy(meshInfo[i].uvs2, m_CachedMeshInfo[i].uvs2, length); Array.Copy(meshInfo[i].colors32, m_CachedMeshInfo[i].colors32, length); //Array.Copy(meshInfo[i].normals, m_CachedMeshInfo[i].normals, length); //Array.Copy(meshInfo[i].tangents, m_CachedMeshInfo[i].tangents, length); //Array.Copy(meshInfo[i].triangles, m_CachedMeshInfo[i].triangles, meshInfo[i].triangles.Length); } return m_CachedMeshInfo; } /// /// Resizes any of the structure contained in the TMP_TextInfo class. /// /// Element type of the array. /// The array to resize (passed by reference). /// The required number of elements; actual size may be rounded up to next power of two. /// /// Uses the next power of two (or size plus 256 when above 1024) to reduce frequent reallocations while TMP grows character, word, or line tables during layout. /// public static void Resize (ref T[] array, int size) { // Allocated to the next power of two int newSize = size > 1024 ? size + 256 : Mathf.NextPowerOfTwo(size); Array.Resize(ref array, newSize); } /// /// Resizes any of the structure contained in the TMP_TextInfo class. /// /// Element type of the array. /// The array to resize (passed by reference). /// The required number of elements; when isBlockAllocated is true, rounded up to next power of two. /// When true, size is rounded up to the next power of two for block allocation. /// /// When is false, the array is resized to exactly if different from the current length, /// which is used for structures that already use explicit sizing instead of power-of-two blocks. /// public static void Resize(ref T[] array, int size, bool isBlockAllocated) { if (isBlockAllocated) size = size > 1024 ? size + 256 : Mathf.NextPowerOfTwo(size); if (size == array.Length) return; //Debug.Log("Resizing TextInfo from [" + array.Length + "] to [" + size + "]"); Array.Resize(ref array, size); } } }