Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Bug Can't create bindings for an enum - "not compatible"

Discussion in 'UIElements' started by Baste, Aug 14, 2019 at 7:35 PM.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,096
    Code (csharp):
    1. public enum MyEnum
    2. {
    3.     A,
    4.     B,
    5.     C
    6. }
    7.  
    8. public class Test : MonoBehaviour
    9. {
    10.     public MyEnum myEnum;
    11. }
    12.  
    13. [CustomEditor(typeof(Test))]
    14. public class TestEditor : Editor
    15. {
    16.     private VisualElement rootElement;
    17.  
    18.     private void OnEnable()
    19.     {
    20.         rootElement = new VisualElement();
    21.     }
    22.  
    23.     public override VisualElement CreateInspectorGUI()
    24.     {
    25.         rootElement.Clear();
    26.  
    27.         var enumField = new EnumField("My Enum");
    28.         enumField.bindingPath = "myEnum";
    29.  
    30.         rootElement.Add(enumField);
    31.         rootElement.Bind(serializedObject);
    32.  
    33.         return rootElement;
    34.     }
    35. }
    Gives:
    Code (csharp):
    1. Field type UnityEditor.UIElements.EnumField is not compatible with Enum property "myEnum"
    2. UnityEditor.UIElements.BindingExtensions:Bind(VisualElement, SerializedObject)
    3. TestEditor:CreateInspectorGUI() (at Assets/Editor/TestEditor.cs:23)
    4. UnityEditor.InspectorWindow:RedrawFromNative()
    I tried making a PopupField<MyEnum>, that gave the same result.

    This should work, right?
     
  2. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    88
    Hello,

    This is an oversight that is supposed to be fixed in 2019.3, but as it turned out I have encountered a different issue while trying out your script in both 2019.3 and 2019.2. We've added that to our list of issues.

    Which version of Unity were you trying this with ?
     
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,096
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,096
    I worked around it by using a PropertyField for the property, but that runs into a different issue; I'm not able to get
    RegisterCallback to do anything for a PropertyField that targets an enum:

    Code (csharp):
    1.  
    2. using System;
    3. using UnityEditor;
    4. using UnityEditor.UIElements;
    5. using UnityEngine;
    6. using UnityEngine.UIElements;
    7.  
    8. [CustomEditor(typeof(Test))]
    9. public class TestEditor : Editor
    10. {
    11.     private VisualElement rootElement;
    12.  
    13.     private void OnEnable()
    14.     {
    15.         rootElement = new VisualElement();
    16.     }
    17.  
    18.     public override VisualElement CreateInspectorGUI()
    19.     {
    20.         rootElement.Clear();
    21.  
    22.         var enumProp = new PropertyField(serializedObject.FindProperty("myEnum"));
    23.         var intProp  = new PropertyField(serializedObject.FindProperty("val"));
    24.  
    25.         // none of these gets called
    26.         enumProp.RegisterCallback<ChangeEvent<MyEnum>>(Callback_MyEnum);
    27.         enumProp.RegisterCallback<ChangeEvent<Enum  >>(Callback_Enum);
    28.         enumProp.RegisterCallback<ChangeEvent<int   >>(Callback_Int);
    29.         enumProp.RegisterCallback<ChangeEvent<object>>(Callback_Object);
    30.  
    31.         // this gets called
    32.         intProp.RegisterCallback<ChangeEvent<int>>(Callback_Int);
    33.  
    34.         rootElement.Add(enumProp);
    35.         rootElement.Add(intProp);
    36.         rootElement.Bind(serializedObject);
    37.         return rootElement;
    38.     }
    39.  
    40.     private void Callback_MyEnum(ChangeEvent<MyEnum> evt) => Debug.Log("My enum");
    41.     private void Callback_Int   (ChangeEvent<int>    evt) => Debug.Log("int");
    42.     private void Callback_Enum  (ChangeEvent<Enum>   evt) => Debug.Log("enum");
    43.     private void Callback_Object(ChangeEvent<object> evt) => Debug.Log("object");
    44. }
     
  5. unity_IpxdANggCs1roQ

    unity_IpxdANggCs1roQ

    Joined:
    Feb 19, 2018
    Posts:
    10
    Maybe, this could be helpful. But, I'm on 2019.3.0a12
    Code (CSharp):
    1.  
    2. [CustomEditor(typeof(Test))]
    3. public class TestEditor : Editor
    4. {
    5.   Test _boundData;
    6.  
    7.   public override VisualElement CreateInspectorGUI()
    8.   {
    9.     /*
    10.     ...
    11.     after setting up your inspector
    12.     ...
    13.      */
    14.  
    15.     // get object which is bound with this custom editor
    16.     _boundData = (Test)target;
    17.     // set visualelement reference which you want to send event to from your Test object.
    18.     _boundData.event_send_target = yourVisualElement;
    19.     // register event callback
    20.     yourVisualElement.RegisterCallback<ChangeEvent<Test>>(your_callback_function);
    21.  
    22.   }
    23. }
    24.  
    25. public class Test : MonoBehaviour
    26. {
    27.   public MyEnum myEnum;
    28.   public VisualElement event_send_target;
    29.  
    30. #if UNITY_EDITOR
    31.   // detect change and send event
    32.   void OnValidate()
    33.   {
    34.     // send event
    35.     if (event_send_target != null)
    36.     {
    37.       using (var changeEvent = ChangeEvent<Test>.GetPooled())
    38.       {
    39.         changeEvent.target = event_send_target;
    40.         event_send_target.SendEvent(changeEvent);
    41.       }
    42.     }
    43.   }
    44. #endif
    45. }
    46.   public enum MyEnum
    47.   {
    48.     A,
    49.     B,
    50.     C
    51.   }
     
    Last edited: Aug 17, 2019 at 1:15 PM
    Baste likes this.
  6. unity_IpxdANggCs1roQ

    unity_IpxdANggCs1roQ

    Joined:
    Feb 19, 2018
    Posts:
    10
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,096
    Thanks!

    I'd really prefer not to leak details about the editor into the runtime code, but I can hide those details behind #if's, so I'll look into if it's viable..