fieldInfo member is null in ObjectDrawer instance

slipyfrog

New member
Hello I hope you are doing well! Thanks again for the great support and BT product here. Just a quick question regarding the ObjectDrawer its fieldInfo member.


Goal:
I want to be able to access type information regarding the field is being drawn by a custom ObjectDrawer.

Problem:
fieldInfo is not set when the ObjectDrawer is created from an ObjectDrawerAttribute attribute. Not sure if leaving this null in the case of an attribute triggered ObjectDrawer is by design or not. If so, how can I determine the type of the field that is being drawn? My thoughts are that it is a bug. In any case, here are the specifics:


Here is a a trivial example :
Code:
  public class MyTask : Conditional
  {
     [BTObjectReference]
     private Foo m_Foo;
  }

  [CustomPropertyDrawer ( typeof( AssigmentCheck ) )]
  public class BTObjectReferenceAttribute : ObjectDrawerAttribute
  {
  }

  [CustomObjectDrawer ( typeof( BTObjectReferenceAttribute ) )]
  public class BTObjectReferenceDrawer : ObjectDrawer
  {
     //-- fieldInfo is null but it should report info about m_Foo
    Object input = EditorGUILayout.ObjectField( label, (Object) value,fieldInfo.FieldType true );   // <-- fieldInfo is null :( :(
  }

The ObjectDrawer is created through the overload of GetObjectDrawer. In this version of the method, the objectDrawer fieldInfo is not set.

1603830958744.png

Minor API change request:
The sender of GetObjectDrawer has a reference to the fieldInfo instance. It can easily be passed down via a minor refactor to the ObjectDrawerForType method prototype.

1603831206983.png


Code:
if ((customAttributes = field.GetCustomAttributes(typeof (ObjectDrawerAttribute), true) as ObjectDrawerAttribute[]).Length <= 0
     || (objectDrawer2 = ObjectDrawerUtility.GetObjectDrawer(field, task, customAttributes[0])) == null)



As always, thanks for the ongoing support on the Behaviour Designer asset!

W
 

Attachments

  • 1603830943064.png
    1603830943064.png
    81.5 KB · Views: 2
Last edited:

Justin

Administrator
Staff member
Thanks! That does look like a good change. I am having trouble finding the same code that you are looking at though. Where did you see the following?

Code:
(customAttributes = field.GetCustomAttributes(typeof (ObjectDrawerAttribute), true) as ObjectDrawerAttribute[]).Length <= 0
 

slipyfrog

New member
Okay awesome! That code was from the BehaviorDesigner.Editor.FieldInspector class defined in FieldInspector.cs (line 109 inside the DrawField method) and (line 432 inside the DrawSharedVariable method).

Please let me know if you need more insight.

Thanks again!
 

Justin

Administrator
Staff member
Hmm, I'm still not seeing it. Are you running the latest version? Lets try this. There are two methods to GetObjectDrawer within the ObjectDrawerUtility:

Code:
public static ObjectDrawer GetObjectDrawer(Task task, FieldInfo field)
Code:
public static ObjectDrawer GetObjectDrawer(Task task, FieldInfo field, ObjectDrawerAttribute attribute)

Both of these have the field as a parameter. This what what you are looking for, correct?
 

slipyfrog

New member
Hey Justin.

I was on 1.6.4 but have just upgraded to 1.6.6.

Apologies on my last message - I just realized that I pointed you to the call that was one level too high.

You are correct that the GetObjectDrawer both take in the field parameter. However. only one of the methods actually assigns the the FieldInfo member of the newly created ObjectDrawer instance.

See below for snipers from the (v1.6.6) version of ObjectDrawerUtility.cs. Notice in Snippet A FieldInfo is assigned but in Snippet B that FiledInfo of the objectiveDrawer is not assigned. Snippet C presents the requested/proposed fix.


Snippet A
Code:
public static ObjectDrawer GetObjectDrawer(Task task, FieldInfo field)
{
  ObjectDrawer objectDrawer = (ObjectDrawer) null;
  Type objectDrawerType = (Type) null;
  if (!ObjectDrawerUtility.ObjectDrawerForType(field.FieldType, ref objectDrawer, ref objectDrawerType, (task == null ? 0 : task.GetHashCode()) + field.GetHashCode()))
    return (ObjectDrawer) null;
  if (objectDrawer == null)
  {
    objectDrawer = Activator.CreateInstance(objectDrawerType) as ObjectDrawer;
    ObjectDrawerUtility.objectDrawerMap.Add((task == null ? 0 : task.GetHashCode()) + field.GetHashCode(), objectDrawer);
  }
  objectDrawer.FieldInfo = field;
  objectDrawer.Task = task;
  return objectDrawer;
}

Snippet B
Code:
public static ObjectDrawer GetObjectDrawer(
  Task task,
  FieldInfo field,
  ObjectDrawerAttribute attribute)
{
  ObjectDrawer objectDrawer = (ObjectDrawer) null;
  Type objectDrawerType = (Type) null;
  if (!ObjectDrawerUtility.ObjectDrawerForType(attribute.GetType(), ref objectDrawer, ref objectDrawerType, (task == null ? 0 : task.GetHashCode()) + field.GetHashCode() + attribute.GetHashCode()))
    return (ObjectDrawer) null;
  if (objectDrawer != null)
  {
    objectDrawer.Task = task;
    return objectDrawer;
  }
  objectDrawer = Activator.CreateInstance(objectDrawerType) as ObjectDrawer;
  objectDrawer.Attribute = attribute;
  objectDrawer.Task = task;
  ObjectDrawerUtility.objectDrawerMap.Add((task == null ? 0 : task.GetHashCode()) + field.GetHashCode() + attribute.GetHashCode(), objectDrawer);
  return objectDrawer;
}



Snippet C (proposed changed)
Code:
public static ObjectDrawer GetObjectDrawer(
  Task task,
  FieldInfo field,
  ObjectDrawerAttribute attribute)
{
  ObjectDrawer objectDrawer = (ObjectDrawer) null;
  Type objectDrawerType = (Type) null;
  if (!ObjectDrawerUtility.ObjectDrawerForType(attribute.GetType(), ref objectDrawer, ref objectDrawerType, (task == null ? 0 : task.GetHashCode()) + field.GetHashCode() + attribute.GetHashCode()))
    return (ObjectDrawer) null;
  if (objectDrawer != null)
  {
    objectDrawer.Task = task;
    return objectDrawer;
  }
  objectDrawer = Activator.CreateInstance(objectDrawerType) as ObjectDrawer;
  objectDrawer.Attribute = attribute;

  // new code start
  objectDrawer.FieldInfo = field;  // <-- {We add this line to ensure that the FieldInfo is propagated to the ObjectDrawer.
  // new code end

  objectDrawer.Task = task;
  ObjectDrawerUtility.objectDrawerMap.Add((task == null ? 0 : task.GetHashCode()) + field.GetHashCode() + attribute.GetHashCode(), objectDrawer);
  return objectDrawer;
}
 

Justin

Administrator
Staff member
Ahh, I see it now. Thank you!

I can send you a new BD version with this change if you send me what version of Unity you are on.
 

slipyfrog

New member
thank you for this. I just migrated over to 2020.1.X

What is the best way to relay the update over?
 
Last edited:

slipyfrog

New member
Hey, Pardon the additional message here. Just wondering on an ETA for this? It is not a huge priority on my end but I did want to get a sense as to when I can loop back on this. Thanks again and please do rush to get this done if you are busy.
 
Top