/// <summary> /// 代码来源于TMPro.EditorUtilities.TMP_SpriteAssetMenu脚本中 /// </summary> /// <param name="source"></param> /// <param name="spriteCharacterTable"></param> /// <param name="spriteGlyphTable"></param> private static void PopulateSpriteTables(Texture source, ref List <TMP_SpriteCharacter> spriteCharacterTable, ref List <TMP_SpriteGlyph> spriteGlyphTable) { string filePath = AssetDatabase.GetAssetPath(source); // Get all the Sprites sorted by Index Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray(); for (int i = 0; i < sprites.Length; i++) { Sprite sprite = sprites[i]; TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); spriteGlyph.index = (uint)i; spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, -sprite.pivot.x, sprite.rect.height - sprite.pivot.y, sprite.rect.width); spriteGlyph.glyphRect = new GlyphRect(sprite.rect); spriteGlyph.scale = 1.0f; spriteGlyph.sprite = sprite; spriteGlyphTable.Add(spriteGlyph); TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph); spriteCharacter.name = sprite.name; spriteCharacter.scale = 1.0f; spriteCharacterTable.Add(spriteCharacter); } }
private static void PopulateSpriteTables(SpriteAtlas spriteAtlas, ref List <TMP_SpriteCharacter> spriteCharacterTable, ref List <TMP_SpriteGlyph> spriteGlyphTable) { // Get number of sprites contained in the sprite atlas. int spriteCount = spriteAtlas.spriteCount; Sprite[] sprites = new Sprite[spriteCount]; // Get all the sprites spriteAtlas.GetSprites(sprites); for (int i = 0; i < sprites.Length; i++) { Sprite sprite = sprites[i]; TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); spriteGlyph.index = (uint)i; spriteGlyph.metrics = new GlyphMetrics(sprite.textureRect.width, sprite.textureRect.height, -sprite.pivot.x, sprite.textureRect.height - sprite.pivot.y, sprite.textureRect.width); spriteGlyph.glyphRect = new GlyphRect(sprite.textureRect); spriteGlyph.scale = 1.0f; spriteGlyph.sprite = sprite; spriteGlyphTable.Add(spriteGlyph); TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0xFFFE, spriteGlyph); spriteCharacter.name = sprite.name; spriteCharacter.scale = 1.0f; spriteCharacterTable.Add(spriteCharacter); } }
/// <summary> /// 缓存图集数据 /// </summary> private void CacheSpriteAssetData() { TMP_SpriteAsset spriteAsset = AssetDatabase.LoadAssetAtPath <TMP_SpriteAsset>(SpriteAssetPath); if (spriteAsset != null) { cacheSpriteGlyphs = new List <TMP_SpriteGlyph>(spriteAsset.spriteGlyphTable.Count); for (int i = 0; i < spriteAsset.spriteGlyphTable.Count; i++) { TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); TMP_SpriteGlyph originSpriteGlyph = spriteAsset.spriteGlyphTable[i]; spriteGlyph.sprite = originSpriteGlyph.sprite; spriteGlyph.atlasIndex = originSpriteGlyph.atlasIndex; spriteGlyph.scale = originSpriteGlyph.scale; spriteGlyph.index = originSpriteGlyph.index; spriteGlyph.metrics = new GlyphMetrics(originSpriteGlyph.metrics.width, originSpriteGlyph.metrics.height, originSpriteGlyph.metrics.horizontalBearingX, originSpriteGlyph.metrics.horizontalBearingY, originSpriteGlyph.metrics.horizontalAdvance); spriteGlyph.glyphRect = new GlyphRect(originSpriteGlyph.glyphRect.x, originSpriteGlyph.glyphRect.y, originSpriteGlyph.glyphRect.width, originSpriteGlyph.glyphRect.height); cacheSpriteGlyphs.Add(spriteGlyph); } //spriteCharacterTable cacheSpriteCharacters = new List <TMP_SpriteCharacter>(spriteAsset.spriteCharacterTable.Count); for (int i = 0; i < spriteAsset.spriteCharacterTable.Count; i++) { TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(); TMP_SpriteCharacter originSpriteCharacter = spriteAsset.spriteCharacterTable[i]; spriteCharacter.unicode = originSpriteCharacter.unicode; spriteCharacter.glyphIndex = originSpriteCharacter.glyphIndex; spriteCharacter.scale = originSpriteCharacter.scale; spriteCharacter.name = originSpriteCharacter.name; spriteCharacter.glyph = cacheSpriteGlyphs[i]; cacheSpriteCharacters.Add(spriteCharacter); } } }
/// <summary> /// 更新图集数据 /// </summary> private void ApplySpriteAssetData() { if (cacheSpriteGlyphs == null || cacheSpriteGlyphs.Count == 0 || cacheSpriteCharacters == null || cacheSpriteCharacters.Count == 0) { Debug.LogError("无缓存数据"); } //1.解析新的tpsheet string str = File.ReadAllText(arrangeIconAtlasTpsheetFilePath); string[] strArr = str.Split('\n'); //以Name为key的GlyphRect数据 Dictionary <string, GlyphRect> glyphRectDic = new Dictionary <string, GlyphRect>(); foreach (var item in strArr) { if (item.StartsWith("#") || item.StartsWith(":") || string.IsNullOrEmpty(item) || item.StartsWith("\r")) { continue; } string[] strArr2 = item.Split(';'); int x = int.Parse(strArr2[1]); int y = int.Parse(strArr2[2]); int w = int.Parse(strArr2[3]); int h = int.Parse(strArr2[4]); GlyphRect rect = new GlyphRect(x, y, w, h); glyphRectDic.Add(strArr2[0], rect); } //1.1获取新的数据,主要使用GlyphMetrics Texture texture = AssetDatabase.LoadAssetAtPath <Texture>(AtlasPngPath); List <TMP_SpriteCharacter> newSpriteCharacters = new List <TMP_SpriteCharacter>(); List <TMP_SpriteGlyph> newSpriteGlyphs = new List <TMP_SpriteGlyph>(); PopulateSpriteTables(texture, ref newSpriteCharacters, ref newSpriteGlyphs); //2.更新Cache //2.1 cacheSpriteGlyphs //2.2 cacheSpriteCharacters if (cacheSpriteGlyphs != null && cacheSpriteGlyphs.Count > 0) { //更新Cache的SpriteGlyph的Rect for (int i = 0; i < cacheSpriteGlyphs.Count; i++) { TMP_SpriteGlyph glyph = cacheSpriteGlyphs[i]; string spriteName = cacheSpriteCharacters[(int)glyph.index].name; if (glyphRectDic.ContainsKey(spriteName)) { GlyphRect newRect = glyphRectDic[spriteName]; glyph.glyphRect = new GlyphRect(newRect.x, newRect.y, newRect.width, newRect.height); } } } foreach (KeyValuePair <string, GlyphRect> glyphRect in glyphRectDic) { TMP_SpriteCharacter findSpriteCharacter = cacheSpriteCharacters.Find(character => character.name == glyphRect.Key); TMP_SpriteCharacter newSpriteCharacter = newSpriteCharacters.Find(character => character.name == glyphRect.Key); if (findSpriteCharacter == null) { //新增的Sprite TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); spriteGlyph.sprite = null; spriteGlyph.atlasIndex = 0; spriteGlyph.scale = 1.0f; spriteGlyph.index = (uint)cacheSpriteGlyphs.Count; GlyphMetrics metrics = newSpriteCharacter.glyph.metrics; spriteGlyph.metrics = new GlyphMetrics(metrics.width, metrics.height, metrics.horizontalBearingX, metrics.horizontalBearingY, metrics.horizontalAdvance); spriteGlyph.glyphRect = new GlyphRect(glyphRect.Value.x, glyphRect.Value.y, glyphRect.Value.width, glyphRect.Value.height); cacheSpriteGlyphs.Add(spriteGlyph); TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph); spriteCharacter.glyphIndex = (uint)cacheSpriteCharacters.Count; spriteCharacter.scale = 1; spriteCharacter.name = glyphRect.Key; cacheSpriteCharacters.Add(spriteCharacter); } } //3.cache写入SpriteAsset TMP_SpriteAsset spriteAsset = AssetDatabase.LoadAssetAtPath <TMP_SpriteAsset>(SpriteAssetPath); FieldInfo spriteCharacterTablePi = spriteAsset.GetType().GetField("m_SpriteCharacterTable", BindingFlags.NonPublic | BindingFlags.Instance); if (null != spriteCharacterTablePi) { spriteCharacterTablePi.SetValue(spriteAsset, cacheSpriteCharacters); } FieldInfo spriteGlyphTablePi = spriteAsset.GetType().GetField("m_SpriteGlyphTable", BindingFlags.NonPublic | BindingFlags.Instance); if (null != spriteGlyphTablePi) { spriteGlyphTablePi.SetValue(spriteAsset, cacheSpriteGlyphs); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }
internal static void UpdateSpriteAsset(TMP_SpriteAsset spriteAsset) { // Get a list of all the sprites contained in the texture referenced by the sprite asset. // This only works if the texture is set to sprite mode. string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet); if (string.IsNullOrEmpty(filePath)) { return; } // Get all the sprites defined in the sprite sheet texture referenced by this sprite asset. Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).ToArray(); // Return if sprite sheet texture does not have any sprites defined in it. if (sprites.Length == 0) { Debug.Log("Sprite Asset <color=#FFFF80>[" + spriteAsset.name + "]</color>'s atlas texture does not appear to have any sprites defined in it. Use the Unity Sprite Editor to define sprites for this texture.", spriteAsset.spriteSheet); return; } List <TMP_SpriteGlyph> spriteGlyphTable = spriteAsset.spriteGlyphTable; // Find available glpyh indexes uint[] existingGlyphIndexes = spriteGlyphTable.Select(x => x.index).ToArray(); List <uint> availableGlyphIndexes = new List <uint>(); uint lastGlyphIndex = existingGlyphIndexes.Length > 0 ? existingGlyphIndexes.Last() : 0; int elementIndex = 0; for (uint i = 0; i < lastGlyphIndex; i++) { uint existingGlyphIndex = existingGlyphIndexes[elementIndex]; if (i == existingGlyphIndex) { elementIndex += 1; } else { availableGlyphIndexes.Add(i); } } // Iterate over sprites contained in the updated sprite sheet to identify new and / or modified sprites. for (int i = 0; i < sprites.Length; i++) { Sprite sprite = sprites[i]; // Check if current sprites is already contained in the sprite glyph table of the sprite asset. TMP_SpriteGlyph spriteGlyph = spriteGlyphTable.FirstOrDefault(x => x.sprite == sprite); if (spriteGlyph != null) { // update existing sprite glyph if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height) { spriteGlyph.glyphRect = new GlyphRect(sprite.rect); } } else { TMP_SpriteCharacter spriteCharacter; // Check if this sprite potentially exists under the same name in the sprite character table. if (spriteAsset.spriteCharacterTable != null && spriteAsset.spriteCharacterTable.Count > 0) { spriteCharacter = spriteAsset.spriteCharacterTable.FirstOrDefault(x => x.name == sprite.name); spriteGlyph = spriteCharacter != null ? spriteGlyphTable[(int)spriteCharacter.glyphIndex] : null; if (spriteGlyph != null) { // Update sprite reference and data spriteGlyph.sprite = sprite; if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height) { spriteGlyph.glyphRect = new GlyphRect(sprite.rect); } } } // Add new Sprite Glyph to the table spriteGlyph = new TMP_SpriteGlyph(); // Get available glyph index if (availableGlyphIndexes.Count > 0) { spriteGlyph.index = availableGlyphIndexes[0]; availableGlyphIndexes.RemoveAt(0); } else { spriteGlyph.index = (uint)spriteGlyphTable.Count; } spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, -sprite.pivot.x, sprite.rect.height - sprite.pivot.y, sprite.rect.width); spriteGlyph.glyphRect = new GlyphRect(sprite.rect); spriteGlyph.scale = 1.0f; spriteGlyph.sprite = sprite; spriteGlyphTable.Add(spriteGlyph); spriteCharacter = new TMP_SpriteCharacter(0xFFFE, spriteGlyph); spriteCharacter.name = sprite.name; spriteCharacter.scale = 1.0f; spriteAsset.spriteCharacterTable.Add(spriteCharacter); } } // Update Sprite Character Table to replace unicode 0x0 by 0xFFFE for (int i = 0; i < spriteAsset.spriteCharacterTable.Count; i++) { TMP_SpriteCharacter spriteCharacter = spriteAsset.spriteCharacterTable[i]; if (spriteCharacter.unicode == 0) { spriteCharacter.unicode = 0xFFFE; } } // Sort glyph table by glyph index spriteAsset.SortGlyphTable(); spriteAsset.UpdateLookupTables(); TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, spriteAsset); }
internal static void UpdateSpriteAsset(TMP_SpriteAsset spriteAsset) { // Get a list of all the sprites contained in the texture referenced by the sprite asset. // This only works if the texture is set to sprite mode. string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet); if (string.IsNullOrEmpty(filePath)) { return; } // Get all the Sprites sorted Left to Right / Top to Bottom Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray(); List <TMP_SpriteGlyph> spriteGlyphTable = spriteAsset.spriteGlyphTable; // Finding available glyph indexes to insert new glyphs into. var tempGlyphTable = spriteGlyphTable.OrderBy(glyph => glyph.index).ToList(); List <uint> availableGlyphIndexes = new List <uint>(); int elementIndex = 0; for (uint i = 0; i < tempGlyphTable[tempGlyphTable.Count - 1].index; i++) { uint currentElementIndex = tempGlyphTable[elementIndex].index; if (i == currentElementIndex) { elementIndex += 1; } else { availableGlyphIndexes.Add(i); } } // Iterate over each of the sprites in the texture to try to match them to existing sprites in the sprite asset. for (int i = 0; i < sprites.Length; i++) { int id = sprites[i].GetInstanceID(); int glyphIndex = spriteGlyphTable.FindIndex(item => item.sprite.GetInstanceID() == id); if (glyphIndex == -1) { // Add new Sprite Glyph to the table Sprite sprite = sprites[i]; TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph(); // Get available glyph index if (availableGlyphIndexes.Count > 0) { spriteGlyph.index = availableGlyphIndexes[0]; availableGlyphIndexes.RemoveAt(0); } else { spriteGlyph.index = (uint)spriteGlyphTable.Count; } spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, -sprite.pivot.x, sprite.rect.height - sprite.pivot.y, sprite.rect.width); spriteGlyph.glyphRect = new GlyphRect(sprite.rect); spriteGlyph.scale = 1.0f; spriteGlyph.sprite = sprite; spriteGlyphTable.Add(spriteGlyph); TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph); spriteCharacter.name = sprite.name; spriteCharacter.scale = 1.0f; spriteAsset.spriteCharacterTable.Add(spriteCharacter); } else { // Look for changes in existing Sprite Glyph Sprite sprite = sprites[i]; TMP_SpriteGlyph spriteGlyph = spriteGlyphTable[glyphIndex]; // We only update changes to the sprite position / glyph rect. if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height) { spriteGlyph.glyphRect = new GlyphRect(sprite.rect); } } } // Sort glyph table by glyph index spriteAsset.SortGlyphTable(); spriteAsset.UpdateLookupTables(); TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, spriteAsset); }