Files
beyond/Assets/Plugins/Easy performant outline/Scripts/Editor/SerializedPassPropertyDrawer.cs
2024-11-20 15:21:28 +01:00

220 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace EPOOutline
{
public static class SerializedPropertyExtentions
{
private static MethodInfo getFieldInfoAndStaticTypeFromProperty;
public static Attribute[] GetFieldAttributes(this SerializedProperty prop)
{
if (getFieldInfoAndStaticTypeFromProperty == null)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var t in assembly.GetTypes())
{
if (t.Name != "ScriptAttributeUtility")
continue;
getFieldInfoAndStaticTypeFromProperty = t.GetMethod("GetFieldAttributes", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var info in getFieldInfoAndStaticTypeFromProperty.GetParameters())
Debug.Log(info.ParameterType + " " + info.Name);
break;
}
if (getFieldInfoAndStaticTypeFromProperty != null)
break;
}
}
var p = new object[] { prop, null };
var fieldInfo = getFieldInfoAndStaticTypeFromProperty.Invoke(null, p) as Attribute[];
return fieldInfo;
}
public static T GetCustomAttributeFromProperty<T>(this SerializedProperty prop) where T : System.Attribute
{
return Array.Find(GetFieldAttributes(prop), x => x is T) as T;
}
}
[CustomPropertyDrawer(typeof(SerializedPass))]
public class SerializedPassPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var drawingPosition = position;
drawingPosition.height = EditorGUIUtility.singleLineHeight;
var shaderProperty = property.FindPropertyRelative("shader");
var currentShaderReference = shaderProperty.objectReferenceValue as Shader;
var attribute = (SerializedPassInfoAttribute)null;// property.GetCustomAttributeFromProperty<SerializedPassInfoAttribute>();
var prefix = attribute == null ? "Hidden/EPO/Fill/" : attribute.ShadersFolder;
var fillLabel = currentShaderReference == null ? "none" : currentShaderReference.name.Substring(prefix.Length);
if (shaderProperty.hasMultipleDifferentValues)
fillLabel = "-";
if (EditorGUI.DropdownButton(position, new GUIContent(label.text + " : " + fillLabel), FocusType.Passive))
{
var menu = new GenericMenu();
menu.AddItem(new GUIContent("none"), currentShaderReference == null && !shaderProperty.hasMultipleDifferentValues, () =>
{
shaderProperty.objectReferenceValue = null;
shaderProperty.serializedObject.ApplyModifiedProperties();
});
var shaders = AssetDatabase.FindAssets("t:Shader");
foreach (var shader in shaders)
{
var loadedShader = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(shader), typeof(Shader)) as Shader;
if (!loadedShader.name.StartsWith(prefix))
continue;
menu.AddItem(new GUIContent(loadedShader.name.Substring(prefix.Length)), loadedShader == shaderProperty.objectReferenceValue && !shaderProperty.hasMultipleDifferentValues, () =>
{
shaderProperty.objectReferenceValue = loadedShader;
shaderProperty.serializedObject.ApplyModifiedProperties();
});
}
menu.ShowAsContext();
}
if (shaderProperty.hasMultipleDifferentValues)
return;
if (currentShaderReference != null)
{
position.x += EditorGUIUtility.singleLineHeight;
position.width -= EditorGUIUtility.singleLineHeight;
var properties = new Dictionary<string, SerializedProperty>();
var serializedProperties = property.FindPropertyRelative("serializedProperties");
for (var index = 0; index < serializedProperties.arraySize; index++)
{
var subProperty = serializedProperties.GetArrayElementAtIndex(index);
var propertyName = subProperty.FindPropertyRelative("PropertyName");
var propertyValue = subProperty.FindPropertyRelative("Property");
if (propertyName == null || propertyValue == null)
break;
properties.Add(propertyName.stringValue, propertyValue);
}
var fillParametersPosition = position;
fillParametersPosition.height = EditorGUIUtility.singleLineHeight;
for (var index = 0; index < ShaderUtil.GetPropertyCount(currentShaderReference); index++)
{
var propertyName = ShaderUtil.GetPropertyName(currentShaderReference, index);
if (!propertyName.StartsWith("_Public"))
continue;
fillParametersPosition.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
SerializedProperty currentProperty;
if (!properties.TryGetValue(propertyName, out currentProperty))
{
serializedProperties.InsertArrayElementAtIndex(serializedProperties.arraySize);
currentProperty = serializedProperties.GetArrayElementAtIndex(serializedProperties.arraySize - 1);
currentProperty.FindPropertyRelative("PropertyName").stringValue = propertyName;
currentProperty = currentProperty.FindPropertyRelative("Property");
var tempMaterial = new Material(currentShaderReference);
switch (ShaderUtil.GetPropertyType(currentShaderReference, index))
{
case ShaderUtil.ShaderPropertyType.Color:
currentProperty.FindPropertyRelative("ColorValue").colorValue = tempMaterial.GetColor(propertyName);
break;
case ShaderUtil.ShaderPropertyType.Vector:
currentProperty.FindPropertyRelative("VectorValue").vector4Value = tempMaterial.GetVector(propertyName);
break;
case ShaderUtil.ShaderPropertyType.Float:
currentProperty.FindPropertyRelative("FloatValue").floatValue = tempMaterial.GetFloat(propertyName);
break;
case ShaderUtil.ShaderPropertyType.Range:
currentProperty.FindPropertyRelative("FloatValue").floatValue = tempMaterial.GetFloat(propertyName);
break;
case ShaderUtil.ShaderPropertyType.TexEnv:
currentProperty.FindPropertyRelative("TextureValue").objectReferenceValue = tempMaterial.GetTexture(propertyName);
break;
}
GameObject.DestroyImmediate(tempMaterial);
properties.Add(propertyName, currentProperty);
}
if (currentProperty == null)
continue;
var content = new GUIContent(ShaderUtil.GetPropertyDescription(currentShaderReference, index));
switch (ShaderUtil.GetPropertyType(currentShaderReference, index))
{
case ShaderUtil.ShaderPropertyType.Color:
var colorProperty = currentProperty.FindPropertyRelative("ColorValue");
colorProperty.colorValue = EditorGUI.ColorField(fillParametersPosition, content, colorProperty.colorValue, true, true, true);
break;
case ShaderUtil.ShaderPropertyType.Vector:
var vectorProperty = currentProperty.FindPropertyRelative("VectorValue");
vectorProperty.vector4Value = EditorGUI.Vector4Field(fillParametersPosition, content, vectorProperty.vector4Value);
break;
case ShaderUtil.ShaderPropertyType.Float:
EditorGUI.PropertyField(fillParametersPosition, currentProperty.FindPropertyRelative("FloatValue"), content);
break;
case ShaderUtil.ShaderPropertyType.Range:
var floatProperty = currentProperty.FindPropertyRelative("FloatValue");
floatProperty.floatValue = EditorGUI.Slider(fillParametersPosition, content, floatProperty.floatValue,
ShaderUtil.GetRangeLimits(currentShaderReference, index, 1),
ShaderUtil.GetRangeLimits(currentShaderReference, index, 2));
break;
case ShaderUtil.ShaderPropertyType.TexEnv:
EditorGUI.PropertyField(fillParametersPosition, currentProperty.FindPropertyRelative("TextureValue"), content);
break;
}
currentProperty.FindPropertyRelative("PropertyType").intValue = (int)ShaderUtil.GetPropertyType(currentShaderReference, index);
}
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (property.FindPropertyRelative("shader").hasMultipleDifferentValues)
return EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
var shaderProperty = property.FindPropertyRelative("shader");
var currentShaderReference = shaderProperty.objectReferenceValue as Shader;
var additionalCount = 0;
if (currentShaderReference != null)
{
for (var index = 0; index < ShaderUtil.GetPropertyCount(currentShaderReference); index++)
{
var propertyName = ShaderUtil.GetPropertyName(currentShaderReference, index);
if (!propertyName.StartsWith("_Public"))
continue;
additionalCount++;
}
}
return (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing) * (additionalCount + 1);
}
}
}