- Home /
Applying a PropertyDrawer to elements of a List<>
I have set up a PropertyDrawer, and it works for single elements:
public class ResourceReferenceAttribute : PropertyAttribute
{
public ResourceReferenceAttribute()
{
}
}
...
[CustomPropertyDrawer(typeof(ResourceReferenceAttribute))]
public class ResourceReferenceDrawer : PropertyDrawer
{
public override void OnGUI(Rect pos,
SerializedProperty prop,
GUIContent label)
{
Object obj = AssetDatabase.LoadMainAssetAtPath(prop.stringValue);
Object newObj = EditorGUI.ObjectField(pos, label, obj, typeof(GameObject), false);
if (obj != newObj)
{
prop.stringValue = AssetDatabase.GetAssetPath(newObj);
}
}
}
...
[ResourceReference] public string healthyString;
Which works as you would expect.
I would also like to apply this to arrays of items, but am having no luck:
[ResourceReference] public List<string> rootSoundsPaths = new List<string>();
The result of this is that I get the entire array field replaced in the Inspector with an ObjectField, and an error occurs, complaining that there's no prop.stringValue
.
While researching this, I came across this post on the forums that suggests that this ought to be possible.
I have tried changing rootSoundsPaths
to be of type string[]
, but no change. It's also possible this is breaking because this is a defined within a nested serialized class, but that seems to be clutching at straws...
Hmm, Rune's example (in that forum post) doesn't work either. If I use this:
[Range (0, 10)]
public float[] myFloats;
The property drawer just displays an error, saying Range should only be used with float or int. Looks like array support is missing, broken, or not released yet. (I'm on Unity 4.1.5.)
Answer by Jamora · Aug 01, 2013 at 05:53 AM
The reason you got the error at prop.stringvalue is that prop wasn't a string; it was an array. So after a few tweaks and Unity crashes, I managed to get this cobbled together. It's not pretty; all the rects overlap eachother... but it works, at least for the List. Didn't check if it worked for the actual string...
[CustomPropertyDrawer(typeof(ResourceReferenceAttribute))]
public class ResourceReferenceDrawer : PropertyDrawer
{
List<string> debugList = new List<string>();
int index = 0;
public override void OnGUI (Rect pos,
SerializedProperty prop,
GUIContent label)
{
index = EditorGUI.IntField(pos,"Size:",index);
if(prop.isArray && index > 0){
while(index > prop.arraySize)
prop.InsertArrayElementAtIndex(prop.arraySize);
while(index < prop.arraySize)
prop.DeleteArrayElementAtIndex(prop.arraySize-1);
}
if(prop.arraySize>0){
for(int i = 0; i<prop.arraySize;i++){
Object obj = AssetDatabase.LoadMainAssetAtPath (prop.GetArrayElementAtIndex(i).stringValue);
Object newObj = EditorGUI.ObjectField (pos, label, obj, typeof(GameObject), false);
if (obj != newObj) {
prop.GetArrayElementAtIndex(i).stringValue = AssetDatabase.GetAssetPath (newObj);
}
debugList.Add(prop.GetArrayElementAtIndex(i).stringValue);
pos.y += 20;
}
}
if(!prop.isArray || prop.arraySize == 0){
Object newObj = null;
newObj = EditorGUI.ObjectField (pos, label, newObj, typeof(GameObject), false);
if (newObj != null) {
prop.InsertArrayElementAtIndex(0);
prop.GetArrayElementAtIndex(0).stringValue = AssetDatabase.GetAssetPath (newObj);
}
}
foreach(string s in debugList)
Debug.Log(s);
debugList.Clear();
}
}