Search Unity

Adding VisualElement to default Editor

Discussion in 'UI Toolkit' started by JohannesPD, Jan 23, 2020.

  1. JohannesPD

    JohannesPD

    Joined:
    Jan 9, 2020
    Posts:
    2
    In Unity 2020.1.0a19, with a custom editor I can add text to the bottom of a MonoBehaviour's default Inspector GUI using:

    Code (CSharp):
    1. [CustomEditor(typeof(Test))]
    2. public class TestEditor : Editor
    3. {
    4.     public override void OnInspectorGUI()
    5.     {
    6.         base.OnInspectorGUI();
    7.         GUILayout.Label("test imgui");
    8.     }
    9. }
    However I can't seem to figure out how to do the same thing using just the new
    CreateInspectorGUI()
    .

    I can override
    public VisualElement CreateInspectorGUI()
    but the base just returns null. I can't seem to get a visual element that is the current inspector, and then append a
    TextElement
    to that:

    Code (CSharp):
    1. [CustomEditor(typeof(Test))]
    2. public class TestEditor : Editor
    3. {
    4.     public override VisualElement CreateInspectorGUI()
    5.     {
    6.         VisualElement gui = base.CreateInspectorGUI(); // returns null
    7.         TextElement text = new TextElement();
    8.         text.text = "test element";
    9.         gui.Add(text); // unsurprising null ref exception
    10.         return gui;
    11.     }
    12. }
    I'm assuming that this is because the Inspector has not been fully ported and so it only falls back to the original
    OnInspectorGUI()
    implementation when
    CreateInspectorGUI()
    returns null. Is that about right?

    Is there any workaround or easy way I can start using VisualElements to extend a default base Inspector without having to manually re-draw each property using the new system?
     
    Last edited: Jan 23, 2020
  2. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,913
    I think it's like this:
    Code (csharp):
    1. [CustomEditor(typeof(Test))]
    2. public class TestEditor : Editor
    3. {
    4.    public override VisualElement CreateInspectorGUI()
    5.    {
    6.        var container = new VisualElement();
    7.  
    8.        container.Add(new IMGUIContainer(OnInspectorGUI));
    9.        container.Add(new Label("Test"));
    10.  
    11.        return container;
    12.    }
    13.  
    14.    public override void OnInspectorGUI()
    15.    {
    16.        DrawDefaultInspector();
    17.    }
    18.  
    19. }
     
  3. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    Goodness... They decided using "HTML" and "CSS" (note the quotes) instead of XAML (note the lack of quotes) wasn't enough, so they made a basic operation unintuitive.
    By the way, `DrawDefaultInspector()` isn't even an exact replica. Actually, I have the hypothesis that it is, but your editor overrides parts of the default editor, or something. The custom editor doesn't work with certain components either, I suppose it's vice-versa of the above.

    Unity, get your S*** together: this is .NET, not the web. You make the much needed move of killing UnityScript and then this? Are you trying to apologize to the web developers or what? This is also .NET in 2020, not in the 90s; why the hell do we need an attribute instead of just doing this:
    Code (CSharp):
    1. public class MonoBehaviorEditor : Editor<MonoBehavior> // Notice the lack of the "u" in MonoBehaviour. US English.
    2. {
    3.     public override bool EditorForChildClasses => true; // Don't worry, I do understand the excruciating pain caused by following established .NET naming conventions.
    4.  
    5.     public override VisualElement CreateInspectorGui() // Another convention: "Gui" instead of "GUI": https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.Uri/src/System/Uri.cs#L260
    6.     {
    7.         VisualElement visualElement = base.CreateInpectorGui();
    8.  
    9.         visualElement.hierarchy.Insert(0, new HelpBox($"Type: {Target.GetType().Name}", HelpBoxMessageType.Info));
    10.  
    11.         return visualElement;
    12.     }
    13. }
    Now tell me the current way is better. Backwards compatibility is a problem when it gets in your way, you know. Ask, I don't know, this guy. There's just way too much wrong with Unity right now.

    EDIT: Okay, I calmed down a little. I figured out that you don't actually have to override `OnInspectorGUI()` there, you can just call base: `container.Add(new IMGUIContainer(base.OnInspectorGUI))`. This doesn't change my opinion on anything described, though.
     
    Last edited: Feb 23, 2020
    IndieForger and LudiKha like this.
  4. andrew-lukasik

    andrew-lukasik

    Joined:
    Jan 31, 2013
    Posts:
    249
    Thanks @Stardog !

    Code (CSharp):
    1. [CustomEditor(typeof(Test))]
    2. public class TestEditor : Editor
    3. {
    4.     public override VisualElement CreateInspectorGUI()
    5.     {
    6.         var root = new VisualElement();
    7.         root.Add(new IMGUIContainer(base.OnInspectorGUI));
    8.         root.Add(new Label("This is a custom inspector"));
    9.         return root;
    10.     }
    11. }
    Code (CSharp):
    1. [CustomEditor(typeof(Test))]
    2. public class TestEditor : Editor
    3. {
    4.     public override VisualElement CreateInspectorGUI()
    5.     {
    6.         var root = new VisualElement();
    7.         InspectorElement.FillDefaultInspector( root , this.serializedObject , this );
    8.         root.Add(new Label("This is a custom inspector"));
    9.         return root;
    10.     }
    11. }
     
    Last edited: Oct 31, 2022