Skip to content

Instantly share code, notes, and snippets.

@splinterofchaos
Created July 29, 2022 05:45
Show Gist options
  • Save splinterofchaos/73f47c982d9c803e819710b28afc692d to your computer and use it in GitHub Desktop.
Save splinterofchaos/73f47c982d9c803e819710b28afc692d to your computer and use it in GitHub Desktop.
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
// Full disclosure: This is based on another gist, but I neglected to write down the link to it.
[CreateAssetMenu]
public class IconPacker : ScriptableObject {
public Texture2D[] textures;
public string outputTexturePath;
public int powerOfTwo = 32;
public int pixelSize = 1;
public int spacing = 2;
public bool needsCreate = false;
public TextTooltipLine tooltipLinePrefab;
void ReplaceFile(string path, byte[] contents) {
File.Delete(path);
File.WriteAllBytes(path, contents);
}
void ReplaceAsset(Object newAsset, string path) {
AssetDatabase.DeleteAsset(path);
AssetDatabase.Refresh();
AssetDatabase.CreateAsset(newAsset, path);
}
[ContextMenu("Pack textures")]
public void PackTextures() {
Texture2D outputTexture = new(pixelSize, pixelSize);
Color32[] fillColor = outputTexture.GetPixels32();
for (int i = 0; i < fillColor.Length; ++i)
fillColor[i] = Color.clear;
outputTexture.SetPixels32(fillColor);
if (textures.Length == 0) {
Debug.LogError("No textures to pack.");
return;
}
List<TMPro.TMP_Sprite> sprites = new();
Rect[] rects = outputTexture.PackTextures(textures, 2, 512);
SpriteMetaData[] meta = new SpriteMetaData[textures.Length];
int width = textures[0].width;
int height = textures[0].height;
int x = 0;
int y = 0;
for (int i = 0; i < textures.Length; ++i) {
meta[i] = new SpriteMetaData {
name = textures[i].name,
rect = new Rect(rects[i].x * outputTexture.width,
rects[i].y * outputTexture.height,
rects[i].width * outputTexture.width,
rects[i].height * outputTexture.height),
pivot = new Vector2(0.5f, 0.5f),
border = Vector4.zero,
alignment = 0
};
TMPro.TMP_Sprite s = new();
s.id = i;
s.name = textures[i].name;
s.hashCode = TMPro.TMP_TextUtilities.GetSimpleHashCode(s.name);
s.x = meta[i].rect.x;
s.y = meta[i].rect.y;
s.width = meta[i].rect.width;
s.height = meta[i].rect.height;
s.pivot = new Vector2(0.5f, 0.5f);
s.scale = 1;
s.xAdvance = meta[i].rect.width;
s.yOffset = meta[i].rect.height * 0.8f;
sprites.Add(s);
x += width;
if (x + width > pixelSize) {
x = 0;
y += height;
if (y + height > pixelSize) {
Debug.LogError("Too many textures to pack. " +
"Increase pixel size.");
return;
}
}
}
string pngPath = outputTexturePath + ".png";
outputTexture.Apply(false, false);
ReplaceFile(pngPath, outputTexture.EncodeToPNG());
TextureImporter importer = (TextureImporter)TextureImporter.GetAtPath(pngPath);
importer.spriteImportMode = SpriteImportMode.Multiple;
importer.textureType = TextureImporterType.Sprite;
importer.textureCompression = TextureImporterCompression.Uncompressed;
importer.filterMode = FilterMode.Bilinear;
importer.maxTextureSize = 4096;
importer.spritesheet = meta;
AssetDatabase.ImportAsset(pngPath, ImportAssetOptions.ForceUpdate);
string spriteAssetPath = outputTexturePath + "TMP.asset";
TMPro.TMP_SpriteAsset spriteAsset;
if (needsCreate) {
spriteAsset = CreateInstance<TMPro.TMP_SpriteAsset>();
ReplaceAsset(spriteAsset, spriteAssetPath);
spriteAsset.spriteInfoList = new();
} else {
spriteAsset = AssetDatabase.LoadAssetAtPath<TMPro.TMP_SpriteAsset>(
spriteAssetPath);
spriteAsset.spriteInfoList.Clear();
}
spriteAsset.hashCode = TMPro.TMP_TextUtilities.GetSimpleHashCode(spriteAsset.name);
spriteAsset.spriteSheet = AssetDatabase.LoadAssetAtPath<Texture2D>(pngPath);
spriteAsset.spriteInfoList = sprites;
if (needsCreate) {
Shader shader = Shader.Find("TextMeshPro/Sprite");
Material material = new Material(shader);
material.SetTexture(TMPro.ShaderUtilities.ID_MainTex, spriteAsset.spriteSheet);
spriteAsset.material = material;
material.hideFlags = HideFlags.None;
AssetDatabase.AddObjectToAsset(material, spriteAsset);
}
spriteAsset.UpdateLookupTables();
tooltipLinePrefab.SetSpriteAsset(spriteAsset);
EditorUtility.SetDirty(spriteAsset);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
spriteAsset.UpdateLookupTables();
Debug.Log($"Successfully wrote {textures.Length} texturs.");
}
private void OnValidate() {
pixelSize = (int)Mathf.Pow(2, powerOfTwo);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment