Files
Convention-Unity/Convention/Editor/BasicEdior.cs

511 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Convention.Internal;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
namespace Convention
{
public class AbstractCustomEditor : Editor
{
protected int currentTab = 0;
protected IEnumerable<FieldInfo> ContentFields;
protected IEnumerable<MethodInfo> ContentMethods;
protected IEnumerable<FieldInfo> ResourcesFields;
protected IEnumerable<MethodInfo> ResourcesMethods;
protected IEnumerable<FieldInfo> SettingFields;
protected IEnumerable<MethodInfo> SettingMethods;
protected virtual string TopHeader => "CM Top Header";
protected void OnEnable()
{
Type _CurType = target.GetType();
HashSet<string> MemberNames = new();
List<FieldInfo> fields = new();
List<MethodInfo> methods = new();
fields.AddRange(from field in _CurType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
where MemberNames.Add(field.Name)
select field);
methods.AddRange(from method in _CurType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
where MemberNames.Add(method.Name)
select method);
while (_CurType != null && _CurType != typeof(UnityEngine.MonoBehaviour) && _CurType != typeof(object))
{
fields.AddRange(from field in _CurType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
where MemberNames.Add(field.Name)
select field);
methods.AddRange(from method in _CurType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
where MemberNames.Add(method.Name)
select method);
_CurType = _CurType.BaseType;
}
fields.RemoveAll((field) =>
{
bool NotContent = field.GetCustomAttributes(typeof(ContentAttribute), true).Length == 0;
bool NotResources = field.GetCustomAttributes(typeof(ResourcesAttribute), true).Length == 0;
bool NotSetting = field.GetCustomAttributes(typeof(SettingAttribute), true).Length == 0;
return field.IsPrivate && NotContent && NotResources && NotSetting;
});
static bool ContentCheck(FieldInfo field)
{
bool isContent = field.GetCustomAttributes(typeof(ContentAttribute), true).Length != 0;
bool isResources = field.GetCustomAttributes(typeof(ResourcesAttribute), true).Length != 0;
bool isSetting = field.GetCustomAttributes(typeof(SettingAttribute), true).Length != 0;
return
isContent ||
(!isResources && !isSetting && !field.FieldType.IsSubclassOf(typeof(UnityEngine.Object)));
}
ContentFields = from field in fields
where ContentCheck(field)
select field;
ContentMethods = from method in methods
where method.GetCustomAttributes(typeof(ContentAttribute), true).Length != 0
//where method.GetParameters().Length == 0
select method;
static bool ResourcesCheck(FieldInfo field)
{
bool isContent = field.GetCustomAttributes(typeof(ContentAttribute), true).Length != 0;
bool isResources = field.GetCustomAttributes(typeof(ResourcesAttribute), true).Length != 0;
bool isSetting = field.GetCustomAttributes(typeof(SettingAttribute), true).Length != 0;
return
isResources ||
(!isContent && !isSetting && field.FieldType.IsSubclassOf(typeof(UnityEngine.Object)));
}
ResourcesFields = from field in fields
where ResourcesCheck(field)
select field;
ResourcesMethods = from method in methods
where method.GetCustomAttributes(typeof(ResourcesAttribute), true).Length != 0
//where method.GetParameters().Length == 0
select method;
static bool SettingCheck(FieldInfo field)
{
return field.GetCustomAttributes(typeof(SettingAttribute), true).Length != 0;
}
SettingFields = from field in fields
where SettingCheck(field)
select field;
SettingMethods = from method in methods
where method.GetCustomAttributes(typeof(SettingAttribute), true).Length != 0
//where method.GetParameters().Length == 0
select method;
}
public void OnNotChangeGUI(UnityAction action)
{
GUI.enabled = false;
action();
GUI.enabled = true;
}
public void HelpBox(string message, MessageType messageType)
{
EditorGUILayout.HelpBox(message, messageType);
}
public void HorizontalBlock(UnityAction action)
{
GUILayout.BeginHorizontal();
action();
GUILayout.EndHorizontal();
}
public void HorizontalBlockWithBox(UnityAction action)
{
GUILayout.BeginHorizontal(EditorStyles.helpBox);
action();
GUILayout.EndHorizontal();
}
public void VerticalBlockWithBox(UnityAction action)
{
GUILayout.BeginVertical(EditorStyles.helpBox);
action();
GUILayout.EndVertical();
}
protected void IgnoreField(FieldInfo field)
{
this.OnNotChangeGUI(() => Field(field, false));
}
protected virtual void PlayModeField(FieldInfo field)
{
HelpBox($"{field.Name}<{field.FieldType}> only play mode", MessageType.Info);
}
protected virtual void Field(FieldInfo field, bool isCheckIgnore = true)
{
bool HasOnlyPlayMode = field.GetCustomAttributes(typeof(OnlyPlayModeAttribute), true).Length != 0;
bool HasWhen = field.GetCustomAttributes(typeof(WhenAttribute), true).Length != 0;
bool HasOnlyNotNullMode = field.GetCustomAttributes(typeof(OnlyNotNullModeAttribute), true).Length != 0;
bool HasHopeNotNullMode = field.GetCustomAttributes(typeof(HopeNotNullAttribute), true).Length != 0;
bool HasIgnore = field.GetCustomAttributes(typeof(IgnoreAttribute), true).Length != 0;
bool HasSerializeField = field.GetCustomAttributes(typeof(SerializeField), true).Length != 0;
bool HasOpt = field.GetCustomAttributes(typeof(OptAttribute), true).Length != 0;
bool HasArgPackage = field.GetCustomAttributes(typeof(ArgPackageAttribute), true).Length != 0;
object currentFieldValue = field.GetValue(target);
if (HasOnlyPlayMode && Application.isPlaying == false)
{
OnlyDisplayOnPlayMode(field, isCheckIgnore);
return;
}
else if (HasWhen)
{
foreach (var attr in field.GetCustomAttributes<WhenAttribute>(true))
{
if (attr.Check(target) == false)
return;
}
}
bool IsTypenCheckFailed = false;
foreach (var attr in field.GetCustomAttributes<TypeCheckAttribute>(true))
{
if (attr.Check(currentFieldValue) == false)
{
GUILayout.BeginVertical(EditorStyles.helpBox);
HelpBox(attr.description.Replace("${type}", currentFieldValue == null
? "null"
: currentFieldValue.GetType().Name), MessageType.Error);
IsTypenCheckFailed = true;
break;
}
}
if (HasOnlyNotNullMode || HasHopeNotNullMode)
DisplayOnlyNotNull(field, isCheckIgnore);
else if (isCheckIgnore && (HasIgnore || (field.IsPublic == false && !HasSerializeField)))
IgnoreField(field);
else
DisplayDefaultField(field, isCheckIgnore);
if (IsTypenCheckFailed)
{
GUILayout.EndVertical();
}
void OnlyDisplayOnPlayMode(FieldInfo field, bool isCheckIgnore)
{
PlayModeField(field);
}
void DisplayBoolValue(FieldInfo field, bool isCheckIgnore)
{
if (isCheckIgnore)
this.Toggle(field.Name);
else
field.SetValue(target, this.Toggle((bool)field.GetValue(target), field.Name));
}
void DisplayDefaultField(FieldInfo field, bool isCheckIgnore)
{
if (field.FieldType == typeof(bool))
DisplayBoolValue(field, isCheckIgnore);
else
{
var p = serializedObject.FindProperty(field.Name);
//var tfattr = field.GetCustomAttribute<ToolFile.FileAttribute>(true);
//if (tfattr != null)
// GUILayout.BeginVertical(EditorStyles.helpBox);
if (p == null)
{
var parser = field.FieldType.GetMethod("Parse", new Type[] { typeof(string) });
if (parser != null)
{
GUILayout.BeginHorizontal();
GUILayout.Label(field.Name);
EditorGUI.BeginChangeCheck();
string str = GUILayout.TextField(field.GetValue(target).ToString());
if (EditorGUI.EndChangeCheck())
{
field.SetValue(target, parser.Invoke(null, new object[] { str }));
}
GUILayout.EndHorizontal();
}
else if (field.FieldType.FullName.StartsWith("System.") == false && isCheckIgnore)
HelpBox($"{field.Name}<{field.FieldType}> cannt draw", MessageType.Warning);
}
else
{
EditorGUILayout.PropertyField(p);
//if (tfattr != null && field.FieldType == typeof(string))
//{
// if (GUILayout.Button("Browse"))
// p.stringValue = ToolFile.BrowseFile("*");
//}
}
//if (tfattr != null)
// GUILayout.EndHorizontal();
}
}
void DisplayOnlyNotNull(FieldInfo field, bool isCheckIgnore)
{
bool isWarning = false;
bool isError = false;
bool isNotDisplay = true;
foreach (var attr in field.GetCustomAttributes<OnlyNotNullModeAttribute>(true))
{
if (attr.IsSelf())
{
isNotDisplay = false;
if (!attr.Check(field.GetValue(target)))
{
isError = true;
break;
}
}
else
{
isNotDisplay = isNotDisplay && !attr.Check(target);
}
}
if (isError == false)
{
foreach (var attr in field.GetCustomAttributes<HopeNotNullAttribute>(true))
{
isNotDisplay = false;
if (!attr.Check(field.GetValue(target)))
{
isWarning = true;
break;
}
}
}
if (isNotDisplay)
return;
else if (isError)
VerticalBlockWithBox(() =>
{
HelpBox($"{field.Name} is null", MessageType.Error);
DisplayDefaultField(field, isCheckIgnore);
});
else if (isWarning)
VerticalBlockWithBox(() =>
{
HelpBox($"{field.Name} is null", MessageType.Warning);
DisplayDefaultField(field, isCheckIgnore);
});
else
DisplayDefaultField(field, isCheckIgnore);
}
}
protected virtual void Method(MethodInfo method)
{
if (method.GetCustomAttributes(typeof(OnlyPlayModeAttribute), true).Length == 0 || Application.isPlaying)
if (GUILayout.Button(method.Name))
method.Invoke(target, new object[0]);
}
public virtual void OnOriginGUI()
{
DrawDefaultInspector();
}
public virtual void OnContentGUI()
{
foreach (var method in ContentMethods)
{
if (method.IsStatic)
{
Method(method);
}
}
foreach (var field in ContentFields)
{
Field(field);
}
foreach (var method in ContentMethods)
{
if (!method.IsStatic)
{
Method(method);
}
}
}
public virtual void OnResourcesGUI()
{
foreach (var method in ResourcesMethods)
{
if (method.IsStatic)
{
Method(method);
}
}
foreach (var field in ResourcesFields)
{
Field(field);
}
foreach (var method in ResourcesMethods)
{
if (!method.IsStatic)
{
Method(method);
}
}
}
public virtual void OnSettingsGUI()
{
foreach (var method in SettingMethods)
{
if (method.IsStatic)
{
Method(method);
}
}
foreach (var field in SettingFields)
{
Field(field);
}
foreach (var method in SettingMethods)
{
if (!method.IsStatic)
{
Method(method);
}
}
}
protected GUISkin customSkin;
protected Color defaultColor;
public void Toggle(SerializedProperty enableTrigger, string label)
{
GUILayout.BeginHorizontal(EditorStyles.helpBox);
enableTrigger.boolValue = GUILayout.Toggle(enableTrigger.boolValue, new GUIContent(label), customSkin.FindStyle("Toggle"));
enableTrigger.boolValue = GUILayout.Toggle(enableTrigger.boolValue, new GUIContent(""), customSkin.FindStyle("Toggle Helper"));
GUILayout.EndHorizontal();
}
public void Toggle(string name)
{
var enableTrigger = serializedObject.FindProperty(name);
if (name.StartsWith("m_"))
{
name = name[2..];
}
Toggle(enableTrigger, name);
}
public bool Toggle(bool value, string label)
{
bool result;
GUILayout.BeginHorizontal(EditorStyles.helpBox);
result = GUILayout.Toggle(value, new GUIContent(label), customSkin.FindStyle("Toggle"));
result = GUILayout.Toggle(value, new GUIContent(""), customSkin.FindStyle("Toggle Helper"));
GUILayout.EndHorizontal();
return result;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
defaultColor = GUI.color;
if (EditorGUIUtility.isProSkin == true)
customSkin = (GUISkin)Resources.Load("Editor\\ADUI Skin Dark");
else
customSkin = (GUISkin)Resources.Load("Editor\\ADUI Skin Light");
GUILayout.BeginHorizontal();
GUI.backgroundColor = defaultColor;
GUILayout.Box(new GUIContent(""), customSkin.FindStyle(TopHeader));
GUILayout.EndHorizontal();
GUILayout.Space(-42);
bool ContentNotEmpty = ContentFields.Count() != 0;
bool ResourcesNotEmpty = ResourcesFields.Count() != 0;
bool SettingNotEmpty = SettingFields.Count() != 0;
List<GUIContent> toolbarTabs = new();
if ((ContentNotEmpty ? 1 : 0) + (ResourcesNotEmpty ? 1 : 0) + (SettingNotEmpty ? 1 : 0) != 1)
toolbarTabs.Add(new GUIContent("Origin"));
if (ContentNotEmpty)
toolbarTabs.Add(new GUIContent("Content"));
if (ResourcesFields.Count() != 0)
toolbarTabs.Add(new GUIContent("Resources"));
if (SettingFields.Count() != 0)
toolbarTabs.Add(new GUIContent("Settings"));
GUILayout.BeginHorizontal();
GUILayout.Space(17);
currentTab = GUILayout.Toolbar(currentTab, toolbarTabs.ToArray(), customSkin.FindStyle("Tab Indicator"));
GUILayout.EndHorizontal();
GUILayout.Space(-40);
GUILayout.BeginHorizontal();
GUILayout.Space(17);
if ((ContentNotEmpty ? 1 : 0) + (ResourcesNotEmpty ? 1 : 0) + (SettingNotEmpty ? 1 : 0) != 1)
GUILayout.Button(new GUIContent("Origin", "Origin"), customSkin.FindStyle("Tab Data"));
if (ContentFields.Count() != 0)
GUILayout.Button(new GUIContent("Content", "Content"), customSkin.FindStyle("Tab Content"));
if (ResourcesFields.Count() != 0)
GUILayout.Button(new GUIContent("Resources", "Resources"), customSkin.FindStyle("Tab Resources"));
if (SettingFields.Count() != 0)
GUILayout.Button(new GUIContent("Settings", "Settings"), customSkin.FindStyle("Tab Settings"));
GUILayout.EndHorizontal();
string currentTabStr = toolbarTabs[currentTab].text;
if (currentTabStr == "Content")
{
HorizontalBlockWithBox(() => HelpBox("Content", MessageType.Info));
OnContentGUI();
}
else if (currentTabStr == "Resources")
{
HorizontalBlockWithBox(() => HelpBox("Resources", MessageType.Info));
OnResourcesGUI();
}
else if (currentTabStr == "Settings")
{
HorizontalBlockWithBox(() => HelpBox("Settings", MessageType.Info));
OnSettingsGUI();
}
else
{
HorizontalBlockWithBox(() => HelpBox("Origin", MessageType.Info));
OnOriginGUI();
}
serializedObject.ApplyModifiedProperties();
}
public void MakeUpNumericManager(string thatNumericManagerName)
{
SerializedProperty property = serializedObject.FindProperty(thatNumericManagerName);
VerticalBlockWithBox(() =>
{
if (property.stringValue.StartsWith("Default"))
HelpBox("Numeric Manager Is Idle", MessageType.Info);
else
HelpBox("You Can Name It Start With Default To Make It Idle", MessageType.Info);
EditorGUILayout.PropertyField(property);
});
}
}
public class AnyBehaviourEditor : AbstractCustomEditor { }
public abstract class EditorWindow : UnityEditor.EditorWindow
{
/*
[MenuItem("MyWindow/Window")]
static void window()
{
Mybianyi mybianyi = GetWindow<Mybianyi>();
mybianyi.Show();
}
private void OnGUI()
*/
}
}