Window position in GUILayout (or GUI)

Question:

Is there a way to get windows to fit within the containing GUILayout flow? Or do I have to calculate the container position and set the rectangle variables for each window? (meh)

Situation:

My problem is that both GUI.Window and GUILayout.Window constructors require a rectangle (unlike GUILayout.buttons). So my cargo windows aren’t fitting within the GUILayout flow like everything else, they’re statically set by this rectangle. Why is there a GUILayout.Window then?

void DisplayCargo ()	{
	GUILayout.BeginArea(rectCargoArea);
	GUILayout.BeginVertical ("Cargo", GUI.skin.GetStyle("Box"));
	GUILayout.Space(20);
	
	rectCargo = GUILayout.Window (0, 
	                        rectCargo, 
	                        CargoWindow, 
	                        new GUIContent("", "Parts"), 
	                        GUI.skin.GetStyle("Button"));

	GUILayout.EndVertical();
	GUILayout.EndArea ();
}

void CargoWindow (int windowID)	{
	GUILayout.BeginVertical();
	GUI.DrawTexture(new Rect(0,0,40,40), iconOptions, ScaleMode.ScaleToFit);
	GUILayout.Label (cargoAmount, "labelCenteredSmall");		
	GUILayout.EndVertical();
	GUI.DragWindow (rectWindowDrag);
}

I believe the difference between GUI.Window and GUILayout.Window is whether or not the elements contained within the window will be laid out using GUILayout logic.

Both Windows need a rectangle because they need to know where to draw themselves on the screen. If you want your window to appear in a fixed position, then it's not a window (it's a box or a label).

If you want to have a draggable Window that is constrained within a given rectangle, you will have to clamp the window position yourself (this is very easy). This is why it is helpful to pass the rectangle parameter to GUI.Window: you can clamp it yourself before drawing the Window.

Here's a function that we use to clamp the position of a GUI.Window. This function clamps a rectangle relative to the entire screen, but it would be easy to make it so it works for any arbitrary rectangle:


function clampWindowPosition ( theRect : Rect, dragClampPct : float )
{
    var minX =  0 - theRect.width * ( 1 - dragClampPct );
    var maxX =  Screen.width - theRect.width * dragClampPct;

    var minY =  0 - theRect.height * ( 1 - dragClampPct );
    var maxY =  Screen.height - theRect.height * dragClampPct;

    theRect.x = Mathf.Clamp(theRect.x, minX, maxX);
    theRect.y = Mathf.Clamp(theRect.y, minY, maxY);
}

The function clamps the position of the rectangle named theRect so that at most dragClampPct percentage can be off the screen. For example, calling calmpWindowPosition with a 100x100 rectangle and dragClampPct equal to .50 will make it so only half of theRect (or 50 pixels) can be off the screen at any given time.

If the user tries to drag it further, it will not go. I believe this is the effect you're looking for.