Skip to content

Instantly share code, notes, and snippets.

@j1mmie
Last active November 1, 2024 22:12
Show Gist options
  • Save j1mmie/3ae4f62dc002cd5a7f2effa3d7c68ca7 to your computer and use it in GitHub Desktop.
Save j1mmie/3ae4f62dc002cd5a7f2effa3d7c68ca7 to your computer and use it in GitHub Desktop.
Flatten Unity SpriteAtlas via Context Menu
#nullable enable
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
/// <summary>
/// This script flattens a SpriteAtlas, i.e. removes all folders and adds all
/// sprites individually. It can be accessed by right-clicking on a SpriteAtlas
/// in the Project window and selecting "Flatten SpriteAtlas".
///
/// Drop this file into any folder named "Editor" and it will be available in
/// the Unity Editor.
///
/// @author Jimmie Tyrrell
/// </summary>
public static class FlattenSpriteAtlasContextMenu {
public static readonly string[] ImageLikeExtensions = new [] { "png", "jpg", "jpeg", "psd", "gif", "tga" };
[MenuItem("Assets/Flatten SpriteAtlas", true)]
private static bool Validate() {
return Selection.activeObject is SpriteAtlas;
}
private static List<string> GetTexturesAtPath(string path) {
var enumerations = new IEnumerable<string>[ImageLikeExtensions.Length];
for (int i = 0; i < ImageLikeExtensions.Length; i++) {
enumerations[i] = Directory.EnumerateFiles(path, $"*.{ImageLikeExtensions[i]}", SearchOption.AllDirectories);
}
return enumerations.SelectMany(_ => _).ToList();
}
[MenuItem("Assets/Flatten SpriteAtlas")]
private static void Perform() {
if (Selection.activeObject is not SpriteAtlas atlas) return;
// Remove all old sprites + folders from the atlas
var packables = atlas.GetPackables();
var packablesToRemove = new List<Object>();
var spritesToAdd = new List<Sprite>();
foreach (var packable in packables) {
var path = AssetDatabase.GetAssetPath(packable);
// If the packable is not a folder, ignore it
if (!Directory.Exists(path)) continue;
// If it is a folder, schedule the packable for removal
packablesToRemove.Add(packable);
// Get all sprites in that directory
var spritePaths = GetTexturesAtPath(path);
foreach (var spritePath in spritePaths) {
// Load the sprite and add it to the atlas
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(spritePath);
if (sprite != null) {
spritesToAdd.Add(sprite);
}
}
}
// Remove any packables that were folders
if (packablesToRemove.Count > 0) {
SpriteAtlasExtensions.Remove(atlas, packablesToRemove.ToArray());
}
// Add any sprites that were found in those converted folders
if (spritesToAdd.Count > 0) {
SpriteAtlasExtensions.Add(atlas, spritesToAdd.ToArray());
}
// Refresh the atlas
EditorUtility.SetDirty(atlas);
AssetDatabase.SaveAssets();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment