public virtual void DoEffect(TMProLinkAnimator context, int start, int length) { CurrentContext = context; CurrentStart = start; CurrentLength = length; MeshVertUpdateLoop(context, start, length, TransFunc, ColorFunc, mode); }
/// <summary> /// Same as calcing a character mid but averaging over all characters in the given character range /// </summary> /// <param name="context"></param> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> static public Vector2 CalcMidFromChars(TMProLinkAnimator context, int start, int end) { Vector3 middle = Vector3.zero; var chInfo = context.TMProComponent.textInfo.characterInfo; for (int i = start; i < end; i++) { int materialIndex = chInfo[i].materialReferenceIndex; int vertexIndex = chInfo[i].vertexIndex; Vector3[] sourceVertices = context.CachedMeshInfo[materialIndex].vertices; middle += (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2; } return(middle / (end - start)); }
/// <summary> /// Helper for mesh vertex updating within a found link, adapted from TMPRo examples VertexJitter. /// </summary> /// <param name="context"></param> /// <param name="start"></param> /// <param name="length"></param> /// <param name="transformFunc"></param> /// <param name="colorFunc"></param> /// <param name="mode"></param> static public void MeshVertUpdateLoop(TMProLinkAnimator context, int start, int length, System.Func <int, Matrix4x4> transformFunc, System.Func <int, Color32, Color32> colorFunc, TMPLinkAnimatorMode mode) { var tmproComponent = context.TMProComponent; var textInfo = tmproComponent.textInfo; var end = start + length; var cachedMeshInfo = context.CachedMeshInfo; Matrix4x4 matrix = Matrix4x4.identity; Vector2 middle = Vector2.zero; Color32 col = Color.white; int wordIndex = -1; int lineIndex = -1; for (int i = start; i < end; i++) { //required as TMPro is putting non visible invalid elements in the charinfo array assuming I will follow this rule // if we don't character 0 ends up getting an effect applied to it even though it shouldn't if (!textInfo.characterInfo[i].isVisible) { continue; } // Get the index of the material used by the current character. int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; // Get the index of the first vertex used by this text element. int vertexIndex = textInfo.characterInfo[i].vertexIndex; // Get the cached vertices of the mesh used by this text element (character or sprite). Vector3[] sourceVertices = cachedMeshInfo[materialIndex].vertices; Color32[] vertexColors = cachedMeshInfo[materialIndex].colors32; if (i == start && mode == TMPLinkAnimatorMode.PerSection) { matrix = transformFunc(start); middle = CalcMidFromChars(context, start, end); col = colorFunc(start, vertexColors[vertexIndex]); } // Determine the center point of each character at the baseline. //Vector2 charMidBasline = new Vector2((sourceVertices[vertexIndex + 0].x + sourceVertices[vertexIndex + 2].x) / 2, charInfo.baseLine); // Determine the center point of each character. if (mode == TMPLinkAnimatorMode.PerCharacter) { middle = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2; matrix = transformFunc(i); col = colorFunc(i, vertexColors[vertexIndex]); } else if (mode == TMPLinkAnimatorMode.PerWord) { var newWordIndex = CalcWordFromChar(i, textInfo.wordInfo); if (newWordIndex != -1 && wordIndex != newWordIndex) { wordIndex = newWordIndex; middle = CalcMidFromChars(context, Mathf.Max(start, textInfo.wordInfo[wordIndex].firstCharacterIndex), Mathf.Min(end, textInfo.wordInfo[wordIndex].lastCharacterIndex)); matrix = transformFunc(i); col = colorFunc(i, vertexColors[vertexIndex]); } } else if (mode == TMPLinkAnimatorMode.PerLine) { var newLineIndex = textInfo.characterInfo[i].lineNumber; if (newLineIndex != -1 && lineIndex != newLineIndex) { lineIndex = newLineIndex; middle = CalcMidFromChars(context, Mathf.Max(start, textInfo.lineInfo[lineIndex].firstCharacterIndex), Mathf.Min(end, textInfo.lineInfo[lineIndex].lastCharacterIndex)); matrix = transformFunc(i); col = colorFunc(i, vertexColors[vertexIndex]); } } // Need to translate all 4 vertices of each quad to aligned with middle of character / baseline. // This is needed so the matrix TRS is applied at the origin for each character. Vector3 offset = middle; Vector3[] destinationVertices = textInfo.meshInfo[materialIndex].vertices; Color32[] destinationVertColors = textInfo.meshInfo[materialIndex].colors32; destinationVertices[vertexIndex + 0] = sourceVertices[vertexIndex + 0] - offset; destinationVertices[vertexIndex + 1] = sourceVertices[vertexIndex + 1] - offset; destinationVertices[vertexIndex + 2] = sourceVertices[vertexIndex + 2] - offset; destinationVertices[vertexIndex + 3] = sourceVertices[vertexIndex + 3] - offset; destinationVertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 0]); destinationVertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 1]); destinationVertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 2]); destinationVertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(destinationVertices[vertexIndex + 3]); destinationVertices[vertexIndex + 0] += offset; destinationVertices[vertexIndex + 1] += offset; destinationVertices[vertexIndex + 2] += offset; destinationVertices[vertexIndex + 3] += offset; destinationVertColors[vertexIndex + 0] = col; destinationVertColors[vertexIndex + 1] = col; destinationVertColors[vertexIndex + 2] = col; destinationVertColors[vertexIndex + 3] = col; } }