127 lines
4.2 KiB
C#
127 lines
4.2 KiB
C#
#if UNITY_EDITOR
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Coffee.UIExtensions
|
|
{
|
|
public class MaterialResolver
|
|
{
|
|
static readonly StringBuilder s_StringBuilder = new StringBuilder();
|
|
|
|
static readonly Dictionary<string, Material> s_MaterialMap = new Dictionary<string, Material>();
|
|
|
|
public static Material GetOrGenerateMaterialVariant(Shader shader, params object[] append)
|
|
{
|
|
if (!shader)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Material mat = null;
|
|
string variantName = GetVariantName(shader, append);
|
|
if (s_MaterialMap.TryGetValue(variantName, out mat) && mat)
|
|
{
|
|
return mat;
|
|
}
|
|
|
|
string[] keywords = append.Where(x => 0 < (int)x)
|
|
.Select(x => x.ToString().ToUpper())
|
|
.ToArray();
|
|
mat = GetMaterial(shader, append);
|
|
if (mat)
|
|
{
|
|
if (!mat.shaderKeywords.OrderBy(x => x).SequenceEqual(keywords.OrderBy(x => x)))
|
|
{
|
|
mat.shaderKeywords = keywords;
|
|
EditorUtility.SetDirty(mat);
|
|
if (!Application.isPlaying)
|
|
{
|
|
EditorApplication.delayCall += AssetDatabase.SaveAssets;
|
|
}
|
|
}
|
|
return mat;
|
|
}
|
|
|
|
if (s_MaterialMap.TryGetValue(variantName, out mat) && mat)
|
|
{
|
|
return mat;
|
|
}
|
|
|
|
Debug.Log("Generate material : " + variantName);
|
|
mat = new Material(shader);
|
|
mat.shaderKeywords = keywords;
|
|
|
|
mat.name = variantName;
|
|
mat.hideFlags |= HideFlags.NotEditable;
|
|
s_MaterialMap[variantName] = mat;
|
|
|
|
bool isMainAsset = append.Cast<int>().All(x => x == 0);
|
|
EditorApplication.delayCall += () => SaveMaterial(mat, shader, isMainAsset);
|
|
return mat;
|
|
}
|
|
|
|
static void SaveMaterial(Material mat, Shader shader, bool isMainAsset)
|
|
{
|
|
string materialPath = GetDefaultMaterialPath(shader);
|
|
|
|
#if UIEFFECT_SEPARATE
|
|
string dir = Path.GetDirectoryName(materialPath);
|
|
materialPath = Path.Combine(Path.Combine(dir, "Separated"), mat.name + ".mat");
|
|
isMainAsset = true;
|
|
#endif
|
|
if (isMainAsset)
|
|
{
|
|
Directory.CreateDirectory(Path.GetDirectoryName(materialPath));
|
|
AssetDatabase.CreateAsset(mat, materialPath);
|
|
}
|
|
else
|
|
{
|
|
GetOrGenerateMaterialVariant(shader);
|
|
mat.hideFlags |= HideFlags.HideInHierarchy;
|
|
AssetDatabase.AddObjectToAsset(mat, materialPath);
|
|
}
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
public static Material GetMaterial(Shader shader, params object[] append)
|
|
{
|
|
string variantName = GetVariantName(shader, append);
|
|
return AssetDatabase.FindAssets("t:Material " + Path.GetFileName(shader.name))
|
|
.Select(x => AssetDatabase.GUIDToAssetPath(x))
|
|
.SelectMany(x => AssetDatabase.LoadAllAssetsAtPath(x))
|
|
.OfType<Material>()
|
|
.FirstOrDefault(x => x.name == variantName);
|
|
}
|
|
|
|
public static string GetDefaultMaterialPath(Shader shader)
|
|
{
|
|
var name = Path.GetFileName(shader.name);
|
|
return AssetDatabase.FindAssets("t:Material " + name)
|
|
.Select(x => AssetDatabase.GUIDToAssetPath(x))
|
|
.FirstOrDefault(x => Path.GetFileNameWithoutExtension(x) == name)
|
|
?? ("Assets/" + name + ".mat");
|
|
}
|
|
|
|
public static string GetVariantName(Shader shader, params object[] append)
|
|
{
|
|
s_StringBuilder.Length = 0;
|
|
|
|
#if UIEFFECT_SEPARATE
|
|
s_StringBuilder.Append("[Separated] ");
|
|
#endif
|
|
s_StringBuilder.Append(Path.GetFileName(shader.name));
|
|
foreach (object mode in append.Where(x => 0 < (int)x))
|
|
{
|
|
s_StringBuilder.Append("-");
|
|
s_StringBuilder.Append(mode.ToString());
|
|
}
|
|
return s_StringBuilder.ToString();
|
|
}
|
|
}
|
|
}
|
|
#endif
|