Hey there,
I was wondering if anyone could share the best way to go about getting collections to draw using the ReorderableList drawer when using a “Default UIElements CustomEditor Drawer”?
I spent a bunch of time trying to make the few dictionaries I had look good with a custom drawer which required me to make the CustomEditors derive from a UIElements default inspector, only to now basically have the rest of the inspectors look much better in debug mode/view, because all the list and arrays look nice.
I would imagine that within the loop below I could get the collections by name, I am just not sure what I would have to do to them from there to use the current list drawer?
Default Inspector
[CustomEditor(typeof(Object), true, isFallback = true)]
[CanEditMultipleObjects]
public class DefaultEditorDrawer : Editor
{
public bool showScript = false;
public List<string> excludedFields = new List<string>();
public override VisualElement CreateInspectorGUI()
{
var root = new VisualElement();
var property = serializedObject.GetIterator();
if (property.NextVisible(true)) // Expand first child.
{
do
{
var field = new PropertyField(property) {name = "PropertyField:" + property.propertyPath};
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
{
if (showScript) field.SetEnabled(false);
else continue;
}
if (excludedFields.Contains(property.propertyPath) && serializedObject.targetObject != null)
{
continue;
}
root.Add(field);
} while (property.NextVisible(false));
}
return root;
}
}
Thanks,
-MH
Ok, I was able to get this worked out. Using the following, with the addition of a SerializedPropery extension method to determine if a property is an appropriate collection, it creates an IMGUI reorderable list out of it.
The “excluded fields” part can be omitted, I just used it to filter out fields from being drawn.
Default UIElements Drawer
[CustomEditor(typeof(Object), true, isFallback = true)]
[CanEditMultipleObjects]
public class DefaultEditorDrawer : Editor
{
public bool showScript;
public List<string> excludedFields = new List<string>();
string m_IMGUIPropNeedsRelayout;
ScrollView m_ScrollView;
public override VisualElement CreateInspectorGUI()
{
var root = new VisualElement();
var property = serializedObject.GetIterator();
m_ScrollView = new ScrollView();
root.Add(m_ScrollView);
if (property.NextVisible(true)) // Expand first child.
{
do
{
var field = new PropertyField(property) {name = "PropertyField:" + property.propertyPath};
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
{
if (showScript) field.SetEnabled(false);
else continue;
}
if (property.IsReallyArray() && serializedObject.targetObject != null)
{
var copiedProperty = property.Copy();
var imDefaultProperty = new IMGUIContainer(() =>
{
DoDrawDefaultIMGUIProperty(serializedObject, copiedProperty);
}) {name = property.propertyPath};
m_ScrollView.Add(imDefaultProperty);
continue;
}
if (excludedFields.Contains(property.propertyPath) && serializedObject.targetObject != null)
{
continue;
}
root.Add(field);
} while (property.NextVisible(false));
}
foreach (var foldout in m_ScrollView.Query<Foldout>().ToList())
{
foldout.RegisterValueChangedCallback(e =>
{
var fd = e.target as Foldout;
if (fd == null) return;
var path = fd.bindingPath;
var container = m_ScrollView.Q<IMGUIContainer>(name: path);
RecomputeSize(container);
});
}
return root;
}
private void RecomputeSize(IMGUIContainer container)
{
if (container == null) return;
var parent = container.parent;
container.RemoveFromHierarchy();
parent.Add(container);
}
public void DoDrawDefaultIMGUIProperty(SerializedObject serializedObject, SerializedProperty property)
{
EditorGUI.BeginChangeCheck();
serializedObject.Update();
bool wasExpanded = property.isExpanded;
EditorGUILayout.PropertyField(property, true);
if (property.isExpanded != wasExpanded) m_IMGUIPropNeedsRelayout = property.propertyPath;
serializedObject.ApplyModifiedProperties();
EditorGUI.EndChangeCheck();
}
}
Extension:
Used property Extension Method
public static class PropertyExtensions
{
public static bool IsReallyArray(this SerializedProperty property)
{
return property.isArray && property.propertyType != SerializedPropertyType.String;
}
}