- Home /
How to clamp EditorGUILayout controls' width ?
Hello there !
So here's the problem.
When I do this for example :
EditorGUILayout.BeginHorizontal();
EditorGUILayout.FloatField("FloatField 1", 1);
EditorGUILayout.FloatField("FloatField 2", 2);
EditorGUILayout.FloatField("FloatField 3", 2);
EditorGUILayout.EndHorizontal();
The widgets are well aligned. The only problem is that they are way too large, so I get an horizontal scrollbar. And when I try to clamp their width with GUILayout.Width(100), the display is all messed up. Widgets are overlapping each other...
Is there a way to keep all widgets inside the Inspector's rectangle ?
Thanks in advance for your answers.
Answer by booyah · Feb 13, 2015 at 11:03 AM
Bit of an old question but I had the exact same problem trying to replicate the VectorXField for integers and after an intense session of pulling out my hair I figured out the problem does not actually reside in the begin/end horizontal functions but rather in the FloatField/IntField prefix labels and narrowed it down to the PrefixLabel widget.
So to answer your question, to achieve what you meant, you can do :
EditorGUILayout.BeginHorizontal();
GUILayout.Label("FloatField 1");
EditorGUILayout.FloatField(1);
GUILayout.Label("FloatField 2");
EditorGUILayout.FloatField(2);
GUILayout.Label("FloatField 3");
EditorGUILayout.FloatField(2);
EditorGUILayout.EndHorizontal();
And everything should be laid out properly.
My guess is that the PrefixLabel doesn't adapt its width to the divided line it's in but rather invariably take the window/area's width, ofsetting everything, I'll file a bug report.
Answer by Bill-Robinson · Sep 04, 2017 at 07:17 PM
I just had this problem too in a horizontal group, found an answer by setting this before each one:
Not so pretty, but it works at least.
Answer by wiiarethesound · Aug 22, 2013 at 04:03 PM
EditorGUILayout.BeginHorizontal();
EditorGUILayout.FloatField("FloatField 1", 1, GUILayout.MaxWidth(100.0f));
EditorGUILayout.FloatField("FloatField 2", 2, GUILayout.MaxWidth(100.0f));
EditorGUILayout.FloatField("FloatField 3", 2, GUILayout.MaxWidth(100.0f));
EditorGUILayout.EndHorizontal();
Alternatively, (although I haven't tested this, so I don't know if it works)
GUILayoutOption[] options = { GUILayout.MaxWidth(100.0f), GUILayout.MinWidth(10.0f) };
EditorGUILayout.BeginHorizontal();
EditorGUILayout.FloatField("FloatField 1", 1, options);
EditorGUILayout.FloatField("FloatField 2", 2, options);
EditorGUILayout.FloatField("FloatField 3", 2, options);
EditorGUILayout.EndHorizontal();
Check out GUILayoutOption in the scripting reference.
In C# you have to create the array like this:
// C#
GUILayoutOption[] options = new GUILayoutOption[]{ GUILayout.$$anonymous$$axWidth(100.0f), GUILayout.$$anonymous$$inWidth(10.0f) };
or
// C#
var options = new GUILayoutOption[]{ GUILayout.$$anonymous$$axWidth(100.0f), GUILayout.$$anonymous$$inWidth(10.0f) };
which is a bit shorter ;)
Or, since the array has the params keyword you can do this:
EditorGUILayout.FloatField("FloatField 1", 1, GUILayout.$$anonymous$$axWidth(100.0f), GUILayout.$$anonymous$$inWidth(10.0f));
which is the usual way. But it you use the same options on several controls, creating an array doesn't hurt ;)
I already tried $$anonymous$$axWidth() and $$anonymous$$inWidth(), but that does bretty much the same thing as Width() : control overlapping. :x But thanks for your input !
Any other idea ? :)
Answer by CaJerry87 · Dec 20, 2016 at 07:15 AM
FOR ANYONE WHO IS LOOKING TO MAKE YOUR BEGINHORIZONTAL TO CHANGE WIDTH:
This is actually an intermediate question so congratulations for asking!
The solution is simple yet will require some basic website layout knowledge, let's use HTML!: In HTML you would normally go as follows:
table td td td
tr [ | | | | | | ]
tr [ | | | | | | ]
tr [ | | | | | | ]
/table
(*for those of you who think this is how you combine Begin Vertical/Horizontal to make a layout, unfortunately this is not the case.)
Instead you must define x, y, w, h (x position, y position, width of..., height of...). And for those of you pulling out your hair saying, "I've already heard this!" ask yourself if you know what it means.
Well THIS......is GUILayout.BeginArea...
REMEMBER TO USE GUILayout.EndArea() TO CLOSE THE AREA (its the "/table" of GUILayout.BeginArea)
Simply use BeginArea to create a rect then place your BeginVertical/Horizontal inside and it will only span the width and height of its parent object which is now the BeginArea.
This image is only to show you the first step to understanding. But with the image above you should be able to understand the next image which will answer "How to adjust the width and height of BeginHorizontal or BeginVertical":
*Not to DEV's, please allow me to put up at least 3 images as I had another one that would've really driven the point home... P
Using only BeginArea completely defeats the point of using GUILayout in the first place. The layout options "$$anonymous$$inWidth", "$$anonymous$$axWidth" and "Width" are specifically to restrict certain layouted elements in width. When you use BeginArea you don't use the layout system, but create a new area manually with relative coordinates.
The point of the layout system is to not deal with rects but have the elements be arranged automatically and adapt to the available space. If you don't want to use the layout feature, you would simply use the EditorGUI stuff ins$$anonymous$$d of EditorGUILayout. However things like the inspector GUI completely builds on top of the layouting system. Using BeginArea makes no sense in the inspector. "BeginArea" breaks the current layout stack and starts a new one. BeginArea also starts a new GUI.BeginGroup, that's why you can actually nest them, but it doesn't make much sense.
The layouting system works just fine, however you seem to compare it with an HT$$anonymous$$L table which is just a false conclusion. A table is a "2d" construct while Unitys layout groups are strictly "1d".
If you really need a "table like" structure inside the layout system you would aquire a layouted rectangle for the whole table manually by using GUILayoutUtility.GetRect and then use the GUI / EditorGUI methods and split up the rect as you like.
ps: Using ALL CAPS is generally a bad habit and won't make your post more readable or more "right". You can use bold text if you want to emphasize something but it should by used sparsely.
Every thing you say sounds relevant and accurate but consider the reason for why the question was asked. Simply assu$$anonymous$$g that someone hasn't done their research is almost as bad as someone who doesn't do the research at all. While you're right that $$anonymous$$axWidth and the like exist and have a versatility to them that is needed in layout the concept of using BeginArea to "wrap" your context I feel answers a lot more.
A simple experiment that I'm sure most who have heard of BeginHorizontal/Vertical has thought or done is simply creating several BeginBlahs and rearranging them (Vert inside Vert inside Vert etc...) I think that DocteurCox was thinking this when the question was asked and you have to admit that while not always necessary, BeginArea is an applicable solution to the question. Using beginarea to restrict elements is slightly more work than $$anonymous$$axWidth but if you're going to put a bgimage or any design to your editor window you're probably going to use BeginArea anyways so why not?
And also... "DocteurCox · Aug 22, 2013 at 09:01 P$$anonymous$$ 0 Reply Share I already tried $$anonymous$$axWidth() and $$anonymous$$inWidth(), but that does bretty much the same thing as Width() : control overlapping. :x But thanks for your input !
Any other idea ? :)"
ps: sorry if the all caps seemed crude but if you noticed I used it as sparingly as bold, it's just easier to go CAPS-type-GO than to stop, highlight, bold...please excuse the all caps...
Answer by Moeyvozhenie · Feb 18, 2018 at 04:47 PM
I found solution. You should use negative Space between controls.
EditorGUILayout.BeginHorizontal();
EditorGUILayout.FloatField("FloatField 1", 1, GuiLayout.MaxWidth(50));
GuiLayout.Space(-30);
EditorGUILayout.FloatField("FloatField 2", 2, GuiLayout.MaxWidth(50));
GuiLayout.Space(-30);
EditorGUILayout.FloatField("FloatField 3", 2, GuiLayout.MaxWidth(50));
EditorGUILayout.EndHorizontal();