You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			261 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			261 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C#
		
	
| #if UNITY_EDITOR
 | |
| using System;
 | |
| using System.Linq;
 | |
| using UnityEditor;
 | |
| using UnityEngine;
 | |
| using Object = UnityEngine.Object;
 | |
| 
 | |
| namespace AllIn1VfxToolkit
 | |
| {
 | |
|     public class AllIn1VfxGradientDrawer : MaterialPropertyDrawer
 | |
|     {
 | |
|         private int resolution;
 | |
|         private Texture2D textureAsset;
 | |
| 
 | |
|         public AllIn1VfxGradientDrawer()
 | |
|         {
 | |
|             resolution = 64;
 | |
|         }
 | |
| 
 | |
|         public AllIn1VfxGradientDrawer(float res)
 | |
|         {
 | |
|             resolution = (int) res;
 | |
|         }
 | |
| 
 | |
|         private static bool IsPropertyTypeSuitable(MaterialProperty prop)
 | |
|         {
 | |
|             return prop.type == MaterialProperty.PropType.Texture;
 | |
|         }
 | |
| 
 | |
|         public string TextureName(MaterialProperty prop) => $"{prop.name}Tex";
 | |
| 
 | |
|         public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
 | |
|         {
 | |
|             if(!IsPropertyTypeSuitable(prop))
 | |
|             {
 | |
|                 EditorGUI.HelpBox(position, $"[Gradient] used on non-texture property \"{prop.name}\"",
 | |
|                     MessageType.Error);
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             if(!AssetDatabase.Contains(prop.targets.FirstOrDefault()))
 | |
|             {
 | |
|                 EditorGUI.HelpBox(position,
 | |
|                     "Save Material To Folder to use this effect",
 | |
|                     MessageType.Error);
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             string textureName = TextureName(prop);
 | |
| 
 | |
|             Gradient currentGradient = null;
 | |
|             if(prop.targets.Length == 1)
 | |
|             {
 | |
|                 Material target = (Material) prop.targets[0];
 | |
|                 string path = AssetDatabase.GetAssetPath(target);
 | |
|                 textureAsset = GetTextureAsset(path, textureName);
 | |
|                 if(textureAsset != null)
 | |
|                     currentGradient = DecodeGradient(prop, textureAsset.name);
 | |
|                 if(currentGradient == null)
 | |
|                     currentGradient = new Gradient() { };
 | |
| 
 | |
|                 EditorGUI.showMixedValue = false;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 EditorGUI.showMixedValue = true;
 | |
|             }
 | |
| 
 | |
|             using(EditorGUI.ChangeCheckScope changeScope = new EditorGUI.ChangeCheckScope())
 | |
|             {
 | |
|                 currentGradient = EditorGUILayout.GradientField(label, currentGradient, GUILayout.Height(15));
 | |
| 
 | |
|                 if(changeScope.changed)
 | |
|                 {
 | |
|                     string encodedGradient = EncodeGradient(currentGradient);
 | |
|                     string fullAssetName = textureName + encodedGradient;
 | |
|                     foreach(Object target in prop.targets)
 | |
|                     {
 | |
|                         if(!AssetDatabase.Contains(target)) continue;
 | |
| 
 | |
|                         string path = AssetDatabase.GetAssetPath(target);
 | |
|                         Texture2D textureAsset = GetTexture(path, textureName);
 | |
|                         Undo.RecordObject(textureAsset, "Change Material Gradient");
 | |
|                         textureAsset.name = fullAssetName;
 | |
|                         BakeGradient(currentGradient, textureAsset);
 | |
|                         EditorUtility.SetDirty(textureAsset);
 | |
| 
 | |
|                         Material material = (Material) target;
 | |
|                         material.SetTexture(prop.name, textureAsset);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             EditorGUI.showMixedValue = false;
 | |
|         }
 | |
| 
 | |
|         private Texture2D GetTexture(string path, string name)
 | |
|         {
 | |
|             textureAsset = GetTextureAsset(path, name);
 | |
|             if(textureAsset == null) CreateTexture(path, name);
 | |
|             if(textureAsset.width != resolution) textureAsset.Resize(resolution, 1);
 | |
|             return textureAsset;
 | |
|         }
 | |
| 
 | |
|         private void CreateTexture(string path, string name = "unnamed texture")
 | |
|         {
 | |
|             textureAsset = new Texture2D(resolution, 1, TextureFormat.RGBA32, false);
 | |
|             textureAsset.wrapMode = TextureWrapMode.Clamp;
 | |
|             textureAsset.filterMode = FilterMode.Bilinear;
 | |
|             textureAsset.name = name;
 | |
|             AssetDatabase.AddObjectToAsset(textureAsset, path);
 | |
|             AssetDatabase.Refresh();
 | |
|         }
 | |
| 
 | |
|         private string EncodeGradient(Gradient gradient)
 | |
|         {
 | |
|             if(gradient == null) return null;
 | |
|             return JsonUtility.ToJson(new GradientRepresentation(gradient));
 | |
|         }
 | |
| 
 | |
|         private Gradient DecodeGradient(MaterialProperty prop, string name)
 | |
|         {
 | |
|             string json = name.Substring(TextureName(prop).Length);
 | |
|             try
 | |
|             {
 | |
|                 return JsonUtility.FromJson<GradientRepresentation>(json).ToGradient();
 | |
|             }
 | |
|             catch(Exception)
 | |
|             {
 | |
|                 return null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private Texture2D GetTextureAsset(string path, string name)
 | |
|         {
 | |
|             return AssetDatabase.LoadAllAssetsAtPath(path).FirstOrDefault(asset => asset.name.StartsWith(name)) as
 | |
|                 Texture2D;
 | |
|         }
 | |
| 
 | |
|         private void BakeGradient(Gradient gradient, Texture2D texture)
 | |
|         {
 | |
|             if(gradient == null) return;
 | |
|             for(int x = 0; x < texture.width; x++)
 | |
|             {
 | |
|                 Color color = gradient.Evaluate((float) x / (texture.width - 1));
 | |
|                 for(int y = 0; y < texture.height; y++) texture.SetPixel(x, y, color);
 | |
|             }
 | |
| 
 | |
|             texture.Apply();
 | |
|         }
 | |
| 
 | |
|         [MenuItem("Assets/AllIn1Vfx/Remove All Gradient Textures")]
 | |
|         static void RemoveAllSubAssets()
 | |
|         {
 | |
|             foreach(Object asset in Selection.GetFiltered<Object>(SelectionMode.Assets))
 | |
|             {
 | |
|                 string path = AssetDatabase.GetAssetPath(asset);
 | |
|                 AssetDatabase.ImportAsset(path);
 | |
|                 foreach(Object subAsset in AssetDatabase.LoadAllAssetRepresentationsAtPath(path))
 | |
|                 {
 | |
|                     Object.DestroyImmediate(subAsset, true);
 | |
|                 }
 | |
|                 AssetDatabase.ImportAsset(path);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         class GradientRepresentation
 | |
|         {
 | |
|             public GradientMode mode;
 | |
|             public ColorKey[] colorKeys;
 | |
|             public AlphaKey[] alphaKeys;
 | |
| 
 | |
|             public GradientRepresentation()
 | |
|             {
 | |
|             }
 | |
| 
 | |
|             public GradientRepresentation(Gradient source)
 | |
|             {
 | |
|                 FromGradient(source);
 | |
|             }
 | |
| 
 | |
|             public void FromGradient(Gradient source)
 | |
|             {
 | |
|                 mode = source.mode;
 | |
|                 colorKeys = source.colorKeys.Select(key => new ColorKey(key)).ToArray();
 | |
|                 alphaKeys = source.alphaKeys.Select(key => new AlphaKey(key)).ToArray();
 | |
|             }
 | |
| 
 | |
|             public void ToGradient(Gradient gradient)
 | |
|             {
 | |
|                 gradient.mode = mode;
 | |
|                 gradient.colorKeys = colorKeys.Select(key => key.ToGradientKey()).ToArray();
 | |
|                 gradient.alphaKeys = alphaKeys.Select(key => key.ToGradientKey()).ToArray();
 | |
|             }
 | |
| 
 | |
|             public Gradient ToGradient()
 | |
|             {
 | |
|                 Gradient gradient = new Gradient();
 | |
|                 ToGradient(gradient);
 | |
|                 return gradient;
 | |
|             }
 | |
| 
 | |
|             [Serializable]
 | |
|             public struct ColorKey
 | |
|             {
 | |
|                 public Color color;
 | |
|                 public float time;
 | |
| 
 | |
|                 public ColorKey(GradientColorKey source)
 | |
|                 {
 | |
|                     color = default;
 | |
|                     time = default;
 | |
|                     FromGradientKey(source);
 | |
|                 }
 | |
| 
 | |
|                 public void FromGradientKey(GradientColorKey source)
 | |
|                 {
 | |
|                     color = source.color;
 | |
|                     time = source.time;
 | |
|                 }
 | |
| 
 | |
|                 public GradientColorKey ToGradientKey()
 | |
|                 {
 | |
|                     GradientColorKey key;
 | |
|                     key.color = color;
 | |
|                     key.time = time;
 | |
|                     return key;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             [Serializable]
 | |
|             public struct AlphaKey
 | |
|             {
 | |
|                 public float alpha;
 | |
|                 public float time;
 | |
| 
 | |
|                 public AlphaKey(GradientAlphaKey source)
 | |
|                 {
 | |
|                     alpha = default;
 | |
|                     time = default;
 | |
|                     FromGradientKey(source);
 | |
|                 }
 | |
| 
 | |
|                 public void FromGradientKey(GradientAlphaKey source)
 | |
|                 {
 | |
|                     alpha = source.alpha;
 | |
|                     time = source.time;
 | |
|                 }
 | |
| 
 | |
|                 public GradientAlphaKey ToGradientKey()
 | |
|                 {
 | |
|                     GradientAlphaKey key;
 | |
|                     key.alpha = alpha;
 | |
|                     key.time = time;
 | |
|                     return key;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| #endif |