using UnityEditor; using UnityEngine; using System.Collections.Generic; using System.IO; namespace gay.lilyy.TextureAtlasGenerator { [CreateAssetMenu(fileName = "TextureAtlasSettings", menuName = "Texture Atlas/Settings")] public class TextureAtlasSettings : ScriptableObject { public Texture2D[] textures; public int atlasSize = 1024; public int columns = 4; public int rows = 4; public string savePath = "Assets/Atlas.png"; } [CustomEditor(typeof(TextureAtlasSettings))] public class TextureAtlasEditor : Editor { private SerializedProperty texturesProp; private SerializedProperty columnsProp; private SerializedProperty rowsProp; private void OnEnable() { texturesProp = serializedObject.FindProperty("textures"); columnsProp = serializedObject.FindProperty("columns"); rowsProp = serializedObject.FindProperty("rows"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.LabelField("Texture Atlas Settings", EditorStyles.boldLabel); EditorGUILayout.PropertyField(serializedObject.FindProperty("atlasSize")); EditorGUILayout.PropertyField(columnsProp); EditorGUILayout.PropertyField(rowsProp); EditorGUILayout.PropertyField(serializedObject.FindProperty("savePath")); DrawTextureGrid(); if (GUILayout.Button("Generate Atlas")) { GenerateAtlas(); } serializedObject.ApplyModifiedProperties(); } private void DrawTextureGrid() { int totalSlots = columnsProp.intValue * rowsProp.intValue; if (texturesProp.arraySize != totalSlots) texturesProp.arraySize = totalSlots; EditorGUILayout.LabelField("Textures Grid", EditorStyles.boldLabel); int gridWidth = 80; int gridHeight = 80; for (int y = 0; y < rowsProp.intValue; y++) { EditorGUILayout.BeginHorizontal(); for (int x = 0; x < columnsProp.intValue; x++) { int index = y * columnsProp.intValue + x; SerializedProperty textureProp = texturesProp.GetArrayElementAtIndex(index); textureProp.objectReferenceValue = (Texture2D)EditorGUILayout.ObjectField( textureProp.objectReferenceValue, typeof(Texture2D), false, GUILayout.Width(gridWidth), GUILayout.Height(gridHeight)); } EditorGUILayout.EndHorizontal(); } } private void GenerateAtlas() { TextureAtlasSettings settings = (TextureAtlasSettings)target; if (settings.textures == null || settings.textures.Length == 0) { Debug.LogError("No textures assigned!"); return; } Texture2D atlas = new Texture2D(settings.atlasSize, settings.atlasSize); Color[] blackPixels = new Color[settings.atlasSize * settings.atlasSize]; for (int i = 0; i < blackPixels.Length; i++) blackPixels[i] = Color.black; atlas.SetPixels(blackPixels); int cellWidth = settings.atlasSize / settings.columns; int cellHeight = settings.atlasSize / settings.rows; for (int i = 0; i < settings.textures.Length; i++) { if (settings.textures[i] == null) continue; int x = (i % settings.columns) * cellWidth; int y = (settings.rows - 1 - (i / settings.columns)) * cellHeight; Texture2D resized = ResizeTexture(settings.textures[i], cellWidth, cellHeight); atlas.SetPixels(x, y, cellWidth, cellHeight, resized.GetPixels(), 0); } atlas.Apply(); byte[] bytes = atlas.EncodeToPNG(); File.WriteAllBytes(settings.savePath, bytes); AssetDatabase.Refresh(); Debug.Log("Atlas saved at: " + settings.savePath); } private Texture2D ResizeTexture(Texture2D texture, int width, int height) { RenderTexture rt = new RenderTexture(width, height, 32); Graphics.Blit(texture, rt); Texture2D result = new Texture2D(width, height); RenderTexture.active = rt; result.ReadPixels(new Rect(0, 0, width, height), 0, 0); result.Apply(); RenderTexture.active = null; return result; } } }