UnityGame/Library/PackageCache/com.unity.ugui/Runtime/TMP/TMP_SpriteAnimator.cs

158 lines
6.0 KiB
C#
Raw Normal View History

2024-10-27 10:53:47 +03:00
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;
}
}
}
}