Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

CustomAttribute and CustomPropertyDrawer on array?

Discussion in 'Scripting' started by gregzo, Jul 2, 2014.

  1. gregzo

    gregzo

    Joined:
    Dec 17, 2011
    Posts:
    795
    Hi!

    I've got a custom attribute on a value type array:
    Code (CSharp):
    1. public class MyValueAttribute : PropertyAttribute
    2. {
    3.      public MyValueAttribute(){} //Just an example...
    4. }
    5.  
    6. public class Test : MonoBehaviour
    7. {
    8.      [ MyValueAttribute() ]
    9.      public int[] myLovelyInts;
    10. }
    11.  
    12. [ CustomPropertyDrawer( typeof( MyValueAttribute ) ) ]
    13. public class ArrayDrawer : PropertyDrawer
    14. {
    15.      public override float GetPropertyHeight( SerializedProperty prop, GUIContent label )
    16.      {
    17.           return 100f;
    18.      }
    19.      
    20.     public override void OnGUI( Rect position, SerializedProperty prop, GUIContent label )
    21.     {
    22.           Debug.Log( prop.isArray ); //false
    23.     }
    24. }
    What I'm getting is one OnGUI call per array element, instead of just one with the array itself. Is that just the way it is, or am I missing something here?

    Many thanks for your help!

    Gregzo

    P.S.: At the moment, I'm just encapsulating the array in a serializable class, and that works fine. Hacky, though...
     
    Carrotpie likes this.
  2. edwardrowe

    edwardrowe

    Joined:
    Feb 11, 2014
    Posts:
    52
    (Late response - this is for people digging up this thread)

    DecoratorDrawers were introduced in 4.6, I believe, and they have the trait that they should only be drawn once for elements in an array: http://docs.unity3d.com/ScriptReference/DecoratorDrawer.html

    I'm not sure if your attribute "qualifies" for being decorative (it "conceptually is not meant to be associated with a specific field"), but it might work for what you are wanting.
     
    codestage likes this.
  3. derHugo

    derHugo

    Joined:
    Nov 1, 2017
    Posts:
    11
    Unfortunately this has nothing to do with the actual problem ... I am also stuck on creating an Attribute with CustomPropertyDrawer that accounts for a whole List or array instead to each element ...
     
    Carrotpie and noio like this.
  4. Pangamini

    Pangamini

    Joined:
    Aug 8, 2012
    Posts:
    54
    Did you solve this by any chance?
     
  5. hk1ll3r

    hk1ll3r

    Joined:
    Sep 13, 2018
    Posts:
    88
    2020 .... still wondering...
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    I had this issue years ago and came up with my solution.

    But it AIN'T pretty.

    I basically hijack the the entire unity editor process by creating my own custom editor that is flagged as:
    [CustomEditor(typeof(Component), true)]

    This forces anything without a custom editor to use my editor (all unity components are fine with theirs because I'm not trying to inject behaviour into their editors). Then I always make sure my custom editors inherit from this thing.

    Next, I actually reflect out the necessary methods from the UnityEditor.dll and make sure that it behaves exactly as Unity does.

    BUT... inject a layer to sort out my own custom attributes and manage them uniquely myself. One of which is propertydrawers that are flagged via a 'IArrayHandlingPropertyDrawer' which I then only call ONCE for the entire array allowing it to do what is needed for the array/list as a whole.

    ...

    All of this though... is not trivial.

    Like... just to give you a glimpse...

    The SPEditor class that hijacks the editor:
    https://github.com/lordofduct/space...er/SpacepuppyUnityFrameworkEditor/SPEditor.cs

    The IArrayHandlingPropertyDrawer interface:
    https://github.com/lordofduct/space...ameworkEditor/IArrayHandlingPropertyDrawer.cs

    The code that facilitates reflecting out all the internal unity stuff so I can make sure to call the appropriate functions to make the editor behave correctly:
    https://github.com/lordofduct/space...aster/SpacepuppyUnityFrameworkEditor/Internal

    And there is oh so much more going on.

    But I got it working... and it's how I got things like my 'ReorderableArrayAttribute' that draws arrays with the prettier ReorderList drawer:
    https://github.com/lordofduct/space...buteDrawers/ReorderableArrayPropertyDrawer.cs

    Which looks like:
    upload_2020-4-24_21-28-57.png

    Which is all accomplished via propertydrawers and attributes:
    Code (csharp):
    1.  
    2.         #region Fields
    3.  
    4.         [SerializeField]
    5.         [DefaultFromSelf(Relativity = EntityRelativity.Entity)]
    6.         [TypeRestriction(typeof(IPathSeeker))]
    7.         private Component _seeker;
    8.  
    9.         [SerializeField()]
    10.         [DefaultFromSelf(Relativity = EntityRelativity.Entity)]
    11.         [TypeRestriction(typeof(IPathingMovementStyle))]
    12.         private Component _movementStyle;
    13.  
    14.         [SerializeField]
    15.         [ReorderableArray]
    16.         private Transform[] _guardPoints;
    17.  
    18.         [SerializeField]
    19.         private bool _useInitialPointAsGuardPoint;
    20.  
    21.         [SerializeField]
    22.         private bool _alignWithGuardPoint;
    23.  
    24.         [SerializeField]
    25.         [Tooltip("Degrees per second")]
    26.         private float _alignSpeed = 90f;
    27.  
    28.         [SerializeField]
    29.         [TypeRestriction(typeof(IAIState))]
    30.         private Component _onFailState;
    31.  
    32.         //internal stuff
    33.         [System.NonSerialized()]
    34.         private IEntity _entity;
    35.  
    36.         [System.NonSerialized]
    37.         private Vector3 _initialPoint;
    38.         [System.NonSerialized]
    39.         private Quaternion _initialRotation;
    40.  
    41.         [System.NonSerialized()]
    42.         private IAIStateMachine _stateMachine;
    43.  
    44.         [System.NonSerialized()]
    45.         private RadicalCoroutine _pathQueryRoutine;
    46.  
    47.         #endregion
    48.  
    ...

    Sorry, I know this answer probably doesn't necessarily "help" you, because it's not something you can easily take and stick into your project. The source code for what I did is up there on my github, but I don't really offer support for any of it. It's up there mostly as like a public "hey, here's how I do what I do... if you want to read it, have fun!"
     
    Last edited: Apr 25, 2020
    Soraphis and tspersonal like this.
  7. hk1ll3r

    hk1ll3r

    Joined:
    Sep 13, 2018
    Posts:
    88
    Thanks @lordofduct . That actually helps. Good to know other people tried and to know their solutions. I'll take a deeper look into your git project later on. You have a lot going on there.
     
  8. tspersonal

    tspersonal

    Joined:
    Jul 26, 2019
    Posts:
    9
    "NaughtyAttributes" is a plugin in Unity Asset Store, and same as @lordofduct solution