I have a custom inspector script for a scriptable object which holds a few basic values, and a custom serialized dictionary. I have created an editor script for adding/removing values from the dictionary, but I’m encountering an issue where the values don’t appear update when I add/remove from the dictionary. e.g, I press the ‘Add Element’ button and nothing appears to happen, but if I then deselect and reselect the SO it updates and displays that the dictionary has been properly modified. How do I update the GUI while editing it, rather than having to go through the whole deselect/reselect process?
Here is the script:
[CustomEditor(typeof(AgentDecision))]
public class AgentDecisionInspector : AgentActionInspectorBase
{
public override VisualElement CreateInspectorGUI()
{
AgentActions action = (AgentActions)target;
if (action.emotionalWeights == null)
{
action.emotionalWeights = new EmotionDictionary();
}
VisualElement myInspector = new VisualElement();
Label header = new Label("Decision");
header.style.unityFontStyleAndWeight = FontStyle.Bold;
Button addButton = new Button(() => AddNewEmotion(action.emotionalWeights, out action.emotionalWeights));
addButton.text = "Add Element";
myInspector.Add(header);
myInspector.Add(NameInput());
myInspector.Add(GenerateDictionaryUI(action.emotionalWeights, out action.emotionalWeights));
myInspector.Add(addButton);
EditorUtility.SetDirty(target);
return myInspector;
}
}
[CustomEditor(typeof(AgentActions))]
public abstract class AgentActionInspectorBase : Editor
{
SerializedProperty nameProperty;
private void OnEnable()
{
nameProperty = serializedObject.FindProperty("Label");
}
public VisualElement NameInput ()
{
VisualElement element = new VisualElement();
TextField txtField = new TextField("Enter Name:", 32, false, false, '*');
txtField.BindProperty(nameProperty);
element.Add(txtField);
return element;
}
public VisualElement GenerateDictionaryUI (EmotionDictionary dict, out EmotionDictionary outDict)
{
AgentActions action = (AgentActions)target;
VisualElement entries = new VisualElement();
entries.style.borderTopColor = Color.gray;
entries.style.borderBottomColor = Color.gray;
entries.style.borderLeftColor = Color.gray;
entries.style.borderRightColor = Color.gray;
entries.style.borderTopWidth = 2;
entries.style.borderBottomWidth = 2;
entries.style.borderLeftWidth = 2;
entries.style.borderRightWidth = 2;
foreach (KeyValuePair<Emotion, float> element in dict)
{
VisualElement box = new VisualElement();
box.style.borderBottomWidth = 2;
box.style.borderBottomColor = Color.gray;
box.style.flexDirection = FlexDirection.Column;
EnumField label = new EnumField(element.Key);
Slider slider = new Slider(-1, 1);
Button removeButton = new Button(
() => RemoveEmotion(element.Key, action.emotionalWeights, out action.emotionalWeights));
removeButton.text = "Remove";
slider.value = element.Value;
box.Add(label);
box.Add(slider);
box.Add(removeButton);
entries.Add(box);
}
outDict = dict;
return entries;
}
public void RemoveEmotion (Emotion key, EmotionDictionary inDict, out EmotionDictionary outDict)
{
inDict.Remove(key);
outDict = inDict;
}
public void AddNewEmotion (EmotionDictionary inDict, out EmotionDictionary outDict)
{
if (inDict == null)
{
inDict = new EmotionDictionary();
}
for (int i = 0; i < Enum.GetNames(typeof(Emotion)).Length; i++)
{
if (!inDict.ContainsKey((Emotion)i))
{
inDict.Add((Emotion)i, 0);
break;
}
}
outDict = inDict;
}
}