Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

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