public SharedVariablePresetListDrawer(SerializedObject serializedObject, SerializedProperty presetVariables, ISharedVariableHandler variableHandler, Func <int, Type> elementTypeGetter) { float lineHeight = EditorGUIUtility.singleLineHeight; float lineHeightSpace = lineHeight + EditorGUIUtility.standardVerticalSpacing; presetVariableList = new ReorderableList(serializedObject, presetVariables, true, true, true, true) { drawElementCallback = (rect, index, isFocused, isActive) => { serializedObject.UpdateIfRequiredOrScript(); EditorGUI.BeginChangeCheck(); SerializedProperty variable = presetVariables.GetArrayElementAtIndex(index); Type type = elementTypeGetter(index); SerializedProperty name = variable.FindPropertyRelative("_name"); List <SharedVariable> variables = variableHandler.GetVariables(type); EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), variable, new GUIContent(string.IsNullOrEmpty(name.stringValue) ? $"({type.Name})" : name.stringValue)); Rect valueRect = new Rect(rect.x, rect.y + lineHeightSpace, rect.width - 46, lineHeight); if (variable.isExpanded) { //这里的isShared用来标识变量名的填写方式,不作正常用途 SerializedProperty isShared = variable.FindPropertyRelative("isShared"); int typeIndex = isShared.boolValue ? 1 : 0; typeIndex = EditorGUI.Popup(new Rect(rect.x + rect.width - 44, rect.y + lineHeightSpace, 44, lineHeight), typeIndex, varType); switch (typeIndex) { case 0: isShared.boolValue = false; break; case 1: isShared.boolValue = true; break; } if (typeIndex == 1) { string[] varNames = variables.Select(x => x.name).ToArray(); bool noNames = varNames.Length < 1; int nameIndex = Array.IndexOf(varNames, name.stringValue); if (noNames) { varNames = varNames.Prepend("未选择").ToArray(); } if (nameIndex < 0) { nameIndex = 0; } nameIndex = EditorGUI.Popup(valueRect, "关联变量名称", nameIndex, varNames); string nameStr = name.stringValue; if (!noNames && nameIndex >= 0 && nameIndex < variables.Count) { nameStr = varNames[nameIndex]; } name.stringValue = nameStr; } else { EditorGUI.PropertyField(valueRect, name, new GUIContent("关联变量名称")); } SerializedProperty value = variable.FindPropertyRelative("value"); EditorGUI.PropertyField(new Rect(rect.x, rect.y + lineHeightSpace * 2, rect.width, EditorGUI.GetPropertyHeight(value, true) - lineHeight), value, new GUIContent("预设值"), true); } if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } }, elementHeightCallback = (index) => { if (index >= presetVariables.arraySize) { return(0); } SerializedProperty variable = presetVariables.GetArrayElementAtIndex(index); if (variable.isExpanded) { return(EditorGUI.GetPropertyHeight(presetVariables.GetArrayElementAtIndex(index), true)); } else { return(lineHeightSpace); } }, onAddDropdownCallback = (rect, list) => { GenericMenu menu = new GenericMenu(); foreach (var type in TypeCache.GetTypesDerivedFrom <SharedVariable>()) { if (!type.IsGenericType) { menu.AddItem(new GUIContent($"自定义/{type.Name}"), false, () => { InsertNewVariable(type, false); }); } } if (ZetanUtility.Editor.TryGetValue(presetVariables, out var value)) { List <SharedVariable> variables = value as List <SharedVariable>; foreach (var variable in variableHandler.Variables) { Type type = variable.GetType(); if (!variables.Exists(x => x.name == variable.name && x.GetType() == type)) { menu.AddItem(new GUIContent(variable.name), false, () => { InsertNewVariable(type, true, variable.name); }); } } } menu.DropDown(rect); }, onRemoveCallback = (list) => { serializedObject.UpdateIfRequiredOrScript(); SerializedProperty _name = presetVariables.GetArrayElementAtIndex(list.index).FindPropertyRelative("_name"); if (EditorUtility.DisplayDialog("删除变量", $"确定要删除预设 {_name.stringValue} 吗?", "确定", "取消")) { list.serializedProperty.DeleteArrayElementAtIndex(list.index); GUIUtility.ExitGUI(); } serializedObject.ApplyModifiedProperties(); }, onCanRemoveCallback = (list) => { return(list.IsSelected(list.index)); }, drawHeaderCallback = (rect) => { EditorGUI.LabelField(rect, $"变量预设列表"); }, serializedProperty = presetVariables }; void InsertNewVariable(Type type, bool select, string name = "") { if (ZetanUtility.Editor.TryGetValue(presetVariables, out var value) && value is List <SharedVariable> list) { SharedVariable variable = (SharedVariable)Activator.CreateInstance(type); variable.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(variable, name); variable.isShared = select; list.Add(variable); presetVariableList.Select(presetVariables.arraySize); } else { Debug.LogError("添加失败,请检查变量列表归属"); } } }
public SharedVariableListDrawer(SerializedObject serializedObject, SerializedProperty serializedVariables, bool isShared) { variableList = new ReorderableList(serializedObject, serializedVariables, true, true, true, true) { drawElementCallback = (rect, index, isFocused, isActive) => { if (serializedObject.targetObject) { serializedObject.UpdateIfRequiredOrScript(); EditorGUI.BeginChangeCheck(); SerializedProperty variable = serializedVariables.GetArrayElementAtIndex(index); EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), variable, true); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } if (ZetanUtility.Editor.TryGetValue(variable, out var value) && value is SharedVariable sv && sv.GetType().GetField("linkedVariables", ZetanUtility.CommonBindingFlags).GetValue(sv) is HashSet <SharedVariable> lvs) { foreach (var lv in lvs) { lv.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(lv, sv.name); } } } }, elementHeightCallback = (index) => { if (index >= serializedVariables.arraySize) { return(0); } return(EditorGUI.GetPropertyHeight(serializedVariables.GetArrayElementAtIndex(index), true)); }, onAddDropdownCallback = (rect, list) => { GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("新建类型"), false, CreateVariableScript); menu.AddSeparator(""); foreach (var type in TypeCache.GetTypesDerivedFrom <SharedVariable>()) { if (!type.IsGenericType) { menu.AddItem(new GUIContent(type.Name), false, () => { InsertNewVariable(type); }); } } menu.DropDown(rect); }, onRemoveCallback = (list) => { serializedObject.UpdateIfRequiredOrScript(); SerializedProperty _name = serializedVariables.GetArrayElementAtIndex(list.index).FindPropertyRelative("_name"); if (EditorUtility.DisplayDialog("删除变量", $"确定要删除变量 {_name.stringValue} 吗?", "确定", "取消")) { if (ZetanUtility.Editor.TryGetValue(serializedVariables.GetArrayElementAtIndex(list.index), out var value) && value is SharedVariable sv && sv.GetType().GetField("linkedVariables", ZetanUtility.CommonBindingFlags).GetValue(sv) is HashSet <SharedVariable> lvs) { foreach (var lv in lvs) { lv.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(lv, string.Empty); lv.GetType().GetField("linkedVariable", ZetanUtility.CommonBindingFlags).SetValue(lv, null); } } list.serializedProperty.DeleteArrayElementAtIndex(list.index); } serializedObject.ApplyModifiedProperties(); }, onCanRemoveCallback = (list) => { return(list.IsSelected(list.index)); }, drawHeaderCallback = (rect) => { string typeMsg = EditorUtility.IsPersistent(serializedObject.targetObject) ? "(不可引用场景对象)" : "(可引用场景对象)"; EditorGUI.LabelField(rect, $"{(isShared ? "共享变量列表" : "全局变量列表")}{typeMsg}"); }, serializedProperty = serializedVariables }; void InsertNewVariable(Type type) { if (ZetanUtility.Editor.TryGetValue(serializedVariables, out var value) && value is List <SharedVariable> list) { SharedVariable variable = (SharedVariable)Activator.CreateInstance(type); string newName = $"{char.ToLower(type.Name[0])}{type.Name.Substring(1)}_{serializedVariables.arraySize}"; variable.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(variable, newName); variable.isShared = isShared; variable.isGlobal = !isShared; list.Add(variable); variableList.Select(serializedVariables.arraySize); } else { Debug.LogError("添加失败,请检查变量列表归属"); } } }