TLDR; How do you implement reorderablList in a classes custom property draw. Class is a serialisable class, not a scriptable object or Monobehaviour.
Hi,
During this transition from IMGUI to UIToolkit I’m struggling to find concise documentation and example that covers displaying List properties with custom layouts.
i’ve found some examples of implementing reorderableList, but the issue is the examples all do this within a custom editor, not a custom propertyDraw, and as i understand it there are issues with custom property draws because you can’t instantiate the reorderableList in an OnEnable() because that method doesn’t exist. So i’m thinking that you’d need to do this with perhaps a dictionary of reorderableList instances keyed of the list properties name/parent. (trying to find the refence example where i think someones sort of achieved this).
In the mean time, below is pretty much the kind of scenario I have.
I have the following in psuedo code.
class Mission : ScribtableObject
{
public MainTask mainTask;
}
class MainTask
{
public List<SubTask> subTasks;
}
class SubTask
{
public string decription;
public bool complete;
}
// Note, It was my original intention to have the following, but of course you immediately get into Unitys limitation on serialisation this sort of scenario.
class Task {
public string decription;
List<Task> subTasks;
}
The editor classes look like
/// Mission Editor, nothing special here.
[CustomEditor(typeof(Mission), false)]
public class MissionEditor : UnityEditor.Editor {
private void OnEnable()
{
// in other examples this method can be used to create an instance of ReorderableList
// Which by all accounts might work, I'll at some point implemented it just to know that it does.
// However, as you can see, its my MainTask class that has a list of subTasks, and its this i want to be reorderable.
// subTasks = new ReorderableList(serializedObject,
// serializedObject.FindProperty("subTasks"),
// true, true, true, true);
}
// As I understand it this is the old way and wouldn't use if doing it the new way with UIElements (
public override void OnInspectorGUI() {
// serializedObject.Update();
// EditorGUILayout.PropertyField(descriptionProp);
// EditorGUILayout.PropertyField(taskProp);
// serializedObject.ApplyModifiedProperties();
}
// This is the new way, and this is something i got from an example to simply render properties with default UIElements.
public override VisualElement CreateInspectorGUI()
{
var container = new VisualElement();
var iterator = serializedObject.GetIterator();
if (iterator.NextVisible(true))
{
do
{
var propertyField = new PropertyField(iterator.Copy()) { name = "PropertyField:" + iterator.propertyPath };
if (iterator.propertyPath == "m_Script" && serializedObject.targetObject != null)
propertyField.SetEnabled(value: false);
container.Add(propertyField);
}
while (iterator.NextVisible(false));
}
return container;
}
}
// I've currently made assumption that i need to create a PropertyDrawer for the MainTask class and not just a custom Editor?
// I'm wondering if i can just extend MainTask with scriptable object, despite not really needing it to be a scriptable object? I don't feel the need currently to use scriptable objects.
[CustomPropertyDrawer(typeof(MainTask))]
public class MainTaskDrawer: PropertyDrawer
{
private ReorderableList subTasks;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
// Create property container element.
VisualElement container = new VisualElement();
// Task fields
PropertyField nameField = new PropertyField(property.FindPropertyRelative("name"));
PropertyField subTasksField = new PropertyField(property.FindPropertyRelative("subTasks"));
// Add fields to the container.
container.Add(nameField);
container.Add(subTasksField);
// So the question is, How, or can you? implement reorderable list
// Where to do the initialisation of the ReorderableList as in the Editor example?
// How to add ReorderableList to the Container? and where/how to call DoLayoutList()?
var listProperty = property.FindPropertyRelative("subTasks");
subTasks = new ReorderableList( property.serializedObject,
listProperty,
true, true, true, true);
subTasks.drawHeaderCallback = (Rect rect) => {
EditorGUI.LabelField(rect, "List header");
};
//subTasks?.DoLayoutList();
return container;
}
}

