如何在CustomEditor中的嵌套ReorderableList中选择元素?

时间:2019-02-04 12:33:28

标签: c# unity3d unity3d-editor unity-editor

我的CustomEditor脚本中有一个ReorderableList。在drawElementCallback中,我添加了第二个嵌套的ReorderableList。一切正常,我可以在此处将元素添加到两个列表中

enter image description here

,您会因为某种原因看到我无法选择内部ReorderableList的元素,因此也无法删除项目。

如何在内部列表中选择项目?


将这些类分解为基本示例

using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

[Serializable]
public class SomeClass
{
    public string Name;
    public List<SomeClass> InnerList;
}

[CreateAssetMenu(menuName = "Example", fileName = "new Example Asset")]
public class Example : ScriptableObject
{
    public List<SomeClass> SomeClasses;

    [CustomEditor(typeof(Example))]
    private class ModuleDrawer : Editor
    {
        private SerializedProperty SomeClasses;
        private ReorderableList list;

        private void OnEnable()
        {
            SomeClasses = serializedObject.FindProperty("SomeClasses");

            // setupt the outer list
            list = new ReorderableList(serializedObject, SomeClasses)
            {
                displayAdd = true,
                displayRemove = true,
                draggable = true,

                drawHeaderCallback = rect =>
                {
                    EditorGUI.LabelField(rect, "Outer List");
                },

                drawElementCallback = (rect, index, a, h) =>
                {
                    // get outer element
                    var element = SomeClasses.GetArrayElementAtIndex(index);

                    var InnerList = element.FindPropertyRelative("InnerList");

                    // Setup the inner list
                    var innerReorderableList = new ReorderableList(element.serializedObject, InnerList)
                    {
                        displayAdd = true,
                        displayRemove = true,
                        draggable = true,

                        drawHeaderCallback = innerRect =>
                        {
                            EditorGUI.LabelField(innerRect, "Inner List");
                        },

                        drawElementCallback = (innerRect, innerIndex, innerA, innerH) =>
                        {
                            // Get element of inner list
                            var innerElement = InnerList.GetArrayElementAtIndex(innerIndex);

                            var name = innerElement.FindPropertyRelative("Name");

                            EditorGUI.PropertyField(innerRect, name);
                        }
                    };

                    var height = (InnerList.arraySize + 3) * EditorGUIUtility.singleLineHeight;
                    innerReorderableList.DoList(new Rect(rect.x, rect.y, rect.width, height));
                },

                elementHeightCallback = index =>
                {
                    var element = SomeClasses.GetArrayElementAtIndex(index);

                    var innerList = element.FindPropertyRelative("InnerList");

                    return (innerList.arraySize + 4) * EditorGUIUtility.singleLineHeight;
                }
            };
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            list.DoLayoutList();

            serializedObject.ApplyModifiedProperties();
        }
    }
}

更新

如果我在ReorderableList中有一个CustomPropertyDrawer,同样显然也行不通。

但是让我惊讶的是,如果我同时拥有UnityEvent,那么都可以:将其放在CustomPropertyDrawerReorderableList中。我可以按预期添加和删除项目。

如您所见,我通过添加

添加了一个UnityEvent字段
[Serializable]
public class SomeClass
{
    public string Name;
    public List<SomeClass> InnerList;
}

并使用

//...
innerReorderableList.DoList(new Rect(rect.x, rect.y, rect.width, height));

var InnerEvent = element.FindPropertyRelative("InnerEvent");
var pers = InnerEvent.FindPropertyRelative("m_PersistentCalls.m_Calls");
var evHeight = (Mathf.Max(1, pers.arraySize) * 2 + 3) * EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, evHeight), InnerEvent);

并将elementHeightCallback调整为

elementHeightCallback = index =>
{
    var element = SomeClasses.GetArrayElementAtIndex(index);

    var innerList = element.FindPropertyRelative("InnerList");
    var InnerEvent = element.FindPropertyRelative("InnerEvent");
    var pers = InnerEvent.FindPropertyRelative("m_PersistentCalls.m_Calls");

    return (Mathf.Max(1, innerList.arraySize) + 4 + Mathf.Max(1, pers.arraySize) * 2 + 4) * EditorGUIUtility.singleLineHeight;
}

我可以按预期与之进行完全交互,并且可以选择和删除条目。

enter image description here

那么他们有什么不同?

1 个答案:

答案 0 :(得分:2)

似乎您是一遍又一遍地创建内部列表,而没有将它们存储在任何地方。我修改了代码,以<script src="//unpkg.com/lodash/lodash.min.js"></script>为键将可重排列表存储在字典中。希望这会有所帮助。

element.propertyPath