Injecting Focused Inspector into UI?

Is there a way to launch a Focused Inspector programmatically? Perhaps via reflection?
I’m building an editor with the UI toolkit and would like to “inject” one into a VisualElement area.

Previously, I was doing this by launching an inspector instance. This has a lot of cons though. I have to unlock that inspector instance, cache the Selection.activeTransform, change the activeTransform, re-lock my inspector instance, and finally change the activeTransform for the rest of the inspectors back to the cached selection.

I’m hoping Focused Inspector’s are a way I can achieve this, but perhaps a PropertyEditor?

Any input would be greatly appreciated. Thank you!

Have you tried the InspectorElement? See:

But also, I’m not sure what you mean by “Focused Inspector”. Do you mean the locked mini-inspector that you get by right-clicking an object or component or asset and selecting “Properties”?

Thanks for the reply, Damian.
Yes, I tried InspectorElement, and that works great for drawing all the properties. However, I’m literally needing all the functionality of the inspector, ideally. So the collapsible headers, the Add Component button etc. This would be a direction I could potentially go without embedding the inspector, if I could get the headers and Add Component functionality in.

And yes, that’s exactly what I mean https://docs.unity3d.com/Manual/InspectorFocused.html.
I love that feature, by the way :slight_smile: Is it possible to launch one via reflection? Or are they just an InspectorWindow with some changes so they don’t change on Selection being changed?

I figured out how to launch an InpectorWindow via reflection previously. And right now I’m adding the Inspector’s rootVisualElement as a child element to a VisualElement I’ve defined in my UXML. That’s working okay for the most part, it just feels very hacky. In 2019 I also have to make sure to remove the inspector on editor close so that there isn’t an error about a window previously existing in my Unity layout upon restarting the editor.

Then again, I’m sure you guys didn’t design EditorWindow’s to be embedded in other EditorWindow’s like that in the first place haha.

I’m basically building a custom panel that only shows objects in the scene with a specific component type (there’s usually 100~ in the scene at a time). This makes it easy to work with objects people in my department commonly need to switch between. And being able to have our own full inspector in the window prevents the other inspectors and the hierarchy selection from being tied up and will speed up their work flow pretty drastically, hence the design choice.

Perhaps I should consider InspectorElement and re-creating the header and Add Component functionality. Do you think what I’m currently doing could have some side effects I’m not aware of?

Basically, this. :slight_smile: You are very far from expected use cases, but don’t let that discourage you. I am a bit curious why you can’t have your custom EditorWindow just have the collection of the 100~ scene items, with the ability to select them, but continue to use the normal Inspector for actual editing. Having 100~ embedded Inspectors in a single EditorWindow (if I understand correctly) is going to lead to some bad times when everything is UI Toolkit and all those controls need to be created on the first frame.

This, as well. :slight_smile: Your best bet is to recreate the component headers (just use Foldouts, you don’t need to be fancy here) and the Add Component functionality (I’d need to check the code, but either this is easy via reflection, or you just create your own simple auto-complete text field).

The main issue with stealing another EditorWindow’s rootVisualElement is that any code in that window that assumes UI lives there, or any code in the UI that assumes it’s running in that window, will break. And you’ll never know when this break happens because all of this is internal and we can break it at any time (like when you use reflection). You probably already know this, but VisualElements can only have one parent. So when you re-assign the parent of another EditorWindow’s rootVisualElement, you are literally stealing its entire UI. That’s not very nice of you.

1 Like

For work flow reasons, it’s important to us to not touch the Selection in the hierarchy, we really want to keep our inspector and Unity’s inspector’s separate for hierarchy navigation reasons. We lean heavily into Unity Event’s, and not forcing the hierarchy ScrollView to jump around would really help.

This has been working pretty great, and I’ve successfully cloned most of the inspector behavior, including the headers and Add Component button thanks to help from the Unsupported binding’s class. Visually, my inspector and Unity’s look almost 1:1 :smile:

The next piece of the puzzle is figuring out a way to detect components being added/removed. Right now, I’m basically creating editors for all the components using GetComponents on selection change. That’s working nicely, but I don’t want to have to run GetComponents on every single frame for the sake of keeping my inspector updated with what components are actually on the object. I feel like that would be really heavy, and it would be a mess creating/deleting editors for each component.

Is there perhaps a delegate hidden away somewhere I can use for detecting when a component has been added or removed from a target? I’ve been scrubbing through the UnityCsReference repository, trying to see if there’s some undocumented class that might be able to help, but not really finding anything.

Ideally, I would like to keep my inspector in sync with Unity’s, just in case someone changes what components are on the object in Unity’s regular inspector as well.

1 Like

You can launch one with EditorUtility.OpenPropertyEditor.

EDIT
I know this isn’t specifically related to UITK, but they should add a mention of that method in the Focused Inspectors page of the Manual.

2 Likes

Good find! I’m sure we’ll lean into this once we migrate to 2021.

In 2020.x you can use reflection to open these windows too.

1 Like