using System; using UnityEditorInternal; using UnityEngine; using UnityEngine.UI; using UnityEngine.UIElements; using UnityEditor; using UnityEditor.UIElements; namespace UnityEditor.UI { [CustomPropertyDrawer(typeof(Dropdown.OptionDataList), true)] /// /// This is a PropertyDrawer for Dropdown.OptionDataList. It is implemented using the standard Unity PropertyDrawer framework. /// class DropdownOptionListDrawer : PropertyDrawer { const string kOptionsPath = "m_Options"; const string kTextPath = "m_Text"; const string kImagePath = "m_Image"; const string kHeader = "Options"; const string kListViewUssName = "unity-list-view__header"; const string kVisualElementName = "DropdownOptionDataList"; // Offset for fixed size list items, so it wouldn't look tight or overlap each other const float itemOffset = 4; private ReorderableList m_ReorderableList; private void Init(SerializedProperty property) { if (m_ReorderableList != null && m_ReorderableList.serializedProperty.serializedObject.m_NativeObjectPtr != IntPtr.Zero) { return; } SerializedProperty array = property.FindPropertyRelative(kOptionsPath); m_ReorderableList = new ReorderableList(property.serializedObject, array); m_ReorderableList.drawElementCallback = DrawOptionData; m_ReorderableList.drawHeaderCallback = DrawHeader; m_ReorderableList.elementHeight += 16; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { Init(property); m_ReorderableList.DoList(position); } private void DrawHeader(Rect rect) { GUI.Label(rect, kHeader); } private void DrawOptionData(Rect rect, int index, bool isActive, bool isFocused) { SerializedProperty itemData = m_ReorderableList.serializedProperty.GetArrayElementAtIndex(index); SerializedProperty itemText = itemData.FindPropertyRelative(kTextPath); SerializedProperty itemImage = itemData.FindPropertyRelative(kImagePath); RectOffset offset = new RectOffset(0, 0, -1, -3); rect = offset.Add(rect); rect.height = EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(rect, itemText, GUIContent.none); rect.y += EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(rect, itemImage, GUIContent.none); } public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { Init(property); return m_ReorderableList.GetHeight(); } public override VisualElement CreatePropertyGUI(SerializedProperty property) { var root = new VisualElement(); root.name = kVisualElementName; Init(property); var headerElement = new VisualElement(); headerElement.AddToClassList(kListViewUssName); var header = new Label(kHeader); headerElement.Add(header); root.Add(headerElement); var listView = CreateListView(property); root.Add(listView); return root; } ListView CreateListView(SerializedProperty property) { var listView = new ListView { showAddRemoveFooter = true, reorderMode = ListViewReorderMode.Animated, showBorder = true, showFoldoutHeader = false, showBoundCollectionSize = false, showAlternatingRowBackgrounds = AlternatingRowBackground.None, fixedItemHeight = m_ReorderableList.elementHeight + itemOffset, horizontalScrollingEnabled = false, name = kHeader }; var propertyRelative = property.FindPropertyRelative(kOptionsPath); listView.bindingPath = propertyRelative.propertyPath; listView.makeItem += () => new DropdownOptionListItem(kTextPath, kImagePath); return listView; } } }