- Home /
Editor Scripting: calling a Property Drawer by reference
is there some way that I could call a property Drawer for a class from either a CustomInspector, or from a EditorWindow (essentially another Editor class)?
Context: I have gone through and made some property Drawers for classes, and was wondering if I could just call those PropertyDrawers in some CustomInspectors, so that I can get the same behavior, and appearance.
Answer by gardian06 · Sep 24, 2013 at 03:54 PM
mostly solved by using the suggestion posted here by @Bunny83 though I have found that because I use List in several places that I need to find a different approach to getting at those.
// in [customInspector(typeof(ClassA))]
ClassA classA;
SerializedObject obj;
SerializedProperty property;
// in OnEnable
classA = (ClassA)target;
obj = new SerializedObject(classA);
// later in OnInspecotGUI
// CustomPropertyDrawer is for field named "data"
property = obj.FindProperty("data");
EditorGUI.PropertyField(GUILayoutUtility.GetRect(
(float)Screen.width, EditorGUI.GetPropertyHeight(property) ),
property);
this uses the CustomePropertyDrawer that was defined for the type "data" is
Answer by whydoidoit · Sep 24, 2013 at 02:39 PM
Well you could use the EditorGUI.PropertyField to have the system draw them for you.
Or you could hack around and retrieve the actual drawer for a given serialized property:
static Func<SerializedProperty, PropertyDrawer> getDrawer;
public static PropertyDrawer GetDrawer(SerializedProperty property)
{
if(getDrawer == null)
{
var mtd = typeof(PropertyDrawer).GetMethod("GetDrawer", BindingFlags.NonPublic | BindingFlags.Static);
getDrawer = (Func<SerializedProperty, PropertyDrawer>)Delegate.CreateDelegate(typeof(Func<SerializedProperty, PropertyDrawer>), null, mtd);
}
return getDrawer(property);
}
could you show the other half of the example (actually calling it),
or how to get from a data value/pointer to a SerializedProperty?
Hey @whydoidoit
First, love your answers -- thanks for all of them! (from one of the lurkers).
Second, this glorious hack doesn't seem to work in Unity 4.5.0f6. I guess GetDrawer() might have been removed from PropertyDrawer? Any chance for an updated version (using your magical Editor insight!) ?
(line 7's $$anonymous$$ethodInfo comes back null.)
Thanks, Rupert.
$$anonymous$$y use-case is wishing to delegate from one PropertyDrawer to another -- easy enough for OnGUI() (simply use PropertyField()) but harder for GetPropertyHeight()! (suggestions that achieve this welcome too!)
Found answer in http://answers.unity3d.com/questions/542669/displaying-a-list-of-propertydrawers-in-a-custom-i.html
One can simply ask EditorGUI.GetPropertyHeight() and it calls the target's PropertyDrawer.GetPropertyHeight() for you :-)
HTH others following this path. Rupert.
@Arkade:
Well, it seems they changed a lot. All the property drawer stuff is now in a seperate internal class called "ScriptAttributeUtility". They implemented a new class called "PropertyHandler" (also internal) which handles the drawing of a SerializedProperty including it's children. The PropertyHandler itself has a methods to deter$$anonymous$$e the correct "Type" for a certain property.
There is now also a DecoratorDrawer and "ScriptAttributeUtility.GetDrawerTypeForType" might return either a PropertyDrawer or a DecoratorDrawer. Inside the PropertyHandler they do this:
public void HandleDrawnType(Type drawnType, Type propertyType, FieldInfo field, PropertyAttribute attribute)
{
Type drawerTypeForType = ScriptAttributeUtility.GetDrawerTypeForType(drawnType);
if (drawerTypeForType != null)
{
if (typeof(PropertyDrawer).IsAssignableFrom(drawerTypeForType))
{
if (propertyType.IsArrayOrList())
{
return;
}
this.m_PropertyDrawer = (PropertyDrawer)Activator.CreateInstance(drawerTypeForType);
this.m_PropertyDrawer.m_FieldInfo = field;
this.m_PropertyDrawer.m_Attribute = attribute;
}
else
{
// [... handle DecoratorDrawer]
}
}
}
It looks like the PropertyDrawers aren't chached seperately anymore. Only the PropertyHanders which contain the PropertyDrawer and an additional list of PropertyDecorators if there are some. If you just want a PropertyDrawer-instance, you might duplicate the above method but you have to use reflection to be able to call ScriptAttributeUtility.GetDrawerTypeForType.
All in all it's getting more and more complicated ;) You might want to download ILSpy and see for yourself.
wow, alright, Got to check that out. also thanks to @Bunny83 for the ILSpy, quite a mess, when the only thing you want to do is trigger the ProperyDrawer^^ but yeah, $$anonymous$$ches me a lot. Although i'm still a bit confused about that entire reflect into internal classes and functions^^ But hey we can't wait for the dev $$anonymous$$m to instantly fulfill our desires^^
Your answer

Follow this Question
Related Questions
Create an Attribute that references another property 1 Answer
Custom Editor script to show non-native class in inspector 1 Answer
Using CustomPropertyDrawer in OnGUI of ScriptableWizard 0 Answers
Multiple Instances of the Same Type of Editor Window 0 Answers
EditorWindow, Utility Popup, not using custom PropertyDrawers 0 Answers