public static void DrawArrayField(ArrayFieldField field) { IList arr = (IList)field.GetValue(); field.editor_showContent = EditorGUILayout.Foldout(field.editor_showContent, field.GetName() + System.String.Format(": ({0} Elements)", arr != null ? arr.Count : 0)); if (field.editor_showContent) { EditorGUI.indentLevel = 1 + field.IndentLevel; if (arr != null) { if (field.IsReadOnly()) { if (arr.Count == 0) { EditorGUILayout.LabelField("The array is empty"); } for (int i = 0; i < arr.Count; ++i) { System.Object v = arr[i]; if (v != null) { EditorGUILayout.LabelField(string.Format("[{0}]", i), arr[i].ToString()); } else { EditorGUILayout.LabelField(string.Format("[{0}]", i), "(null)"); } } } else { System.Type type = field.GetFieldType(); if (field.CompactArrayLayout && type.IsPrimitive) { EditorGUILayout.BeginHorizontal(); if (field.Type == SerializedPropertyType.Boolean) { // for some reason, editor gui layout doesn't work here GUILayout.Space(EditorGUI.indentLevel * 24); } for (int i = 0; i < arr.Count; ++i) { arr[i] = DrawFieldElementCompact(field.Type, arr[i], type, field.ValueRange, field.Style); } EditorGUILayout.EndHorizontal(); } else { int indexToRemove = -1; for (int i = 0; i < arr.Count; ++i) { EditorGUILayout.BeginHorizontal(); if (field.CanModifyArrayLength) { if (GUILayout.Button("-", new GUILayoutOption[] { GUILayout.Width(24) })) { indexToRemove = i; } } arr[i] = DrawFieldElement(field.Type, string.Format("[{0}]", i), arr[i], type, field.ValueRange, field.Style); EditorGUILayout.EndHorizontal(); } if (indexToRemove != -1) { field.RemoveAt(indexToRemove); } EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Add", new GUILayoutOption[] { GUILayout.Width(80) })) { field.Add(System.Activator.CreateInstance(type)); } EditorGUILayout.EndHorizontal(); } } } } }
public static MemberField[] GetFieldsFromType(System.Type type, System.Object obj, int level = 0) { List <MemberField> fields = new List <MemberField>(); Dictionary <int, List <MethodField> > buttonFields = new Dictionary <int, List <MethodField> >(); BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; foreach (MemberInfo member in type.GetMembers(bindingFlags)) { ShowInEditor attribute = member.GetCustomAttributes(false).OfType <ShowInEditor>().FirstOrDefault(); if (level > 0 && attribute == null && (member is FieldInfo) && ((FieldInfo)member).IsPublic) { attribute = new ShowInEditor(); } if (attribute != null) { if (member is PropertyInfo) { PropertyInfo property = member as PropertyInfo; if (!property.CanRead) { continue; } // skip array property, to do (or is it neccessary?) if (property.PropertyType.IsArray) { continue; } if (attribute != null) { SerializedPropertyType serializedType = SerializedPropertyType.Integer; bool isKnownType = PropertyField.GetSerializedType(property, out serializedType); if (!isKnownType) { attribute.Flags = ShowInEditorFlags.ReadOnly; } fields.Add(new PropertyField(obj, attribute, serializedType, property)); } } else if (member is FieldInfo) { FieldInfo field = member as FieldInfo; System.Type realType = field.FieldType; if (realType.IsArray) { realType = field.FieldType.GetElementType(); } bool isObjectRef = !FieldField.IsReadOnly(attribute, field); isObjectRef &= (realType.IsClass || (realType.IsValueType && !realType.IsEnum && !realType.IsPrimitive)); if (isObjectRef) { ShowInEditor showInEditor = realType.GetCustomAttributes(false).OfType <ShowInEditor>().FirstOrDefault(); isObjectRef &= (showInEditor != null); } MemberField mf; if (isObjectRef) { MemberField[] memberFields = GetFieldsFromType(realType, null, level + 2); if (!field.FieldType.IsArray) { mf = (new ObjectReferenceField(obj, attribute, SerializedPropertyType.ObjectReference, field, memberFields)); } else { mf = (new ArrayObjectReferenceField(obj, attribute, SerializedPropertyType.ObjectReference, field, memberFields)); } } else { SerializedPropertyType serializedType = SerializedPropertyType.Integer; bool isKnownType = FieldField.GetSerializedType(field, out serializedType); if (!isKnownType) { attribute.Flags = ShowInEditorFlags.ReadOnly; } if (!field.FieldType.IsArray) { mf = new FieldField(obj, attribute, serializedType, field); } else { mf = new ArrayFieldField(obj, attribute, serializedType, field); } } if (field.IsPublic) { attribute.CanModifyArrayLength = true; } if (mf != null) { if (mf.IndentLevel == 0) { mf.IndentLevel = level; } fields.Add(mf); } } else if (member is MethodInfo) { MethodInfo method = member as MethodInfo; if (method.GetParameters().Length == 0) { if (method.ReturnType != typeof(void)) { fields.Add(new MethodField(obj, attribute, SerializedPropertyType.Generic, method)); } else if (attribute.Style == ShowInEditorStyle.Button) { if (attribute.Group == -1) { fields.Add(new MethodField(obj, attribute, SerializedPropertyType.Generic, method)); } else { List <MethodField> group; if (!buttonFields.TryGetValue(attribute.Group, out group)) { group = new List <MethodField>(); buttonFields.Add(attribute.Group, group); } group.Add(new MethodField(obj, attribute, SerializedPropertyType.Generic, method)); } } else { Debug.LogError("[ShowInEditor] Method that returns nothing cannot be shown in the editor"); } } else { Debug.LogError("[ShowInEditor] Method with arguments cannot be shown in the editor"); } } } } foreach (List <MethodField> buttonGroup in buttonFields.Values) { fields.Add(new ButtonGroupField(buttonGroup.ToArray())); } return(fields.ToArray()); }