158 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			158 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using UnityEngine; | |||
|  | using UnityEngine.TextCore; | |||
|  | using System.Collections; | |||
|  | using System.Collections.Generic; | |||
|  | 
 | |||
|  | namespace TMPro | |||
|  | { | |||
|  |     [DisallowMultipleComponent] | |||
|  |     public class TMP_SpriteAnimator : MonoBehaviour | |||
|  |     { | |||
|  |         private Dictionary<int, bool> m_animations = new Dictionary<int, bool>(16); | |||
|  |         //private bool isPlaying = false; | |||
|  | 
 | |||
|  |         private TMP_Text m_TextComponent; | |||
|  | 
 | |||
|  | 
 | |||
|  |         void Awake() | |||
|  |         { | |||
|  |             m_TextComponent = GetComponent<TMP_Text>(); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         void OnEnable() | |||
|  |         { | |||
|  |             //m_playAnimations = true; | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         void OnDisable() | |||
|  |         { | |||
|  |             //m_playAnimations = false; | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         public void StopAllAnimations() | |||
|  |         { | |||
|  |             StopAllCoroutines(); | |||
|  |             m_animations.Clear(); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         public void DoSpriteAnimation(int currentCharacter, TMP_SpriteAsset spriteAsset, int start, int end, int framerate) | |||
|  |         { | |||
|  |             bool isPlaying; | |||
|  | 
 | |||
|  |             // Need to add tracking of coroutines that have been lunched for this text object. | |||
|  |             if (!m_animations.TryGetValue(currentCharacter, out isPlaying)) | |||
|  |             { | |||
|  |                 StartCoroutine(DoSpriteAnimationInternal(currentCharacter, spriteAsset, start, end, framerate)); | |||
|  |                 m_animations.Add(currentCharacter, true); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         IEnumerator DoSpriteAnimationInternal(int currentCharacter, TMP_SpriteAsset spriteAsset, int start, int end, int framerate) | |||
|  |         { | |||
|  |             if (m_TextComponent == null) yield break; | |||
|  | 
 | |||
|  |             // We yield otherwise this gets called before the sprite has rendered. | |||
|  |             yield return null; | |||
|  | 
 | |||
|  |             int currentFrame = start; | |||
|  | 
 | |||
|  |             // Make sure end frame does not exceed the number of sprites in the sprite asset. | |||
|  |             if (end > spriteAsset.spriteCharacterTable.Count) | |||
|  |                 end = spriteAsset.spriteCharacterTable.Count - 1; | |||
|  | 
 | |||
|  |             // Get a reference to the current character's info | |||
|  |             TMP_CharacterInfo charInfo = m_TextComponent.textInfo.characterInfo[currentCharacter]; | |||
|  | 
 | |||
|  |             int materialIndex = charInfo.materialReferenceIndex; | |||
|  |             int vertexIndex = charInfo.vertexIndex; | |||
|  | 
 | |||
|  |             TMP_MeshInfo meshInfo = m_TextComponent.textInfo.meshInfo[materialIndex]; | |||
|  | 
 | |||
|  |             float baseSpriteScale = spriteAsset.spriteCharacterTable[start].scale * spriteAsset.spriteCharacterTable[start].glyph.scale; | |||
|  | 
 | |||
|  |             float elapsedTime = 0; | |||
|  |             float targetTime = 1f / Mathf.Abs(framerate); | |||
|  | 
 | |||
|  |             while (true) | |||
|  |             { | |||
|  |                 if (elapsedTime > targetTime) | |||
|  |                 { | |||
|  |                     elapsedTime = 0; | |||
|  | 
 | |||
|  |                     // Return if sprite was truncated or replaced by the Ellipsis character. | |||
|  |                     uint character = m_TextComponent.textInfo.characterInfo[currentCharacter].character; | |||
|  |                     if (character == 0x03 || character == 0x2026) | |||
|  |                     { | |||
|  |                         m_animations.Remove(currentCharacter); | |||
|  |                         yield break; | |||
|  |                     } | |||
|  | 
 | |||
|  |                     // Get a reference to the current sprite | |||
|  |                     TMP_SpriteCharacter spriteCharacter = spriteAsset.spriteCharacterTable[currentFrame]; | |||
|  | 
 | |||
|  |                     // Update the vertices for the new sprite | |||
|  |                     Vector3[] vertices = meshInfo.vertices; | |||
|  | 
 | |||
|  |                     Vector2 origin = new Vector2(charInfo.origin, charInfo.baseLine); | |||
|  | 
 | |||
|  |                     float spriteScale = charInfo.scale / baseSpriteScale * spriteCharacter.scale * spriteCharacter.glyph.scale; | |||
|  | 
 | |||
|  |                     Vector3 bl = new Vector3(origin.x + spriteCharacter.glyph.metrics.horizontalBearingX * spriteScale, origin.y + (spriteCharacter.glyph.metrics.horizontalBearingY - spriteCharacter.glyph.metrics.height) * spriteScale); | |||
|  |                     Vector3 tl = new Vector3(bl.x, origin.y + spriteCharacter.glyph.metrics.horizontalBearingY * spriteScale); | |||
|  |                     Vector3 tr = new Vector3(origin.x + (spriteCharacter.glyph.metrics.horizontalBearingX + spriteCharacter.glyph.metrics.width) * spriteScale, tl.y); | |||
|  |                     Vector3 br = new Vector3(tr.x, bl.y); | |||
|  | 
 | |||
|  |                     vertices[vertexIndex + 0] = bl; | |||
|  |                     vertices[vertexIndex + 1] = tl; | |||
|  |                     vertices[vertexIndex + 2] = tr; | |||
|  |                     vertices[vertexIndex + 3] = br; | |||
|  | 
 | |||
|  |                     // Update the UV to point to the new sprite | |||
|  |                     Vector4[] uvs0 = meshInfo.uvs0; | |||
|  | 
 | |||
|  |                     Vector2 uv0 = new Vector2((float)spriteCharacter.glyph.glyphRect.x / spriteAsset.spriteSheet.width, (float)spriteCharacter.glyph.glyphRect.y / spriteAsset.spriteSheet.height); | |||
|  |                     Vector2 uv1 = new Vector2(uv0.x, (float)(spriteCharacter.glyph.glyphRect.y + spriteCharacter.glyph.glyphRect.height) / spriteAsset.spriteSheet.height); | |||
|  |                     Vector2 uv2 = new Vector2((float)(spriteCharacter.glyph.glyphRect.x + spriteCharacter.glyph.glyphRect.width) / spriteAsset.spriteSheet.width, uv1.y); | |||
|  |                     Vector2 uv3 = new Vector2(uv2.x, uv0.y); | |||
|  | 
 | |||
|  |                     uvs0[vertexIndex + 0] = uv0; | |||
|  |                     uvs0[vertexIndex + 1] = uv1; | |||
|  |                     uvs0[vertexIndex + 2] = uv2; | |||
|  |                     uvs0[vertexIndex + 3] = uv3; | |||
|  | 
 | |||
|  |                     // Update the modified vertex attributes | |||
|  |                     meshInfo.mesh.vertices = vertices; | |||
|  |                     meshInfo.mesh.SetUVs(0, uvs0); | |||
|  |                     m_TextComponent.UpdateGeometry(meshInfo.mesh, materialIndex); | |||
|  | 
 | |||
|  | 
 | |||
|  |                     if (framerate > 0) | |||
|  |                     { | |||
|  |                         if (currentFrame < end) | |||
|  |                             currentFrame += 1; | |||
|  |                         else | |||
|  |                             currentFrame = start; | |||
|  |                     } | |||
|  |                     else | |||
|  |                     { | |||
|  |                         if (currentFrame > start) | |||
|  |                             currentFrame -= 1; | |||
|  |                         else | |||
|  |                             currentFrame = end; | |||
|  |                     } | |||
|  |                 } | |||
|  | 
 | |||
|  |                 elapsedTime += Time.deltaTime; | |||
|  | 
 | |||
|  |                 yield return null; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |     } | |||
|  | } |