问题描述
I have a ReorderableList
in my CustomEditor
script. In the drawElementCallback
I added a second nested ReorderableList
. Everything works fine and I can add elements to both lists like here
但,由于某些原因,您无法选择内部ReorderableList
的元素,因此也无法删除项目.
BUT as you can see for some reason I can not select the elements of the inner ReorderableList
s so I also can not remove items.
如何在内部列表中选择项目?
将这些类分解为基本示例
Here the classes broken down to the basic example
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();
}
}
}
更新
如果我在CustomPropertyDrawer
中有一个ReorderableList
,同样显然也行不通.
The same apprantly also doesn't work if I have a ReorderableList
within a CustomPropertyDrawer
.
但是让我惊讶的是,如果我有 UnityEvent
均有效:将其放在CustomPropertyDrawer
内或ReorderableList
内.我可以按预期添加和删除项目.
But to my suprise if I have a UnityEvent
both works: Having it inside a CustomPropertyDrawer
or within a ReorderableList
. I can add and remove items as expected.
如您所见,我通过添加
[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;
}
我可以按预期与之完全交互,并且可以选择和删除条目.
I can fully interact with it as expected and also select and remove entries.
那他们有什么不同?
推荐答案
似乎您是一遍又一遍地创建内部列表,而没有将它们存储在任何地方.我修改了您的代码以将可重新排序的列表存储在以element.propertyPath
为键的字典中.希望这会有所帮助.
It looks like you are creating the inner lists over and over without storing them anywhere. I modified your code to store the reorderable lists in a dictionary with the element.propertyPath
as a key. Hope this helps.
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 Dictionary<string, ReorderableList> innerListDict = new Dictionary<string, ReorderableList>();
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");
string listKey = element.propertyPath;
ReorderableList innerReorderableList;
if (innerListDict.ContainsKey(listKey))
{
// fetch the reorderable list in dict
innerReorderableList = innerListDict[listKey];
}
else
{
// create reorderabl list and store it in dict
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);
}
};
innerListDict[listKey] = innerReorderableList;
}
// Setup the inner list
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();
}
}
}
这篇关于如何在CustomEditor中的嵌套ReorderableList中选择元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!