using UnityEditor; using UnityEngine; using System.IO; namespace gay.lilyy.TextureStitcher { [CreateAssetMenu(fileName = "TextureStitcherSettings", menuName = "Texture Stitcher/Settings")] public class TextureStitcherSettings : ScriptableObject { public Texture2D[] textures; public string savePath = "Assets/StitchedTexture.png"; } [CustomEditor(typeof(TextureStitcherSettings))] public class TextureStitcherEditor : Editor { private SerializedProperty texturesProp; private SerializedProperty savePathProp; private void OnEnable() { texturesProp = serializedObject.FindProperty("textures"); savePathProp = serializedObject.FindProperty("savePath"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.LabelField("Texture Layers (Top → Bottom)", EditorStyles.boldLabel); EditorGUILayout.PropertyField(savePathProp); DrawReversedArray(texturesProp); GUILayout.Space(10); if (GUILayout.Button("Generate Stitched Texture")) GenerateStitchedTexture(); serializedObject.ApplyModifiedProperties(); } private void DrawReversedArray(SerializedProperty array) { if (!array.isArray) return; // Draw size field (normal Unity behavior) EditorGUILayout.PropertyField(array.FindPropertyRelative("Array.size")); // Reverse array in-place int count = array.arraySize; for (int i = 0; i < count / 2; i++) array.MoveArrayElement(i, count - 1 - i); // Draw array normally EditorGUILayout.PropertyField(array, GUIContent.none, true); // Restore original order for (int i = 0; i < count / 2; i++) array.MoveArrayElement(i, count - 1 - i); } private void GenerateStitchedTexture() { TextureStitcherSettings settings = (TextureStitcherSettings)target; GenerateStitchedTexture(settings); } internal static void GenerateStitchedTexture(TextureStitcherSettings settings) { int width = 0; int height = 0; foreach (var tex in settings.textures) { if (!tex) continue; width = Mathf.Max(width, tex.width); height = Mathf.Max(height, tex.height); } Texture2D output = new Texture2D(width, height, TextureFormat.RGBA32, false); Color[] pixels = new Color[width * height]; for (int i = 0; i < pixels.Length; i++) pixels[i] = Color.clear; output.SetPixels(pixels); // Bottom → top for (int i = 0; i < settings.textures.Length; i++) { var tex = settings.textures[i]; if (!tex) continue; Texture2D resized = Resize(tex, width, height); Color[] src = resized.GetPixels(); Color[] dst = output.GetPixels(); for (int p = 0; p < dst.Length; p++) { Color s = src[p]; dst[p] = Color.Lerp(dst[p], s, s.a); } output.SetPixels(dst); } output.Apply(); File.WriteAllBytes(settings.savePath, output.EncodeToPNG()); AssetDatabase.Refresh(); Debug.Log("Stitched texture saved to " + settings.savePath); } private static Texture2D Resize(Texture2D src, int width, int height) { RenderTexture rt = RenderTexture.GetTemporary(width, height, 0); Graphics.Blit(src, rt); RenderTexture.active = rt; Texture2D result = new Texture2D(width, height, TextureFormat.RGBA32, false); result.ReadPixels(new Rect(0, 0, width, height), 0, 0); result.Apply(); RenderTexture.active = null; RenderTexture.ReleaseTemporary(rt); return result; } } }