public static object GenericListDrawer(object obj, InvokeWrapper wrapper, GUISkin skin) { System.Collections.IList list = wrapper.Get <System.Collections.IList>(obj); var target = obj as Object; if (GUI.Foldout(EditorData.Instance.GetData(target, wrapper.Member.Name), MakeLabel(wrapper.Member), skin)) { object insertElementBefore = null; object insertElementAfter = null; object eraseElement = null; var buttonLayout = new GUILayoutOption[] { GUILayout.Width(26), GUILayout.Height(18) }; using (new GUI.Indent(12)) { foreach (var listObject in list) { GUI.Separator(); using (new GUI.Indent(12)) { GUILayout.BeginHorizontal(); { GUILayout.BeginVertical(); { // Using target to render listObject since it normally (CollisionGroupEntry) isn't an Object. InspectorEditor.DrawMembersGUI(new Object[] { target }, ignored => listObject); } GUILayout.EndVertical(); using (GUI.NodeListButtonColor) { if (GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListInsertElementBefore.ToString(), false, "Insert new element before this"), skin.button, buttonLayout)) { insertElementBefore = listObject; } if (GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListInsertElementAfter.ToString(), false, "Insert new element after this"), skin.button, buttonLayout)) { insertElementAfter = listObject; } if (GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListEraseElement.ToString(), false, "Erase this element"), skin.button, buttonLayout)) { eraseElement = listObject; } } } GUILayout.EndHorizontal(); } } if (list.Count == 0) { GUILayout.Label(GUI.MakeLabel("Empty", true), skin.label); } else { GUI.Separator(); } } bool addElementToList = false; GUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); using (GUI.NodeListButtonColor) addElementToList = GUILayout.Button(GUI.MakeLabel(GUI.Symbols.ListInsertElementAfter.ToString(), false, "Add new element to list"), skin.button, buttonLayout); } GUILayout.EndHorizontal(); object newObject = null; if (addElementToList || insertElementBefore != null || insertElementAfter != null) { newObject = Activator.CreateInstance(list.GetType().GetGenericArguments()[0], new object[] { }); } if (eraseElement != null) { list.Remove(eraseElement); } else if (newObject != null) { if (addElementToList || (list.Count > 0 && insertElementAfter != null && insertElementAfter == list[list.Count - 1])) { list.Add(newObject); } else if (insertElementAfter != null) { list.Insert(list.IndexOf(insertElementAfter) + 1, newObject); } else if (insertElementBefore != null) { list.Insert(list.IndexOf(insertElementBefore), newObject); } } if (eraseElement != null || newObject != null) { EditorUtility.SetDirty(target); } } // A bit of a hack until I figure out how to handle multi-selection // of lists, if that should be possible at all. We're handling the // list from inside this drawer and by returning null the return // value isn't propagated to any targets. return(null); }
public static object GenericListDrawer(object[] objects, InvokeWrapper wrapper) { var list = wrapper.Get <System.Collections.IList>(objects[0]); var target = objects[0] as Object; if (InspectorGUI.Foldout(EditorData.Instance.GetData(target, wrapper.Member.Name), InspectorGUI.MakeLabel(wrapper.Member))) { object insertElementBefore = null; object insertElementAfter = null; object eraseElement = null; var skin = InspectorEditor.Skin; var buttonLayout = new GUILayoutOption[] { GUILayout.Width(1.0f * EditorGUIUtility.singleLineHeight), GUILayout.Height(1.0f * EditorGUIUtility.singleLineHeight) }; foreach (var listObject in list) { using (InspectorGUI.IndentScope.Single) { GUILayout.BeginHorizontal(); { InspectorGUI.Separator(1.0f, EditorGUIUtility.singleLineHeight); if (InspectorGUI.Button(MiscIcon.EntryInsertBefore, true, "Insert new element before this.", buttonLayout)) { insertElementBefore = listObject; } if (InspectorGUI.Button(MiscIcon.EntryInsertAfter, true, "Insert new element after this.", buttonLayout)) { insertElementAfter = listObject; } if (InspectorGUI.Button(MiscIcon.EntryRemove, true, "Remove this element.", buttonLayout)) { eraseElement = listObject; } } GUILayout.EndHorizontal(); InspectorEditor.DrawMembersGUI(new Object[] { target }, ignored => listObject); } } InspectorGUI.Separator(1.0f, 0.5f * EditorGUIUtility.singleLineHeight); if (list.Count == 0) { GUILayout.Label(GUI.MakeLabel("Empty", true), skin.Label); } bool addElementToList = false; GUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); addElementToList = InspectorGUI.Button(MiscIcon.EntryInsertAfter, true, "Add new element.", buttonLayout); } GUILayout.EndHorizontal(); object newObject = null; if (addElementToList || insertElementBefore != null || insertElementAfter != null) { newObject = Activator.CreateInstance(list.GetType().GetGenericArguments()[0], new object[] { }); } if (eraseElement != null) { list.Remove(eraseElement); } else if (newObject != null) { if (addElementToList || (list.Count > 0 && insertElementAfter != null && insertElementAfter == list[list.Count - 1])) { list.Add(newObject); } else if (insertElementAfter != null) { list.Insert(list.IndexOf(insertElementAfter) + 1, newObject); } else if (insertElementBefore != null) { list.Insert(list.IndexOf(insertElementBefore), newObject); } } if (eraseElement != null || newObject != null) { EditorUtility.SetDirty(target); } } // A bit of a hack until I figure out how to handle multi-selection // of lists, if that should be possible at all. We're handling the // list from inside this drawer and by returning null the return // value isn't propagated to any targets. return(null); }