Search Unity

How does GetControlRect work?

Discussion in 'Immediate Mode GUI (IMGUI)' started by KeithKong, Dec 5, 2017.

  1. KeithKong

    KeithKong

    Joined:
    May 31, 2015
    Posts:
    73
    Watching the debugger, EditorGUILayout.GetControlRect () always returns (0,0,1,1)–or a width and height of size 1. I assumed this represented a percentage of the space reserved. For example using the rects (0, 0, 0.5, 1) and (0.5, 0, 1, 1) on two different EditorGUI fields will evenly split the horizontal space between them. And this works!

    But take this code which treats the rect as if it were in pixels.

    Code (CSharp):
    1. Rect controlRect = EditorGUILayout.GetControlRect ();
    2. float labelWidthInPixels = 100f;
    3.  
    4. Rect labelRect = new Rect (controlRect.x, controlRect.y, labelWidthInPixels, controlRect.height);
    5. Rect valueRect = new Rect (controlRect.x + labelWidthInPixels, controlRect.y, controlRect.width - labelWidthInPixels, controlRect.height);
    6.  
    7. EditorGUI.LabelField (labelRect, "Label:");
    8. EditorGUI.FloatField (valueRect, 10f);
    The debugger shows labelRect to be (0, 0, 100, 1) and valueRect to be (100, 0, -99, 1). But it works! The label takes up 100 pixels and the value field extends the remaining width.

    So is this intended? Does it detect crazy values and assume the person was thinking in pixel terms or something? And should I rely on this method?

    Any clarification would be greatly appreciated, thanks!
     
  2. KeithKong

    KeithKong

    Joined:
    May 31, 2015
    Posts:
    73
    Further investigation has shown that GetControlRect () actually forces the GUI to redraw when it gets the strange values and the next time around returns a rect in pixels. So it does seem to have an auto backup, but I'd like to know if this is an intended solution or just a "handle the dummies" kind of thing.

    Is there a better way to specify the units you want the Rect to come in?
     
  3. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    If you look at Event.current.type you should see EventType.Layout when there is crazy values. The GUI is calculating automatic layout. The second time is EventType.Repaint when the GUI is rendering.

    For your code you can do it pretty easly:
    Code (CSharp):
    1. EditorGUIUtility.labelWidth = 100f;
    2. EditorGUILayout.FloatField("Label", 10f);
    EditorGUIUtility.labelWidth is controlling width of prefix label in inspector/editor.

    You maybe need restore previous value of EditorGUIUtility.labelWidth after having done your stuff.
     
    karl_jones likes this.
  4. KeithKong

    KeithKong

    Joined:
    May 31, 2015
    Posts:
    73
    The example code above is just that. My actual project requires that I start with a Control Rect that accurately represents the available width and then divides it up using a custom multipurpose algorithm that can have any number of sections/labels/fields/etc. I'm providing custom Rects to all my fields using EditorGUI (Not EditorGUILayout).

    Still, it sounds like you're implying that the crazy values are just a preliminary step in formatting the layout. Is there something I should be doing to handle this step? As is, my code is working visually so is it standard to first just use the crazy values and then immediately "paint" over them?
     
  5. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,277