BITKit/Src/Unity/Scripts/Utility/Editor/BITInspector.cs

313 lines
12 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using System.Reflection;
using System;
#if UNITY_EDITOR
using MackySoft.SerializeReferenceExtensions.Editor;
using UnityEditor;
using Editor = UnityEditor.Editor;
using UnityEditor.UIElements;
#endif
namespace BITKit
{
public class BITAttribute : System.Attribute
{
}
#if UNITY_EDITOR
[CanEditMultipleObjects]
[CustomEditor(typeof(MonoBehaviour),true)]
public class MonoBehaviorInspector : BITInspector<MonoBehaviour>
{
}
[CanEditMultipleObjects]
[CustomEditor(typeof(ScriptableObject),true)]
public class ScriptableObjectInspector : BITInspector<ScriptableObject>
{
}
[CustomPropertyDrawer(typeof(ReadOnlyAttribute),true)]
public class ReadOnlyDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var field = new PropertyField(property)
{
name = "PropertyField:" + property.propertyPath
};
Debug.Log("ReadOnlyAttribute");
field.pickingMode = PickingMode.Ignore;
field.SetEnabled(false);
field.style.opacity = 1;
var x = field.Q("unity-text-input");
var clearColor = new Color(0, 0, 0, 0);
x.style.backgroundColor = clearColor;
x.style.borderTopColor = clearColor;
x.style.borderBottomColor = clearColor;
x.style.borderLeftColor = clearColor;
x.style.borderRightColor = clearColor;
foreach (var visualElement in field.Children())
{
visualElement.pickingMode = PickingMode.Ignore;
}
field.Bind(property.serializedObject);
return field;
}
}
#endif
public class BITEditorUtils
{
public const string InspectorPath = "Assets/BITKit/Unity/UX/BITInspector.uss";
public const string StylePath = "Assets/BITKit/Unity/UX/Common/Common.uss";
#if UNITY_EDITOR
public static StyleSheet Style => AssetDatabase.LoadAssetAtPath<StyleSheet>(StylePath);
public static StyleSheet InspectorStyleSheet => AssetDatabase.LoadAssetAtPath<StyleSheet>(InspectorPath);
#endif
}
#if UNITY_EDITOR
public static class BITInspectorExtensions
{
public static T Get<T>(this SerializedProperty self)
{
var obj = self.serializedObject.targetObject;
var type = obj.GetType();
var field = type.GetField(self.propertyPath, ReflectionHelper.Flags);
if (field is null)
{
throw new NullReferenceException($"Field {self.propertyPath} is null");
}
return (T)field.GetValue(obj);
}
public static void FillDefaultInspector(VisualElement container, SerializedObject serializedObject, bool hideScript)
{
container.Clear();
if (serializedObject.targetObject is null)
{
var label = container.Create<Label>();
label.text = "Null";
return;
}
var property = serializedObject.GetIterator();
if (!property.NextVisible(true)) return; // Expand first child.
do
{
if (property.propertyPath == "m_Script" && hideScript)
{
continue;
}
var type = serializedObject.targetObject.GetType();
var fieldInfo = serializedObject.targetObject.GetType().GetField(property.propertyPath, ReflectionHelper.Flags);
// if (fieldInfo is not null && type == typeof(string) && Attribute.IsDefined(fieldInfo, typeof(ReadOnlyAttribute),true))
// {
// var attribute = fieldInfo.GetCustomAttribute<ReadOnlyAttribute>();
// var _container = container.Create<VisualElement>();
// _container.style.flexDirection = FlexDirection.Row;
//
// if (attribute.HideLabel is false)
// {
// _container.Create<Label>().text = $"{property.displayName}:";
// _container.Create<VisualElement>().style.flexGrow = 1;
// }
// _container.Create<Label>().bindingPath = property.propertyPath;
// }
// else
// if (PropertyDrawerCache.TryGetPropertyDrawer(type, out var drawer))
// {
// var ve = drawer.CreatePropertyGUI(property);
// container.Add(ve);
// }
// else
{
//var label = container.Create<Label>();
//label.text =$"propertyPath:{property.propertyPath} fieldInfo:{fieldInfo} type:{type} fieldInfo:{fieldInfo}";
var field = new PropertyField(property)
{
name = "PropertyField:" + property.propertyPath
};
if (fieldInfo is not null && Attribute.IsDefined(fieldInfo, typeof(ReadOnlyAttribute), true))
{
var attribute = fieldInfo.GetCustomAttribute<ReadOnlyAttribute>();
field.pickingMode = PickingMode.Ignore;
field.SetEnabled(false);
field.style.opacity = 1;
field.AddToClassList("readonly");
if (attribute.HideLabel)
{
field.AddToClassList("hide-label");
}
}
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
{
field.SetEnabled(false);
}
// if (fieldInfo?.FieldType == typeof(Texture2D) && fieldInfo.GetValue(serializedObject) is Texture2D texture && texture)
// {
// _container = container.Create<VisualElement>();
//
// var foldout = _container.Create<Foldout>();
// foldout.text = property.displayName;
//
// var icon = foldout.Create<VisualElement>();
// var slider = foldout.Create<Slider>();
//
// var width = 128;
// var m = texture.height /width;
//
// icon.style.width = width;
// icon.style.height = width*m;
// icon.style.backgroundImage = texture;
//
// field.style.flexGrow = 1;
//
// _container.style.backgroundColor =new StyleColor(new Color32(31,31,31,255)) ;
// _container.style.borderBottomLeftRadius = 5;
// _container.style.borderBottomRightRadius = 5;
// _container.style.borderTopLeftRadius = 5;
// _container.style.borderTopRightRadius = 5;
//
// slider.label = "Scale";
// slider.lowValue = 1;
// slider.highValue = 2;
// slider.RegisterValueChangedCallback(x =>
// {
// icon.style.width = width * x.newValue;
// icon.style.height = width*m * x.newValue;
// });
// }
container.Add(field);
}
// try
// {
// var header = type?.GetCustomAttribute<HeaderAttribute>();
// if (header != null)
// {
// var label = new Label(header.header);
// label.AddToClassList("subTitle");
// container.Add(label);
// }
// }
// catch (System.Exception e)
// {
// Debug.LogException(e);
// }
} while (property.NextVisible(false));
foreach (var method in serializedObject.targetObject.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
if (method.GetCustomAttribute<BITAttribute>() is null&& method.GetCustomAttribute<ContextMenu>() is null) continue;
if (method.GetParameters().Length is not 0) continue;
var button = new Button(() =>
{
method.Invoke(serializedObject.targetObject, null);
})
{
text = method.Name
};
container.Add(button);
}
}
}
public class BITInspector<T> : Editor
{
private const string ussName = "BITInspector";
public class VisualElementCreator
{
public static implicit operator VisualElement(VisualElementCreator self)
{
return self.root;
}
public VisualElement root;
public VE Create<VE>() where VE : VisualElement, new()
{
root = root ?? new();
var ve = new VE();
root.Add(ve);
return ve;
}
}
protected VisualElementCreator root = new();
protected T agent;
public override VisualElement CreateInspectorGUI()
{
try
{
FillDefaultInspector();
}
catch (Exception e)
{
Debug.LogException(e);
return base.CreateInspectorGUI();
}
return root;
}
protected Label CreateSubTitle(string value)
{
var label = root.Create<Label>();
label.text = value;
label.AddToClassList("subTitle");
return label;
}
void Awake()
{
root.root = new();
if (serializedObject.targetObject is T value)
{
agent = value;
}
}
protected virtual void OnAwake(){}
void OnEnable()
{
//StyleSheet css = Addressables.LoadAssetAsync<StyleSheet>(ussName).WaitForCompletion();
StyleSheet css = AssetDatabase.LoadAssetAtPath<StyleSheet>(BITEditorUtils.InspectorPath);
root.root.styleSheets.Add(css);
EditorApplication.update += OnUpdate;
OnEnabled();
}
protected virtual void OnEnabled(){}
void OnDisable()
{
EditorApplication.update -= OnUpdate;
OnDisabled();
}
protected virtual void OnDisabled(){}
protected virtual void OnUpdate()
{
}
protected void FillDefaultInspector()
{
root.root.Clear();
BITInspectorExtensions.FillDefaultInspector(root, serializedObject, true);
}
}
public class BITProperty : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
PropertyField propertyField = new(property);
return propertyField;
}
}
#endif
}