Trapping mouseclicks in multiple OnGui handlers

Hi guys. I have a game I’m working on that has on-screen GUI buttons, but also does point-and-clicks in the 3d world. Think of a game like Diablo or Sims where you are both clicking “in the world” but also in UI elements in the screen. When you click on a GUI button, I don’t want the click to “punch through” into the 3d scene.

This is the solution I came up with, and it works for one OnGUI call:

// Javascript: 
function OnGUI{
if( GUI.Button(Rect(5,5,75,40) , "Test") )
	{
	print("it worked."); 
	Event.current.Use();
	}

if(Event.current.type == EventType.MouseDown  Event.current.button==0) 
	{
	print("your click did not happen on a GUIbutton."); 
	mouse0 = 1; 
	}
else if(Event.current.type == EventType.MouseUp  Event.current.button==0) 
	{
	mouse0 = 0; 
	}
}

What happens in if you click on the button, mouse0 stays set to 0. If you don’t click on the button, mouse0 gets set to 1. When you release, it goes back to 0.

Works great! BUT …

My problem is I need to have multiple scripts with OnGUI in them. buttons in the other scripts don’t trap the mouse click. It seems to be based on what order onGUI is being called. I think I need to call the “Event.current.type” functions after ALL OnGUI scripts have executed. Since I can’t control the order in which scripts trigger, I can’t figure out how to do this.

Any suggestions?

How about you just have the scripts that take mouse clicks check to see if your click is within the GUI border using Input.mousePosition?

You could say if (Input.mousePosition.y > topRect) or something. It’d be much easier than event trapping.

Not sure how that would help. Can you explain a bit more?

BTW, my problem isn’t the buttons. The buttons work fine. It’s my 3d game world that is the problem. I want to know when the user has clicked but not on a button.

I can’t simply figure out how to do it.

Well, what I’m saying would help with that. Basically, if the click isn’t within the GUI rectangle, then it would do things like move you or interact. If you were within the GUI, however, it would ignore it.

Hey Hanford,

What I’ve done in the past is not use an OnGUI function to catch mouse action in my 3d game, but instead directly query Input.mousePosition, and the Input.GetMouseButton* family of calls.

Let me know if that works better for ya,

Bye, Lucas

Hi Lucas,

I do this for the 3d world stuff. The Mouse0 var in my example is used by other scripts to tell when the mouse is down and not clicking a button.

I would manually map out areas like GargerathSunman suggests, but there’s a few problems with this:

  1. I don’t have regular, rectangular toolbar shapes in my game. I have odd shaped buttons in corners and whatnot.

  2. a lot of the UI is based on modular scripts, for example, clicking on a chest in the game world may open some UI on-screen. These come from multiple scripts, so tracking when the mouse is over a button and not in the game world would require some heavy framework that I really don’t want to write.

What I’d like to do is something like this:

  1. Beginning of frame: clear a “click” flag.
  2. Process all GUI buttons. These buttons could set the flag in same way you’d do event.current.use().
  3. at the end of this process, if the click flag is set, then I ignore GetMouseButton. if it’s still clear, I know no button got clicked, and I can perform my 3d world code.

Edit: I tried the steps above, but completely forgot that a button is going to test true only once, whereas the mouse button will test true for more than one frame (even if the user clicks and releases very quickly). This means while the trick above works for one frame, subsequent frames it doesn’t work.

back to the drawing board.

No one has a better idea on how to solve this?

the idea of manually testing rects seems so … removed from what a GUI system should be about that I can’t believe there’s no way to do this other than that.