Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Create a PropertyDrawer context menu

Discussion in 'Extensions & OnGUI' started by Estecka, Aug 2, 2018.

  1. Estecka

    Estecka

    Joined:
    Oct 11, 2013
    Posts:
    59
    Is it possible to create a right-click menu on a specifc propertyDrawer? Just like when you right click on an element in a list or an array.
    (I noticed that when using my custom propertyDrawer, the array's context menu no longer work, so I assume this menu is actually a part of the propertyDrawer ?)

    I found a lot of doc on how adding entries to various existing menu, but nothing about specifc properties.
     
  2. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    450
    Sure. Check for a MouseDown event with a button of 1, make sure the mouse position is inside the property rect, then create a
    GenericMenu
    and call
    ShowAsContext
    on it.
     
    Estecka likes this.
  3. Estecka

    Estecka

    Joined:
    Oct 11, 2013
    Posts:
    59
    @Madgvox Thanks a lot for the directions !
    If it can help anyone else, this is what the code would look like :

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. public class CustomDrawer : PropertyDrawer {
    7.     // Methods that will be called by the Context menu
    8.     SerializedProperty activeProperty;
    9.     void Expand     () { activeProperty.isExpanded = true;  }
    10.     void Unexpand() { activeProperty.isExpanded = false; }
    11.  
    12.  
    13.     public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
    14.         Event e = Event.current;
    15.      
    16.         if (e.type == EventType.MouseDown && e.button == 1 && position.Contains(e.mousePosition)) {
    17.          
    18.             activeProperty = property;
    19.             GenericMenu context = new GenericMenu ();
    20.          
    21.             context.AddItem (new GUIContent ("Expand"),    property.isExpanded, Expand);
    22.             context.AddItem (new GUIContent ("Unexpand"), !property.isExpanded, Unexpand);
    23.          
    24.             context.ShowAsContext ();
    25.         }
    26.  
    27.         /*...
    28.         Actually draw the property
    29.         ... */
    30.          
    31.     }//
    32.  
    33.  
    34. } // END Drawer
    35.  
    I noticed a small oddity though.
    If I use the context menu to change the SerializedProperty actual value, everything works perfectly. However, if a menu entry does nothing but changing the value of
    property.isExpanded
    , (like the code above), the inspector will actuall struggle to reflect these changes : sometimes it will take a small second to update, sometimes it won't update until I interact with it again, sometimes it flashes between 'expanded' and 'not expanded' for a moment before stabilizing... It can get even funkier when fiddling with more than one property in the inspector.
    I tried several tricks to try and force the inspector to repaint immediatly, but no luck.
    Any idea what's causing this ?
     
    Last edited: Aug 4, 2018
  4. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    92
    You have to call property.serializedObject.Update() before changing property and call property.serializedObject.ApplyModifiedProperties() after.
     
    karl_jones likes this.
  5. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    450
    Not for property drawers. That logic wraps the inspector GUI on a custom editor. If you put it in a property drawer it would at best do nothing and at worst cause state issues.

    You might try using
    EditorGUI.BeginProperty
    and
    EditorGUI.EndProperty
    , but I wouldn't be surprised if that doesn't work since the callback for the context menu is not synchronous with the GUI method.
     
  6. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    3,025
    If you are using a context menu then the Update and Apply will be missed as it's not done inline with PropertyDrawer code, menus are executed at a different time. Calling Apply inside the menu is fine and should solve the issues.
     
    Madgvox likes this.
  7. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    450
    When you put it like that it seems bloody obvious that that'd be the case. I don't know why that didn't occur to me!
     
    karl_jones likes this.