Search Unity

Multiple Attributes

Discussion in 'Immediate Mode GUI (IMGUI)' started by BinaryCats, Feb 22, 2016.

  1. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    317
    Is it possible to know if a variable has multiple attributes, and what they are, from the drawer?


    --

    Case:
    I have an attribute called ReadOnly, This attribute disallows editing in the inspector.
    example code: http://answers.unity3d.com/questions/489942/how-to-make-a-readonly-property-in-inspector.html

    However, using ReadOnly on a variable which also uses the Range(...) attribute does not work. What happens is the variable is rendered in the inspector like a normal (read only) float and not like a Range attributed float.

    I would like to know what attributes are currently on the variable I am drawing (in the property drawer) so I can deal with them accordingly.
     
    Last edited: Mar 24, 2016
  2. skalev

    skalev

    Joined:
    Feb 16, 2012
    Posts:
    264
  3. MrMatthias

    MrMatthias

    Joined:
    Sep 18, 2012
    Posts:
    191
    you can do this with reflection:
    Code (CSharp):
    1. using System.Reflection;
    2. ...
    3.  
    4. FieldInfo[] fields = this.GetType ().GetFields (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    5. foreach (FieldInfo field in fields) {
    6.     object[] attributes = field.GetCustomAttributes (true);
    7. }
     
    jj_unity328 likes this.
  4. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    317
    Thanks for the reply, However, im not sure if you are barking up the wrong tree, or maybe I don't understand how to use that code.

    I Tried, to use your code, in my attribute's drawer, and discovered that the fields it got was the fields in that class. I don't want this, I want to get the field that the property is being drawn from and check it's attribute.

    This is the case I want to do this, ill update the OP as well.

    I have an attribute called ReadOnly, This attribute disallows editing in the inspector.
    example code: http://answers.unity3d.com/questions/489942/how-to-make-a-readonly-property-in-inspector.html

    However, using ReadOnly on a variable which also uses the Range(...) attribute does not work. What happens is the variable is rendered in the inspector like a normal (read only) float and not like a Range attributed float.

    I would like to know what attributes are currently on the variable I am drawing (in the property drawer) so I can deal with them accordingly.

    Thanks
     
  5. MaximusLitvinov

    MaximusLitvinov

    Joined:
    Jan 27, 2017
    Posts:
    1
    Hello I am having the same problem. Were you ever able to solve this issue?

    Thank you!
     
  6. TrickyHandz

    TrickyHandz

    Joined:
    Jul 23, 2010
    Posts:
    196
    @MaximusLitvinov The problem here is that you can't have 2 different PropertyDrawers for the same field. Unity will only use the first PropertyDrawer and ignore all others.
     
    Ash-Blue likes this.
  7. jj_unity328

    jj_unity328

    Joined:
    Jun 7, 2018
    Posts:
    22
    From a `SerializedProperty`, you can find the associated `FieldInfo` ( http://answers.unity.com/answers/1347452/view.html ) then use `GetCustomAttributes` or `GetCustomAttribue<YourAttribute>` if you're only looking for a specific one.

    If it doesn't return null, you know this other attribute is there too and you can call its drawer's GUI.

    Code (CSharp):
    1. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    2. {
    3.     // Do stuff before and/or after this if desired
    4.     if(HasAttr<MyAttr>(property))
    5.          new MyDrawer().OnGUI(position, property, label);
    6. }
    7.  
    8. private static bool HasAttr<T>(SerializedProperty property) where T: Attribute
    9. {
    10.     // Inspired by http://answers.unity.com/answers/1347452/view.html
    11.     // and https://forum.unity.com/threads/multiple-attributes.387515/#post-2566777
    12.     Type parentType = property.serializedObject.targetObject.GetType();
    13.     FieldInfo fi = parentType.GetField(property.propertyPath, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    14.     // fi is sometimes null for reasons I ignore but it still seems to work
    15.     return fi?.GetCustomAttribute<T>() != null;
    16. }
    @TrickyHandz You can if you call one GUI from the other.
     
    Last edited: Jul 30, 2018