UIElements: problems with inserting and deleting obejcts in an array
I am trying to troubleshoot a problem in my custom Inspector. I am manipulating a List
through SerializedProperty
s. At some point it seems like an object ends up multiple times in the same list. I have spent hours debugging, but I can't figure it out.. Hope someone can help
These are two classes, one references a List
of the other
using System.Collections.Generic;
using UnityEngine;
public class Foo : MonoBehaviour {
public List<Bar> list = new List<Bar>();
}
[System.Serializable]
public class Bar {
public string value;
}
My Editor just lists the Bar
objects. I also provides a button to append to the end of the List
and remove elements. It looks like so..
using UnityEditor.UIElements;
using UnityEngine.UIElements;
using UnityEditor;
[CustomEditor(typeof(Foo))]
public class FooEditor : Editor {
SerializedProperty listProperty;
Foo foo;
VisualElement container;
VisualElement listContainer;
private void OnEnable() {
listProperty = serializedObject.FindProperty("list");
container = new VisualElement();
listContainer = new VisualElement();
foo = (Foo)target;
}
public override VisualElement CreateInspectorGUI() {
for (int i = 0; i < listProperty.arraySize; i++) {
SerializedProperty sp = listProperty.GetArrayElementAtIndex(i);
SetupBarProperty(sp);
}
Button newStageButton = new Button(() => {
CreateBar(listProperty.arraySize);
});
newStageButton.text = "Add new Bar";
container.Add(listContainer);
container.Add(newStageButton);
return container;
}
public void CreateBar(int index) {
serializedObject.Update();
listProperty.InsertArrayElementAtIndex(index);
SetupBarProperty(listProperty.GetArrayElementAtIndex(index));
serializedObject.ApplyModifiedProperties();
container.Bind(serializedObject);
}
private void DeleteBar(int index) {
serializedObject.Update();
listProperty.DeleteArrayElementAtIndex(index);
listContainer.RemoveAt(index);
serializedObject.ApplyModifiedProperties();
container.Bind(serializedObject);
}
private void SetupBarProperty(SerializedProperty barProperty) {
VisualElement row = new VisualElement();
row.style.flexDirection = FlexDirection.Row;
PropertyField stageField = new PropertyField(barProperty);
stageField.style.flexGrow = 1;
Button removeButton = new Button(() => { DeleteBar(listContainer.IndexOf(row)); });
removeButton.text = "-";
row.Add(stageField);
row.Add(removeButton);
listContainer.Add(row);
}
}
To reproduce the error:
Apply Foo to an object and open it in the inspector
Insert 2 new items
Give them distinguishable names (like
E0
andE1
)Delete element at position 0 (
E0
)Insert a new element
Change name of any of the two elements and the other will change at the same time