123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- using XGame.Framework.ObjectCollection;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text.RegularExpressions;
- using UnityEditor;
- using UnityEditorInternal;
- using UnityEngine;
- using System.Reflection;
- namespace XGame.Editor.ObjectCollection
- {
- [CustomPropertyDrawer(typeof(ObjectCollector))]
- public partial class ObjectCollectorEditor : PropertyDrawer
- {
- private static BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
- private ReorderableList collectList;
- private ReorderableList DrawsearchList;
- private List<string> searchList = new List<string>();
- private SerializedProperty keys;
- private SerializedProperty values;
- private SerializedProperty bindTypes;
- private ObjectCollector objectCollector;
- //搜索框
- private string m_InputSearchText;
- private GUIStyle TextFieldRoundEdge;
- private GUIStyle TextFieldRoundEdgeCancelButton;
- private GUIStyle TextFieldRoundEdgeCancelButtonEmpty;
- private GUIStyle TransparentTextField;
- private void SetData(SerializedProperty property)
- {
- var ob = property.serializedObject.targetObject;
- var selfFields = ob.GetType().GetFields(flags);
- var baseFields = ob.GetType().BaseType.GetFields(flags);
- var fields = selfFields.Concat(baseFields).ToArray();
- foreach (var field in fields)
- {
- if (field.FieldType == typeof(ObjectCollector))
- {
- objectCollector = field.GetValue(ob) as ObjectCollector;
- break;
- }
- }
- }
- private void OnInit(SerializedProperty property)
- {
- SetData(property);
- collectList.headerHeight = 0;
- DrawsearchList.headerHeight = 0;
- // 绘制
- collectList.drawElementCallback = (Rect rect, int index, bool selected, bool focused) =>
- {
- var key = keys.GetArrayElementAtIndex(index);
- var value = values.GetArrayElementAtIndex(index);
- var bindType = bindTypes.GetArrayElementAtIndex(index);
- EditorGUILayout.BeginHorizontal();
- GUILayout.Space(10);
- // 3等分,中间间隔10像素
- var copyRect = new Rect(rect.x, rect.y + 2, (rect.width - 20) / 3, EditorGUIUtility.singleLineHeight);
- if (GUI.Button(copyRect, "", "HelpBox"))
- {
- TextEditor textEditor = new TextEditor();
- textEditor.text = key.stringValue;
- textEditor.OnFocus();
- textEditor.Copy();
- Debug.Log($"序列化器Key复制成功!Key:{key.stringValue}");
- };
- EditorGUI.BeginDisabledGroup(true);
- //key
- var keyRect = copyRect;
- EditorGUI.TextField(keyRect, key.stringValue);
- EditorGUI.EndDisabledGroup();
- //value
- var valueRect = keyRect;
- valueRect.x += keyRect.width + 10;
- Type type = objectCollector.collectorType;
- var tmp = value.objectReferenceValue;
- value.objectReferenceValue = EditorGUI.ObjectField(valueRect, value.objectReferenceValue, type, true);
- if (tmp != value.objectReferenceValue)
- {
- if (value.objectReferenceValue != null)
- {
- if (CheckForSameValue(value.objectReferenceValue, index))
- {
- value.objectReferenceValue = null;
- key.stringValue = "";
- bindType.stringValue = "";
- }
- else
- {
- string name = value.objectReferenceValue.name.Replace(" ", "");
- if (!CheckForReName(name, index, value.objectReferenceValue))
- {
- key.stringValue = name;
- bindType.stringValue = GetTypeName(value.objectReferenceValue);
- }
- else
- {
- value.objectReferenceValue = null;
- key.stringValue = "";
- bindType.stringValue = "";
- }
- }
- }
- else
- {
- key.stringValue = string.Empty;
- bindType.stringValue = string.Empty;
- }
- }
- else
- {
- if (value.objectReferenceValue != null)
- {
- string name = value.objectReferenceValue.name.Replace(" ", "");
- key.stringValue = name;
- }
- else
- {
- key.stringValue = string.Empty;
- bindType.stringValue = string.Empty;
- }
- }
- //type
- if (value.objectReferenceValue != null)
- {
- var bindTypeVal = bindType.stringValue;
- var typeRect = valueRect;
- typeRect.x += valueRect.width + 10;
- var options = GetObjectTypes(value.objectReferenceValue);
- var selectIdx = 0;
- if (!string.IsNullOrEmpty(bindTypeVal))
- {
- selectIdx = Array.FindIndex(options, (a) => bindTypeVal.Equals(a, StringComparison.OrdinalIgnoreCase));
- if (selectIdx < 0)
- selectIdx = 0;
- }
- selectIdx = EditorGUI.Popup(typeRect, selectIdx, options);
- bindType.stringValue = options[selectIdx];
- }
- EditorGUILayout.EndHorizontal();
- };
- collectList.onAddCallback = list =>
- {
- values.arraySize++;
- var size = values.arraySize;
- keys.arraySize = size;
- bindTypes.arraySize = size;
- values.GetArrayElementAtIndex(size - 1).objectReferenceValue = null;
- keys.GetArrayElementAtIndex(size - 1).stringValue = "";
- bindTypes.GetArrayElementAtIndex(size - 1).stringValue = "";
- };
- collectList.onRemoveCallback = list =>
- {
- var index = list.index;
- if (list.index == -1)
- {
- index = values.arraySize - 1;
- }
- values.GetArrayElementAtIndex(index).objectReferenceValue = null;
- keys.GetArrayElementAtIndex(index).stringValue = null;
- bindTypes.GetArrayElementAtIndex(index).stringValue = null;
- values.DeleteArrayElementAtIndex(index);
- keys.DeleteArrayElementAtIndex(index);
- bindTypes.DeleteArrayElementAtIndex(index);
- };
- DrawsearchList.drawElementCallback = (Rect rect, int index, bool selected, bool focused) =>
- {
- var key = searchList[index];
- SerializedProperty value = null;
- SerializedProperty bindType = null;
- for (int i = 0; i < keys.arraySize; i++)
- {
- if (keys.GetArrayElementAtIndex(i).stringValue == key)
- {
- value = values.GetArrayElementAtIndex(i);
- bindType = bindTypes.GetArrayElementAtIndex(i);
- break;
- }
- }
- EditorGUILayout.BeginHorizontal();
- GUILayout.Space(10);
- //key
- var keyRect = new Rect(rect.x, rect.y + 2, (rect.width - 20) / 3, EditorGUIUtility.singleLineHeight);
- EditorGUI.BeginDisabledGroup(true);
- EditorGUI.TextField(keyRect, key);
- //value
- var valueRect = keyRect;
- valueRect.x += keyRect.width + 10;
- Type type = objectCollector.collectorType;
- value.objectReferenceValue = EditorGUI.ObjectField(valueRect, value.objectReferenceValue, type, true);
- //type
- if (value.objectReferenceValue != null)
- {
- var typeRect = valueRect;
- typeRect.x += valueRect.width + 10;
- EditorGUI.TextField(typeRect, bindType.stringValue);
- }
- EditorGUI.EndDisabledGroup();
- EditorGUILayout.EndHorizontal();
- };
- }
- private string[] GetObjectTypes(UnityEngine.Object obj)
- {
- var types = new List<string>();
- GameObject go = null;
- if (obj is Component component)
- {
- go = component.gameObject;
- }
- else if (obj is GameObject tmpGo)
- {
- go = tmpGo;
- }
- if (go != null)
- {
- types.Add(typeof(GameObject).Name);
- types.Add(typeof(Transform).Name);
- var components = go.GetComponents<Component>();
- foreach (var item in components)
- {
- types.Add(GetTypeName(item));
- }
- }
- else
- {
- types.Add(GetTypeName(obj));
- }
- return types.ToArray();
- }
- const string UnityNamespace = "UnityEngine";
- private string GetTypeName(object obj)
- {
- var type = obj.GetType();
- if (type.Namespace == UnityNamespace)
- {
- return type.Name;
- }
- return type.FullName;
- }
- private bool CheckForSameValue(UnityEngine.Object value, int index)
- {
- for (int i = 0; i < values.arraySize; i++)
- {
- if (index == i) continue;
- var compareValue = values.GetArrayElementAtIndex(i).objectReferenceValue;
- if (compareValue == null) continue;
- if (value.GetInstanceID() == compareValue.GetInstanceID())
- {
- EditorUtility.DisplayDialog("Warning",
- $"已经添加过该{objectCollector.collectorType.Name}啦!",
- "确定");
- return true;
- }
- }
- return false;
- }
- private bool CheckForReName(string name, int index, UnityEngine.Object ob)
- {
- for (int i = 0; i < values.arraySize; i++)
- {
- if (i == index) continue;
- var value = values.GetArrayElementAtIndex(i);
- if (value.objectReferenceValue == null) continue;
- string compareName = value.objectReferenceValue.name.Replace(" ", "");
- if (!string.IsNullOrEmpty(compareName) && name == compareName)
- {
- EditorUtility.DisplayDialog("Warning",
- $"该{objectCollector.collectorType.Name}名称{name}重名啦!请修改GameObject名称。",
- "确定");
- EditorGUIUtility.PingObject(ob);
- return true;
- }
- }
- return false;
- }
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- {
- return 0;
- }
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- keys = property.FindPropertyRelative("keys");
- values = property.FindPropertyRelative("values");
- bindTypes = property.FindPropertyRelative("bindTypes");
- GUILayout.BeginVertical("HelpBox");
- DrawInputTextField();
- EditorGUILayout.Space();
- if (collectList == null)
- {
- collectList = new ReorderableList(property.serializedObject, values, true, false, true, true);
- DrawsearchList = new ReorderableList(searchList, typeof(string), true, false, false, false);
- OnInit(property);
- }
- if (Application.isPlaying) EditorGUI.BeginDisabledGroup(true);
- if (string.IsNullOrEmpty(m_InputSearchText))
- {
- GUI.contentColor = Color.white;
- var dragArea = GUILayoutUtility.GetRect(0f, 45f);
- GUI.color = Color.grey;
- UnityEngine.Object ob = DragAreaGUI.ObjectField(dragArea, objectCollector.collectorType, objectCollector.blackTypes);
- if (ob != null)
- AddObjectToList(ob);
- GUI.color = Color.white;
- GUILayout.Space(8);
- collectList.DoLayoutList();
- }
- else
- {
- GetSearchList();
- DrawsearchList.DoLayoutList();
- }
- GUILayout.EndVertical();
- if (Application.isPlaying) EditorGUI.EndDisabledGroup();
- }
- private void AddObjectToList(UnityEngine.Object ob)
- {
- if (CheckForSameValue(ob, -1)) return;
- string name = ob.name.Replace(" ", "");
- if (CheckForReName(name, -1, ob)) return;
- values.arraySize++;
- var size = values.arraySize;
- keys.arraySize = size;
- bindTypes.arraySize = size;
- values.GetArrayElementAtIndex(size - 1).objectReferenceValue = ob;
- keys.GetArrayElementAtIndex(size - 1).stringValue = ob.name;
- bindTypes.GetArrayElementAtIndex(size - 1).stringValue = GetTypeName(ob);
- }
- private void GetSearchList()
- {
- searchList.Clear();
- for (int index = 0; index < keys.arraySize; index++)
- {
- var key = keys.GetArrayElementAtIndex(index);
- if (!string.IsNullOrEmpty(m_InputSearchText))
- {
- var inputStr = m_InputSearchText.ToLower();
- var compareStr = key.stringValue.ToLower();
- Regex r = new Regex(inputStr);
- Match m = r.Match(compareStr);
- if (m.Success)
- {
- searchList.Add(key.stringValue);
- }
- }
- }
- }
- private void DrawInputTextField()
- {
- if (TextFieldRoundEdge == null)
- {
- TextFieldRoundEdge = new GUIStyle("SearchTextField");
- TextFieldRoundEdgeCancelButton = new GUIStyle("SearchCancelButton");
- TextFieldRoundEdgeCancelButtonEmpty = new GUIStyle("SearchCancelButtonEmpty");
- TransparentTextField = new GUIStyle(EditorStyles.whiteLabel);
- TransparentTextField.normal.textColor = EditorStyles.textField.normal.textColor;
- }
- Rect position = EditorGUILayout.GetControlRect();
- GUIStyle textFieldRoundEdge = TextFieldRoundEdge;
- GUIStyle transparentTextField = TransparentTextField;
- GUIStyle gUIStyle = (m_InputSearchText != "") ? TextFieldRoundEdgeCancelButton : TextFieldRoundEdgeCancelButtonEmpty;
- position.width -= gUIStyle.fixedWidth;
- if (Event.current.type == EventType.Repaint)
- {
- GUI.contentColor = (EditorGUIUtility.isProSkin ? Color.white : Color.black);
- if (string.IsNullOrEmpty(m_InputSearchText))
- {
- textFieldRoundEdge.Draw(position, new GUIContent("输入查询,可模糊匹配"), 0);
- }
- else
- {
- textFieldRoundEdge.Draw(position, new GUIContent(""), 0);
- }
- GUI.contentColor = Color.white;
- }
- Rect rect = position;
- float num = textFieldRoundEdge.CalcSize(new GUIContent("")).x - 2f;
- rect.width -= num;
- rect.x += num;
- rect.y += 1f;
- m_InputSearchText = EditorGUI.TextField(rect, m_InputSearchText, transparentTextField);
- position.x += position.width;
- position.width = gUIStyle.fixedWidth;
- position.height = gUIStyle.fixedHeight;
- if (GUI.Button(position, GUIContent.none, gUIStyle) && m_InputSearchText != "")
- {
- m_InputSearchText = "";
- GUI.changed = true;
- GUIUtility.keyboardControl = 0;
- }
- }
- }
- }
|