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

Using PropertyDrawers and Enums to switch between extended classes

Discussion in 'Scripting' started by Lachee1, Apr 16, 2014.

  1. Lachee1

    Lachee1

    Joined:
    Aug 21, 2012
    Posts:
    16
    Hello Unity Community,

    I have been working/playing around with unitys PropertyDrawers, trying to make a script to allow me to more easily make my GUI's by using a set of extended classes base of one class called UIElement.

    What I wish to accomplish with this script is to be able to have a array (with buttons to move elements up and down [which will be covered by a editor script] ) with these elements in them and a enum pop above each one to change their type (eg: from button to a label, which will update the variables shown)

    So far it is going well, I have made a UIElement property that is displaying okay (ish) and the enum i am using to switch types is appearing and switchable, however I cannot seem to make it determine the extended version of UIElement i wish to use.

    I realize I might not be able to use this method, and thats okay, I will just stick it one class and a Object array to store variables, but any help / ideas would be awesome.

    Here is some code, to clear it up a bit:

    UIElement Class and extending classes
    Code (csharp):
    1.  
    2. public enum UIType { button = 0, label = 1};
    3.  
    4. [Serializable]
    5. public class UIElement {
    6.     public UIType elementType;
    7.  
    8.     public string name;
    9.  
    10.     public virtual void OnGUI () {}
    11.     public virtual UIType getUIType() { return UIType.label; }
    12. }
    13.  
    14. public class UIButton : UIElement {
    15.     public new UIType elementType = UIType.button;
    16.  
    17.     public Texture2D image;
    18.     public override void OnGUI () {
    19.        
    20.     }
    21.    
    22.     public static void OnInspector(Rect position,  SerializedProperty property) {
    23.         //EditorGUI.PropertyField(position, property.FindPropertyRelative("image"));
    24.         EditorGUI.PropertyField(position, property.FindPropertyRelative("name"));
    25.     }
    26.  
    27.     public static int InspectorLines() {
    28.         return 1;
    29.     }
    30. }
    31.  
    32. public class UILabel : UIElement {
    33.     public new UIType elementType = UIType.label;
    34.  
    35.     public string text;
    36.     public override void OnGUI () {
    37.  
    38.     }
    39.  
    40.     public static void OnInspector(Rect position,  SerializedProperty property) {      
    41.         //EditorGUI.PropertyField(position, property.FindPropertyRelative("text"));
    42.         EditorGUI.PropertyField(position, property.FindPropertyRelative("name"));
    43.     }
    44.  
    45.     public static int InspectorLines() {
    46.         return 1;
    47.     }
    48.  
    49.  

    PropertyDrawer Class:
    Code (csharp):
    1.  
    2.  
    3. [CustomPropertyDrawer(typeof(UIElement))]
    4. public class UIElementDrawer : PropertyDrawer {
    5.     UIType lastType;
    6.     public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
    7.         //Debug.Log(property.FindPropertyRelative("uiType").intValue);
    8.  
    9.         label = EditorGUI.BeginProperty(position, label, property);
    10.        
    11.         position.height = 16;
    12.  
    13.         SerializedProperty elementType = property.FindPropertyRelative("elementType");
    14.         lastType = (UIType) EditorGUI.EnumPopup(position,label,(UIType) elementType.intValue);
    15.         elementType.intValue = (int) lastType;
    16.  
    17.         position.y += 18;
    18.  
    19.         EditorGUI.PropertyField(position, property.FindPropertyRelative("name"));
    20.        
    21.         position.y += 18;
    22.  
    23.         //This works, however I cannot seem to assign it as a specific UIElemen
    24.         switch(lastType) {
    25.         default :
    26.             UIButton.OnInspector(position,property); break;
    27.  
    28.         case UIType.button :
    29.             UIButton.OnInspector(position,property); break;
    30.  
    31.         case UIType.label :
    32.             UILabel.OnInspector(position,property); break;
    33.  
    34.         }
    35.    
    36.         EditorGUI.EndProperty();
    37.     }
    38.  
    39.     public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
    40.         float height = 18F*2F;
    41.  
    42.         switch(lastType) {
    43.         default :
    44.             height += 18F * UIButton.InspectorLines(); break;
    45.            
    46.         case UIType.button :
    47.             height += 18F * UIButton.InspectorLines(); break;
    48.            
    49.         case UIType.label :
    50.             height += 18F * UILabel.InspectorLines(); break;
    51.            
    52.         }
    53.  
     
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    I think you're lacking a kind of wrapper that would hold your UIElement... Maybe I'm wrong, but I would go;

    Code (csharp):
    1.  
    2. public class UIContainer
    3. {
    4.      public UIType type;
    5.      // When type change, do "element = new UIButton()"...
    6.      public UIElement element;
    7. }
    8.  
     
  3. Lachee1

    Lachee1

    Joined:
    Aug 21, 2012
    Posts:
    16
    That is a good idea, however I don't know how (or even possible) to change the UIElement field using PropertyDrawers as they only return SerializedProperty on FindRelativeProperty.
     
  4. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    You could also not use PropertyDrawers.... My experience is extremely limited with them, sorry.
     
  5. Lachee1

    Lachee1

    Joined:
    Aug 21, 2012
    Posts:
    16
    you're right. Any ideas of how the editor code would go as it says in the docs it is not recommended to use 'target' when using OnInspectorGUI(), which is the only way I could think of doing it :|