Search Unity

Question PropertyDrawer used in multiple Editors does not update UI value when changed in one of them

Discussion in 'UI Toolkit' started by npatch, May 29, 2023.

  1. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    I'm writing a GraphView tool that operates on a ScriptableObject. I have polymorphic node types and to be able to easily draw their properties on either the tool or the inspector, I created PropertyDrawers and I'm manually selecting the PropertyDrawer to draw a serializedProperty with, based on Node type.

    1) For some reason, because the PropertyDrawer is getting fed a SerializedProperty from a ListView, FindRelativeProperty returns null, so I'm newing a SerializedObject on the property's objectValueReference. Is there an explanation as to why you need a new SO to get a relative property?!

    Among the nodes there is one whose derived type contains a VideoClip property. Initially I had used a PropertyField for it.
    2) PropertyField gets the serializedProperty as a parameter, yet does not render at all. I have added the field to the root VisualElement. You need to explicitly BindProperty(videoClipProperty) to it for the field to get rendered.

    3) While having the same node rendered with two instances of the PropertyDrawer (one in graph tool and one in inspector), I tried changing the Clip reference to a specific clip. Both instances update instantly. But when I try to select None to clear the value, only the PropertyDrawer that I'm not engaging with updates fully(e.g. Change the clip in Inspector, Graph tool updates fully, Inspector does not) and this only ever happens when I revert the field back to None. Works properly if I set a reference to another existing clip. The one I engage with, actually updates its underlying value correctly, but does not update its UI. If I click on the field's reference it doesn't show an asset in Project window. I tried all sorts of things with serializedObject.Update, ApplyModifiedProperties and all kinds of Callback registrations (RegisterEvent<ChangeEvent>, RegisterValueChangeEvent, TrackPropertyValue on the field), no dice. Also tried adding EditorUtility.SetDirty on the targetObject of the SerializedProperty which supposedly triggers a repaint, still no dice. Tried field.MarkDirtyRepaint. Again no dice.

    The only solution after losing a lot of time, was to try switching to an ObjectField which supposedly PropertyField should default to for this type of property. Works without callback registration or serializedObject.Update/Apply.
    Suddenly both Drawers have properly updated UI when reverting from an asset reference to None.

    Can anyone explain what's going on? Am I missing sth? Or is this a bug?
     
    Last edited: May 29, 2023
  2. cpalma-unity

    cpalma-unity

    Unity Technologies

    Joined:
    Nov 30, 2020
    Posts:
    110
    Hi,

    You still need to call Bind() even if you call the constructor with SerializedProperty. This might be the cause of some of the issues you are having (1 and 2).

    3 sounds like a bug. Could you fill a bug report so we can look into it? https://unity.com/releases/editor/qa/bug-reporting

    Thank you.
     
  3. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    For 1), I bind the List<Node> with BindProperty to the ListView. Then in the BindItem function I just GetArrayElementAtIndex to get the SerializedProperty from the list, find the drawer by type(of the objectReferenceValue) and then use the property with the drawer's CreatePropertyGUI function.
    Am I missing sth on what to bind where? Do I need to bind the property to the drawer somehow before being able to call FindRelative within CreatePropertyGUI?!

    As for 3), I'll see if I can repro this in a smaller project.


    UPDATE: Realizing I was only trying this out with both the tool and inspector in view at all times, I tried the PropertyField again but this time without the tool, so just one PropertyDrawer being used (PD also overrides cancache and returns false). Still fails when set back to None.
     
    Last edited: May 29, 2023
  4. npatch

    npatch

    Joined:
    Jun 26, 2015
    Posts:
    247
    CASE IN-42431

    Weirdly enough, the link in the mail does not allow me to see the ticket. Tells me I have no access to the request.

    Also I found another issue while making a simpler repro.

    Made this Scriptable with a List of Node (just string Name and VideoClip Clip properties). When you press the Add button of the List (+), it creates a new node but the clip PropertyField does not immediately render even in its default state (null value). Only does so after reselecting the asset.

    Tried single Node property on Scriptable. It also has the reference->None issue. And the same applies with a MonoBehaviour with the same Node node property.

    Everything so far points to PropertyField. And specifically only the UIElements version. Tried it with the IMGUI version( CustomInspector calling OnInspectorGUI with EditorGUILayout.PropertyField), having disabled the PropertyDrawer for Node, but had no issue. As soon as, I switched the CustomInspector of the Scriptable back to UIElements (CreateInspectorGUI and PropertyField), it failed again.

    UPDATE: Bug got confirmed and has been added to Issue Tracker.
    https://issuetracker.unity3d.com/is...n-changing-it-back-from-a-valid-asset-to-none
     
    Last edited: May 30, 2023
    griendeau_unity likes this.
  5. griendeau_unity

    griendeau_unity

    Unity Technologies

    Joined:
    Aug 25, 2020
    Posts:
    248
    Thanks, I see the bug in our system and the new information is part of it.