Input Filtering

Jan 6, 2012 at 11:05 AM
Edited Jan 6, 2012 at 11:14 AM

Hi there,

Firstly, thanks for this well-written library, I think it's going to save me a lot of work. I have a question regarding input filtering.

What's the intended solution here for managing input that's intended for the UI, versus input that's intended for the world? Generally, I've seen the following solutions adopted in games:

  • some kind of 'glass panel' UI element that is essentially just a normal, invisible panel that covers the screen; input events that reach it are known to be intended for user interaction with the world (e.g. clicking on a unit or terrain tile, or whatever). Handled accordingly through the 'glass panels' own UI event handlers etc. In order for this to work, there has to be some kind of input hierarchy or filtering, i.e input intended for a button must be 'captured', and not passed on to UI elements behind the button (i.e. our glass panel). On that note, does Ruminate support the ordering of UI elements for input filtering in this way? i.e. if I click a button which is inside a panel, does the panel get the input event, or is it filtered out?
  • The GUI offers a simple 'mouse is over a UI element' method. In your HandleInput() method in your game loop, first check that the mouse is not over a UI element, and if not, check input yourself and handle accordingly. Simpler to implement, but you're basically left with two separate input systems (one for UI, one for in-world). 


I see there's no way of checking (at the RuminateGUI level anyway) whether the mouse is over any UI element, just wondering if you had any thoughts as to how to handle input in a game composed of both UI and in-world interaction? I'm thinking a glass panel approach would fit with your current library without too much hassle.

Jan 6, 2012 at 2:04 PM
Edited Jan 6, 2012 at 2:13 PM

Having done some tests I can see that, yes, input events are indeed captured by controls in the foreground, and don't get propagated to controls behind them. Only problem is that invisible elements can't receive input, which should be trivial enough to change. Then I think it's good to go for a glass panel approach.



Edit: Yeah, I've removed the condition in the InputManager for an element to be both active AND visible before FindHover is called, and just make sure that the glass panel is the first element added to the tree. 

Jan 6, 2012 at 4:31 PM

Glad you figured it out. I was planning to push out a minor update this weekend to fix a few small alignment issues I noticed with the text and scroll bars. When I do that I think I will expose all of the events from the topmost widget (the dudelement) though the RuminateGUI class which should allow you to have all of the buffered input events associated with the elements (mousedown, click, double click, ect..) but will only be fired if the mouse doesn't click any of the other widgets. I think I'll just expose keyboard such as CharEntered regardless.

Also for those who prefer to use XNA standard polling and not buffered input I'll add a HasMouse property that will return true if the mouse is hovering over any (visible || active) widgets. 

That way I should be able to avoid interfering with any existing code if my GUI is added in later (they will just check the HasMouse property) and if people want to they can use event driven input by subscribing to the exposed events. 

Anyways thanks for bringing this to my attention. I made the GUI to use for internal development tools so I haven't used it much in a true game environment, so give me a heads up if anything else doesn't adapt well.