Bug? Focused window ruins EGET_MENU_ITEM event?

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.
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Bug? Focused window ruins EGET_MENU_ITEM event?

Post by Virror »

I ran across something strange while playing around with a Table and a ContextMenu. Strange thing is that EGET_MENU_ITEM works very well, until i select something from the Table, then i stop getting EGET_MENU_ITEM events. Also, are EGET_MENU_ITEM not working with sub-menus?
Last edited by Virror on Tue May 10, 2011 9:43 am, edited 1 time in total.
Digan
Posts: 16
Joined: Tue Aug 24, 2010 11:21 am

Post by Digan »

Maybe elements of the ContextMenu and elements of tables have the equal ID?
Image
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

I have tried to create all menus and elements with different ids, but same problem.
CuteAlien
Admin
Posts: 9729
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

I don't know about such a bug so far.

It would help if you could post code which I can use to reproduce the problem (it's easier for you to do this, as you can start with a reproducible bug, while I would have to go on a wild hunt writing examples until I might or might not run in a problem and often people here see the problem anyway as soon as they see the code).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Hmm, realized that it happens when the window the table is in has focus, not only when an item is selected. Currently i do this:

Code: Select all

if(event.GUIEvent.Caller == contextMenu)
		{
			if(event.GUIEvent.EventType == EGET_MENU_ITEM_SELECTED)
			{
				switch(contextMenu->getSelectedItem())
				{
Maybe it cant be done that way when i have focus on a window? Wrong event caller?

And, why cant i get event on a submenu? Is it not possible?

Edit code for Gui creation:

Code: Select all

	// Inventory
	IGUIWindow * inventoryWindow = irrGui->addWindow(rect<s32>(674, 100, 994, 600), false, L"Inventory");
	inventoryWindow->setVisible(false);
	irrGui->addStaticText(L"Equipment",rect<s32>(10, 30, 310, 45),false,true,inventoryWindow);
	IGUITable * equipmentTree = irrGui->addTable(rect<s32>(10, 45, 310, 75),inventoryWindow, -1, false);
	equipmentTree->addColumn(L"Body part");
	equipmentTree->addColumn(L"Item");
	equipmentTree->addColumn(L"Weight");
	equipmentTree->setColumnWidth(0,78);
	equipmentTree->setColumnWidth(1,170);
	equipmentTree->addRow(0);
	equipmentTree->setCellText(0,0,L"Hand:");
	irrGui->addStaticText(L"Items",rect<s32>(10, 85, 310, 100),false,true,inventoryWindow);
	IGUITable * invTree = irrGui->addTable(rect<s32>(10, 100, 310, 470),inventoryWindow, -1, false);
	invTree->addColumn(L"Item");
	invTree->addColumn(L"Weight");
	invTree->setColumnWidth(0,248);
	irrGui->addStaticText(L"Total weight: 2.0kg / 100kg",rect<s32>(10, 480, 310, 495),false,true,inventoryWindow);
	// Contex menu
	IGUIContextMenu * contextMenu = irrGui->addContextMenu((rect<s32>(0,0,0,0)),0,30);
	contextMenu->setCloseHandling(ECMC_HIDE);
	contextMenu->addItem(L"Equip",11);
	u32 craftMenu = contextMenu->addItem(L"Craft",12, true, true);
	contextMenu->getSubMenu(craftMenu)->addItem(L"Stone axe",15);
	contextMenu->getSubMenu(craftMenu)->addItem(L"Stone hammer",16);
	contextMenu->addItem(L"Drop",13);
	contextMenu->addItem(L"Examine",14);
	contextMenu->setVisible(false);
	irrGui->removeFocus(irrGui->getFocus());
	contextMenu->setItemEnabled(0, false);
	contextMenu->setItemEnabled(1, false);
	contextMenu->setItemEnabled(2, false);
	contextMenu->setItemEnabled(3, false);
CuteAlien
Admin
Posts: 9729
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

The idea behind posting code is to make it reproducible for others to get the bug. Setting windows invisible, putting the context-menu on 0,0,0,0 (which makes it obviously not visible), making it invisible additionally - well - really not sure what exactly you want me to look at.

I suspect you make it visible again at some other part of your application and maybe do resize it, etc... but well, I'm not able to look at your monitor - so really - I have no idea.

I've adapted your code a little bit so it compiles at least - so please take that as a starting-point and show us how to reproduce the problems exactly. It would also be nice if you remove every line that's not needed to show the bug.

So slightly reworked code that shows the Window and context-menu:

Code: Select all

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

struct SAppContext
{
	IrrlichtDevice * device;
	IGUIContextMenu * contextMenu;
};


class MyEventReceiver : public IEventReceiver
{
public:
	MyEventReceiver(SAppContext & context) : Context(context) { }

	virtual bool OnEvent(const SEvent& event)
	{
		if (event.EventType == EET_GUI_EVENT)
		{
			if ( event.GUIEvent.Caller == Context.contextMenu )
			{
				 if(event.GUIEvent.EventType == EGET_MENU_ITEM_SELECTED) 
					 std::cout << "item selected: " << Context.contextMenu->getSelectedItem() << std::endl;
			}
		}

		return false;
	}

private:
	SAppContext & Context;
};


int main()
{
	video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
	IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(1024, 768));
	if (device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = device->getVideoDriver();
	IGUIEnvironment* irrGui = device->getGUIEnvironment();
	
	IGUIWindow * inventoryWindow = irrGui->addWindow(rect<s32>(674, 100, 994, 600), false, L"Inventory");
//	inventoryWindow->setVisible(false); 
	irrGui->addStaticText(L"Equipment",rect<s32>(10, 30, 310, 45),false,true,inventoryWindow);
	IGUITable * equipmentTree = irrGui->addTable(rect<s32>(10, 45, 310, 75),inventoryWindow, -1, false);
	equipmentTree->addColumn(L"Body part");
	equipmentTree->addColumn(L"Item");
	equipmentTree->addColumn(L"Weight");
	equipmentTree->setColumnWidth(0,78);
	equipmentTree->setColumnWidth(1,170);
	equipmentTree->addRow(0);
	equipmentTree->setCellText(0,0,L"Hand:");
	irrGui->addStaticText(L"Items",rect<s32>(10, 85, 310, 100),false,true,inventoryWindow);
	IGUITable * invTree = irrGui->addTable(rect<s32>(10, 100, 310, 470),inventoryWindow, -1, false);
	invTree->addColumn(L"Item");
	invTree->addColumn(L"Weight");
	invTree->setColumnWidth(0,248);
	irrGui->addStaticText(L"Total weight: 2.0kg / 100kg",rect<s32>(10, 480, 310, 495),false,true,inventoryWindow);
	// Contex menu
	IGUIContextMenu * contextMenu = irrGui->addContextMenu((rect<s32>(0,0,100,30)),0,30);
	contextMenu->setCloseHandling(ECMC_HIDE);
	contextMenu->addItem(L"Equip",11);
	u32 craftMenu = contextMenu->addItem(L"Craft",12, true, true);
	contextMenu->getSubMenu(craftMenu)->addItem(L"Stone axe",15);
	contextMenu->getSubMenu(craftMenu)->addItem(L"Stone hammer",16);
	contextMenu->addItem(L"Drop",13);
	contextMenu->addItem(L"Examine",14);
//   contextMenu->setVisible(false);
//	irrGui->removeFocus(irrGui->getFocus());
	contextMenu->setItemEnabled(0, false);
	contextMenu->setItemEnabled(1, false);
	contextMenu->setItemEnabled(2, false);
	contextMenu->setItemEnabled(3, false);	
	
	SAppContext context;
	context.device = device;
	context.contextMenu = contextMenu;
	MyEventReceiver receiver(context);
	device->setEventReceiver(&receiver);
	

	while(device->run() && driver)
	{
		if (device->isWindowActive())
		{
			driver->beginScene(true, true, SColor(0,200,200,200));
	
			irrGui->drawAll();
		
			driver->endScene();
		}
	}

	device->drop();

	return 0;
}
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Hehe, sorry about that. Here comes better code i hope:

Creating menu:

Code: Select all

IGUIContextMenu * contextMenu = irrGui->addContextMenu((rect<s32>(0,0,0,0)),0,30);
contextMenu->addItem(L"Equip",11);
u32 craftMenu = contextMenu->addItem(L"Craft",12, true, true);
contextMenu->getSubMenu(craftMenu)->addItem(L"Stone axe",15);
contextMenu->getSubMenu(craftMenu)->addItem(L"Stone hammer",16);
contextMenu->addItem(L"Drop",13);
contextMenu->addItem(L"Examine",14);
Event handler:

Code: Select all

bool EventReceiver::OnEvent(const SEvent& event)
{
   ....
   else if(event.EventType == EET_GUI_EVENT)
	{
        ....
        else if(event.GUIEvent.Caller == contextMenu)
		{
			if(event.GUIEvent.EventType == EGET_MENU_ITEM_SELECTED)
			{
				switch(contextMenu->getSelectedItem())
				{
					case 0:	// Equip
This works great, until i focus the inventory window, thats the window i click in to create the context menu. Code:

Creating window and table:

Code: Select all

IGUIWindow * inventoryWindow = irrGui->addWindow(rect<s32>(674, 100, 994, 600), false, L"Inventory");
IGUITable * equipmentTree = irrGui->addTable(rect<s32>(10, 45, 310, 75),inventoryWindow, -1, false);
Event that runs on right-click. To only show menu when clicking on table and to extract index of table:

Code: Select all

void EventReceiver::EventRightDown(const SEvent& event)	//Item list
{
	rightButtonDown = true;
	if(0 != invTree->getElementFromPoint(vector2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
	{
		int pos = event.MouseInput.Y - invTree->getAbsolutePosition().UpperLeftCorner.Y;
		int index = pos / 15 - 1;
		if(index >= 0 && index < myPlayer->getInvCount())
		{
			contextMenu->setRelativePosition(vector2d<s32>(event.MouseInput.X, event.MouseInput.Y));
			contextMenu->setVisible(true);
			irrGui->setFocus(contextMenu);
			irrDevice->getCursorControl()->setVisible(true);
			camera->setInputReceiverEnabled(false);
			myPlayer->setClickedItem(myPlayer->GetItem(index));
			myPlayer->setSelectedItem(myPlayer->GetItem(invTree->getSelected()));
			if(myPlayer->getClickedItem() != myPlayer->getSelectedItem() &&
				myPlayer->getClickedItem()->getType() == IT_COMPONENT &&
				myPlayer->getSelectedItem()->getType() == IT_COMPONENT)
			{//Rest just selects what menus to enable
As soon as this window gets focus, the EGET_MENU_ITEM_SELECTED event stops for some reason. It Works if i focus another window, just not the same as i click in.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Ehh, no. Compilable code means 'copy all and press compile'. You only show some code fragments. If chosen wisely, this can be enough. But as you were already told that the problem is not that easily visible, you have to provide moree if you really need some help. Just take your *full code* and remove methods and code parts until the problem does not appear anymore. Go back one step and clean up other places of your code the same way. If you cannot find any code fragment which can be removed, post the code here.
CuteAlien
Admin
Posts: 9729
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Hybrid was faster than me ;-) But a note about event-handling in Irrlicht: mouse-events are always going to the focused element.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Sure thing, will look at it tomorrow. But not one has still not answered my question about events from sub-menus. Are they possible and if, how will they be indexed?
CuteAlien
Admin
Posts: 9729
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

EGET_MENU_ITEM_SELECTED also works for sub-menus. You get the menu in Caller and the item with getSelectedItem. Notice that you can pass custom command-id's to menu-items, which is often needed when you work with dynamic menues to identify the items easy.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Ok, here we go again : )
This time its code that should be copy-paste-compilable : p

Still same issue, when window is focused, i cant get anymore EGET_MENU_ITEM_SELECTED events. Also i would be greatful if someone showed me an example on how the get the submenu here give event.

Code: Select all

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

#include <irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

class EventReceiver :
	public IEventReceiver
{
public:

	EventReceiver::EventReceiver(IGUIContextMenu * newContextMenu, IGUIEnvironment * myGui)
	{
		contextMenu = newContextMenu;
		irrGui = myGui;
	}

	bool EventReceiver::OnEvent(const SEvent& event)
	{
		if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
		{
			if(event.EventType == EET_MOUSE_INPUT_EVENT)
			{
				contextMenu->setRelativePosition(vector2d<s32>(event.MouseInput.X, event.MouseInput.Y));
				contextMenu->setVisible(true);
				irrGui->setFocus(contextMenu);
				return true;
			}
		}
		else if(event.EventType == EET_GUI_EVENT)
		{
			if(event.GUIEvent.Caller == contextMenu)
			{
				if(event.GUIEvent.EventType == EGET_MENU_ITEM_SELECTED)
				{
					switch(contextMenu->getSelectedItem())
					{
						case 0:
							break;

						case 1:
							break;

						case 2:
							break;
					}
					return true;
				}
			}
		}
		return false;
	}

private:
	IGUIContextMenu * contextMenu;
	IGUIEnvironment * irrGui;
};

int main()
{
	IrrlichtDevice * irrDevice = createDevice(EDT_DIRECT3D9, dimension2d<u32>(1024,768));
	IGUIEnvironment* irrGui = irrDevice->getGUIEnvironment();
	IVideoDriver * irrVideo = irrDevice->getVideoDriver();
	ISceneManager* irrScene = irrDevice->getSceneManager();
	//Gui
	IGUIWindow * inventoryWindow = irrGui->addWindow(rect<s32>(674, 100, 994, 600), false, L"Inventory");
	IGUITable * invTree = irrGui->addTable(rect<s32>(10, 100, 310, 470),inventoryWindow, -1, false);
	invTree->addColumn(L"Item");
	invTree->addRow(0);
	invTree->setCellText(0,0,L"Cell");

	IGUIContextMenu * contextMenu = irrGui->addContextMenu((rect<s32>(0,0,0,0)),0,30);
	contextMenu->setCloseHandling(ECMC_HIDE);
	contextMenu->addItem(L"Equip",11);
	u32 craftMenu = contextMenu->addItem(L"Craft",12, true, true);
	contextMenu->getSubMenu(craftMenu)->addItem(L"Stone axe",15);
	contextMenu->getSubMenu(craftMenu)->addItem(L"Stone hammer",16);
	contextMenu->addItem(L"Drop",13);
	contextMenu->addItem(L"Examine",14);
	contextMenu->setVisible(false);

	EventReceiver receiver(contextMenu, irrGui);
	irrDevice->setEventReceiver(&receiver);

	// Main loop
	while(irrDevice->run()) 
	{
		irrVideo->beginScene(true, true, SColor(0,0,0,0));
		irrScene->drawAll();
		irrGui->drawAll();      
		irrVideo->endScene();
	}
	irrDevice->drop();
    return 0;
}
[/code]
CuteAlien
Admin
Posts: 9729
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

I'm still at work, but on a quick view I see 2 problems. The first one is simply that it's not nice checking for MouseInput.Event before checking for event.EventType, you should do this the other way round (you don't know if you have a valid MouseInput before you check for EET_MOUSE_INPUT_EVENT).

The other problem is that you return true which marks the event as handled and so it will not be further processed. So the Irrlicht gui never receives the EMIE_RMOUSE_PRESSED_DOWN events. Try returning false instead.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Hehe, the first point is very valid ; )
Did no notice that, very bad practice. But i see now in my original code that i do it right there.

About the other issue, i will test and see.

Edit: I think i found the issue, the problems seems to be that the contextMenu is created behind the inventory, so when inventory is focused the keypresses don't hit the menu, but the window instead. Not sure how to fix this though, the "bringToFront" function don't seem to do the trick...
CuteAlien
Admin
Posts: 9729
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

bringToFront works relative to other childs which have the same parent. Not sure if you still use the same test-case (where it doesn't seem to have a parent, so it should work), but in general you should give context-menus no parent except the gui-environment itself to make sure a bringToFront on them brings them really to the top.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply