A game about forced loneliness, made by TACStudios
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 564 lines 22 kB view raw
1using UnityEngine; 2using UnityEngine.TextCore; 3using System.Collections.Generic; 4using System.Linq; 5using UnityEngine.Serialization; 6 7 8namespace TMPro 9{ 10 [HelpURL("https://docs.unity3d.com/Packages/com.unity.ugui@2.0/manual/TextMeshPro/Sprites.html")] 11 [ExcludeFromPresetAttribute] 12 public class TMP_SpriteAsset : TMP_Asset 13 { 14 internal Dictionary<int, int> m_NameLookup; 15 internal Dictionary<uint, int> m_GlyphIndexLookup; 16 17 // The texture which contains the sprites. 18 public Texture spriteSheet; 19 20 /// <summary> 21 /// 22 /// </summary> 23 public List<TMP_SpriteCharacter> spriteCharacterTable 24 { 25 get 26 { 27 if (m_GlyphIndexLookup == null) 28 UpdateLookupTables(); 29 30 return m_SpriteCharacterTable; 31 } 32 internal set { m_SpriteCharacterTable = value; } 33 } 34 [SerializeField] 35 private List<TMP_SpriteCharacter> m_SpriteCharacterTable = new List<TMP_SpriteCharacter>(); 36 37 38 /// <summary> 39 /// Dictionary used to lookup sprite characters by their unicode value. 40 /// </summary> 41 public Dictionary<uint, TMP_SpriteCharacter> spriteCharacterLookupTable 42 { 43 get 44 { 45 if (m_SpriteCharacterLookup == null) 46 UpdateLookupTables(); 47 48 return m_SpriteCharacterLookup; 49 } 50 internal set { m_SpriteCharacterLookup = value; } 51 } 52 internal Dictionary<uint, TMP_SpriteCharacter> m_SpriteCharacterLookup; 53 54 public List<TMP_SpriteGlyph> spriteGlyphTable 55 { 56 get { return m_GlyphTable; } 57 internal set { m_GlyphTable = value; } 58 } 59 [FormerlySerializedAs("m_SpriteGlyphTable")] 60 [SerializeField] 61 private List<TMP_SpriteGlyph> m_GlyphTable = new List<TMP_SpriteGlyph>(); 62 63 internal Dictionary<uint, TMP_SpriteGlyph> m_SpriteGlyphLookup; 64 65 // List which contains the SpriteInfo for the sprites contained in the sprite sheet. 66 public List<TMP_Sprite> spriteInfoList; 67 68 /// <summary> 69 /// List which contains the Fallback font assets for this font. 70 /// </summary> 71 [SerializeField] 72 public List<TMP_SpriteAsset> fallbackSpriteAssets; 73 74 internal bool m_IsSpriteAssetLookupTablesDirty = false; 75 76 77 void Awake() 78 { 79 // Check version number of sprite asset to see if it needs to be upgraded. 80 if (this.material != null && string.IsNullOrEmpty(m_Version)) 81 UpgradeSpriteAsset(); 82 } 83 84 85 /// <summary> 86 /// Create a material for the sprite asset. 87 /// </summary> 88 /// <returns></returns> 89 Material GetDefaultSpriteMaterial() 90 { 91 ShaderUtilities.GetShaderPropertyIDs(); 92 93 // Add a new material 94 Shader shader = Shader.Find("TextMeshPro/Sprite"); 95 Material tempMaterial = new Material(shader); 96 tempMaterial.SetTexture(ShaderUtilities.ID_MainTex, spriteSheet); 97 98 #if UNITY_EDITOR 99 UnityEditor.AssetDatabase.AddObjectToAsset(tempMaterial, this); 100 UnityEditor.AssetDatabase.ImportAsset(UnityEditor.AssetDatabase.GetAssetPath(this)); 101 #endif 102 103 return tempMaterial; 104 } 105 106 107 /// <summary> 108 /// Function to update the sprite name and unicode lookup tables. 109 /// This function should be called when a sprite's name or unicode value changes or when a new sprite is added. 110 /// </summary> 111 public void UpdateLookupTables() 112 { 113 //Debug.Log("Updating [" + this.name + "] Lookup tables."); 114 115 // Check version number of sprite asset to see if it needs to be upgraded. 116 if (this.material != null && string.IsNullOrEmpty(m_Version)) 117 UpgradeSpriteAsset(); 118 119 // Initialize / Clear glyph index lookup dictionary. 120 if (m_GlyphIndexLookup == null) 121 m_GlyphIndexLookup = new Dictionary<uint, int>(); 122 else 123 m_GlyphIndexLookup.Clear(); 124 125 // 126 if (m_SpriteGlyphLookup == null) 127 m_SpriteGlyphLookup = new Dictionary<uint, TMP_SpriteGlyph>(); 128 else 129 m_SpriteGlyphLookup.Clear(); 130 131 // Initialize SpriteGlyphLookup 132 for (int i = 0; i < m_GlyphTable.Count; i++) 133 { 134 TMP_SpriteGlyph spriteGlyph = m_GlyphTable[i]; 135 uint glyphIndex = spriteGlyph.index; 136 137 if (m_GlyphIndexLookup.ContainsKey(glyphIndex) == false) 138 m_GlyphIndexLookup.Add(glyphIndex, i); 139 140 if (m_SpriteGlyphLookup.ContainsKey(glyphIndex) == false) 141 m_SpriteGlyphLookup.Add(glyphIndex, spriteGlyph); 142 } 143 144 // Initialize name lookup 145 if (m_NameLookup == null) 146 m_NameLookup = new Dictionary<int, int>(); 147 else 148 m_NameLookup.Clear(); 149 150 151 // Initialize character lookup 152 if (m_SpriteCharacterLookup == null) 153 m_SpriteCharacterLookup = new Dictionary<uint, TMP_SpriteCharacter>(); 154 else 155 m_SpriteCharacterLookup.Clear(); 156 157 158 // Populate Sprite Character lookup tables 159 for (int i = 0; i < m_SpriteCharacterTable.Count; i++) 160 { 161 TMP_SpriteCharacter spriteCharacter = m_SpriteCharacterTable[i]; 162 163 // Make sure sprite character is valid 164 if (spriteCharacter == null) 165 continue; 166 167 uint glyphIndex = spriteCharacter.glyphIndex; 168 169 // Lookup the glyph for this character 170 if (m_SpriteGlyphLookup.ContainsKey(glyphIndex) == false) 171 continue; 172 173 // Assign glyph and text asset to this character 174 spriteCharacter.glyph = m_SpriteGlyphLookup[glyphIndex]; 175 spriteCharacter.textAsset = this; 176 177 int nameHashCode = TMP_TextUtilities.GetHashCode(m_SpriteCharacterTable[i].name); 178 179 if (m_NameLookup.ContainsKey(nameHashCode) == false) 180 m_NameLookup.Add(nameHashCode, i); 181 182 uint unicode = m_SpriteCharacterTable[i].unicode; 183 184 if (unicode != 0xFFFE && m_SpriteCharacterLookup.ContainsKey(unicode) == false) 185 m_SpriteCharacterLookup.Add(unicode, spriteCharacter); 186 } 187 188 m_IsSpriteAssetLookupTablesDirty = false; 189 } 190 191 192 /// <summary> 193 /// Function which returns the sprite index using the hashcode of the name 194 /// </summary> 195 /// <param name="hashCode"></param> 196 /// <returns></returns> 197 public int GetSpriteIndexFromHashcode(int hashCode) 198 { 199 if (m_NameLookup == null) 200 UpdateLookupTables(); 201 202 int index; 203 204 if (m_NameLookup.TryGetValue(hashCode, out index)) 205 return index; 206 207 return -1; 208 } 209 210 211 /// <summary> 212 /// Returns the index of the sprite for the given unicode value. 213 /// </summary> 214 /// <param name="unicode"></param> 215 /// <returns></returns> 216 public int GetSpriteIndexFromUnicode (uint unicode) 217 { 218 if (m_SpriteCharacterLookup == null) 219 UpdateLookupTables(); 220 221 TMP_SpriteCharacter spriteCharacter; 222 223 if (m_SpriteCharacterLookup.TryGetValue(unicode, out spriteCharacter)) 224 return (int)spriteCharacter.glyphIndex; 225 226 return -1; 227 } 228 229 230 /// <summary> 231 /// Returns the index of the sprite for the given name. 232 /// </summary> 233 /// <param name="name"></param> 234 /// <returns></returns> 235 public int GetSpriteIndexFromName (string name) 236 { 237 if (m_NameLookup == null) 238 UpdateLookupTables(); 239 240 int hashCode = TMP_TextUtilities.GetSimpleHashCode(name); 241 242 return GetSpriteIndexFromHashcode(hashCode); 243 } 244 245 246 /// <summary> 247 /// Used to keep track of which Sprite Assets have been searched. 248 /// </summary> 249 private static HashSet<int> k_searchedSpriteAssets; 250 251 /// <summary> 252 /// Search through the given sprite asset and its fallbacks for the specified sprite matching the given unicode character. 253 /// </summary> 254 /// <param name="spriteAsset">The font asset to search for the given character.</param> 255 /// <param name="unicode">The character to find.</param> 256 /// <param name="glyph">out parameter containing the glyph for the specified character (if found).</param> 257 /// <returns></returns> 258 public static TMP_SpriteAsset SearchForSpriteByUnicode(TMP_SpriteAsset spriteAsset, uint unicode, bool includeFallbacks, out int spriteIndex) 259 { 260 // Check to make sure sprite asset is not null 261 if (spriteAsset == null) { spriteIndex = -1; return null; } 262 263 // Get sprite index for the given unicode 264 spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(unicode); 265 if (spriteIndex != -1) 266 return spriteAsset; 267 268 // Initialize list to track instance of Sprite Assets that have already been searched. 269 if (k_searchedSpriteAssets == null) 270 k_searchedSpriteAssets = new HashSet<int>(); 271 else 272 k_searchedSpriteAssets.Clear(); 273 274 // Get instance ID of sprite asset and add to list. 275 int id = spriteAsset.GetInstanceID(); 276 k_searchedSpriteAssets.Add(id); 277 278 // Search potential fallback sprite assets if includeFallbacks is true. 279 if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) 280 return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, true, out spriteIndex); 281 282 // Search default sprite asset potentially assigned in the TMP Settings. 283 if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null) 284 return SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, unicode, true, out spriteIndex); 285 286 spriteIndex = -1; 287 return null; 288 } 289 290 291 /// <summary> 292 /// Search through the given list of sprite assets and fallbacks for a sprite whose unicode value matches the target unicode. 293 /// </summary> 294 /// <param name="spriteAssets"></param> 295 /// <param name="unicode"></param> 296 /// <param name="includeFallbacks"></param> 297 /// <param name="spriteIndex"></param> 298 /// <returns></returns> 299 private static TMP_SpriteAsset SearchForSpriteByUnicodeInternal(List<TMP_SpriteAsset> spriteAssets, uint unicode, bool includeFallbacks, out int spriteIndex) 300 { 301 for (int i = 0; i < spriteAssets.Count; i++) 302 { 303 TMP_SpriteAsset temp = spriteAssets[i]; 304 if (temp == null) continue; 305 306 int id = temp.GetInstanceID(); 307 308 // Skip sprite asset if it has already been searched. 309 if (k_searchedSpriteAssets.Add(id) == false) 310 continue; 311 312 temp = SearchForSpriteByUnicodeInternal(temp, unicode, includeFallbacks, out spriteIndex); 313 314 if (temp != null) 315 return temp; 316 } 317 318 spriteIndex = -1; 319 return null; 320 } 321 322 323 /// <summary> 324 /// Search the given sprite asset and fallbacks for a sprite whose unicode value matches the target unicode. 325 /// </summary> 326 /// <param name="spriteAsset"></param> 327 /// <param name="unicode"></param> 328 /// <param name="includeFallbacks"></param> 329 /// <param name="spriteIndex"></param> 330 /// <returns></returns> 331 private static TMP_SpriteAsset SearchForSpriteByUnicodeInternal(TMP_SpriteAsset spriteAsset, uint unicode, bool includeFallbacks, out int spriteIndex) 332 { 333 // Get sprite index for the given unicode 334 spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(unicode); 335 336 if (spriteIndex != -1) 337 return spriteAsset; 338 339 if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) 340 return SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, unicode, true, out spriteIndex); 341 342 spriteIndex = -1; 343 return null; 344 } 345 346 347 /// <summary> 348 /// Search the given sprite asset and fallbacks for a sprite whose hash code value of its name matches the target hash code. 349 /// </summary> 350 /// <param name="spriteAsset">The Sprite Asset to search for the given sprite whose name matches the hashcode value</param> 351 /// <param name="hashCode">The hash code value matching the name of the sprite</param> 352 /// <param name="includeFallbacks">Include fallback sprite assets in the search</param> 353 /// <param name="spriteIndex">The index of the sprite matching the provided hash code</param> 354 /// <returns>The Sprite Asset that contains the sprite</returns> 355 public static TMP_SpriteAsset SearchForSpriteByHashCode(TMP_SpriteAsset spriteAsset, int hashCode, bool includeFallbacks, out int spriteIndex) 356 { 357 // Make sure sprite asset is not null 358 if (spriteAsset == null) { spriteIndex = -1; return null; } 359 360 spriteIndex = spriteAsset.GetSpriteIndexFromHashcode(hashCode); 361 if (spriteIndex != -1) 362 return spriteAsset; 363 364 // Initialize or clear list to Sprite Assets that have already been searched. 365 if (k_searchedSpriteAssets == null) 366 k_searchedSpriteAssets = new HashSet<int>(); 367 else 368 k_searchedSpriteAssets.Clear(); 369 370 int id = spriteAsset.instanceID; 371 372 // Add to list of font assets already searched. 373 k_searchedSpriteAssets.Add(id); 374 375 TMP_SpriteAsset tempSpriteAsset; 376 377 // Search potential fallbacks assigned to local sprite asset. 378 if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) 379 { 380 tempSpriteAsset = SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, true, out spriteIndex); 381 382 if (spriteIndex != -1) 383 return tempSpriteAsset; 384 } 385 386 // Search default sprite asset potentially assigned in the TMP Settings. 387 if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null) 388 { 389 tempSpriteAsset = SearchForSpriteByHashCodeInternal(TMP_Settings.defaultSpriteAsset, hashCode, true, out spriteIndex); 390 391 if (spriteIndex != -1) 392 return tempSpriteAsset; 393 } 394 395 // Clear search list since we are now looking for the missing sprite character. 396 k_searchedSpriteAssets.Clear(); 397 398 uint missingSpriteCharacterUnicode = TMP_Settings.missingCharacterSpriteUnicode; 399 400 // Get sprite index for the given unicode 401 spriteIndex = spriteAsset.GetSpriteIndexFromUnicode(missingSpriteCharacterUnicode); 402 if (spriteIndex != -1) 403 return spriteAsset; 404 405 // Add current sprite asset to list of assets already searched. 406 k_searchedSpriteAssets.Add(id); 407 408 // Search for the missing sprite character in the local sprite asset and potential fallbacks. 409 if (includeFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) 410 { 411 tempSpriteAsset = SearchForSpriteByUnicodeInternal(spriteAsset.fallbackSpriteAssets, missingSpriteCharacterUnicode, true, out spriteIndex); 412 413 if (spriteIndex != -1) 414 return tempSpriteAsset; 415 } 416 417 // Search for the missing sprite character in the default sprite asset and potential fallbacks. 418 if (includeFallbacks && TMP_Settings.defaultSpriteAsset != null) 419 { 420 tempSpriteAsset = SearchForSpriteByUnicodeInternal(TMP_Settings.defaultSpriteAsset, missingSpriteCharacterUnicode, true, out spriteIndex); 421 if (spriteIndex != -1) 422 return tempSpriteAsset; 423 } 424 425 spriteIndex = -1; 426 return null; 427 } 428 429 430 /// <summary> 431 /// 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. 432 /// </summary> 433 /// <param name="spriteAssets"></param> 434 /// <param name="hashCode"></param> 435 /// <param name="searchFallbacks"></param> 436 /// <param name="spriteIndex"></param> 437 /// <returns></returns> 438 private static TMP_SpriteAsset SearchForSpriteByHashCodeInternal(List<TMP_SpriteAsset> spriteAssets, int hashCode, bool searchFallbacks, out int spriteIndex) 439 { 440 // Search through the list of sprite assets 441 for (int i = 0; i < spriteAssets.Count; i++) 442 { 443 TMP_SpriteAsset temp = spriteAssets[i]; 444 if (temp == null) continue; 445 446 int id = temp.instanceID; 447 448 // Skip sprite asset if it has already been searched. 449 if (k_searchedSpriteAssets.Add(id) == false) 450 continue; 451 452 temp = SearchForSpriteByHashCodeInternal(temp, hashCode, searchFallbacks, out spriteIndex); 453 454 if (temp != null) 455 return temp; 456 } 457 458 spriteIndex = -1; 459 return null; 460 } 461 462 463 /// <summary> 464 /// Search through the given sprite asset and fallbacks for a sprite whose hash code value of its name matches the target hash code. 465 /// </summary> 466 /// <param name="spriteAsset"></param> 467 /// <param name="hashCode"></param> 468 /// <param name="searchFallbacks"></param> 469 /// <param name="spriteIndex"></param> 470 /// <returns></returns> 471 private static TMP_SpriteAsset SearchForSpriteByHashCodeInternal(TMP_SpriteAsset spriteAsset, int hashCode, bool searchFallbacks, out int spriteIndex) 472 { 473 // Get the sprite for the given hash code. 474 spriteIndex = spriteAsset.GetSpriteIndexFromHashcode(hashCode); 475 if (spriteIndex != -1) 476 return spriteAsset; 477 478 if (searchFallbacks && spriteAsset.fallbackSpriteAssets != null && spriteAsset.fallbackSpriteAssets.Count > 0) 479 return SearchForSpriteByHashCodeInternal(spriteAsset.fallbackSpriteAssets, hashCode, true, out spriteIndex); 480 481 spriteIndex = -1; 482 return null; 483 } 484 485 486 /// <summary> 487 /// Sort the sprite glyph table by glyph index. 488 /// </summary> 489 public void SortGlyphTable() 490 { 491 if (m_GlyphTable == null || m_GlyphTable.Count == 0) return; 492 493 m_GlyphTable = m_GlyphTable.OrderBy(item => item.index).ToList(); 494 } 495 496 /// <summary> 497 /// Sort the sprite character table by Unicode values. 498 /// </summary> 499 internal void SortCharacterTable() 500 { 501 if (m_SpriteCharacterTable != null && m_SpriteCharacterTable.Count > 0) 502 m_SpriteCharacterTable = m_SpriteCharacterTable.OrderBy(c => c.unicode).ToList(); 503 } 504 505 /// <summary> 506 /// Sort both sprite glyph and character tables. 507 /// </summary> 508 internal void SortGlyphAndCharacterTables() 509 { 510 SortGlyphTable(); 511 SortCharacterTable(); 512 } 513 514 515 /// <summary> 516 /// Internal method used to upgrade sprite asset. 517 /// </summary> 518 private void UpgradeSpriteAsset() 519 { 520 m_Version = "1.1.0"; 521 522 Debug.Log("Upgrading sprite asset [" + this.name + "] to version " + m_Version + ".", this); 523 524 // Convert legacy glyph and character tables to new format 525 m_SpriteCharacterTable.Clear(); 526 m_GlyphTable.Clear(); 527 528 for (int i = 0; i < spriteInfoList.Count; i++) 529 { 530 TMP_Sprite oldSprite = spriteInfoList[i]; 531 532 TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); 533 spriteGlyph.index = (uint)i; 534 spriteGlyph.sprite = oldSprite.sprite; 535 spriteGlyph.metrics = new GlyphMetrics(oldSprite.width, oldSprite.height, oldSprite.xOffset, oldSprite.yOffset, oldSprite.xAdvance); 536 spriteGlyph.glyphRect = new GlyphRect((int)oldSprite.x, (int)oldSprite.y, (int)oldSprite.width, (int)oldSprite.height); 537 538 spriteGlyph.scale = 1.0f; 539 spriteGlyph.atlasIndex = 0; 540 541 m_GlyphTable.Add(spriteGlyph); 542 543 TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(); 544 spriteCharacter.glyph = spriteGlyph; 545 spriteCharacter.unicode = oldSprite.unicode == 0x0 ? 0xFFFE : (uint)oldSprite.unicode; 546 spriteCharacter.name = oldSprite.name; 547 spriteCharacter.scale = oldSprite.scale; 548 549 m_SpriteCharacterTable.Add(spriteCharacter); 550 } 551 552 // Clear legacy glyph info list. 553 //spriteInfoList.Clear(); 554 555 UpdateLookupTables(); 556 557 #if UNITY_EDITOR 558 UnityEditor.EditorUtility.SetDirty(this); 559 UnityEditor.AssetDatabase.SaveAssets(); 560 #endif 561 } 562 563 } 564}