- Home /
Precise Editor GUI Control Layout
Hi There
I am trying to create a custom inspector and in my Editor I am overriding OnInspectorGUI() to draw the UI for this editor GUI.
I have used GUI and GUILayout and the Editor GUI in the past but am admittedly a little (very) rusty.
I see that using GUI in the inspector doesn't appear to work well as Unity doesn't appear to know the height of your UI.
Using GUILayout seems to be fine, but when you want to have precise control over your layout, it seems to be quite tricky. I see there's a BeginArea() but this doesn't appear to be very useful, as you must specify a Rect and I have no idea how for down the inspector I currently am, so aside from guessing, which doesn't seem a great idea, I don't know how to specify the Rect reliably. I see there is GetLastControlRect() or some such call but this doesn't always tell me useful Rect - I often get 0,0,1,1.
A particular use-case I have is that I'd like to display an unwrapped cube so the user can pick a side. Something like the below:
E
NBST
W
The letters corresponding to north, east, south, west, top and bottom. Ignore the underscores.
I'd have a button for each box face, but getting this to layout so that the east and west faces on the top and bottom rows are aligned with the bottom (B) face is very tricky.
If anyone has any guidance as to how to create the above or use GUI or GUILayout to precisely place control for a custom inspector, then I'd be very pleased to hear your suggestions.
Cheers Bovine
Apologies, no idea why my line-breaks are not showing, the E is meant to above the B and the W is meant to be below the B, but hey ho. I'll do an image later if it's confusing.
Answer by Bunny83 · Jun 20, 2019 at 10:36 AM
I recommend to read my GUI crashcourse (Since the markdown here on UA is messedup since about 2 years now I have a copy on github which is formatted correctly).
The Inspector editor window is actually using optimised GUI blocks internally which doesn't involve GUILayout in the traditional sense. The top left corner is the top left of the whole inspector. If you create a custom inspector for one of your type, Unity will change the way the gui is handled. Yes in custom inspectors you should use GUILayout. Inside PropertyDrawers you must not as propertydrawers get a predefined Rect they have available. PropertyDrawers however can request any height they want for their property by overriding GetPropertyHeight.
Though since you created a custom editor you have to use GUILayout. If you read my crash course you might know already that almost all the GUILayout controls actually just call "GUILayoutUtility.GetRect" to get a Rect from the layout system and then use the corresponding GUI control with that Rect. You are free to use GUILayoutUtility.GetRect yourself and split that Rect according to your desired layout. That's actually what many of the built-in editor controls do. For example the prefix label width so all the content after the lables are indented equally.
Though instead of manually disecting one large allocated Rect you can also directly use the Layout system to arrange your different controls using several horizontal layout groups and using Space() and GUILayoutOptions to control the size of the different controls.
Keep in mind that the layout system is essentially a preprocess step of the actual GUI drawing or input processing. Before any actual event is processed, Unity will issue the layout event. Note that during the Layout event GetLastControlRect will return 0,0,-1,-1 since it hasn't actually layouted anything yet since it collects all the information about all controls during the Layout event. It will return the correct rect during any other events (especially the Repaint event).
Thanks. I read the git posting also and found it really useful.
I was able to do it using the GetRect() method and GUI.Button() but also using a combination of BeginHorizontal, BeginVertical() and a marginless button style, to make placement easier. The former was simpler however.
Couple of questions - do I basically need to know the height of what I want to display when I call GetRect() ?
Presumably Layout continues below the Rect requested?