How to add an array of gameObjects to an Editor window in the new Unity UI ToolKit?

979 Views Asked by At

I can't find how to add an array of gameObjects to an Editor window in the new Unity UI ToolKit like in the picture:

enter image description here

I don't find an array component in the UI Builder library and the ListView does not seem to be the right choice for me.

2

There are 2 best solutions below

3
derHugo On BEST ANSWER

I'm not very familiar with the "new" UIToolkit (still not getting warm with it ^^) but this seems to work for me

public class TEstEditorWindow : EditorWindow
{
    private List<GameObject> prefabs;
    private ListView list;

    [MenuItem("TEEST/Testitest")]
    public static void Open()
    {
        var window = GetWindow<TEstEditorWindow>();
        window.Show();
    }

    private void CreateGUI()
    {
        DrawReorderableList(prefabs, rootVisualElement);
    }

    // jut making this static so it can be generalized and used everywhere
    public static void DrawReorderableList<T>(List<T> sourceList, VisualElement rootVisualElement, bool allowSceneObjects = true) where T : UnityEngine.Object
    {
        var list = new ListView(sourceList)
        {
            virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight,
            showFoldoutHeader = true,
            headerTitle = "Prefabs",
            showAddRemoveFooter = true,
            reorderMode = ListViewReorderMode.Animated,
            makeItem = () => new ObjectField
            {
                objectType = typeof(T),
                allowSceneObjects = allowSceneObjects
            },
            bindItem = (element, i) =>
            {
                ((ObjectField)element).value = sourceList[i];
                ((ObjectField)element).RegisterValueChangedCallback((value) =>
                {
                    sourceList[i] = (T)value.newValue;
                });
            }
        };

        rootVisualElement.Add(list);
    }
}

I sure hope there is a better an more stable way to do this though ^^

enter image description here

See also

4
derHugo On

Easier way via ProperyField directly

public class TEstEditorWindow : EditorWindow
{
    [SerializeField] private List<GameObject> prefabs;

    [MenuItem("TEEST/Testitest")]
    public static void Open()
    {
        var window = GetWindow<TEstEditorWindow>();
        window.Show();
    }

    private void CreateGUI()
    {
        var serializedObject = new SerializedObject(this);
        var property = serializedObject.FindProperty(nameof(prefabs));

        var field = new PropertyField(property);
        field.Bind(serializedObject);

        rootVisualElement.Add(field);
    }
}

Alternatively

Just for this property you could go through IMGUI and do

public class TEstEditorWindow : EditorWindow
{
    [SerializeField] private List<GameObject> prefabs;

    [MenuItem("TEEST/Testitest")]
    public static void Open()
    {
        var window = GetWindow<TstEditorWindow>();
        window.Show();
    }

    private void CreateGUI()
    {
        var container = new IMGUIContainer(() =>
        {
            var serializedObject = new SerializedObject(this);
            var property = serializedObject.FindProperty(nameof(prefabs));
            serializedObject.Update();
            EditorGUILayout.PropertyField(property);
            serializedObject.ApplyModifiedProperties();
        });

        rootVisualElement.Add(container);
    }
}

until there is better support for such lists.

This simply uses the default list drawer and works for any type of list (as long as type is serializable of course) and is more stable then re-inventing it via the ListView