ProjectDDD/Assets/Plugins/Animate UI Materials/Editor/GraphicPropertyOverrideEditor.cs

164 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
namespace Plugins.Animate_UI_Materials.Editor
{
using PropertyType = ShaderUtil.ShaderPropertyType;
[CustomEditor(typeof(GraphicPropertyOverride), true)]
[CanEditMultipleObjects]
public class GraphicPropertyOverrideEditor : UnityEditor.Editor
{
SerializedProperty _propertyName;
SerializedProperty _propertyValue;
void OnEnable()
{
// Get the serializedProperty of the shader property name
_propertyName = serializedObject.FindProperty("propertyName");
// Get the serializedProperty of the shader property propertyValue
_propertyValue = serializedObject.FindProperty("propertyValue");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
// Draw the script header
using (new EditorGUI.DisabledScope(true))
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Script"));
// Start change check
using EditorGUI.ChangeCheckScope scope = new();
// If single target (not multi-editing)
if (targets.Length == 1)
{
// Draw a warning if the material cannot be found
if (!GetTargetMaterial())
EditorGUILayout.HelpBox(
"The parent doesn't contain a GraphicMaterialOverride. Add one to continue",
MessageType.Error);
string[] properties = GetPropertyNames().ToArray();
// Draw a dropdown list of float properties in the material
EditorGUI.BeginChangeCheck();
int currentIndex = GetPropertyIndexDropdown();
int index = EditorGUILayout.Popup("Property Name", currentIndex, properties);
if (EditorGUI.EndChangeCheck()) _propertyName.stringValue = properties[index];
}
else
{
EditorGUILayout.LabelField("Cannot multi-edit property name");
}
DrawPropertiesExcluding(serializedObject, "m_Script", "propertyName", "propertyValue");
DrawValueProperty(_propertyValue);
// If change happened, apply modified properties
if (scope.changed) serializedObject.ApplyModifiedProperties();
}
/// <summary>
/// Overridable method to draw the value property
/// Overriden by GraphicPropertyOverrideRange to display ranges
/// </summary>
protected virtual void DrawValueProperty(SerializedProperty property)
{
EditorGUILayout.PropertyField(property);
}
/// <summary>
/// Try to get the material of the associated Graphic object
/// </summary>
/// <returns>The material being overriden or null</returns>
protected Material GetTargetMaterial()
{
GraphicPropertyOverride animated = (GraphicPropertyOverride)target;
return animated.transform.parent.TryGetComponent(out Graphic graphic) ? graphic.material : null;
}
/// <summary>
/// Get the property type from the target object
/// </summary>
/// <returns></returns>
protected PropertyType GetPropertyType()
{
GraphicPropertyOverride animated = (GraphicPropertyOverride)target;
return animated switch
{
GraphicPropertyOverrideColor => PropertyType.Color,
GraphicPropertyOverrideFloat => PropertyType.Float,
GraphicPropertyOverrideVector => PropertyType.Vector,
GraphicPropertyOverrideInt => PropertyType.Int,
GraphicPropertyOverrideRange => PropertyType.Range,
GraphicPropertyOverrideTexture => PropertyType.TexEnv,
GraphicPropertyOverrideScaleAndOffset => PropertyType.TexEnv,
_ when target != null => throw new Exception($"Unknown type {target.GetType()}"),
_ => throw new Exception($"Target is null"),
};
}
/// <summary>
/// Get the index inside the filtered dropdown
/// </summary>
/// <returns>The index, or -1 in case of invalid property</returns>
int GetPropertyIndexDropdown()
{
string propertyName = _propertyName.stringValue;
return GetPropertyNames()
.FindIndex(dropdownOptionName => dropdownOptionName == propertyName);
}
/// <summary>
/// Get the index of the property in the shade
/// </summary>
/// <returns>The index of the property or -1 in vase of invalid property</returns>
protected int GetPropertyIndex()
{
Material material = GetTargetMaterial();
string propertyName = _propertyName.stringValue;
return ShaderPropertyInfo.GetMaterialProperties(material)
.Find(p => p.name == propertyName)
?.index ??
-1;
}
/// <summary>
/// Get all matching properties from the shader
/// </summary>
/// <returns></returns>
List<string> GetPropertyNames()
{
Material material = GetTargetMaterial();
PropertyType type = GetPropertyType();
return ShaderPropertyInfo.GetMaterialProperties(material)
.Where(p => p.type == type)
.Select(p => p.name)
.ToList();
}
/// <summary>
/// Override the reset context menu to implement the reset function
/// Needed instead of "MonoBehavior.Reset" on GraphicMaterialOverride because Reset is called in other contexts
/// </summary>
[MenuItem("CONTEXT/GraphicPropertyOverride/Reset")]
static void ResetPropertyValue(MenuCommand b)
{
if (b.context is not GraphicPropertyOverride propertyOverride) return;
Undo.RecordObject(propertyOverride, "Reset material override");
propertyOverride.ResetPropertyToDefault();
PrefabUtility.RecordPrefabInstancePropertyModifications(propertyOverride);
}
}
}