您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
329 行
12 KiB
329 行
12 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace NaughtyAttributes.Editor
|
|
{
|
|
[CanEditMultipleObjects]
|
|
[CustomEditor(typeof(UnityEngine.Object), true)]
|
|
public class InspectorEditor : UnityEditor.Editor
|
|
{
|
|
private SerializedProperty script;
|
|
|
|
private IEnumerable<FieldInfo> fields;
|
|
private HashSet<FieldInfo> groupedFields;
|
|
private Dictionary<string, List<FieldInfo>> groupedFieldsByGroupName;
|
|
private IEnumerable<FieldInfo> nonSerializedFields;
|
|
private IEnumerable<PropertyInfo> nativeProperties;
|
|
private IEnumerable<MethodInfo> methods;
|
|
|
|
private Dictionary<string, SerializedProperty> serializedPropertiesByFieldName;
|
|
|
|
private bool useDefaultInspector;
|
|
|
|
private void OnEnable()
|
|
{
|
|
this.script = this.serializedObject.FindProperty("m_Script");
|
|
|
|
// Cache serialized fields
|
|
this.fields = ReflectionUtility.GetAllFields(this.target, f => this.serializedObject.FindProperty(f.Name) != null);
|
|
|
|
// If there are no NaughtyAttributes use default inspector
|
|
if (this.fields.All(f => f.GetCustomAttributes(typeof(NaughtyAttribute), true).Length == 0))
|
|
{
|
|
this.useDefaultInspector = true;
|
|
}
|
|
else
|
|
{
|
|
this.useDefaultInspector = false;
|
|
|
|
// Cache grouped fields
|
|
this.groupedFields = new HashSet<FieldInfo>(this.fields.Where(f => f.GetCustomAttributes(typeof(GroupAttribute), true).Length > 0));
|
|
|
|
// Cache grouped fields by group name
|
|
this.groupedFieldsByGroupName = new Dictionary<string, List<FieldInfo>>();
|
|
foreach (var groupedField in this.groupedFields)
|
|
{
|
|
string groupName = (groupedField.GetCustomAttributes(typeof(GroupAttribute), true)[0] as GroupAttribute).Name;
|
|
|
|
if (this.groupedFieldsByGroupName.ContainsKey(groupName))
|
|
{
|
|
this.groupedFieldsByGroupName[groupName].Add(groupedField);
|
|
}
|
|
else
|
|
{
|
|
this.groupedFieldsByGroupName[groupName] = new List<FieldInfo>()
|
|
{
|
|
groupedField
|
|
};
|
|
}
|
|
}
|
|
|
|
// Cache serialized properties by field name
|
|
this.serializedPropertiesByFieldName = new Dictionary<string, SerializedProperty>();
|
|
foreach (var field in this.fields)
|
|
{
|
|
this.serializedPropertiesByFieldName[field.Name] = this.serializedObject.FindProperty(field.Name);
|
|
}
|
|
}
|
|
|
|
// Cache non-serialized fields
|
|
this.nonSerializedFields = ReflectionUtility.GetAllFields(
|
|
this.target, f => f.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0 && this.serializedObject.FindProperty(f.Name) == null);
|
|
|
|
// Cache the native properties
|
|
this.nativeProperties = ReflectionUtility.GetAllProperties(
|
|
this.target, p => p.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0);
|
|
|
|
// Cache methods with DrawerAttribute
|
|
this.methods = ReflectionUtility.GetAllMethods(
|
|
this.target, m => m.GetCustomAttributes(typeof(DrawerAttribute), true).Length > 0);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
PropertyDrawerDatabase.ClearCache();
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
if (this.useDefaultInspector)
|
|
{
|
|
this.DrawDefaultInspector();
|
|
}
|
|
else
|
|
{
|
|
this.serializedObject.Update();
|
|
|
|
if (this.script != null)
|
|
{
|
|
GUI.enabled = false;
|
|
EditorGUILayout.PropertyField(this.script);
|
|
GUI.enabled = true;
|
|
}
|
|
|
|
// Draw fields
|
|
HashSet<string> drawnGroups = new HashSet<string>();
|
|
foreach (var field in this.fields)
|
|
{
|
|
if (this.groupedFields.Contains(field))
|
|
{
|
|
// Draw grouped fields
|
|
string groupName = (field.GetCustomAttributes(typeof(GroupAttribute), true)[0] as GroupAttribute).Name;
|
|
if (!drawnGroups.Contains(groupName))
|
|
{
|
|
drawnGroups.Add(groupName);
|
|
|
|
PropertyGrouper grouper = this.GetPropertyGrouperForField(field);
|
|
if (grouper != null)
|
|
{
|
|
grouper.BeginGroup(groupName);
|
|
|
|
this.ValidateAndDrawFields(this.groupedFieldsByGroupName[groupName]);
|
|
|
|
grouper.EndGroup();
|
|
}
|
|
else
|
|
{
|
|
this.ValidateAndDrawFields(this.groupedFieldsByGroupName[groupName]);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Draw non-grouped field
|
|
this.ValidateAndDrawField(field);
|
|
}
|
|
}
|
|
|
|
this.serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
// Draw non-serialized fields
|
|
foreach (var field in this.nonSerializedFields)
|
|
{
|
|
DrawerAttribute drawerAttribute = (DrawerAttribute)field.GetCustomAttributes(typeof(DrawerAttribute), true)[0];
|
|
FieldDrawer drawer = FieldDrawerDatabase.GetDrawerForAttribute(drawerAttribute.GetType());
|
|
if (drawer != null)
|
|
{
|
|
drawer.DrawField(this.target, field);
|
|
}
|
|
}
|
|
|
|
// Draw native properties
|
|
foreach (var property in this.nativeProperties)
|
|
{
|
|
DrawerAttribute drawerAttribute = (DrawerAttribute)property.GetCustomAttributes(typeof(DrawerAttribute), true)[0];
|
|
NativePropertyDrawer drawer = NativePropertyDrawerDatabase.GetDrawerForAttribute(drawerAttribute.GetType());
|
|
if (drawer != null)
|
|
{
|
|
drawer.DrawNativeProperty(this.target, property);
|
|
}
|
|
}
|
|
|
|
// Draw methods
|
|
foreach (var method in this.methods)
|
|
{
|
|
DrawerAttribute drawerAttribute = (DrawerAttribute)method.GetCustomAttributes(typeof(DrawerAttribute), true)[0];
|
|
MethodDrawer methodDrawer = MethodDrawerDatabase.GetDrawerForAttribute(drawerAttribute.GetType());
|
|
if (methodDrawer != null)
|
|
{
|
|
methodDrawer.DrawMethod(this.target, method);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ValidateAndDrawFields(IEnumerable<FieldInfo> fields)
|
|
{
|
|
foreach (var field in fields)
|
|
{
|
|
this.ValidateAndDrawField(field);
|
|
}
|
|
}
|
|
|
|
private void ValidateAndDrawField(FieldInfo field)
|
|
{
|
|
if (!ShouldDrawField(field))
|
|
{
|
|
return;
|
|
}
|
|
|
|
this.ValidateField(field);
|
|
this.ApplyFieldMeta(field);
|
|
this.DrawField(field);
|
|
}
|
|
|
|
private void ValidateField(FieldInfo field)
|
|
{
|
|
ValidatorAttribute[] validatorAttributes = (ValidatorAttribute[])field.GetCustomAttributes(typeof(ValidatorAttribute), true);
|
|
|
|
foreach (var attribute in validatorAttributes)
|
|
{
|
|
PropertyValidator validator = PropertyValidatorDatabase.GetValidatorForAttribute(attribute.GetType());
|
|
if (validator != null)
|
|
{
|
|
validator.ValidateProperty(this.serializedPropertiesByFieldName[field.Name]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool ShouldDrawField(FieldInfo field)
|
|
{
|
|
// Check if the field has draw conditions
|
|
PropertyDrawCondition drawCondition = this.GetPropertyDrawConditionForField(field);
|
|
if (drawCondition != null)
|
|
{
|
|
bool canDrawProperty = drawCondition.CanDrawProperty(this.serializedPropertiesByFieldName[field.Name]);
|
|
if (!canDrawProperty)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Check if the field has HideInInspectorAttribute
|
|
HideInInspector[] hideInInspectorAttributes = (HideInInspector[])field.GetCustomAttributes(typeof(HideInInspector), true);
|
|
if (hideInInspectorAttributes.Length > 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private void DrawField(FieldInfo field)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
PropertyDrawer drawer = this.GetPropertyDrawerForField(field);
|
|
if (drawer != null)
|
|
{
|
|
drawer.DrawProperty(this.serializedPropertiesByFieldName[field.Name]);
|
|
}
|
|
else
|
|
{
|
|
EditorDrawUtility.DrawPropertyField(this.serializedPropertiesByFieldName[field.Name]);
|
|
}
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
OnValueChangedAttribute[] onValueChangedAttributes = (OnValueChangedAttribute[])field.GetCustomAttributes(typeof(OnValueChangedAttribute), true);
|
|
foreach (var onValueChangedAttribute in onValueChangedAttributes)
|
|
{
|
|
PropertyMeta meta = PropertyMetaDatabase.GetMetaForAttribute(onValueChangedAttribute.GetType());
|
|
if (meta != null)
|
|
{
|
|
meta.ApplyPropertyMeta(this.serializedPropertiesByFieldName[field.Name], onValueChangedAttribute);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplyFieldMeta(FieldInfo field)
|
|
{
|
|
// Apply custom meta attributes
|
|
MetaAttribute[] metaAttributes = field
|
|
.GetCustomAttributes(typeof(MetaAttribute), true)
|
|
.Where(attr => attr.GetType() != typeof(OnValueChangedAttribute))
|
|
.Select(obj => obj as MetaAttribute)
|
|
.ToArray();
|
|
|
|
Array.Sort(metaAttributes, (x, y) =>
|
|
{
|
|
return x.Order - y.Order;
|
|
});
|
|
|
|
foreach (var metaAttribute in metaAttributes)
|
|
{
|
|
PropertyMeta meta = PropertyMetaDatabase.GetMetaForAttribute(metaAttribute.GetType());
|
|
if (meta != null)
|
|
{
|
|
meta.ApplyPropertyMeta(this.serializedPropertiesByFieldName[field.Name], metaAttribute);
|
|
}
|
|
}
|
|
}
|
|
|
|
private PropertyDrawer GetPropertyDrawerForField(FieldInfo field)
|
|
{
|
|
DrawerAttribute[] drawerAttributes = (DrawerAttribute[])field.GetCustomAttributes(typeof(DrawerAttribute), true);
|
|
if (drawerAttributes.Length > 0)
|
|
{
|
|
PropertyDrawer drawer = PropertyDrawerDatabase.GetDrawerForAttribute(drawerAttributes[0].GetType());
|
|
return drawer;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private PropertyGrouper GetPropertyGrouperForField(FieldInfo field)
|
|
{
|
|
GroupAttribute[] groupAttributes = (GroupAttribute[])field.GetCustomAttributes(typeof(GroupAttribute), true);
|
|
if (groupAttributes.Length > 0)
|
|
{
|
|
PropertyGrouper grouper = PropertyGrouperDatabase.GetGrouperForAttribute(groupAttributes[0].GetType());
|
|
return grouper;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private PropertyDrawCondition GetPropertyDrawConditionForField(FieldInfo field)
|
|
{
|
|
DrawConditionAttribute[] drawConditionAttributes = (DrawConditionAttribute[])field.GetCustomAttributes(typeof(DrawConditionAttribute), true);
|
|
if (drawConditionAttributes.Length > 0)
|
|
{
|
|
PropertyDrawCondition drawCondition = PropertyDrawConditionDatabase.GetDrawConditionForAttribute(drawConditionAttributes[0].GetType());
|
|
return drawCondition;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|