| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 |
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEditor;
- using System.IO;
- using System.Linq;
- namespace InTerra
- {
- public class InTerra_MaskCreator : EditorWindow
- {
- static bool normalInMask;
- bool info;
- int format;
- string path = "";
- string file = "";
- Vector2Int resolution;
- struct TextureField
- {
- public Texture2D texture;
- public int channel;
- public TextureImporter importer;
- public TextureImporterCompression compression;
- public TextureImporterType type;
- public bool isReadable;
- public bool isChanged;
- }
- TextureField metallic;
- TextureField height;
- TextureField ao;
- TextureField smooth;
- TextureField normal;
- bool isResOk;
- bool invertRough;
- float progress;
- public static void OpenWindow(bool normalMask)
- {
- InTerra_MaskCreator window = (InTerra_MaskCreator)EditorWindow.GetWindow<InTerra_MaskCreator>(true, "Mask Map Creator", true);
- Vector2 size = normalMask ? new Vector2(320, 280) : new Vector2(425, 280);
- normalInMask = normalMask;
- window.minSize = size;
- window.maxSize = size;
- #if UNITY_2020_1_OR_NEWER
- Rect main = EditorGUIUtility.GetMainWindowPosition();
- Rect pos = window.position;
- float centerWidth = (main.width - pos.width) * 0.5f;
- float centerHeight = (main.height - pos.height) * 0.5f;
- pos.x = main.x + centerWidth;
- pos.y = main.y + centerHeight;
- window.position = pos;
- #else
- InTerra_Data.CenterOnMainWin(window);
- #endif
- }
- void OnGUI()
- {
- if (normalInMask)
- {
- NormalInMask();
- }
- else
- {
- Mask();
- }
- }
- //============================================================================================
- //------------------------------------ NORMAL-MASK CREATOR ------------------------------
- //============================================================================================
- void NormalInMask()
- {
- Vector2 size = new Vector2(330, 285);
- using (new GUILayout.VerticalScope(EditorStyles.helpBox))
- {
- using (new GUILayout.HorizontalScope())
- {
- using (var check = new EditorGUI.ChangeCheckScope())
- {
- normal = SelectTextureField("Normal Map", normal, false);
- ao = SelectTextureField("A. Occlusion", ao, true);
- height = SelectTextureField("Heightmap", height, true);
- if (check.changed)
- {
- isResOk = CheckTexturesResolution();
- }
- }
- }
- }
- GUI.enabled = false;
- if (normal.texture != null)
- {
- GUI.enabled = true;
- if (!isResOk)
- {
- EditorGUILayout.HelpBox("Textures must have the same resolution!", MessageType.Warning);
- size = new Vector2(320, 320);
- GUI.enabled = false;
- }
- }
- FileAndPathFields(250);
- info = EditorGUILayout.Foldout(info, "Normal-Mask map Texture info", true);
- if (info)
- {
- EditorGUILayout.HelpBox("In the Import Settings the Texture Type has to be set as \"Default\" and \"sRGB(Color Texture)\" has to be unchecked! \n\nChannels info:\nRed - A.Occlusion \nGreen - Bitangent(Green) from Normal map \nBlue - Height map\nAlpha - Tangent(Red) from Normal map", MessageType.None);
- size = new Vector2(320, 380);
- }
- minSize = size;
- maxSize = size;
- EditorGUILayout.Space();
- GUIStyle buttonStyleBold = new GUIStyle(GUI.skin.button) { fontStyle = FontStyle.Bold };
- if (GUILayout.Button("Save", buttonStyleBold))
- {
- if (!FinalCheck())
- {
- Focus();
- }
- else
- {
- EditorUtility.DisplayProgressBar("Saving", "Getting Pixels...", progress);
- Color[] ga = ImprterSetReadWriteAndGetPixels(ref normal);
- Color[] r = ImprterSetReadWriteAndGetPixels(ref ao);
- Color[] b = ImprterSetReadWriteAndGetPixels(ref height);
- EditorUtility.DisplayProgressBar("Saving", "Setting Pixels...", progress);
- Color[] outputCol = new Color[ga.Length];
- if (ao.texture == null) ao.channel = 4;
- if (height.texture == null) height.channel = 5;
- for (int i = 0; i < outputCol.Length; i++)
- {
- outputCol[i] = new Color(ChooseChanel(r[i], ao.channel), ga[i].g, ChooseChanel(b[i], height.channel), ga[i].r);
- }
- Texture2D n_h_ao_texture = new Texture2D(normal.texture.width, normal.texture.height, TextureFormat.RGBAHalf, true);
- n_h_ao_texture.SetPixels(outputCol);
- progress += 0.3f;
- EditorUtility.DisplayProgressBar("Saving", "Encoding and Saving...", progress);
- SaveMaskTexture(format, n_h_ao_texture, path);
- DestroyImmediate(n_h_ao_texture);
- progress += 0.1f;
- EditorUtility.DisplayProgressBar("Saving", "Importer settings...", progress);
- ImporterSetOriginalValues(normal);
- ImporterSetOriginalValues(height);
- ImporterSetOriginalValues(ao);
- EditorUtility.ClearProgressBar();
- EditorApplication.delayCall += () =>
- {
- Close();
- };
- }
- }
- }
- //=======================================================================================
- //------------------------------- MASK MAP CREATOR ---------------------------------
- //=======================================================================================
- void Mask()
- {
- Vector2 size = new Vector2(442, 287);
- using (new GUILayout.VerticalScope(EditorStyles.helpBox))
- {
- using (new GUILayout.HorizontalScope())
- {
- using (var check = new EditorGUI.ChangeCheckScope())
- {
- metallic = SelectTextureField("Metallic", metallic, true);
- ao = SelectTextureField("A. Occlusion", ao, true);
- height = SelectTextureField("Heightmap", height, true);
- using (new GUILayout.VerticalScope())
- {
- smooth = SelectTextureField("Smoothness", smooth, true);
- EditorStyles.label.fontSize = 10;
- invertRough = EditorGUILayout.ToggleLeft(new GUIContent() { text = "Invert Roughness", tooltip = "This option will convert the Roughness texture into Smoothness texture." }, invertRough);
- EditorStyles.label.fontSize = 12;
- }
- EditorGUILayout.GetControlRect(GUILayout.Width(1));
- if (check.changed)
- {
- isResOk = CheckTexturesResolution();
- }
- }
- }
- }
- GUI.enabled = false;
- if (metallic.texture != null || ao.texture != null || height.texture != null || smooth.texture != null)
- {
- GUI.enabled = true;
- if (!isResOk)
- {
- EditorGUILayout.HelpBox("Textures must have the same resolution!", MessageType.Warning);
- size = new Vector2(425, 320);
- GUI.enabled = false;
- }
- }
- minSize = size;
- maxSize = size;
- FileAndPathFields(350);
- EditorGUILayout.Space();
- GUIStyle buttonStyleBold = new GUIStyle(GUI.skin.button) { fontStyle = FontStyle.Bold };
- if (GUILayout.Button("Save", buttonStyleBold))
- {
- if (!FinalCheck())
- {
- Focus();
- }
- else
- {
- EditorUtility.DisplayProgressBar("Saving", "Getting Pixels...", progress);
- Color[] r = ImprterSetReadWriteAndGetPixels(ref metallic);
- Color[] g = ImprterSetReadWriteAndGetPixels(ref ao);
- Color[] b = ImprterSetReadWriteAndGetPixels(ref height);
- Color[] a = ImprterSetReadWriteAndGetPixels(ref smooth);
- Color[] outputCol = new Color[resolution.x * resolution.y];
- EditorUtility.DisplayProgressBar("Saving", "Setting Pixels...", progress);
- if (ao.texture == null) ao.channel = 4;
- if (height.texture == null) height.channel = 5;
- for (int i = 0; i < outputCol.Length; i++)
- {
- if (invertRough) a[i] = Color.white - a[i];
- outputCol[i] = new Color(ChooseChanel(r[i], metallic.channel), ChooseChanel(g[i], ao.channel), ChooseChanel(b[i], height.channel), ChooseChanel(a[i], smooth.channel));
- }
- progress += 0.1f;
- EditorUtility.DisplayProgressBar("Saving", "Encoding and Saving...", progress);
- Texture2D maskTexture = new Texture2D(resolution.x, resolution.y, TextureFormat.RGBAHalf, true);
- maskTexture.SetPixels(outputCol);
- SaveMaskTexture(format, maskTexture, path);
- DestroyImmediate(maskTexture);
- progress += 0.1f;
- EditorUtility.DisplayProgressBar("Saving", "Importer settings...", progress);
- ImporterSetOriginalValues(metallic);
- ImporterSetOriginalValues(ao);
- ImporterSetOriginalValues(height);
- ImporterSetOriginalValues(smooth);
- EditorUtility.ClearProgressBar();
- EditorApplication.delayCall += () =>
- {
- Close();
- };
- }
- }
- }
-
- //=====================================================================================
- GUIContent Tooltip(string tooltip)
- {
- return new GUIContent() { tooltip = tooltip };
- }
- bool CheckTexturesResolution()
- {
- List<int> widthRes = new List<int>();
- List<int> heightRes = new List<int>();
- AddTextureRes(metallic.texture);
- AddTextureRes(ao.texture);
- AddTextureRes(height.texture);
- AddTextureRes(smooth.texture);
- AddTextureRes(normal.texture);
- void AddTextureRes(Texture2D t)
- {
- if (t != null)
- {
- widthRes.Add(t.width);
- heightRes.Add(t.width);
- }
- }
- return (widthRes.Distinct().ToList().Count <= 1) && (heightRes.Distinct().ToList().Count <= 1);
- }
- TextureField SelectTextureField(string name, TextureField tf, bool channel)
- {
- GUILayout.BeginVertical();
- using (new GUILayout.HorizontalScope(EditorStyles.helpBox, GUILayout.MinWidth(105)))
- {
- var style = new GUIStyle(EditorStyles.boldLabel) { alignment = TextAnchor.MiddleCenter };
- var styleMini = new GUIStyle(EditorStyles.miniLabel) { alignment = TextAnchor.MiddleCenter };
- style.alignment = TextAnchor.UpperCenter;
- style.fixedWidth = 80;
- GUILayout.Label(name, style);
- string tooltip = " ";
- switch (name)
- {
- case "Metallic":
- tooltip = "Metallic Texture usually is not a part of ground materials texture set and can be left empty.";
- break;
- case "A. Occlusion":
- tooltip = "Texture can be aslo refered as \"AO\" or \"Ambient Occlusion\".";
- break;
- case "Heightmap":
- tooltip = "Texture can be aslo refered as Bump map. Displacement map can be also used.";
- break;
- case "Smoothness":
- tooltip = "Roughness texture can be used instead of Smoothness but the “Invert Roughness” has to be checked.";
- break;
- case "Normal Map":
- tooltip = "Normal map texture in GL (OpenGL) format";
- break;
- }
- GUILayout.Label(new GUIContent() { text = "?", tooltip = tooltip }, styleMini, GUILayout.MaxWidth(10));
- }
-
- using (var check = new EditorGUI.ChangeCheckScope())
- {
- tf.texture = (Texture2D)EditorGUILayout.ObjectField(tf.texture, typeof(Texture2D), false, GUILayout.Width(105), GUILayout.Height(105));
- if (check.changed)
- {
- PathAndFile(tf.texture);
- }
- }
- tf.importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(tf.texture)) as TextureImporter;
- if (channel)
- {
- var ch = new List<string> { "Red" };
- if (tf.texture != null && tf.importer != null)
- {
- if (tf.importer.textureType != TextureImporterType.SingleChannel)
- {
- ch.Add("Green");
- ch.Add("Blue");
- }
- if (tf.importer.DoesSourceTextureHaveAlpha())
- {
- ch.Add("Alpha");
- }
- tf.channel = EditorGUILayout.Popup(Tooltip("Map Channel"), tf.channel, ch.ToArray(), GUILayout.Width(105));
- }
- else
- {
- GUI.enabled = false;
- EditorGUILayout.Popup(Tooltip("Map Channel"), tf.channel, ch.ToArray(), GUILayout.Width(105));
- GUI.enabled = true;
- }
- }
- else
- {
- tf.channel = 0;
- EditorGUILayout.GetControlRect(GUILayout.Width(100));
- }
- GUILayout.EndVertical();
- return tf;
- }
- void PathAndFile(Texture2D texture)
- {
- if (texture != null && string.IsNullOrEmpty(path))
- {
- path = AssetDatabase.GetAssetPath(texture);
- path = Path.GetDirectoryName(path);
- path = path.Replace("\\", "/");
- file = texture.name + "_Mask";
- resolution = new Vector2Int(texture.width, texture.height);
- }
- }
- string FileAndPathFields(int width)
- {
- using (new GUILayout.HorizontalScope())
- {
- EditorGUILayout.LabelField("File Name:", EditorStyles.miniLabel);
- EditorGUILayout.LabelField("Format:", EditorStyles.miniLabel, GUILayout.MaxWidth(50));
- }
- using (new GUILayout.HorizontalScope())
- {
- string[] sFormat = { "png", "tga" };
- file = EditorGUILayout.TextField(file);
- Repaint();
- format = EditorGUILayout.Popup(format, sFormat, GUILayout.MaxWidth(50));
- }
- EditorGUILayout.LabelField("Path:", EditorStyles.miniLabel);
- using (new GUILayout.HorizontalScope())
- {
- GUILayout.TextField(path, new GUIStyle(EditorStyles.helpBox) { wordWrap = false }, GUILayout.Width(width));
- if (GUILayout.Button("change", EditorStyles.miniButton))
- {
- string absPath = EditorUtility.SaveFolderPanel("Save textures to folder", path, "");
- if (absPath.Contains(Application.dataPath))
- {
- path = absPath.Substring(absPath.IndexOf("Assets"));
- }
- else if (!string.IsNullOrEmpty(absPath))
- {
- path = absPath;
- }
- }
- }
- return path;
- }
- bool FinalCheck()
- {
- if (!CheckTexturesResolution())
- {
- EditorUtility.DisplayDialog("Texture resolution ", "Textures must have the same resolution!", "OK");
- }
- return CheckTexturesResolution() && CheckCrunchedCompression() && ValidPathAndName();
- }
- Color[] ImprterSetReadWriteAndGetPixels(ref TextureField tf)
- {
- if (tf.importer != null)
- {
- tf.isReadable = tf.importer.isReadable;
- tf.compression = tf.importer.textureCompression;
- tf.type = tf.importer.textureType;
- if (!tf.isReadable || tf.compression != TextureImporterCompression.Uncompressed || tf.type != TextureImporterType.Default)
- {
- tf.importer.isReadable = true;
- tf.importer.textureCompression = TextureImporterCompression.Uncompressed;
- tf.importer.crunchedCompression = false;
- tf.importer.textureType = TextureImporterType.Default;
- tf.isChanged = true;
- tf.importer.SaveAndReimport();
- AssetDatabase.Refresh();
- }
- progress += 0.1f; EditorUtility.DisplayProgressBar("Saving", "Getting Pixels...", progress);
- return tf.texture.GetPixels(0, 0, tf.texture.width, tf.texture.height);
- }
- else
- {
- progress += 0.1f; EditorUtility.DisplayProgressBar("Saving", "Getting Pixels...", progress);
- return new Color[resolution.x * resolution.y]; ;
- }
- }
- bool CheckCrunchedCompression()
- {
- bool isOK = false;
- List<bool> crunched = new List<bool>();
- CheckCrunched(metallic);
- CheckCrunched(ao);
- CheckCrunched(height);
- CheckCrunched(smooth);
- CheckCrunched(normal);
- void CheckCrunched(TextureField tf)
- {
- if (tf.importer != null)
- {
- crunched.Add(tf.importer.crunchedCompression);
- }
- }
- if (!crunched.Contains(true))
- {
- isOK = true;
- }
- else
- {
- if (EditorUtility.DisplayDialog("Crunched Compression", "Some texture(s) are using Crunched Compression, if you will continue the Crunched Compression will be set off. Do you want to continue?", "Yes", "Cancel"))
- {
- isOK = true;
- }
- }
- return isOK;
- }
- bool ValidPathAndName()
- {
- bool isOK = false;
- bool nameOk = !string.IsNullOrEmpty(file);
- bool folderOk = path.Length > 3;
- string pf = path;
- if (!folderOk)
- {
- EditorUtility.DisplayDialog("Invalid Folder", "You cannot save the File in the root of the drive, please choose a folder!", "OK");
- }
- if (!nameOk)
- {
- EditorUtility.DisplayDialog("Empty name ", "You need to enter a file name!", "OK");
- }
- if (nameOk && folderOk)
- {
- pf += "/" + file;
- pf += format == 0 ? ".png" : ".tga";
- if (!File.Exists(pf) || (EditorUtility.DisplayDialog("File already exists", "File " + Path.GetFileName(pf) + " already exists. Do you want to replace it?", "Yes", "Cancel")))
- {
- isOK = true;
- path = pf;
- }
- }
- return isOK;
- }
- float ChooseChanel(Color col, int channel)
- {
- float output;
- switch (channel)
- {
- case 0:
- output = col.r;
- break;
- case 1:
- output = col.g;
- break;
- case 2:
- output = col.b;
- break;
- case 3:
- output = col.a;
- break;
- case 4:
- output = 1.0f;
- break;
- case 5:
- output = 0.5f;
- break;
- default:
- return 0.0f;
- }
- return output;
- }
- void SaveMaskTexture(int format, Texture2D texture, string path)
- {
- try
- {
- switch (format)
- {
- case 0:
- File.WriteAllBytes(path, texture.EncodeToPNG());
- break;
- case 1:
- File.WriteAllBytes(path, texture.EncodeToTGA());
- break;
- }
- SetTextureLinear(path);
- AssetDatabase.Refresh();
- }
- catch
- {
- Debug.LogWarning("Saving File " + path + " failed.");
- }
- }
- void SetTextureLinear(string path)
- {
- EditorApplication.delayCall += () =>
- {
- TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
- if (importer != null)
- {
- importer.sRGBTexture = false;
- AssetDatabase.ImportAsset(path);
- AssetDatabase.Refresh();
- }
- };
- }
- void ImporterSetOriginalValues(TextureField tf)
- {
- if (tf.isChanged)
- {
- tf.importer.isReadable = tf.isReadable;
- tf.importer.textureCompression = tf.compression;
- tf.importer.textureType = tf.type;
- tf.importer.SaveAndReimport();
- AssetDatabase.Refresh();
- progress += 0.1f; EditorUtility.DisplayProgressBar("Saving", "Importer settings...", progress);
- }
- }
- }
- }
|