Files
HauntedBloodlines/Assets/Editor/SimpleAtlasPacker.cs
2025-05-29 22:31:40 +03:00

138 lines
4.8 KiB
C#

using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
public class SimpleAtlasPacker : EditorWindow
{
private DefaultAsset spritesFolder;
private int cellSize = 64;
private int columns = 4;
private int padding = 2;
private string atlasName = "Buttons_Atlas";
[MenuItem("Tools/Simple Atlas Packer")]
public static void ShowWindow()
{
GetWindow(typeof(SimpleAtlasPacker));
}
void OnGUI()
{
GUILayout.Label("Simple Atlas Packer", EditorStyles.boldLabel);
spritesFolder = (DefaultAsset)EditorGUILayout.ObjectField("Sprites Folder", spritesFolder, typeof(DefaultAsset), false);
cellSize = EditorGUILayout.IntField("Cell Size", cellSize);
columns = EditorGUILayout.IntField("Columns", columns);
padding = EditorGUILayout.IntField("Padding", padding);
atlasName = EditorGUILayout.TextField("Atlas Name", atlasName);
if (GUILayout.Button("Generate Atlas"))
{
if (spritesFolder != null)
{
string folderPath = AssetDatabase.GetAssetPath(spritesFolder);
GenerateAtlas(folderPath);
}
else
{
Debug.LogWarning("Please select a folder with sprites!");
}
}
}
void GenerateAtlas(string folderPath)
{
string[] guids = AssetDatabase.FindAssets("t:Texture2D", new[] { folderPath });
List<Texture2D> textures = new List<Texture2D>();
foreach (string guid in guids)
{
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
if (tex != null) textures.Add(tex);
}
if (textures.Count == 0)
{
Debug.LogWarning("No textures found in folder!");
return;
}
int rows = Mathf.CeilToInt((float)textures.Count / columns);
int width = columns * (cellSize + padding) - padding;
int height = rows * (cellSize + padding) - padding;
Texture2D atlas = new Texture2D(width, height, TextureFormat.RGBA32, false);
Color32[] fillColor = new Color32[width * height];
for (int i = 0; i < fillColor.Length; i++) fillColor[i] = new Color32(0, 0, 0, 0);
atlas.SetPixels32(fillColor);
Dictionary<string, Dictionary<string, int>> jsonFrames = new Dictionary<string, Dictionary<string, int>>();
for (int i = 0; i < textures.Count; i++)
{
int col = i % columns;
int row = i / columns;
int x = col * (cellSize + padding);
int y = height - (row + 1) * (cellSize + padding) + padding;
Texture2D tex = textures[i];
Texture2D resized = ResizeTexture(tex, cellSize, cellSize);
atlas.SetPixels(x, y, cellSize, cellSize, resized.GetPixels());
var frame = new Dictionary<string, int>
{
{"x", x},
{"y", y},
{"w", cellSize},
{"h", cellSize}
};
jsonFrames[Path.GetFileName(AssetDatabase.GetAssetPath(textures[i]))] = new Dictionary<string, int>(frame);
}
atlas.Apply();
// Save Atlas PNG
byte[] pngData = atlas.EncodeToPNG();
string atlasPath = $"Assets/{atlasName}.png";
File.WriteAllBytes(atlasPath, pngData);
AssetDatabase.Refresh();
// Save JSON
string json = "{\n \"frames\": {\n";
int count = 0;
foreach (var kv in jsonFrames)
{
json += $" \"{kv.Key}\": {{ \"frame\": {{\"x\":{kv.Value["x"]},\"y\":{kv.Value["y"]},\"w\":{kv.Value["w"]},\"h\":{kv.Value["h"]}}} }}";
count++;
if (count < jsonFrames.Count) json += ",\n"; else json += "\n";
}
json += " },\n \"meta\": { \"app\": \"SimpleAtlasPacker\" }\n}";
File.WriteAllText($"Assets/{atlasName}.json", json);
AssetDatabase.Refresh();
// Set sprite import settings
TextureImporter importer = (TextureImporter)TextureImporter.GetAtPath(atlasPath);
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Multiple;
importer.SaveAndReimport();
Debug.Log(" Atlas and JSON generated!");
}
Texture2D ResizeTexture(Texture2D source, int width, int height)
{
RenderTexture rt = RenderTexture.GetTemporary(width, height);
Graphics.Blit(source, rt);
RenderTexture.active = rt;
Texture2D result = new Texture2D(width, height);
result.ReadPixels(new Rect(0, 0, width, height), 0, 0);
result.Apply();
RenderTexture.active = null;
RenderTexture.ReleaseTemporary(rt);
return result;
}
}