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

Force CreateInspectorGUI and CreatePropertyGUI

Discussion in 'UI Toolkit' started by BubbaRichard, Apr 9, 2020.

  1. BubbaRichard

    BubbaRichard

    Joined:
    Jul 1, 2012
    Posts:
    51
    I've searched but honestly I couldn't think of what to search for :)
    I have a few VisualElement based editors and drawers and I've come to a point where I need to reload the drawers, like when you deselect the gameobject and reselect it. I believe I need to force CreateInspectorGUI to make it reload the drawers but I couldn't find a way. Repaint from anywhere I could and I searched for refresh, load, reload etc but I couldn't find it. Any suggestions would be much appreciated!
     
  2. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    733
    Hello, what do you mean by "reload the drawers" ?

    Do you just need to cause a repaint? Or re-create the hierarchy of elements returned by
    CreatePropertyGUI
    ?
     
  3. BubbaRichard

    BubbaRichard

    Joined:
    Jul 1, 2012
    Posts:
    51
    I need it to recreate the hierarchy.

    When a EnumField changes, a large number of the other fields that are in a Propertydrawer are changed, some are hidden and others that were hidden are shown. Numerous mono behaviours implement the component represented by the PropertyDrawer but each have a different purpose for it. I need the PropertyDrawer to rebind but if I try to rebind in the EnumFields change event or valuechange event then I get an infinite loop locking up Unity

    This code almost works

    private EnumField m_efstyle;

    //the property field attached to the drawer that I need to reload, invalidate or whatever
    private PropertyField m_pfdimensions;


    public override VisualElement CreateInspectorGUI()
    {
    ...............

    m_efstyle = new EnumField()
    {
    label = "Style"
    };
    m_efstyle.bindingPath = "m_definition.m_style";
    m_efstyle = RegisterCallback<ChangeEvent<Enum>, VisualElement(StyleChanged, root);
    ......
    }

    private void StyleChanged(ChangeEvent<Enum> e, VisualElement root)
    {
    //root = m_pfdimensions.panel.visualTree.ElementAt(1);
    //stopping the infinite loop
    m_efstyle.UnregisterCallback<<ChangeEvent<Enum>, VisualElement>(StyleChanged);
    serializedObject.ApplyModifiedProperties();

    //this call updates the backend
    m_lab.m_definition.InitializeId();
    serializedObject.Update();
    m_pfdimensions.UnBind();
    m_pfdimensions.Bind(serializedObject);
    m_efstyle.RegisterCallback<ChangeEvent<Enum>, VisualElement>(StyleChanged, root);
    }

    This works AFTER the first change of the enumfield but not on the first change of the enumfield. The enum is specific to each monobehaviour implementing the m_dimensions class.

    Thank you for any help,
    Bubba
     
  4. andycodes

    andycodes

    Joined:
    Jan 22, 2013
    Posts:
    39
    Was a solution to this ever found? I'm in a similar situation here where I have a button that creates a new instance of a field when clicked on, but I always have to click away before being able to see the change reflected after clicking the button.
     
  5. DmitryMatveev

    DmitryMatveev

    Joined:
    May 9, 2013
    Posts:
    4
    I don't think that it is possible to make Unity editor to invoke CreateInspectorGUI method after the Editor was created and it does not even sound right to try to make it do so.

    So one solution I found was to attach a change callback on a depenency property and then inside that callback I get hold of the previously created inspector GUI component and change it there. This seems like the correct way to go about it, correct me if I am wrong.

    Example editor implementation:
    Code (CSharp):
    1.  
    2.  
    3.     private void OnEnable()
    4.     {
    5.         FormHandlerInstance = (FormHandler)target;
    6.         var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("path/to/ui_document.uxml");
    7.  
    8.         RootElement = new VisualElement();
    9.         visualTree.CloneTree(RootElement);
    10.  
    11.         var targetDocument = RootElement.Query<ObjectField>("MySelector").First();
    12.         targetDocument.objectType = typeof(UIDocument);
    13.         targetDocument.value = FormHandlerInstance.LocalUIDocument;
    14.         targetDocument.RegisterValueChangedCallback(DocumentChanged);
    15.     }
    16.  
    17.     private void DocumentChanged(ChangeEvent<UnityEngine.Object> change)
    18.     {
    19.         Undo.RecordObject(FormHandlerInstance, "Modified property in FormHandler");
    20.         FormHandlerInstance.FromDocument = (UIDocument)change.newValue;
    21.  
    22.         if (PrefabUtility.GetPrefabInstanceStatus(FormHandlerInstance.gameObject) == PrefabInstanceStatus.Connected)
    23.         {
    24.             PrefabUtility.RecordPrefabInstancePropertyModifications(FormHandlerInstance);
    25.         }
    26.  
    27.         UpdateEditorFields();
    28.     }
    29.  
    30.  
    31.     // Create an editor component for each TextField in target UIDocument
    32.     private void UpdateEditorFields()
    33.     {
    34.         var inputs = FormHandlerInstance.FromDocument?.rootVisualElement
    35.             .Query<TextField>()
    36.             .ToList()
    37.             ?? new List<TextField>();
    38.  
    39.         foreach (var input in inputs)
    40.         {
    41.              // create and add ui component here as needed
    42.         }
    43.     }
    44.