Skip to content

Commit

Permalink
v2 - unity 2022.3
Browse files Browse the repository at this point in the history
  • Loading branch information
vanifatovvlad committed Oct 17, 2023
1 parent c3deb1b commit 36159b0
Show file tree
Hide file tree
Showing 15 changed files with 204 additions and 185 deletions.
14 changes: 14 additions & 0 deletions Editor/TmpSpriteAssetData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace TMPro
{
[Serializable]
public class TmpSpriteAssetData
{
public string atlasGuid = string.Empty;
public float bearingX = 0.0f;
public float bearingY = 0.0f;
public float advance = 0.0f;
public float scale = 1.0f;
}
}
3 changes: 3 additions & 0 deletions Editor/TmpSpriteAssetData.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

151 changes: 60 additions & 91 deletions Editor/TmpSpriteAssetGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,67 +1,40 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.AssetImporters;
using UnityEngine;
using UnityEngine.TextCore;
using UnityEngine.U2D;
using SpriteUtility = UnityEditor.Sprites.SpriteUtility;

namespace TMPro
{
public static class TmpSpriteAssetGenerator
{
public static void Update(TmpSpriteAtlasAsset rootAsset, bool updateSprites = true)
public static void Generate(AssetImportContext ctx,
TMP_SpriteAsset mainSpriteAsset, SpriteAtlas atlas, TmpSpriteAssetData data)
{
var rootAssetPath = AssetDatabase.GetAssetPath(rootAsset);

AddMainSpriteAsset(rootAsset);

if (updateSprites)
{
UpdateSpriteAssets(rootAsset);
}

EditorUtility.SetDirty(rootAsset);
AssetDatabase.SaveAssets();
AssetDatabase.ImportAsset(rootAssetPath);

foreach (var spriteAsset in AssetDatabase.LoadAllAssetsAtPath(rootAssetPath).OfType<TMP_SpriteAsset>())
{
TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, spriteAsset);
}
}

private static void UpdateSpriteAssets(TmpSpriteAtlasAsset rootAsset)
{
var rootAssetPath = AssetDatabase.GetAssetPath(rootAsset);
var spriteAtlasPath = AssetDatabase.GetAssetPath(rootAsset.spriteAtlas);

var subSpriteAssets = AssetDatabase.LoadAllAssetsAtPath(rootAssetPath)
.OfType<TMP_SpriteAsset>()
.Where(it => it != rootAsset.mainSpriteAsset)
.ToList();
var spriteAtlasPath = AssetDatabase.GetAssetPath(atlas);

var atlasTextures = AssetDatabase.LoadAllAssetsAtPath(spriteAtlasPath)
.OfType<Texture2D>()
.ToList();

foreach (var atlasTex in atlasTextures)
{
var spriteAsset = subSpriteAssets.FirstOrDefault(it => it.name == atlasTex.name);
if (spriteAsset == null)
{
spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
AssetDatabase.AddObjectToAsset(spriteAsset, rootAsset);
}
var spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
ctx.AddObjectToAsset(atlasTex.name, spriteAsset);

spriteAsset.hideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable;
spriteAsset.name = atlasTex.name;
spriteAsset.version = "1.1.0";
spriteAsset.spriteSheet = atlasTex;
spriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(rootAsset.spriteAtlas.name);
spriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(atlasTex.name);

var spriteGlyphTable = new List<TMP_SpriteGlyph>();
var spriteCharacterTable = new List<TMP_SpriteCharacter>();

PopulateSpriteTables(rootAsset, atlasTex, spriteCharacterTable, spriteGlyphTable);
PopulateSpriteTables(ctx, atlas, data, atlasTex, spriteCharacterTable, spriteGlyphTable);

spriteAsset.spriteCharacterTable = spriteCharacterTable;
spriteAsset.spriteGlyphTable = spriteGlyphTable;
Expand All @@ -71,110 +44,106 @@ private static void UpdateSpriteAssets(TmpSpriteAtlasAsset rootAsset)

if (spriteAsset.material == null)
{
AddDefaultMaterial(spriteAsset);
}

rootAsset.mainSpriteAsset.fallbackSpriteAssets.Add(spriteAsset);
}

foreach (var spriteAsset in subSpriteAssets)
{
if (atlasTextures.FirstOrDefault(it => it.name == spriteAsset.name) != null)
{
continue;
}

if (spriteAsset.material != null)
{
Object.DestroyImmediate(spriteAsset.material, allowDestroyingAssets: true);
AddDefaultMaterial(ctx, spriteAsset);
}

Object.DestroyImmediate(spriteAsset, allowDestroyingAssets: true);
mainSpriteAsset.fallbackSpriteAssets.Add(spriteAsset);
}
}

private static void AddMainSpriteAsset(TmpSpriteAtlasAsset rootAsset)
{
var mainSpriteAsset = rootAsset.mainSpriteAsset;

if (mainSpriteAsset == null)
{
mainSpriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
AssetDatabase.AddObjectToAsset(mainSpriteAsset, rootAsset);

rootAsset.mainSpriteAsset = mainSpriteAsset;
}

mainSpriteAsset.name = rootAsset.spriteAtlas.name;
mainSpriteAsset.hideFlags = HideFlags.NotEditable;
mainSpriteAsset.fallbackSpriteAssets = new List<TMP_SpriteAsset>();
}

private static void PopulateSpriteTables(
TmpSpriteAtlasAsset rootAsset,
AssetImportContext ctx,
SpriteAtlas atlas,
TmpSpriteAssetData data,
Texture2D texture,
List<TMP_SpriteCharacter> spriteCharacterTable,
List<TMP_SpriteGlyph> spriteGlyphTable)
{
var spriteCount = rootAsset.spriteAtlas.spriteCount;
var sprites = new Sprite[spriteCount];

rootAsset.spriteAtlas.GetSprites(sprites);
var spritesCount = atlas.spriteCount;
var sprites = new Sprite[spritesCount];
atlas.GetSprites(sprites);

for (var i = 0; i < sprites.Length; i++)
{
var sprite = sprites[i];
var spriteAccess = sprites[i];

Texture2D spriteTex;
Vector2[] spriteUv;

try
{
spriteTex = SpriteUtility.GetSpriteTexture(spriteAccess, getAtlasData: true);
spriteUv = SpriteUtility.GetSpriteUVs(spriteAccess, getAtlasData: true);
}
catch
{
// for non-packed sprites SpriteUtility throws exception
// this only happens when the atlas is not baked e.g.
// when new assets were added
// after atlas re-baking this function works as it should again

spriteTex = null;
spriteUv = null;

ctx.LogImportError($"Failed to process '{spriteAccess.name}' sprite because it is not packed");
}

if (sprite.texture != texture)
if (spriteTex == null || spriteUv == null || spriteTex != texture)
{
continue;
}

var spriteName = sprite.name;
var spriteName = spriteAccess.name;

if (spriteName.EndsWith("(Clone)"))
{
spriteName = spriteName.Substring(0, spriteName.Length - "(Clone)".Length);
}

var bearing = rootAsset.bearing;
var advance = rootAsset.advance;
var textureRect = new Rect(
x: spriteUv[0].x * spriteTex.width,
y: spriteUv[2].y * spriteTex.height,
width: (spriteUv[1].x - spriteUv[0].x) * spriteTex.width,
height: (spriteUv[1].y - spriteUv[2].y) * spriteTex.height
);

var spriteGlyph = new TMP_SpriteGlyph
{
index = (uint) i,
metrics = new GlyphMetrics(
width: sprite.textureRect.width,
height: sprite.textureRect.height,
bearingX: bearing.x,
bearingY: sprite.textureRect.height - bearing.y,
advance: sprite.textureRect.width + advance),
glyphRect = new GlyphRect(sprite.textureRect),
width: textureRect.width,
height: textureRect.height,
bearingX: data.bearingX,
bearingY: textureRect.height - data.bearingY,
advance: textureRect.width + data.advance),
glyphRect = new GlyphRect(textureRect),
scale = 1.0f,
sprite = sprite,
sprite = spriteAccess,
};

spriteGlyphTable.Add(spriteGlyph);

var spriteCharacter = new TMP_SpriteCharacter(0xFFFE, spriteGlyph)
{
name = spriteName,
scale = rootAsset.scale,
scale = data.scale,
};

spriteCharacterTable.Add(spriteCharacter);
}
}

private static void AddDefaultMaterial(TMP_SpriteAsset spriteAsset)
private static void AddDefaultMaterial(AssetImportContext ctx, TMP_SpriteAsset spriteAsset)
{
var name = $"{spriteAsset.spriteSheet.name} Material";
var shader = Shader.Find("TextMeshPro/Sprite");
var material = new Material(shader);
material.SetTexture(ShaderUtilities.ID_MainTex, spriteAsset.spriteSheet);

spriteAsset.material = material;
material.name = name;
material.hideFlags = HideFlags.HideInHierarchy | HideFlags.NotEditable;
AssetDatabase.AddObjectToAsset(material, spriteAsset);
ctx.AddObjectToAsset(name, material);
}
}
}
64 changes: 64 additions & 0 deletions Editor/TmpSpriteAssetImporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.AssetImporters;
using UnityEngine;
using UnityEngine.U2D;

namespace TMPro
{
[ScriptedImporter(1, FileExtension)]
public class TmpSpriteAssetImporter : ScriptedImporter
{
public const string FileExtension = "tmpspriteatlas";
public const string FileExtensionWithDot = ".tmpspriteatlas";
public const string FileVersion = "1.1.0";

private static string[] GatherDependenciesFromSourceFile(string path)
{
var data = JsonUtility.FromJson<TmpSpriteAssetData>(File.ReadAllText(path));
var spriteAtlasPath = AssetDatabase.GUIDToAssetPath(data.atlasGuid);
return new[] {spriteAtlasPath};
}

public override void OnImportAsset(AssetImportContext ctx)
{
var mainSpriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();

ctx.AddObjectToAsset("main", mainSpriteAsset);
ctx.SetMainObject(mainSpriteAsset);

mainSpriteAsset.name = "main";
mainSpriteAsset.hideFlags = HideFlags.NotEditable;
mainSpriteAsset.fallbackSpriteAssets = new List<TMP_SpriteAsset>();

if (EditorSettings.spritePackerMode != SpritePackerMode.SpriteAtlasV2)
{
ctx.LogImportError("TmpSpriteAtlasAsset can be updates only when spritePackerMode is SpriteAtlasV2");
return;
}

var data = JsonUtility.FromJson<TmpSpriteAssetData>(File.ReadAllText(ctx.assetPath));

if (!GUID.TryParse(data.atlasGuid, out var spriteAtlasGuid))
{
ctx.LogImportError("Failed to import TmpSpriteAtlasAsset: atlas guid is invalid");
return;
}

var spriteAtlas = AssetDatabase.LoadMainAssetAtGUID(spriteAtlasGuid) as SpriteAtlas;
if (spriteAtlas == null)
{
return;
}

mainSpriteAsset.version = FileVersion;
mainSpriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteAtlas.name);

TmpSpriteAssetGenerator.Generate(ctx, mainSpriteAsset, spriteAtlas, data);

mainSpriteAsset.SortGlyphTable();
mainSpriteAsset.UpdateLookupTables();
}
}
}
3 changes: 3 additions & 0 deletions Editor/TmpSpriteAssetImporter.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 36159b0

Please sign in to comment.