You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
14 KiB

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. namespace TMPro
  4. {
  5. public class TMP_SpriteAsset : TMP_Asset
  6. {
  7. internal Dictionary<int, int> m_UnicodeLookup;
  8. internal Dictionary<int, int> m_NameLookup;
  9. /// <summary>
  10. /// Static reference to the default font asset included with TextMesh Pro.
  11. /// </summary>
  12. public static TMP_SpriteAsset defaultSpriteAsset
  13. {
  14. get
  15. {
  16. if (m_defaultSpriteAsset == null)
  17. {
  18. m_defaultSpriteAsset = Resources.Load<TMP_SpriteAsset>("Sprite Assets/Default Sprite Asset");
  19. }
  20. return m_defaultSpriteAsset;
  21. }
  22. }
  23. public static TMP_SpriteAsset m_defaultSpriteAsset;
  24. // The texture which contains the sprites.
  25. public Texture spriteSheet;
  26. // List which contains the SpriteInfo for the sprites contained in the sprite sheet.
  27. public List<TMP_Sprite> spriteInfoList;
  28. /// <summary>
  29. /// Dictionary used to lookup the index of a given sprite based on a Unicode value.
  30. /// </summary>
  31. //private Dictionary<int, int> m_SpriteUnicodeLookup;
  32. /// <summary>
  33. /// List which contains the Fallback font assets for this font.
  34. /// </summary>
  35. [SerializeField]
  36. public List<TMP_SpriteAsset> fallbackSpriteAssets;
  37. //private bool isEditingAsset;
  38. void OnEnable()
  39. {
  40. // Make sure we have a valid material.
  41. //if (this.material == null && !isEditingAsset)
  42. // this.material = GetDefaultSpriteMaterial();
  43. }
  44. #if UNITY_EDITOR
  45. /// <summary>
  46. ///
  47. /// </summary>
  48. void OnValidate()
  49. {
  50. UpdateLookupTables();
  51. TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, this);
  52. }
  53. #endif
  54. /// <summary>
  55. /// Create a material for the sprite asset.
  56. /// </summary>
  57. /// <returns></returns>
  58. Material GetDefaultSpriteMaterial()
  59. {
  60. //isEditingAsset = true;
  61. ShaderUtilities.GetShaderPropertyIDs();
  62. // Add a new material
  63. Shader shader = Shader.Find("TextMeshPro/Sprite");
  64. Material tempMaterial = new Material(shader);
  65. tempMaterial.SetTexture(ShaderUtilities.ID_MainTex, spriteSheet);
  66. tempMaterial.hideFlags = HideFlags.HideInHierarchy;
  67. #if UNITY_EDITOR
  68. UnityEditor.AssetDatabase.AddObjectToAsset(tempMaterial, this);
  69. UnityEditor.AssetDatabase.ImportAsset(UnityEditor.AssetDatabase.GetAssetPath(this));
  70. #endif
  71. //isEditingAsset = false;
  72. return tempMaterial;
  73. }
  74. /// <summary>
  75. /// Function to update the sprite name and unicode lookup tables.
  76. /// This function should be called when a sprite's name or unicode value changes or when a new sprite is added.
  77. /// </summary>
  78. public void UpdateLookupTables()
  79. {
  80. if (m_NameLookup == null) m_NameLookup = new Dictionary<int, int>();
  81. m_NameLookup.Clear();
  82. if (m_UnicodeLookup == null) m_UnicodeLookup = new Dictionary<int, int>();
  83. m_UnicodeLookup.Clear();
  84. for (int i = 0; i < spriteInfoList.Count; i++)
  85. {
  86. int nameHashCode = spriteInfoList[i].hashCode;
  87. if (m_NameLookup.ContainsKey(nameHashCode) == false)
  88. m_NameLookup.Add(nameHashCode, i);
  89. int unicode = spriteInfoList[i].unicode;
  90. if (m_UnicodeLookup.ContainsKey(unicode) == false)
  91. m_UnicodeLookup.Add(unicode, i);
  92. }
  93. }
  94. /// <summary>
  95. /// Function which returns the sprite index using the hashcode of the name
  96. /// </summary>
  97. /// <param name="hashCode"></param>
  98. /// <returns></returns>
  99. public int GetSpriteIndexFromHashcode(int hashCode)
  100. {
  101. if (m_NameLookup == null)
  102. UpdateLookupTables();
  103. int index = 0;
  104. if (m_NameLookup.TryGetValue(hashCode, out index))
  105. return index;
  106. return -1;
  107. }
  108. /// <summary>
  109. /// Returns the index of the sprite for the given unicode value.
  110. /// </summary>
  111. /// <param name="unicode"></param>
  112. /// <returns></returns>
  113. public int GetSpriteIndexFromUnicode (int unicode)
  114. {
  115. if (m_UnicodeLookup == null)
  116. UpdateLookupTables();
  117. int index = 0;
  118. if (m_UnicodeLookup.TryGetValue(unicode, out index))
  119. return index;
  120. return -1;
  121. }
  122. /// <summary>
  123. /// Returns the index of the sprite for the given name.
  124. /// </summary>
  125. /// <param name="name"></param>
  126. /// <returns></returns>
  127. public int GetSpriteIndexFromName (string name)
  128. {
  129. if (m_NameLookup == null)
  130. UpdateLookupTables();
  131. int hashCode = TMP_TextUtilities.GetSimpleHashCode(name);
  132. return GetSpriteIndexFromHashcode(hashCode);
  133. }
  134. /// <summary>
  135. /// Used to keep track of which Sprite Assets have been searched.
  136. /// </summary>
  137. private static List<int> k_searchedSpriteAssets;
  138. /// <summary>
  139. /// Search through the given sprite asset and its fallbacks for the specified sprite matching the given unicode character.
  140. /// </summary>
  141. /// <param name="spriteAsset">The font asset to search for the given character.</param>
  142. /// <param name="unicode">The character to find.</param>
  143. /// <param name="glyph">out parameter containing the glyph for the specified character (if found).</param>
  144. /// <returns></returns>
  145. public static TMP_SpriteAsset SearchForSpriteByUnicode(TMP_SpriteAsset spriteAsset, int unicode, bool includeFallbacks, out int spriteIndex)
  146. {
  147. // Check to make sure sprite asset is not null
  148. if (spriteAsset == null) { spriteIndex = -1; return null; }
  149. // Get sprite index for the given unicode
  150. spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(unicode);
  151. if (spriteIndex != -1)
  152. return spriteAsset;
  153. // Initialize list to track instance of Sprite Assets that have already been searched.
  154. if (k_searchedSpriteAssets == null)
  155. k_searchedSpriteAssets = new List<int>();
  156. k_searchedSpriteAssets.Clear();
  157. // Get instance ID of sprite asset and add to list.
  158. int id = spriteAsset.GetInstanceID();
  159. k_searchedSpriteAssets.Add(id);
  160. // Search potential fallback sprite assets if includeFallbacks is true.
  161. if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
  162. return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, includeFallbacks, out spriteIndex);
  163. // Search default sprite asset potentially assigned in the TMP Settings.
  164. if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null)
  165. return SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, unicode, includeFallbacks, out spriteIndex);
  166. spriteIndex = -1;
  167. return null;
  168. }
  169. /// <summary>
  170. /// Search through the given list of sprite assets and fallbacks for a sprite whose unicode value matches the target unicode.
  171. /// </summary>
  172. /// <param name="spriteAssets"></param>
  173. /// <param name="unicode"></param>
  174. /// <param name="includeFallbacks"></param>
  175. /// <param name="spriteIndex"></param>
  176. /// <returns></returns>
  177. private static TMP_SpriteAsset SearchForSpriteByUnicodeInternal(List<TMP_SpriteAsset> spriteAssets, int unicode, bool includeFallbacks, out int spriteIndex)
  178. {
  179. for (int i = 0; i < spriteAssets.Count; i++)
  180. {
  181. TMP_SpriteAsset temp = spriteAssets[i];
  182. if (temp == null) continue;
  183. int id = temp.GetInstanceID();
  184. // Skip over the fallback sprite asset if it has already been searched.
  185. if (k_searchedSpriteAssets.Contains(id)) continue;
  186. // Add to list of font assets already searched.
  187. k_searchedSpriteAssets.Add(id);
  188. temp = SearchForSpriteByUnicodeInternal(temp, unicode, includeFallbacks, out spriteIndex);
  189. if (temp != null)
  190. return temp;
  191. }
  192. spriteIndex = -1;
  193. return null;
  194. }
  195. /// <summary>
  196. /// Search the given sprite asset and fallbacks for a sprite whose unicode value matches the target unicode.
  197. /// </summary>
  198. /// <param name="spriteAsset"></param>
  199. /// <param name="unicode"></param>
  200. /// <param name="includeFallbacks"></param>
  201. /// <param name="spriteIndex"></param>
  202. /// <returns></returns>
  203. private static TMP_SpriteAsset SearchForSpriteByUnicodeInternal(TMP_SpriteAsset spriteAsset, int unicode, bool includeFallbacks, out int spriteIndex)
  204. {
  205. // Get sprite index for the given unicode
  206. spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(unicode);
  207. if (spriteIndex != -1)
  208. return spriteAsset;
  209. if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
  210. return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, includeFallbacks, out spriteIndex);
  211. spriteIndex = -1;
  212. return null;
  213. }
  214. /// <summary>
  215. /// Search the given sprite asset and fallbacks for a sprite whose hash code value of its name matches the target hash code.
  216. /// </summary>
  217. /// <param name="spriteAsset">The Sprite Asset to search for the given sprite whose name matches the hashcode value</param>
  218. /// <param name="hashCode">The hash code value matching the name of the sprite</param>
  219. /// <param name="includeFallbacks">Include fallback sprite assets in the search</param>
  220. /// <param name="spriteIndex">The index of the sprite matching the provided hash code</param>
  221. /// <returns>The Sprite Asset that contains the sprite</returns>
  222. public static TMP_SpriteAsset SearchForSpriteByHashCode(TMP_SpriteAsset spriteAsset, int hashCode, bool includeFallbacks, out int spriteIndex)
  223. {
  224. // Make sure sprite asset is not null
  225. if (spriteAsset == null) { spriteIndex = -1; return null; }
  226. spriteIndex = spriteAsset.GetSpriteIndexFromHashcode(hashCode);
  227. if (spriteIndex != -1)
  228. return spriteAsset;
  229. // Initialize list to track instance of Sprite Assets that have already been searched.
  230. if (k_searchedSpriteAssets == null)
  231. k_searchedSpriteAssets = new List<int>();
  232. k_searchedSpriteAssets.Clear();
  233. int id = spriteAsset.GetInstanceID();
  234. // Add to list of font assets already searched.
  235. k_searchedSpriteAssets.Add(id);
  236. if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
  237. return SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, includeFallbacks, out spriteIndex);
  238. // Search default sprite asset potentially assigned in the TMP Settings.
  239. if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null)
  240. return SearchForSpriteByHashCodeInternal(TMP_Settings.defaultSpriteAsset, hashCode, includeFallbacks, out spriteIndex);
  241. spriteIndex = -1;
  242. return null;
  243. }
  244. /// <summary>
  245. /// 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.
  246. /// </summary>
  247. /// <param name="spriteAssets"></param>
  248. /// <param name="hashCode"></param>
  249. /// <param name="searchFallbacks"></param>
  250. /// <param name="spriteIndex"></param>
  251. /// <returns></returns>
  252. private static TMP_SpriteAsset SearchForSpriteByHashCodeInternal(List<TMP_SpriteAsset> spriteAssets, int hashCode, bool searchFallbacks, out int spriteIndex)
  253. {
  254. // Search through the list of sprite assets
  255. for (int i = 0; i < spriteAssets.Count; i++)
  256. {
  257. TMP_SpriteAsset temp = spriteAssets[i];
  258. if (temp == null) continue;
  259. int id = temp.GetInstanceID();
  260. // Skip over the fallback sprite asset if it has already been searched.
  261. if (k_searchedSpriteAssets.Contains(id)) continue;
  262. // Add to list of font assets already searched.
  263. k_searchedSpriteAssets.Add(id);
  264. temp = SearchForSpriteByHashCodeInternal(temp, hashCode, searchFallbacks, out spriteIndex);
  265. if (temp != null)
  266. return temp;
  267. }
  268. spriteIndex = -1;
  269. return null;
  270. }
  271. /// <summary>
  272. /// Search through the given sprite asset and fallbacks for a sprite whose hash code value of its name matches the target hash code.
  273. /// </summary>
  274. /// <param name="spriteAsset"></param>
  275. /// <param name="hashCode"></param>
  276. /// <param name="searchFallbacks"></param>
  277. /// <param name="spriteIndex"></param>
  278. /// <returns></returns>
  279. private static TMP_SpriteAsset SearchForSpriteByHashCodeInternal(TMP_SpriteAsset spriteAsset, int hashCode, bool searchFallbacks, out int spriteIndex)
  280. {
  281. // Get the sprite for the given hash code.
  282. spriteIndex = spriteAsset.GetSpriteIndexFromHashcode(hashCode);
  283. if (spriteIndex != -1)
  284. return spriteAsset;
  285. if (searchFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0)
  286. return SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, searchFallbacks, out spriteIndex);
  287. spriteIndex = -1;
  288. return null;
  289. }
  290. }
  291. }