123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587 |
- using UnityEngine;
- using UnityEngine.TextCore;
- using System.Collections.Generic;
- using System.Linq;
- namespace TMPro
- {
- [ExcludeFromPresetAttribute]
- public class TMP_SpriteAsset : TMP_Asset
- {
- internal Dictionary<int, int> m_NameLookup;
- internal Dictionary<uint, int> m_GlyphIndexLookup;
- /// <summary>
- /// The version of the sprite asset class.
- /// Version 1.1.0 updates the asset data structure to be compatible with new font asset structure.
- /// </summary>
- public string version
- {
- get { return m_Version; }
- internal set { m_Version = value; }
- }
- [SerializeField]
- private string m_Version;
- /// <summary>
- /// Information about the sprite asset's face.
- /// </summary>
- public FaceInfo faceInfo
- {
- get { return m_FaceInfo; }
- internal set { m_FaceInfo = value; }
- }
- [SerializeField]
- internal FaceInfo m_FaceInfo;
- // The texture which contains the sprites.
- public Texture spriteSheet;
- /// <summary>
- ///
- /// </summary>
- public List<TMP_SpriteCharacter> spriteCharacterTable
- {
- get
- {
- if (m_GlyphIndexLookup == null)
- UpdateLookupTables();
- return m_SpriteCharacterTable;
- }
- internal set { m_SpriteCharacterTable = value; }
- }
- [SerializeField]
- private List<TMP_SpriteCharacter> m_SpriteCharacterTable = new List<TMP_SpriteCharacter>();
- /// <summary>
- /// Dictionary used to lookup sprite characters by their unicode value.
- /// </summary>
- public Dictionary<uint, TMP_SpriteCharacter> spriteCharacterLookupTable
- {
- get
- {
- if (m_SpriteCharacterLookup == null)
- UpdateLookupTables();
- return m_SpriteCharacterLookup;
- }
- internal set { m_SpriteCharacterLookup = value; }
- }
- internal Dictionary<uint, TMP_SpriteCharacter> m_SpriteCharacterLookup;
- public List<TMP_SpriteGlyph> spriteGlyphTable
- {
- get { return m_SpriteGlyphTable; }
- internal set { m_SpriteGlyphTable = value; }
- }
- [SerializeField]
- private List<TMP_SpriteGlyph> m_SpriteGlyphTable = new List<TMP_SpriteGlyph>();
- internal Dictionary<uint, TMP_SpriteGlyph> m_SpriteGlyphLookup;
- // List which contains the SpriteInfo for the sprites contained in the sprite sheet.
- public List<TMP_Sprite> spriteInfoList;
- /// <summary>
- /// List which contains the Fallback font assets for this font.
- /// </summary>
- [SerializeField]
- public List<TMP_SpriteAsset> fallbackSpriteAssets;
- internal bool m_IsSpriteAssetLookupTablesDirty = false;
- void Awake()
- {
- // Check version number of sprite asset to see if it needs to be upgraded.
- if (this.material != null && string.IsNullOrEmpty(m_Version))
- UpgradeSpriteAsset();
- }
- /// <summary>
- /// Create a material for the sprite asset.
- /// </summary>
- /// <returns></returns>
- Material GetDefaultSpriteMaterial()
- {
- //isEditingAsset = true;
- ShaderUtilities.GetShaderPropertyIDs();
- // Add a new material
- Shader shader = Shader.Find("TextMeshPro/Sprite");
- Material tempMaterial = new Material(shader);
- tempMaterial.SetTexture(ShaderUtilities.ID_MainTex, spriteSheet);
- tempMaterial.hideFlags = HideFlags.HideInHierarchy;
- #if UNITY_EDITOR
- UnityEditor.AssetDatabase.AddObjectToAsset(tempMaterial, this);
- UnityEditor.AssetDatabase.ImportAsset(UnityEditor.AssetDatabase.GetAssetPath(this));
- #endif
- //isEditingAsset = false;
- return tempMaterial;
- }
- /// <summary>
- /// Function to update the sprite name and unicode lookup tables.
- /// This function should be called when a sprite's name or unicode value changes or when a new sprite is added.
- /// </summary>
- public void UpdateLookupTables()
- {
- //Debug.Log("Updating [" + this.name + "] Lookup tables.");
- // Check version number of sprite asset to see if it needs to be upgraded.
- if (this.material != null && string.IsNullOrEmpty(m_Version))
- UpgradeSpriteAsset();
- // Initialize / Clear glyph index lookup dictionary.
- if (m_GlyphIndexLookup == null)
- m_GlyphIndexLookup = new Dictionary<uint, int>();
- else
- m_GlyphIndexLookup.Clear();
- //
- if (m_SpriteGlyphLookup == null)
- m_SpriteGlyphLookup = new Dictionary<uint, TMP_SpriteGlyph>();
- else
- m_SpriteGlyphLookup.Clear();
- // Initialize SpriteGlyphLookup
- for (int i = 0; i < m_SpriteGlyphTable.Count; i++)
- {
- TMP_SpriteGlyph spriteGlyph = m_SpriteGlyphTable[i];
- uint glyphIndex = spriteGlyph.index;
- if (m_GlyphIndexLookup.ContainsKey(glyphIndex) == false)
- m_GlyphIndexLookup.Add(glyphIndex, i);
- if (m_SpriteGlyphLookup.ContainsKey(glyphIndex) == false)
- m_SpriteGlyphLookup.Add(glyphIndex, spriteGlyph);
- }
- // Initialize name lookup
- if (m_NameLookup == null)
- m_NameLookup = new Dictionary<int, int>();
- else
- m_NameLookup.Clear();
- // Initialize character lookup
- if (m_SpriteCharacterLookup == null)
- m_SpriteCharacterLookup = new Dictionary<uint, TMP_SpriteCharacter>();
- else
- m_SpriteCharacterLookup.Clear();
- // Populate Sprite Character lookup tables
- for (int i = 0; i < m_SpriteCharacterTable.Count; i++)
- {
- TMP_SpriteCharacter spriteCharacter = m_SpriteCharacterTable[i];
- // Make sure sprite character is valid
- if (spriteCharacter == null)
- continue;
- uint glyphIndex = spriteCharacter.glyphIndex;
- // Lookup the glyph for this character
- if (m_SpriteGlyphLookup.ContainsKey(glyphIndex) == false)
- continue;
- // Assign glyph and text asset to this character
- spriteCharacter.glyph = m_SpriteGlyphLookup[glyphIndex];
- spriteCharacter.textAsset = this;
- int nameHashCode = m_SpriteCharacterTable[i].hashCode;
- if (m_NameLookup.ContainsKey(nameHashCode) == false)
- m_NameLookup.Add(nameHashCode, i);
- uint unicode = m_SpriteCharacterTable[i].unicode;
- if (unicode != 0xFFFE && m_SpriteCharacterLookup.ContainsKey(unicode) == false)
- m_SpriteCharacterLookup.Add(unicode, spriteCharacter);
- }
- m_IsSpriteAssetLookupTablesDirty = false;
- }
- /// <summary>
- /// Function which returns the sprite index using the hashcode of the name
- /// </summary>
- /// <param name="hashCode"></param>
- /// <returns></returns>
- public int GetSpriteIndexFromHashcode(int hashCode)
- {
- if (m_NameLookup == null)
- UpdateLookupTables();
- int index;
- if (m_NameLookup.TryGetValue(hashCode, out index))
- return index;
- return -1;
- }
- /// <summary>
- /// Returns the index of the sprite for the given unicode value.
- /// </summary>
- /// <param name="unicode"></param>
- /// <returns></returns>
- public int GetSpriteIndexFromUnicode (uint unicode)
- {
- if (m_SpriteCharacterLookup == null)
- UpdateLookupTables();
- TMP_SpriteCharacter spriteCharacter;
- if (m_SpriteCharacterLookup.TryGetValue(unicode, out spriteCharacter))
- return (int)spriteCharacter.glyphIndex;
- return -1;
- }
- /// <summary>
- /// Returns the index of the sprite for the given name.
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public int GetSpriteIndexFromName (string name)
- {
- if (m_NameLookup == null)
- UpdateLookupTables();
- int hashCode = TMP_TextUtilities.GetSimpleHashCode(name);
- return GetSpriteIndexFromHashcode(hashCode);
- }
- /// <summary>
- /// Used to keep track of which Sprite Assets have been searched.
- /// </summary>
- private static HashSet<int> k_searchedSpriteAssets;
- /// <summary>
- /// Search through the given sprite asset and its fallbacks for the specified sprite matching the given unicode character.
- /// </summary>
- /// <param name="spriteAsset">The font asset to search for the given character.</param>
- /// <param name="unicode">The character to find.</param>
- /// <param name="glyph">out parameter containing the glyph for the specified character (if found).</param>
- /// <returns></returns>
- public static TMP_SpriteAsset SearchForSpriteByUnicode(TMP_SpriteAsset spriteAsset, uint unicode, bool includeFallbacks, out int spriteIndex)
- {
- // Check to make sure sprite asset is not null
- if (spriteAsset == null) { spriteIndex = -1; return null; }
- // Get sprite index for the given unicode
- spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(unicode);
- if (spriteIndex != -1)
- return spriteAsset;
- // Initialize list to track instance of Sprite Assets that have already been searched.
- if (k_searchedSpriteAssets == null)
- k_searchedSpriteAssets = new HashSet<int>();
- else
- k_searchedSpriteAssets.Clear();
- // Get instance ID of sprite asset and add to list.
- int id = spriteAsset.GetInstanceID();
- k_searchedSpriteAssets.Add(id);
- // Search potential fallback sprite assets if includeFallbacks is true.
- if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
- return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, true, out spriteIndex);
- // Search default sprite asset potentially assigned in the TMP Settings.
- if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null)
- return SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, unicode, true, out spriteIndex);
- spriteIndex = -1;
- return null;
- }
- /// <summary>
- /// Search through the given list of sprite assets and fallbacks for a sprite whose unicode value matches the target unicode.
- /// </summary>
- /// <param name="spriteAssets"></param>
- /// <param name="unicode"></param>
- /// <param name="includeFallbacks"></param>
- /// <param name="spriteIndex"></param>
- /// <returns></returns>
- private static TMP_SpriteAsset SearchForSpriteByUnicodeInternal(List<TMP_SpriteAsset> spriteAssets, uint unicode, bool includeFallbacks, out int spriteIndex)
- {
- for (int i = 0; i < spriteAssets.Count; i++)
- {
- TMP_SpriteAsset temp = spriteAssets[i];
- if (temp == null) continue;
- int id = temp.GetInstanceID();
- // Skip sprite asset if it has already been searched.
- if (k_searchedSpriteAssets.Add(id) == false)
- continue;
- temp = SearchForSpriteByUnicodeInternal(temp, unicode, includeFallbacks, out spriteIndex);
- if (temp != null)
- return temp;
- }
- spriteIndex = -1;
- return null;
- }
- /// <summary>
- /// Search the given sprite asset and fallbacks for a sprite whose unicode value matches the target unicode.
- /// </summary>
- /// <param name="spriteAsset"></param>
- /// <param name="unicode"></param>
- /// <param name="includeFallbacks"></param>
- /// <param name="spriteIndex"></param>
- /// <returns></returns>
- private static TMP_SpriteAsset SearchForSpriteByUnicodeInternal(TMP_SpriteAsset spriteAsset, uint unicode, bool includeFallbacks, out int spriteIndex)
- {
- // Get sprite index for the given unicode
- spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(unicode);
- if (spriteIndex != -1)
- return spriteAsset;
- if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
- return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, true, out spriteIndex);
- spriteIndex = -1;
- return null;
- }
- /// <summary>
- /// Search the given sprite asset and fallbacks for a sprite whose hash code value of its name matches the target hash code.
- /// </summary>
- /// <param name="spriteAsset">The Sprite Asset to search for the given sprite whose name matches the hashcode value</param>
- /// <param name="hashCode">The hash code value matching the name of the sprite</param>
- /// <param name="includeFallbacks">Include fallback sprite assets in the search</param>
- /// <param name="spriteIndex">The index of the sprite matching the provided hash code</param>
- /// <returns>The Sprite Asset that contains the sprite</returns>
- public static TMP_SpriteAsset SearchForSpriteByHashCode(TMP_SpriteAsset spriteAsset, int hashCode, bool includeFallbacks, out int spriteIndex)
- {
- // Make sure sprite asset is not null
- if (spriteAsset == null) { spriteIndex = -1; return null; }
- spriteIndex = spriteAsset.GetSpriteIndexFromHashcode(hashCode);
- if (spriteIndex != -1)
- return spriteAsset;
- // Initialize or clear list to Sprite Assets that have already been searched.
- if (k_searchedSpriteAssets == null)
- k_searchedSpriteAssets = new HashSet<int>();
- else
- k_searchedSpriteAssets.Clear();
- int id = spriteAsset.instanceID;
- // Add to list of font assets already searched.
- k_searchedSpriteAssets.Add(id);
- TMP_SpriteAsset tempSpriteAsset;
- // Search potential fallbacks assigned to local sprite asset.
- if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
- {
- tempSpriteAsset = SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, true, out spriteIndex);
- if (spriteIndex != -1)
- return tempSpriteAsset;
- }
- // Search default sprite asset potentially assigned in the TMP Settings.
- if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null)
- {
- tempSpriteAsset = SearchForSpriteByHashCodeInternal(TMP_Settings.defaultSpriteAsset, hashCode, true, out spriteIndex);
- if (spriteIndex != -1)
- return tempSpriteAsset;
- }
- // Clear search list since we are now looking for the missing sprite character.
- k_searchedSpriteAssets.Clear();
- uint missingSpriteCharacterUnicode = TMP_Settings.missingCharacterSpriteUnicode;
- // Get sprite index for the given unicode
- spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(missingSpriteCharacterUnicode);
- if (spriteIndex != -1)
- return spriteAsset;
- // Add current sprite asset to list of assets already searched.
- k_searchedSpriteAssets.Add(id);
- // Search for the missing sprite character in the local sprite asset and potential fallbacks.
- if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
- {
- tempSpriteAsset = SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, missingSpriteCharacterUnicode, true, out spriteIndex);
- if (spriteIndex != -1)
- return tempSpriteAsset;
- }
- // Search for the missing sprite character in the default sprite asset and potential fallbacks.
- if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null)
- {
- tempSpriteAsset = SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, missingSpriteCharacterUnicode, true, out spriteIndex);
- if (spriteIndex != -1)
- return tempSpriteAsset;
- }
- spriteIndex = -1;
- return null;
- }
- /// <summary>
- /// Search through the given list of sprite assets and fallbacks for a sprite whose hash code value of its name matches the target hash code.
- /// </summary>
- /// <param name="spriteAssets"></param>
- /// <param name="hashCode"></param>
- /// <param name="searchFallbacks"></param>
- /// <param name="spriteIndex"></param>
- /// <returns></returns>
- private static TMP_SpriteAsset SearchForSpriteByHashCodeInternal(List<TMP_SpriteAsset> spriteAssets, int hashCode, bool searchFallbacks, out int spriteIndex)
- {
- // Search through the list of sprite assets
- for (int i = 0; i < spriteAssets.Count; i++)
- {
- TMP_SpriteAsset temp = spriteAssets[i];
- if (temp == null) continue;
- int id = temp.instanceID;
- // Skip sprite asset if it has already been searched.
- if (k_searchedSpriteAssets.Add(id) == false)
- continue;
- temp = SearchForSpriteByHashCodeInternal(temp, hashCode, searchFallbacks, out spriteIndex);
- if (temp != null)
- return temp;
- }
- spriteIndex = -1;
- return null;
- }
- /// <summary>
- /// Search through the given sprite asset and fallbacks for a sprite whose hash code value of its name matches the target hash code.
- /// </summary>
- /// <param name="spriteAsset"></param>
- /// <param name="hashCode"></param>
- /// <param name="searchFallbacks"></param>
- /// <param name="spriteIndex"></param>
- /// <returns></returns>
- private static TMP_SpriteAsset SearchForSpriteByHashCodeInternal(TMP_SpriteAsset spriteAsset, int hashCode, bool searchFallbacks, out int spriteIndex)
- {
- // Get the sprite for the given hash code.
- spriteIndex = spriteAsset.GetSpriteIndexFromHashcode(hashCode);
- if (spriteIndex != -1)
- return spriteAsset;
- if (searchFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
- return SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, true, out spriteIndex);
- spriteIndex = -1;
- return null;
- }
- /// <summary>
- /// Sort the sprite glyph table by glyph index.
- /// </summary>
- public void SortGlyphTable()
- {
- if (m_SpriteGlyphTable == null || m_SpriteGlyphTable.Count == 0) return;
- m_SpriteGlyphTable = m_SpriteGlyphTable.OrderBy(item => item.index).ToList();
- }
- /// <summary>
- /// Sort the sprite character table by Unicode values.
- /// </summary>
- internal void SortCharacterTable()
- {
- if (m_SpriteCharacterTable != null && m_SpriteCharacterTable.Count > 0)
- m_SpriteCharacterTable = m_SpriteCharacterTable.OrderBy(c => c.unicode).ToList();
- }
- /// <summary>
- /// Sort both sprite glyph and character tables.
- /// </summary>
- internal void SortGlyphAndCharacterTables()
- {
- SortGlyphTable();
- SortCharacterTable();
- }
- /// <summary>
- /// Internal method used to upgrade sprite asset.
- /// </summary>
- private void UpgradeSpriteAsset()
- {
- m_Version = "1.1.0";
- Debug.Log("Upgrading sprite asset [" + this.name + "] to version " + m_Version + ".", this);
- // Convert legacy glyph and character tables to new format
- m_SpriteCharacterTable.Clear();
- m_SpriteGlyphTable.Clear();
- for (int i = 0; i < spriteInfoList.Count; i++)
- {
- TMP_Sprite oldSprite = spriteInfoList[i];
- TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph();
- spriteGlyph.index = (uint)i;
- spriteGlyph.sprite = oldSprite.sprite;
- spriteGlyph.metrics = new GlyphMetrics(oldSprite.width, oldSprite.height, oldSprite.xOffset, oldSprite.yOffset, oldSprite.xAdvance);
- spriteGlyph.glyphRect = new GlyphRect((int)oldSprite.x, (int)oldSprite.y, (int)oldSprite.width, (int)oldSprite.height);
- spriteGlyph.scale = 1.0f;
- spriteGlyph.atlasIndex = 0;
- m_SpriteGlyphTable.Add(spriteGlyph);
- TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter();
- spriteCharacter.glyph = spriteGlyph;
- spriteCharacter.unicode = oldSprite.unicode == 0x0 ? 0xFFFE : (uint)oldSprite.unicode;
- spriteCharacter.name = oldSprite.name;
- spriteCharacter.scale = oldSprite.scale;
- m_SpriteCharacterTable.Add(spriteCharacter);
- }
- // Clear legacy glyph info list.
- //spriteInfoList.Clear();
- UpdateLookupTables();
- #if UNITY_EDITOR
- UnityEditor.EditorUtility.SetDirty(this);
- UnityEditor.AssetDatabase.SaveAssets();
- #endif
- }
- }
- }
|