GUI: how to know, if gui was hit?

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

GUI: how to know, if gui was hit?

Post by MasterD »

Hi there,
I try to find out, if I hit the gui with the mouse. The code below works good so far. The problem is when I click the mouse, while hovering on a submenu.
When the mouse clicks, the root gui element gets returned, not the actual menu or context menu.

Thanks in advance, here's the code:

Code: Select all

	if(event.EventType == irr::EET_MOUSE_INPUT_EVENT &&
		(event.MouseInput.Event == irr::EMIE_LMOUSE_LEFT_UP ||
		event.MouseInput.Event == irr::EMIE_LMOUSE_PRESSED_DOWN ||
		event.MouseInput.Event == irr::EMIE_RMOUSE_LEFT_UP ||
		event.MouseInput.Event == irr::EMIE_MMOUSE_LEFT_UP||
		event.MouseInput.Event == irr::EMIE_MMOUSE_PRESSED_DOWN))
	{
		// if gui was hit, dont process event
		irr::gui::IGUIElement * elem = m_pEnv->getRootGUIElement()->getElementFromPoint
			(irr::core::position2d<irr::s32>(event.MouseInput.X, event.MouseInput.Y));
		if(elem	!= m_pEnv->getRootGUIElement())
		{
			return false;
		}
	}
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

First off all: you should only react on one mouse event...
Either pressed down or left up (not both)...

You get the gui element that was clicked with event.GUIEvent.Caller...

btw: the tutorials are really good, they show all basics (also this one for example in 05.UserInterface)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

Post by MasterD »

Thanks for the replay, but I think you got me wrong.

I hoped not to come the long way, but so I do now:
I´m writing an Editor, so there you pick scenenodes. But, for the usability, it is important not to pick scenenodes when hovering GUI. So I used the code shown above, it is only to determine if there was a mouse action which could be used to modify something in the scene (that's why I react to several mouse events).
It works just the way it should, for every GUI Element I used so far (Buttons, Windows, custom GUI Elements, etc.). It also works whith the menu (the "main" - menu, Enviornment->addMenu(..)), but with the submenu, MainMenu->getSubMenu(..)->addItem(..), which is a IGUIContextMenu, this technique does not work.
It is like clicking "File" in your browser and when you click on "New window" the underlaying "back" button is clicked.

I hope, I made it clearer this time.
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Ahhh, I see... ;)

I didn't test this now, but what about first checking for EET_GUI_EVENT to see if a gui element was clicked ???
And then, if no gui was clicked, for EET_MOUSE_INPUT_EVENT...
(theoretisch müsste das so funktionieren)

Well, I normaly have no patience to rebuild such a scenario for testings...
But as far as we are nearly neighbors (I'm from Mönchengladbach) maybe I will if this also doesn't work... ;)

EDIT:
I just saw this:

Code: Select all

switch(event.GUIEvent.EventType){
  case EGET_MENU_ITEM_SELECTED:{
maybe this can help you ???
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

looks like the problem is that gui context menus are not constrained to the clip area of their parent, so the same problem should happen with buttons which have noclip=true set. I'll look into it.

edit: okay I think GUI Elements need something like "getAbsoluteClippingRect", and this should be checked inside getElementFromPoint. in elements which aren't clipped, they should override getAbsoluteClippingRect and return the AbsolutePosition of the root node (or maybe the absolute clipping rect of their parent). unless anyone can think of a better idea?
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
harukiblue
Posts: 49
Joined: Sun Dec 10, 2006 6:23 pm

te he

Post by harukiblue »

sounds good to me, It would sove this issue I think!
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

Post by MasterD »

I've looked into the the sources, but didn't tried it out so far, its late allready. The method you suggested could work, but I think I did not understood all parts correctly, so here is one of my thoughts:
I didn't found this noclip attribute, but so far, it looks to me that the AbsoluteClippingRect gets clipped to much.

In CGuiContextMenu::recalculateSize(), which is called in the constructor, the RelativeRect gets redefined. After doing so, updateAbsolutePosition() is called. There, the AbsoluteClippingRect is clipped against the Parents Rect, which is in the case of the main-menu somewhere other, than the ContextMenu itself.

So it could be solved, in reimplementing updateAbsolutePosition() without clipping to the parent, or with using this noclip inside of this method. I didn't thought of the effects on "normal" CGUIContextMenu's, but maybe it would work with them too?

edit:
@acki
(ich hoffe, bei euch stürmts nicht zu sehr :shock:)
thanks for the help, but afaik the gui event you mentioned gets created after the mouse click is processed, so i would have had to process this mouse click
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Oh, yeah, this could be a problem, if the mouse click is handled before the gui events... :shock:

But I also don't know if it's this way (but probably it is)...
I will test this, but I have a bad feeling about this... ;)

PS: 'n paar Dachziegel sind 'runtergekommen, aber jetzt ist's hier relativ ruhig... :lol:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
drewbacca
Posts: 38
Joined: Tue Jan 30, 2007 6:49 pm

Post by drewbacca »

I am also having the exact same problem, where I need to be able to tell if a user is interacting with my gui elements or is clicking on an area of the screen not covered by a gui element. This a problem since clicking a gui element will generate a mouse event as well as a gui event.

The current code I have does this by incrementing/decrementing a counter when gui elements are hovered/left. Which works, but requires a bunch of extra code to handle things like subwindows being closed (these dont generate left events). My solution certainly doesn't seem like a good way to handle things.

Has anyone figured out a better way to be able to know if you clicked a gui element or not? MasterD's solution seems much more elegant, but as he mentioned, doesn't work for menu items.
KG
Posts: 35
Joined: Wed Jun 07, 2006 12:00 am

Post by KG »

I solved this problem a little while ago. It works for me, and it might also work with what you're doing. It's similar to what MasterD was trying in the first post, so I don't know why it wasn't working for him. My event handler looks like this:

Code: Select all

bool LEvents::OnEvent(SEvent event)
{
	// GUI events
	if (event.EventType == EET_GUI_EVENT)
	{
		<snip>
	}

	// Mouse events
	if (event.EventType == EET_MOUSE_INPUT_EVENT)
	{
		switch (event.MouseInput.Event) 
		{
			case EMIE_LMOUSE_PRESSED_DOWN:
			{
				leftClick(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
				return false;
			}
			case EMIE_RMOUSE_PRESSED_DOWN:
			{
				rightClick(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
				return false;
			}
		}
	}

	return false;
}
And at the beginning of the rightClick() and leftClick() functions, I use this to stop anything from happening if the UI is clicked on:

Code: Select all

if (GUI->getRootGUIElement()->getElementFromPoint(position)->getID() > 0)
{
	return;
}
Just be sure to give all GUI elements an ID greater than 0, even if you never reference that ID.
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

Post by MasterD »

I'm sorry to post late, but I had written tests in between.

I've not tried out yet, what I think could solve the problem (the stuff about CGuiContextMenu::recalculateSize() mentioned above), I need to get my box working to compile irrlicht (next week should be time for such).

@KG: It looks like you are doing basically the same stuff I did. Does your code work with the Mainmenu and the submenus? Because for all other GUIElements I used so far, it also worked for me.
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
Post Reply