Search Unity

Can't get SelectionGrid to draw over Toggle button

Discussion in 'Immediate Mode GUI (IMGUI)' started by jahroy, Apr 22, 2011.

  1. jahroy

    jahroy

    Joined:
    Apr 22, 2011
    Posts:
    10
    _

    I can't get my SelectionGrid to draw on top of my Toggle buttons. I draw the Toggle buttons first then draw the SelectionGrid, but the Toggle buttons take control of mouse input. Both GUI elements are drawn in the same OnGUI funtion.


    More Info:

    My game has a dropdown menu that I've implemented with a GUI.Toggle and a GUI.SelectionGrid. The toggle button determines whether or not the selection grid should be displayed.

    The SelectionGrid appears over another (unrelated) group of GUI.Toggle buttons. Even though the toggle buttons are drawn first, they still steal the mouse focus when the mouse is over the selection grid.

    Both components are drawn in the same OnGUI function.

    Here is a screenshot that demonstrates the problem:



    The mouse is over the Foo item in the selection grid, yet the toggle button enters its hover state and will become active if I click my mouse. You can see that Foo is in its hover state, but I am unable to select it with a mouse-click.

    Here's the code that draws the selection grid, which is called AFTER the list of toggle buttons has been drawn:

    Code (csharp):
    1.  
    2. var buttonRectangle   =  getDropdownButtonRect();
    3. var choicesRectangle  =  getScrollBoxRect(buttonRectangle);
    4.  
    5. showMenuChoices = GUI.Toggle(buttonRectangle, showMenuChoices, buttonLabel, "dropdownButton");
    6.  
    7. if ( showMenuChoices ) {
    8.  
    9.     lastSelection = chosenMenuOffset;
    10.  
    11.     GUI.Label(choicesRectangle, dropdownBackground);
    12.     chosenMenuOffset = GUI.SelectionGrid(choicesRectangle, chosenMenuOffset, menuNameList, 1, "dropdownMenu");
    13.  
    14.     if ( chosenMenuOffset != lastSelection ) {
    15.         resetButtons();
    16.         showMenuChoices = false;
    17.     }
    18.  
    19.     if ( isCloseDropdownClick() ) {
    20.         showMenuChoices = false;
    21.     }
    22. }
    23.  

    Thanks in advance for any help...
     
    Last edited: Apr 22, 2011
  2. billykater

    billykater

    Joined:
    Mar 12, 2011
    Posts:
    329
    This is a basic unitygui problem look at the following code.

    Code (csharp):
    1.  
    2. if(GUI.Button(new Rect(0,0, 100, 50), "Horizontal"))
    3. {
    4.    print("a");
    5. }
    6. if(GUI.Button(new Rect(0, 0, 50, 100), "Vertical"))
    7. {
    8.    print("b");
    9. }
    10.  
    Unity first checks and draws the first button so "a" is printed upon clicking it. Then the second button is checked and drawn on top of the first but the first button has already used the "click" event. So overlapping objects inside the same OnGUI function can never happen correctly.

    The way around this problem is to have one Monobehaviour/Component OnGUI for every layer of your gui.
    Using http://unity3d.com/support/documentation/ScriptReference/GUI-depth.html you can now control who gets to draw and process events first.
    Keep in mind GUI.depth doesn't work if changed inside the same OnGUI function.
     
  3. jahroy

    jahroy

    Joined:
    Apr 22, 2011
    Posts:
    10
    Thanks for taking the time to respond.

    I guess I mis-interpretted the documentation that suggested that elements drawn from within the same OnGUI function would be layered based on the order they are drawn.


    EDIT:

    I finally solved my problem and just anwered my question in Unity Answers, which you can find here:

    http://answers.unity3d.com/questions/54126/how-to-draw-gui-controls-on-top-of-each-other
     
    Last edited: Apr 23, 2011
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I've just run into the same thing, so thanks for posting this. I guess this is a fundamental flaw in the whole approach the GUI methods take, of having a single function that both draws and returns a result. Drawing (within one OnGUI call) does happen in the order you tell it to, but this means that things in the back capture events rather than things in the front.

    Dang. This makes it really hard to implement a pop-up menu in a way that fits nicely into the way you draw everything else. Still, you've saved me a ton of time staring at disbelief at the evidence I was seeing!
     
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Hey, thinking about this a little bit more... and since it's late, thinking out loud...

    We do get multiple OnGUI calls. The first one is supposed to be for drawing, and subsequent ones for event handling.

    So, in theory, this ought to work, or we ought to be able to make it work (even if we need to make our own custom button class). We already have the GUIUtility.hotControl tag, to indicate which control has temporary control of the mouse. When that is set to anything other than itself, GUI.Button ought to ignore mouse events, making this all work.

    My popup menu code sets hotControl when the popup menu first appears, and clears it when the menu is dismissed... but I think the problem is that the GUI.SelectionGrid mucks with this value as well. It seems to set it to some internal identifier of whatever grid button is moused over, and when none of them are moused over at all, it sets hotControl back to 0.

    When I override this by assigning my own ID to hotControl on every OnGUI call, then the button does indeed ignore the click. But then highlighting and handling of the buttons in the selection grid is broken too.

    So, I still suspect that it may be possible to make a popup menu that works all in one behavior. But it might require replacing the GUI.SelectionGrid code with some custom code that has similar behavior, but doesn't muck with hotControl.

    But it's too late for me to think clearly at the moment. I'll take another look in the morning, and if I manage to figure something out, I'll certainly post my findings here. If anybody else has a good understanding of Unity event dispatching, use of hotControl, etc., please share as well!
     
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859