Hi,
I need some help with binding nested lists of data to a custom editor. I have tried to simplify the problem here as much as possible so it’s easier to understand.
The data consists of a scriptable object that contains info about a list of characters. When I double click this scriptable object I open an editor window.
public class CharactersDataSO : ScriptableObject
{
public List<CharacterInfo> m_Characters;
}
Each character has a name and a list of abilities.
public class CharacterInfo
{
public string m_Name;
public List<Ability> m_Abilities;
}
Each ability has a name.
public class Ability
{
public string m_Name;
}
When I select one of the characters in the first list, I want to display the abilities that it contains in the second tab. Also in the future, if I click on an ability, I would like to display info about that ability in a third tab, and be able to edit it.
As you can see in the gif I attached, the first list of data (the characters list) is binding just fine, but I can’t seem to be able to bind the subsequent data when I select something on the first list.
This is how the EditorWindow script that takes care of everything looks like:
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
public class CharactersDataWindow : EditorWindow
{
[SerializeField] private VisualTreeAsset m_RootUXML;
private VisualElement m_LeftListRoot;
private VisualElement m_RightListRoot;
private CharactersDataSO m_Model;
public static void Open(CharactersDataSO model)
{
CharactersDataWindow wnd = GetWindow<CharactersDataWindow>();
wnd.titleContent = new GUIContent("Characters data");
wnd.Init(model);
}
private void Init(CharactersDataSO model)
{
m_Model = model;
rootVisualElement.Clear();
VisualElement tabsRoot = m_RootUXML.CloneTree();
rootVisualElement.Add(tabsRoot);
m_LeftListRoot = tabsRoot.Q<VisualElement>("left-view");
m_RightListRoot = tabsRoot.Q<VisualElement>("right-view");
m_LeftListRoot.Add(new Label("Characters"));
// Add characters list
MultiColumnListView characterListView = CreateCharactersList();
m_LeftListRoot.Add(characterListView);
rootVisualElement.Bind(new SerializedObject(model));
}
private void OnCharacterSelected(int idx)
{
m_RightListRoot.Clear();
m_RightListRoot.Add(new Label("Abilities"));
// Add abilities list
MultiColumnListView abilitiesListView = CreateAbilitiesList();
abilitiesListView.dataSource = m_Model.m_Characters[idx];
m_RightListRoot.Add(abilitiesListView);
}
private MultiColumnListView CreateCharactersList()
{
MultiColumnListView characterListView = new MultiColumnListView();
characterListView.bindingPath = nameof(CharactersDataSO.m_Characters);
characterListView.selectionChanged += (_) => OnCharacterSelected(characterListView.selectedIndex);
characterListView.columns.Add(new Column
{
title = "Name",
stretchable = true,
makeCell = () => new Label(),
bindingPath = nameof(CharacterInfo.m_Name)
});
characterListView.columns.Add(new Column
{
title = "Empty column",
stretchable = true,
makeCell = () => new Label("Empty"),
});
return characterListView;
}
private MultiColumnListView CreateAbilitiesList()
{
MultiColumnListView abilitiesListView = new MultiColumnListView();
abilitiesListView.bindingPath = nameof(CharacterInfo.m_Abilities);
abilitiesListView.columns.Add(new Column
{
title = "Name",
stretchable = true,
makeCell = () => new Label(),
bindingPath = nameof(Ability.m_Name)
});
abilitiesListView.columns.Add(new Column
{
title = "Empty column",
stretchable = true,
makeCell = () => new Label("Empty"),
});
return abilitiesListView;
}
}
I would really appreciate if you could provide some assistance on how to handle situations like this where I have multiple nested lists that I would want to bind and display.
Thanks!
