This project is read-only.

How to determine if a screen-position (i.e. mouseclick) is on any gui-control ?

Jan 16, 2010 at 12:37 AM

I'm using the GUI for parts of my user-interface (dialog, buttons) in my RTS-type game,
the rest I handle myself (unit-selection, map-dragging etc.).

Now I'm facing the problem that when I handle a mouse-click to place a unit,
it's also handled even when the mouseclick is actually on a part of the GUI.

For example when I press the "Pause" button in the corner of the screen,
my own code also catches the mouseclick and places a unit at that position in the world - under the pause-button.
So basicly I need a way to figure out if a mouseclick would be handled by the GUI, and only if not process it as an "in-world" click.

Is there any way / will there be any way to handle this ?
(Or am I doing it wrong and should I be using another way to get my desired behaviour ?)

 

Jan 16, 2010 at 9:46 AM

That's a problem I'm also facing in my game right now. The GUI doesn't tell whether a mouse click has been handled or whether it went into empty space (the GUI knows this information alright, it just doesn't report it back yet).

I am considering several options currently:

One would be for the Screen to pass on input that the GUI didn't use (either with events or to another IInputReceiver that the game could register). This would allow the GUI to follow its behavior model (eg. if the user presses down a mouse button over a control and moves the cursor away from the control, the input still belongs to that control until the user releases the mouse button again), but I fear it's too intrusive for the game - I want the GUI system to be something that can be added to a game, not something that dictates the game's design.

Another one would be to let the input notifications (Screen.InjectMousePress() etc.) return a boolean that indicates whether the input was handled. This would also allow the GUI to keep adhering to its behavior model, but could be ignored by users not in our situation who just want the darn GUI to work when the user opens the options dialog or whatever. The drawback here would be that it's a bit harder to integrate such selective targeting of input notifications when you actually need it.

 

You're doing it right, you just hit one of the areas where I'm still looking for the best approach. At the moment, the GUI keeps this information to itself, but there will be a way to get it soon, probably one of the two approaches above. If you have any suggestions or input on this, I'd be glad to hear it :-D

Jan 18, 2010 at 10:16 PM
Edited Jan 18, 2010 at 10:17 PM

Well, since I'm using my own (non-Nuclex) code to get the keyboard- and mouse-state, I'd love to have a method that just tells me if a screen-position is 'in' any control.

(I find it easier to just keep a current- and previous-mouse/keyboard state instead of using the 'InjectKeyPress'-stuff ;))

That way I can keep my code as it is, and I think it shouldn't be very hard to add a gui-hit-test to the Nuclex GUI framework that just returns wether or not a specified screen-pos is on a control.

Jan 20, 2010 at 1:52 PM

It's slightly more complicated because if the mouse button is pressed down over a control, input belongs to that control until the mouse button is released again, even if the mouse is dragged away from the control.

I guess the same could be applied in the opposite case: if the user presses the mouse button over the game's view to drag a frame around some units, the mouse input would belong to the game as long as the mouse button is held down - even if the cursor passes through a GUI control.

-

That's why I'm a bit torn between the two options I listed. Otherwise I would have added a simple IsMouseOverControl property right away :)

Maybe a property "MouseCaptured" that indicates whether the GUI thinks the mouse currently belongs to it could do the trick. The Screen just needs to track when a mouse button is pressed (and held) outside of the controls then to enable the selection frame dragging use case to work!

Jan 25, 2010 at 8:46 PM

My vote's for the "MouseCaptured" flag ! :)

Feb 22, 2010 at 3:14 PM

Soooooo........ have you had time to think it over yet ? ;-)

Feb 24, 2010 at 6:54 AM

Yep, working on it. Just a little while longer ;)

I'll post here when it's available in the svn trunk!

Feb 24, 2010 at 5:35 PM

Cool, thanks ! :-)

Apr 14, 2010 at 7:11 PM

Sorry for taking my time with this. I hope I'll find some time to work on this soon, but it may take another 2-3 weeks for the next release!

Sep 2, 2010 at 11:37 AM

Finally added the necessary properties.

The Screen class now provides an IsInputCaptured property that tells when the GUI thinks input belongs to it (but that also stays false when the user clicks outside of any GUI elements and drags the mouse around) and a IsMouseOverGui property that can be used to switch the mouse cursor. Usage is like this:

 

void Update(GameTime gameTime) {
  this.input.Update();
  this.gui.Update();

  if(this.gui.IsInputCaptured) {
    return; // input belongs to the GUI
  }

  if(this.gui.IsMouseOverGui) {
    MouseCursor = GuiCursor;
  } else {
    MouseCursor = getCursorForObjectUnderMouse();
  }
  
  // ...
}

I'm also updating the GUI to use a new library for handling input devices. From the outside, nothing will change, but it won't be necessary anymore to write a custom IInputCapturer to support DirectInput-based game pads or to use a different controller to control the GUI on the XBox 360.