private void OnGUI()
        {
            EditorGUILayout.LabelField("General Settings", EditorStyles.boldLabel);
            EditorGUILayout.Space();
            materialPrefix = EditorGUILayout.TextField("Material Prefix", materialPrefix);
            materialSuffix = EditorGUILayout.TextField("Material Suffix", materialSuffix);
            baseMaterial   = EditorGUILayout.ObjectField("Template Material", baseMaterial, typeof(Material), false) as Material;
            shader         = EditorGUILayout.ObjectField("Shader Override", shader, typeof(Shader), false) as Shader;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Overwrite existing materials?");
            overrideExistingMaterials = EditorGUILayout.Toggle(overrideExistingMaterials);
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Albedo texture \"Alpha is Transparency\" Settings", EditorStyles.boldLabel);
            EditorGUILayout.Space();
            overrideAlphaIsTransparency = EditorGUILayout.BeginToggleGroup("Override alphaIsTransparency", overrideAlphaIsTransparency);
            alphaIsTransparencyNew      = EditorGUILayout.Toggle("alphaIsTransparency new value", alphaIsTransparencyNew);
            EditorGUILayout.EndToggleGroup();
            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Material Albedo Map Settings", EditorStyles.boldLabel);
            EditorGUILayout.Space();
            overrideTexturePropertyName = EditorGUILayout.BeginToggleGroup("Use custom material albedo property", overrideTexturePropertyName);
            materialTexturePropertyName = EditorGUILayout.TextField("Shader Texture Property Name", materialTexturePropertyName);
            EditorGUILayout.EndToggleGroup();
            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Material Normal Map Settings", EditorStyles.boldLabel);
            EditorGUILayout.Space();
            includeNormalMap = EditorGUILayout.BeginToggleGroup("Include normal maps (need to end with \"_n\" or \"_normal\")", includeNormalMap);
            // Normal maps need to start with the regular texture name and end with "_n" or "_normal" to qualify as normal maps
            // The normal maps will also automatically have their import settings changed to normal maps if necessary
            // According to the documentation at https://docs.unity3d.com/ScriptReference/Material.SetTexture.html the default name
            // property for normal maps in Unity's built in shaders is "_BumpMap" (and "_MainTex" for the main texture/albedo)
            overrideNormalMapPropertyName = EditorGUILayout.BeginToggleGroup("Use custom material normal map property", overrideNormalMapPropertyName);
            normalMapPropertyName         = EditorGUILayout.TextField("Normal Map Property", normalMapPropertyName);
            EditorGUILayout.EndToggleGroup();
            EditorGUILayout.EndToggleGroup();
            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Folder Selection", EditorStyles.boldLabel);
            EditorGUILayout.Space();
            EditorGUILayout.LabelField(string.Format("Input folder: {0}", (!string.IsNullOrEmpty(textureSrcFolderPath) ? textureSrcFolderPath : "[not assigned]")));
            EditorGUILayout.LabelField(string.Format("Output folder: {0}", (!string.IsNullOrEmpty(outputFolderPath) ? outputFolderPath : "[not assigned]")));

            if (GUILayout.Button("Use folder of selected asset as input"))
            {
                EditorHelpUtilities.AssignFolderOfSelectedObject(ref textureSrcFolderPath);
            }
            if (GUILayout.Button("Use folder of selected asset as output"))
            {
                EditorHelpUtilities.AssignFolderOfSelectedObject(ref outputFolderPath);
            }
            if (GUILayout.Button("Select Texture Input Folder"))
            {
                string folderPathTemp = null;
                if (EditorHelpUtilities.TryGetFolderSelection(out folderPathTemp, "Select folder with Textures"))
                {
                    textureSrcFolderPath = folderPathTemp;
                }
            }
            if (GUILayout.Button("Select Material Output Folder"))
            {
                string folderPathTemp = null;
                if (EditorHelpUtilities.TryGetFolderSelection(out folderPathTemp, "Select folder to store Materials to"))
                {
                    outputFolderPath = folderPathTemp;
                }
            }
            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Asset Generation", EditorStyles.boldLabel);
            if (GUILayout.Button("Create Materials"))
            {
                CreateMaterials();
            }
        }
 private string GetSanitizedMaterialFileName(string textureName)
 {
     return(EditorHelpUtilities.GetSanetizedFileName(materialPrefix).Replace("/", "") + textureName + EditorHelpUtilities.GetSanetizedFileName(materialSuffix).Replace("/", "") + ".mat");
 }
        private void BuildMaterialsWithNormalMaps(string[] assetGUIDs, Material materialTemplate, string outputPathAssetsRelativeTrimmed)
        {
            // Assume a list size of half the assetGUIDs length, but add a small buffer in case not all textures have proper normals for them
            List <MapSet>           textureSets      = new List <MapSet>((assetGUIDs.Length + 2) / 2);
            List <AssetNameDetails> assetNameDetails = new List <AssetNameDetails>(assetGUIDs.Length);
            bool wereTextureImportSettingsEdited     = false;

            foreach (string guid in assetGUIDs)
            {
                string           assetPath                    = AssetDatabase.GUIDToAssetPath(guid);
                string           assetName                    = EditorHelpUtilities.GetAssetNameFromPath(assetPath);
                string           assetNameLowerCase           = assetName.ToLower();
                int              assetNameLastDotIndex        = assetName.LastIndexOf('.');
                string           assetNameNoFileTypeLowerCase = assetNameLowerCase.Substring(0, assetNameLastDotIndex);
                AssetNameDetails nameDetails                  = new AssetNameDetails(assetPath, assetName, assetNameLowerCase, assetNameNoFileTypeLowerCase);
                assetNameDetails.Add(nameDetails);
            }

            foreach (AssetNameDetails nameDetails in assetNameDetails)
            {
                bool isNormalMap = false;
                foreach (string normalSuffix in normalMapSuffixes)
                {
                    if (nameDetails.AssetNameNoFileTypeLowerCase.EndsWith(normalSuffix))
                    {
                        // Found normal map, continue search for albedo maps only
                        isNormalMap = true;
                        continue;
                    }
                }
                if (isNormalMap)
                {
                    continue;
                }
                Texture2D albedoTexture = AssetDatabase.LoadAssetAtPath(nameDetails.AssetPath, typeof(Texture2D)) as Texture2D;
                if (albedoTexture == null)
                {
                    continue;
                }
                if (overrideAlphaIsTransparency)
                {
                    albedoTexture.alphaIsTransparency = alphaIsTransparencyNew;
                    TextureImporter textureImporter = AssetImporter.GetAtPath(nameDetails.AssetPath) as TextureImporter;
                    if (textureImporter.alphaIsTransparency != alphaIsTransparencyNew)
                    {
                        wereTextureImportSettingsEdited     = true;
                        textureImporter.alphaIsTransparency = alphaIsTransparencyNew;
                    }
                }
                Texture2D normalTexture      = null;
                string    normalMapAssetPath = FindNormalMapAssetPathForTextureName(assetNameDetails, nameDetails.AssetNameNoFileTypeLowerCase);
                if (normalMapAssetPath != null)
                {
                    TextureImporter normalTextureImporter = AssetImporter.GetAtPath(normalMapAssetPath) as TextureImporter;
                    if (normalTextureImporter.textureType != TextureImporterType.NormalMap)
                    {
                        normalTextureImporter.textureType = TextureImporterType.NormalMap;
                        wereTextureImportSettingsEdited   = true;
                    }
                    normalTexture = AssetDatabase.LoadAssetAtPath(normalMapAssetPath, typeof(Texture2D)) as Texture2D;
                }
                MapSet textureCombination = new MapSet(albedoTexture, normalTexture, nameDetails.AssetPath);
                textureSets.Add(textureCombination);
            }
            // Apply the changes to the normal map texture settings to the project, if there were any:
            if (wereTextureImportSettingsEdited)
            {
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }

            foreach (MapSet textureSet in textureSets)
            {
                try
                {
                    Material currentMaterial = new Material(baseMaterial); // copies all properties
                    SetAlbedoMapInMaterial(currentMaterial, textureSet.AlbedoMap);
                    SetNormalMapInMaterial(currentMaterial, textureSet.NormalMap);

                    string textureName  = textureSet.AlbedoMap.name;
                    string fileName     = GetSanitizedMaterialFileName(textureName);
                    string fullSavePath = outputPathAssetsRelativeTrimmed + "/" + fileName;

                    if (!overrideExistingMaterials && !string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(fullSavePath)))
                    {
                        // if we don't allow material overwriting and there is an asset at our path (AssetDatabase.AssetPathToGUID not returning null)
                        // just omit the asset creation
                        Destroy(currentMaterial);
                        continue;
                    }
                    // CreateAsset remark: If an asset already exists at path it will be deleted prior to creating a new asset.
                    AssetDatabase.CreateAsset(currentMaterial, fullSavePath);
                }
                catch (System.Exception e)
                {
                    Debug.LogError(string.Format("Something has gone wrong while processing texture set with albedo map at path {0}: {1}", textureSet.AlbedoMapAssetPath, e));
                }
            }
        }
        private void CreateMaterials()
        {
            // Information for using Directory.Exists:
            // The path parameter is permitted to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory.
            Debug.Log(string.Format("CreateMaterials: InputFolder Path passed {0}, output folder path {1}", textureSrcFolderPath, outputFolderPath));
            if (!Directory.Exists(textureSrcFolderPath))
            {
                EditorHelpUtilities.DisplaySimpleDialog("Invalid folder", string.Format("Input folder path {0} is not valid", textureSrcFolderPath));
                return;
            }
            if (!Directory.Exists(outputFolderPath))
            {
                EditorHelpUtilities.DisplaySimpleDialog("Invalid folder", string.Format("Output folder path {0} is not valid", outputFolderPath));
                return;
            }
            string inputFolderAssetsRelative = null;

            if (!EditorHelpUtilities.TryGetAssetsLocalPathForExistingFolder(textureSrcFolderPath, out inputFolderAssetsRelative))
            {
                EditorHelpUtilities.DisplaySimpleDialog("Invalid folder", string.Format("Input folder path {0} exists but was found to not belong into this project", textureSrcFolderPath));
                return;
            }
            string outputFolderAssetsRelative = null;

            if (!EditorHelpUtilities.TryGetAssetsLocalPathForExistingFolder(outputFolderPath, out outputFolderAssetsRelative))
            {
                EditorHelpUtilities.DisplaySimpleDialog("Invalid folder", string.Format("Input folder path {0} exists but was found to not belong into this project", outputFolderPath));
                return;
            }

            var baseMaterialPrev = baseMaterial;
            var shaderPrev       = shader;

            if (baseMaterial == null)
            {
                Shader initShader = shader != null ? shader : Shader.Find("Standard");
                baseMaterial = new Material(initShader);
            }
            else if (shader != null)
            {
                baseMaterial.shader = shader;
            }

            Debug.Log(string.Format("Output folder path: {0}", outputFolderPath));
            string outputPathAssetsRelativeTrimmed = outputFolderAssetsRelative.TrimEnd('/').TrimEnd('\\');

            string[] assetGUIDs = AssetDatabase.FindAssets("t:texture2D", new string[] { inputFolderAssetsRelative });

            if (includeNormalMap)
            {
                BuildMaterialsWithNormalMaps(assetGUIDs, baseMaterial, outputPathAssetsRelativeTrimmed);
            }
            else
            {
                BuildMaterialsWithoutNormalMaps(assetGUIDs, baseMaterial, outputPathAssetsRelativeTrimmed);
            }
            shader = shaderPrev;
            // If we created a material only for this purpose, destroy it again
            if (baseMaterial != null && baseMaterialPrev == null)
            {
                GameObject.DestroyImmediate(baseMaterial);
            }
            baseMaterial = baseMaterialPrev;
            // Save new alphaIsTransparency setting for asset loaders if neccessary
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }