/// <summary> /// Returns true if any changes were made to the list. /// </summary> public static bool ShowList <T>(IList <T> list, ShowItem <T> showItemDelegate, float viewWidth, ShowListOptions options = ShowListOptions.Reorderable | ShowListOptions.Resizeable | ShowListOptions.Resizeable | ShowListOptions.ShowListSize, int minListSize = 0, int maxListSize = int.MaxValue) where T : new() { // To avoid clipping by vertical scrollbar viewWidth -= 20f; int indexToDelete = -1; int indexToMoveUp = -1; int indexToMoveDown = -1; int listCount = list.Count; var oddStyle = new GUIStyle(); oddStyle.normal.background = blackQuarterAlphaTexture2D; EditorGUI.indentLevel++; var listStyle = new GUIStyle(); listStyle.margin = new RectOffset(0, 0, 10, 0); listStyle.imagePosition = ImagePosition.ImageLeft; EditorGUILayout.BeginVertical(listStyle); if ((options & ShowListOptions.ShowListSize) == ShowListOptions.ShowListSize) { EditorGUILayout.LabelField(new GUIContent("Size: " + listCount), EditorUtils.boldLabelStyle); EditorGUILayout.Separator(); } GUI.changed = false; for (int i = 0; i < listCount; ++i) { var item = list[i]; //------------ // Show Item //------------ if (i % 2 == 0) { EditorGUILayout.BeginHorizontal(); } else { EditorGUILayout.BeginHorizontal(oddStyle); } EditorGUILayout.BeginVertical(GUILayout.Width(viewWidth * 0.94f)); var visible = showItemDelegate(item, i); EditorGUILayout.EndVertical(); //----------------------- // List Manipulation EditorGUILayout.BeginVertical(GUILayout.Width(viewWidth * 0.05f)); if (visible) { if ((options & ShowListOptions.Resizeable) == ShowListOptions.Resizeable) { GUI.enabled = (listCount > minListSize); if (GUILayout.Button("X", "toolbarbutton", GUILayout.ExpandWidth(false))) { indexToDelete = i; } } if ((options & ShowListOptions.Reorderable) == ShowListOptions.Reorderable) { GUI.enabled = (i < listCount - 1); if (GUILayout.Button("\u25BC", EditorStyles.toolbarButton, GUILayout.Width(18))) { indexToMoveDown = i; } GUI.enabled = i > 0; if (GUILayout.Button("\u25B2", EditorStyles.toolbarButton, GUILayout.Width(18))) { indexToMoveUp = i; } } } GUI.enabled = true; EditorGUILayout.EndVertical(); // End List Manipulation //----------------------- EditorGUILayout.EndHorizontal(); } bool itemsChanged = false; if (listCount < maxListSize && (options & ShowListOptions.Resizeable) == ShowListOptions.Resizeable) { if (GUILayout.Button("Add", EditorStyles.toolbarButton, GUILayout.Width(50))) { var newItem = default(T); if (newItem == null) { newItem = new T(); } list.Add(newItem); itemsChanged = true; } } EditorGUILayout.EndVertical(); EditorGUI.indentLevel--; if (indexToDelete >= 0 && listCount > minListSize) { list.RemoveAt(indexToDelete); itemsChanged = true; } if (indexToMoveUp >= 0) { Swap(list, indexToMoveUp, indexToMoveUp - 1); itemsChanged = true; } if (indexToMoveDown >= 0) { Swap(list, indexToMoveDown, indexToMoveDown + 1); itemsChanged = true; } return(itemsChanged || GUI.changed); } // ShowList<T>()
/// <summary> /// Recommend calling SerializedObject.Update() before. /// Returns true if any changes were made to the list. Automatically handles registering Undo, and saving changes to Serialized object. /// Recommend calling SerializedObject.ApplyModifiedProperties() afterwards. /// /// Alternative: Use the ReorderableList class in UnityEditorInternal namespace. See this excellent post: http://va.lent.in/unity-make-your-lists-functional-with-reorderablelist/ /// </summary> public static bool ShowList <T>(SerializedProperty list, ShowItemSerialized showItemDelegate, float viewWidth, ShowListOptions options = ShowListOptions.Reorderable | ShowListOptions.Resizeable | ShowListOptions.Resizeable | ShowListOptions.ShowListSize, int minListSize = 0, int maxListSize = int.MaxValue) { //if (list.isArray) { // throw new ArgumentException( "SaveSystem: ShowList() SerializedProperty must be a List." ); //} // To avoid clipping by vertical scrollbar viewWidth -= 20f; int indexToDelete = -1; int indexToMoveUp = -1; int indexToMoveDown = -1; int listCount = list.arraySize; var oddStyle = new GUIStyle(); oddStyle.normal.background = blackQuarterAlphaTexture2D; EditorGUI.indentLevel++; var listStyle = new GUIStyle(); listStyle.margin = new RectOffset(0, 0, 10, 0); listStyle.imagePosition = ImagePosition.ImageLeft; EditorGUILayout.BeginVertical(listStyle); if ((options & ShowListOptions.ShowListSize) == ShowListOptions.ShowListSize) { EditorGUILayout.LabelField(new GUIContent("Size: " + listCount), EditorUtils.boldLabelStyle); EditorGUILayout.Separator(); } GUI.changed = false; for (int i = 0; i < listCount; ++i) { var item = list.GetArrayElementAtIndex(i); //------------ // Show Item //------------ if (i % 2 == 0) { EditorGUILayout.BeginHorizontal(); } else { EditorGUILayout.BeginHorizontal(oddStyle); } EditorGUILayout.BeginVertical(GUILayout.Width(viewWidth * 0.94f)); var visible = showItemDelegate(item, i); EditorGUILayout.EndVertical(); //----------------------- // List Manipulation EditorGUILayout.BeginVertical(GUILayout.Width(viewWidth * 0.05f)); if (visible) { if ((options & ShowListOptions.Resizeable) == ShowListOptions.Resizeable) { GUI.enabled = (listCount > minListSize); if (GUILayout.Button("X", "toolbarbutton", GUILayout.ExpandWidth(false))) { indexToDelete = i; } } if ((options & ShowListOptions.Reorderable) == ShowListOptions.Reorderable) { GUI.enabled = (i < listCount - 1); if (GUILayout.Button("\u25BC", EditorStyles.toolbarButton, GUILayout.Width(18))) { indexToMoveDown = i; } GUI.enabled = i > 0; if (GUILayout.Button("\u25B2", EditorStyles.toolbarButton, GUILayout.Width(18))) { indexToMoveUp = i; } } } GUI.enabled = true; EditorGUILayout.EndVertical(); // End List Manipulation //----------------------- EditorGUILayout.EndHorizontal(); } if (listCount < maxListSize && (options & ShowListOptions.Resizeable) == ShowListOptions.Resizeable) { if (GUILayout.Button("Add", EditorStyles.toolbarButton, GUILayout.Width(50))) { list.InsertArrayElementAtIndex(listCount); } } EditorGUILayout.EndVertical(); EditorGUI.indentLevel--; if (indexToDelete >= 0 && listCount > minListSize) { list.DeleteArrayElementAtIndex(indexToDelete); } if (indexToMoveUp >= 0) { list.MoveArrayElement(indexToMoveUp, indexToMoveUp - 1); } if (indexToMoveDown >= 0) { list.MoveArrayElement(indexToMoveDown, indexToMoveDown + 1); } return(GUI.changed); }