Search Unity

Stop event propagation on overlaying UI?

Discussion in 'Immediate Mode GUI (IMGUI)' started by Paintbrush, Apr 30, 2009.

  1. Paintbrush

    Paintbrush

    Joined:
    Apr 1, 2009
    Posts:
    23
    Hey everyone,

    Coming from a Flash/AS3 background, I tend to think of UI from the traditional event-driven standpoint... So my question might be unfounded based on Unity's GUI approach. I'm having trouble with GUI events cascading to UI that the currently-focused UI is overlaying. In this example, just drag either window over the other and try clicking the button. you notice that as long as the mouse pointer is over a button, regardless of it being in the currently focused window, it will register a click.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class GameUI : MonoBehaviour {
    6.  
    7.     private Rect windowRect;
    8.     private Rect windowRect2;
    9.     private Vector2 windowScrollPosition;
    10.     // Use this for initialization
    11.     void Start () {
    12.     }
    13.    
    14.     // Update is called once per frame
    15.     void Update () {
    16.    
    17.     }
    18.    
    19.     void OnGUI()
    20.     {
    21.         windowRect = GUILayout.Window(0, windowRect, onWindow, "Window One",GUILayout.Height(100),GUILayout.Width(200));
    22.         windowRect2 = GUILayout.Window(1, windowRect2, onWindow2, "Window Two");
    23.     }
    24.    
    25.     private void onWindow(int i)
    26.     {
    27.         windowScrollPosition = GUILayout.BeginScrollView(windowScrollPosition);
    28.         GUILayout.Button("Meowing Cats");
    29.         GUILayout.Button("Meowing Cats");
    30.         GUILayout.Button("Meowing Cats");
    31.         GUILayout.Button("Meowing Cats");
    32.         GUILayout.Button("Meowing Cats");
    33.         GUILayout.Button("Meowing Cats");
    34.         GUILayout.Button("Meowing Cats");
    35.         GUILayout.EndScrollView();
    36.         GUI.DragWindow();
    37.     }
    38.    
    39.     private void onWindow2(int i)
    40.     {
    41.         GUILayout.Button("Das Button");
    42.         GUI.DragWindow();
    43.     }
    44. }
    45.  
    Is this a feature or a bug? If a feature, what can I use to stop event cascading? If a bug, what're some of the work-arounds?

    Thanks everyone, and apologies if this has been asked before somewhere.

    -Jay
     
    awsapps likes this.
  2. tpelham42

    tpelham42

    Joined:
    Apr 15, 2008
    Posts:
    119
    I'm experiencing a similar issue with this and have been unable to find a resolution.
     
  3. will_w

    will_w

    Joined:
    Feb 20, 2008
    Posts:
    56
    me too
     
  4. Paintbrush

    Paintbrush

    Joined:
    Apr 1, 2009
    Posts:
    23
    I've been tackling this problem over the weekend with no luck. Judging by the silence from the veterans, I'm assuming this is a simple question with a 'RTFM' answer. I'll keep chugging on this and post a solution if I ever find one.
     
  5. will_w

    will_w

    Joined:
    Feb 20, 2008
    Posts:
    56
    I hope this is not the case as I believe everyone who has posted to this thread has done their homework.

    This is yet another example where a better code library, and SEARCHABLE DOCS, and code snippets in the reference would really help rapid development.

    Also, the Unity networking example with the chat would be a great place to implement and demo this.

    Anyway - gonna take a break from sorting my interface bugs, and networking issues and dive into this one again. I'll post any success.
     
  6. Hanford

    Hanford

    Joined:
    Aug 28, 2008
    Posts:
    166
    Specific question:
    I think the answer to the OP's question is to call Event.current.Use() inside of the code that executes your button click. I think calling this in every piece of button code is considered good UnityGUI form.

    http://unity3d.com/support/documentation/ScriptReference/Event.Use.html

    I had to use this to keep the clicks from passing into my game world and making the character walk (it was a click-to-move game). So I assume that it will do the same for multiple GUI buttons overlapping.

    Here's how it finally worked:
    Code (csharp):
    1.     if( GUI.Button(Rect(110,10,100,50) , "Reset Prefs") )
    2.             {
    3.             PlayerPrefs.DeleteAll();
    4.             Event.current.Use();
    5.             }
    General GUI stuff:
    That being said, the gui stuff is tricky becuase each onGUI event gets called multiple times per frame. I learned through a lot of trial and error and the help of others that you have to be very specific inside of onGUI events becuase of this. Either i missed something in the docs, or the docs need better documentation for the GUI stuff.

    For example, I tried to do something like this:
    Code (csharp):
    1. if(Event.current.button==0)
    2.             {
    3.             // Button 0 is held down
    4.             }
    5. else
    6.             {
    7.             //button 0 is NOT held down
    8.             }
    However, I discovered that the Else section of code was not specific enough; the OnGUI gets called many times per frame for different things: one pass may be for mouse buttons but the next pass will be for keyboard, and the mouse test will return false. So I had to change it to this:
    Code (csharp):
    1. if(Event.current.type == EventType.MouseDown  Event.current.button==0)
    2.             {
    3.             //mouse 0 is down
    4.             }
    5.         else if(Event.current.type == EventType.MouseUp  Event.current.button==0)
    6.             {
    7.             //mouse 0 is up
    8.             }
    Re: no answers
    Uh, I noticed a lot of posts on this forum go unanswered; and I don't think it's a "RTFM" approach -- I just think there's a LOT of questions posted here, some of which require long answers (and might have been answered before). I think it's more of a roulette approach. Sometimes you may get it answered quickly, sometimes not.

    Personally I know I can only answer posts I know the answer to (which is rare; I'm still a n00b) and I'm not in the forums every day, so i miss a lot. I try to post the answer to every topic I read that I can help out in, though.
     
  7. Hanford

    Hanford

    Joined:
    Aug 28, 2008
    Posts:
    166
    I'll second code examples for every command. Tiny code examples are by far the fastest way I learn, even more than having intelliSense-style tips.

    For searchable docs, the Script Reference does have search (and is way faster if you use your installed docs rather than the online ones) and I've used Windows XP file "word or phrase inside the file" search (for the reference to find stuff in those pages; it's really fast. Not perfect, but if you keep the a shortcut to the folders you want to search around it does the trick.
     
  8. will_w

    will_w

    Joined:
    Feb 20, 2008
    Posts:
    56
    You Da Man!!!

    Code (csharp):
    1. Event.current.Use();
    Couldn't be easier.

    Course you have to be psychic to track that down from the docs. Thanks very much for your response. I was going the wrong direction with the GUI.utility class.

    Please Unity - MAKE THE DOCS SEARCHABLE!!!! To use the docs the way they are, you basically have to already know the answer to the question you're looking for. This is fine for syntax reference, but very inefficient for those of us trying to learn the necessary classes, objects, and other elements.

    Anyway - thanks again Hanford.
     
  9. Paintbrush

    Paintbrush

    Joined:
    Apr 1, 2009
    Posts:
    23
    Hey Hanford,

    Thanks so much for replying. I understand that many posts do go unanswered, be it due to it being answered already, is not something the reader knows how to answer, or is in the docs. My last comment was just a simple indication that I recognize that the probability of it being in the docs is high, and that I was bracing myself for a more diligent scrutiny of the docs with what time I have :)

    will_w is right in the primary issue with docs, be it searchable or not, is that you'd pretty much have to know the answer to certain things to be able to search for it. For example, I started this topic from the perspective of an AS3 engineer... with a word never used in Unity's programming paradigm. Had I done a search of that, even on Google using advanced search to constrain my search pool to the Unity docs, I wouldn't have been able to get the answer I seek. This is not really the Unity guys' fault... it's a frustration apparent in many other similar scenarios.

    That said, back to the problem :) I think as my original post stood, Events don't actually trickle down to GUI element behind another GUI element. I did some print() tests to verify it. I assumed that it trickled down because when I clicked the button in the window overlaying another button, both buttons react with the 'active' state. using Event.current.Use() didn't fix that. Is there another fix for it? It's not really a blocker, but it is visually misleading. If the problem is not clear, I'd be happy to do a video capture of it in action.

    Thanks again! Let me know
    Jay
     
  10. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    Windows are intended to "isolate" the events that occur within them. If that is not happening and you didn't do anything freaky, then it is most likely a bug and I recommend you report it with the bug reporter.

    It sounds to be as though some the events are shared in "window space" and that brings up the same immediate-mode event handling issues that normal elements have. Just a quick guess though.

    -Jeremy
     
  11. will_w

    will_w

    Joined:
    Feb 20, 2008
    Posts:
    56
    I think the windows are buggy, but my whole system is suspect right now. I mean if my app is in the background - with Firefox on top for example and I mouse over a part of the app with a button - it highlights. Forget whether it trickles within Unity. Its trickling from Firefox into my app. Maybe I'll try turning off the "Run in Background" feature.

    I actually get some pretty cool effects every now and then. If I move my app window around on my desktop, it pans around in Unity. Looks very cool - kinda like virtual binoculars or something.

    As far as solving your prob, a possible work-around might be to have a var that tracks when your overlay drops down, then simply make all the buttons that might fall underneath have to check that as well. Use some var like myOverlayNotActivated and add it to the if statement in your buttons. Not very elegant, but seems like a possible work around.

    if (button1click myOverlayNotActivated) {
    launch the space shuttle;
    }

    heheh - I just got one of those cool side effects. Used the scroll wheel to move back up and read the beginning of my post, and saw my Unity app in the background zoom the 3ps camera in. I love it. I'm not trying to be flippant about your problem, but I've had sooo many goofy errors lately that I don't know what's what any more.

    Another thing to look at might be the GUI.utility class and see if there is anything there. The prob with that is the buttons seem to trigger on the mouse down and the utility doesn't change states till a mouse down, so it's not helpful for mouseover events like entering a window.

    So basically - I'm no help at all - but I offer moral support. Power to ya, brother - hang in there and keep fighting the good fight.
     
  12. Michael-Ryan

    Michael-Ryan

    Joined:
    Apr 10, 2009
    Posts:
    184
    Shouldn't all overlapping GUI elements prevent mouse clicks from falling through to lower elements?

    I currently have Buttons and SelectionGrids in one script and another script that has a GUILayout.BeginArea() containing a GUI.Box() that overlaps the buttons.

    I would expect the higher GUI Box would prevent mouse clicks and OnMouseOver and OnMouseOut events from falling through to the buttons. This does not happen in my current script.

    Is there any way for me to prevent the mouse from interacting with GUI elements underneath the GUI Box?
     
  13. will_w

    will_w

    Joined:
    Feb 20, 2008
    Posts:
    56
    I'd love to get an answer from Unity on this one - but as far as I can tell - its bugged. there is no separation in any script I've tried - including their demos and tutorials.

    The only thing I've been able to do is use the techniques described above to isolate buttons and windows that don't overlap. I have to hide one before using another if they occupy the same space.
     
  14. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    All GUI.Button call Event.Use automatically. (we have some bugs in 2.5 where used events fall through to lower GUI scripts, but this is only tangentially related).

    What you see is that the buttons go into hover state when the mouse is over them (even though there might be another control in front that obstructs it). I'm not quite sure how to solve that (if it was easy, I'd already have done it). However, only the frontmost button actually receive the click event.
     
  15. will_w

    will_w

    Joined:
    Feb 20, 2008
    Posts:
    56
    Hi-
    On the one hand I appreciate greatly the response. On the other - it brings up 2 concerns:

    This is not tangential from our standpoint. I understand that at the Unity/Mono level this may be a different bug - but it manifests itself the same way to an end user: GUI functionality is not there.

    I sympathize, but frankly - that's what we pay for. If it was easy we would have already done it. This is the kind of issue that is a real sore point for me and I think other users. I would never have thought in my 10-20 hours of trying to make my GUI operate correctly that this functionality would be not already be there. Further, this kind of basic functionality is a show stopper for any kind of "professional" GUI. In other words, while you have some features that combine to make a nice feature set, this one lack of a feature/bug is sufficient to mean that Unity will not work for some projects. It is these kinds of gaps that frightens me and causes me to be extremely frustrated with Unity. They are not well documented, and I wasted days trying to sort what was my programming bugs vs. Unity. And now I am forced to question any other bugs/issues I am having. How am I supposed to know what are my issues and what are omissions by Unity?

    Anyways, thanks for the response.
     
  16. Kai

    Kai

    Joined:
    May 28, 2009
    Posts:
    24
    Couldn't you hack it and set a different GUI style when something else is overlapping? I.e. a style where the regular state is the same as the hover state, thereby getting rid of the hover state, effectively?

    I realize it's kludgey, but if that's the only thing holding you back, it might be worth doing until the issue gets resolved.
     
  17. will_w

    will_w

    Joined:
    Feb 20, 2008
    Posts:
    56
    If you do that then it defeats the purpose of putting the controls in a draggable window. You won't be able to drag the window around because the BG would change.
     
  18. Dakta

    Dakta

    Joined:
    Apr 8, 2008
    Posts:
    492
    Just a bump, because I'm really getting annoyed by this issue. And it's been more than HALF A YEAR since this post, not to mention when someone first had an issue with it.

    Like Will has said, this sort of thing is a real show stopper for those of us who want the GUI windows to behave like windows. There's a reason we're using windows, and it is to keep THIS EXACT THING FROM HAPPENING. Otherwise, there's not point in using a draggable window.

    It would be greatly appreciated if you guys would just sit down and spend as long as it takes to get this right, because it is a major flaw in the current GUI implementation. I thought you prided yourselves on doing things right the first time, yadda yadda. If you do, you NEED to fix this. Otherwise feel free to turn into Microsoft (note their mad dash to add features to Windows and not support anything, which has lead to most of today's problems with the OS).


    (Just a thought: How would you feel if things worked like this in your desktop OS? I would be seriously pissed off, and probably switch to another OS until they fixed it. Realize that the Unity GUI is to us exactly the same as that desktop OS in that it generates the exact same feelings when things work, and when things don't work. So do us a favor and save us a whole lotta grief by FIXING THIS ALREADY. Thanks)
     
  19. Bugfoot

    Bugfoot

    Joined:
    Jan 9, 2009
    Posts:
    533
    And another bump for this, as it bugs the hell out of me as well. It's a bit curious this issue has been around for so long, especially when it's such a basic requirement for any UI system...
     
  20. col000r

    col000r

    Joined:
    Mar 27, 2008
    Posts:
    699
    yeah. fix UnityGUI or admit that you've given up on it...
    Personally I hope Unity is working on it and fixes that UnityGUI is not multi-touch-capable on iOS (just another example of its shortcomings), which I find quite embarrassing tbh... :/
     
  21. inewland53

    inewland53

    Joined:
    Mar 31, 2011
    Posts:
    7
    For my game I had special conditions where I couldn't just use the Event.use.Use();

    I simply disabled my in game GUI when the Pause Menu was loaded...

    Code (csharp):
    1.  
    2. function OnGUI ()
    3. {
    4.     if(pauseMenuOpen)
    5.         GUI.enabled = false;
    6.     else
    7.         GUI.enabled = true;
    8. ...
    9.  
    Hope that helps.