Gameplay Ingredients是一组用于 Unity 游戏的运行时和编辑器工具:一组脚本的集合,可在制作游戏和原型时简化简单的任务。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

320 行
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)
{
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 void DrawField(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;
}
}
// Check if the field has HideInInspectorAttribute
HideInInspector[] hideInInspectorAttributes = (HideInInspector[])field.GetCustomAttributes(typeof(HideInInspector), true);
if (hideInInspectorAttributes.Length > 0)
{
return;
}
// Draw the 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;
}
}
}
}