164 lines
5.7 KiB
C#
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);
|
|
}
|
|
}
|
|
} |