GUI + MastEventReceiver + general coding issues. [solved]

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
Dukdalf
Posts: 24
Joined: Thu Jun 21, 2007 9:48 am

GUI + MastEventReceiver + general coding issues. [solved]

Post by Dukdalf »

Here I am again!

I am able code parts of my game without a real problem, probably not hte most beautiful code, but that can only improve over time. I am now trying to combine different code snippets togather, and I experience some unexpected problems with it:

My code is based on the code from some tutorials together with the MastEventReceiver. The problem arises when I try to add some interactive GUI elements. I create a button in my main:

Code: Select all

IGUIButton* button = env->addButton(core::rect<s32>(670,10,740,50),0,1,L"End Turn",L"Press to end turn.");
This button looks fine when I run my program, but I cannot interact with this button.

I added to the MastEventReceiver an if statement to catch the EET_GUI_EVENT but this never really gets triggered. It looks like the only two events that can happen are the EET_MOUSE_EVENT and the EET_KEY_EVENT:

Code: Select all

virtual bool OnEvent(SEvent event)
   {
      bool eventprocessed = false;
      
      cout << event.EventType <<endl;
      //////////////////////////////
      // GUI Event
	  //////////////////////////////
	  if (event.EventType == EET_GUI_EVENT){
		  cout << "YES, you clicked on the button" <<endl;
		  eventprocessed = true;
	  }
}
It feels like there is a bug, but I am sure somebody can explain to me, what I do wrong.

TIA

Dukdalf
Last edited by Dukdalf on Tue Aug 07, 2007 4:56 pm, edited 1 time in total.
Just fooling around abit!
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

hmm, this should work, except you forgot to return success...
either this way:

Code: Select all

virtual bool OnEvent(SEvent event)
   {
      bool eventprocessed = false;
     
      cout << event.EventType <<endl;
      //////////////////////////////
      // GUI Event
     //////////////////////////////
     if (event.EventType == EET_GUI_EVENT){
        cout << "YES, you clicked on the button" <<endl;
        eventprocessed = true;
        return true;
     }
     return false;
}
or in your case simply like this:

Code: Select all

virtual bool OnEvent(SEvent event)
   {
      bool eventprocessed = false;
     
      cout << event.EventType <<endl;
      //////////////////////////////
      // GUI Event
     //////////////////////////////
     if (event.EventType == EET_GUI_EVENT){
        cout << "YES, you clicked on the button" <<endl;
        eventprocessed = true;
     }
     return eventprocessed;
}
also you should check if really the button raised the event...
get the button's id with s32 id = event.GUIEvent.Caller->getID();
and check for button clicked with if(event.GUIEvent.EventType == EGET_BUTTON_CLICKED) or something similar (check tutorials)...
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Dukdalf
Posts: 24
Joined: Thu Jun 21, 2007 9:48 am

Post by Dukdalf »

yeah you are right, I did not add that return statement to the snippet I posted, but it was their the same way you proposed.;-)

the EET_GUI_EVENT is the first of the enumeration of event types so the first 'cout' statement should give a 0 whenever the event happens. The problem is that this statement never produces a '0', so the event never happens. It does show '1' for EET_MOUSE_EVENT and '2' for EET_KEY_EVENT.

Any further ideas?
Just fooling around abit!
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Dukdalf wrote:Any further ideas?
no, sorry, as I told you before: it should work... :shock:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Dukdalf
Posts: 24
Joined: Thu Jun 21, 2007 9:48 am

Post by Dukdalf »

I replaced the MyEventReceiver in the GUI Example with the MastEventReceiver, and I print the type of the event in the beginning of both eventreceivers. THe GUIEvents do not work in the MastEventReceiver, but I really have NO clue why that is.

cout << event.EventType <<endl;

The Mast Receiver does not trigger eventType = 0 (EET_GUI_EVENT) but does trigger the mouse (1) and key (2). The MyEventReceiver triggers all 3.

If somebody with some more experience can have a look at the MastEventReceiver that would be great, because I do like the way it is being setup!

/Cheers

Dukdalf
Just fooling around abit!
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

you could post the complete declaration of your MastEventReceiver and maybe the part where you create the device (set the event receiver)...
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Dukdalf
Posts: 24
Joined: Thu Jun 21, 2007 9:48 am

Post by Dukdalf »

I added the cout statement to the eventviewer to see if the GUI_Event triggers.

Thanks for looking acki!

Code: Select all

/*
This tutorial shows how to use the built in User Interface of
the Irrlicht Engine. It will give a brief overview and show
how to create and use windows, buttons, scroll bars, static 
texts and list boxes.

As always, we include the header files, and use the irrlicht
namespaces. We also store a pointer to the Irrlicht device,
a counter variable for changing the creation position of a window,
and a pointer to a listbox.
*/
#include <irrlicht.h>
#include <iostream>

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

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



s32 cnt = 0;
IGUIListBox* listbox = 0;

/// ==============================
/// MastEventReceiver
/// ==============================
class MastEventReceiver : public IEventReceiver
{

   protected:
   // Enumeration for UP, DOWN, PRESSED and RELEASED key states. Also used for mouse button states.
   enum keyStatesENUM {UP, DOWN, PRESSED, RELEASED};

   // Enumeration for Event Handling State.
   enum processStateENUM {STARTED, ENDED};

   // Mouse button states.
   keyStatesENUM mouseButtonState[2]; //Left(0), Middle(1) and Right(2) Buttons.

   // Keyboard key states.
   keyStatesENUM keyState[KEY_KEY_CODES_COUNT];

   // Mouse X/Y coordinates and Wheel data.
   struct mouseData
   {
   int X;
   int Y;
   float wheel; //wheel is how far the wheel has moved
   };
   struct mouseData mouse;

   processStateENUM processState; // STARTED = handling events, ENDED = not handling events

   virtual bool OnEvent(SEvent event)
   {
      bool eventprocessed = false;
      
      cout << event.EventType <<endl;
      
      //////////////////////////////
      // GUI Event
	  //////////////////////////////
	  if (event.EventType == EET_GUI_EVENT){
		  cout << "YES, you clicked on the button" <<endl;
		  eventprocessed = true;
	  }
	  
	  
		  

      
      //////////////////////////////
      // Keyboard Input Event
      //////////////////////////////
      if (event.EventType == EET_KEY_INPUT_EVENT)
      {
    	 if (processState == STARTED)
         {
            // if key is Pressed Down
            if (event.KeyInput.PressedDown == true)
            {
               // If key was not down before
               if (keyState[event.KeyInput.Key] != DOWN)
               {
                  keyState[event.KeyInput.Key] = PRESSED; // Set to Pressed
               }
               else
               {
                  // if key was down before
                  keyState[event.KeyInput.Key] = DOWN; // Set to Down
               }
            }
            else
            {

                  // if the key is down
                  if (keyState[event.KeyInput.Key] != UP)
                  {
                     keyState[event.KeyInput.Key] = RELEASED; // Set to Released
                  }
            }
         }


         eventprocessed = true;
      }

      //////////////////////////////
      // Mouse Input Event
      //////////////////////////////

      if (event.EventType == EET_MOUSE_INPUT_EVENT)
      {
    	  if (processState == STARTED)
         {
            //Mouse changed position
            if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
            {
               mouse.Y = event.MouseInput.Y;
               mouse.X = event.MouseInput.X;
            }

            //Wheel moved.
            if (event.MouseInput.Event == EMIE_MOUSE_WHEEL)
            {
               mouse.wheel += event.MouseInput.Wheel;
            }

            //Left Mouse Button Pressed
            if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
            {
               //
               if (mouseButtonState[0] == UP || mouseButtonState[0] == RELEASED)
               {
                  mouseButtonState[0] = PRESSED;
               }
               else
               {
                  mouseButtonState[0] = DOWN;
               }
            }

            //Left Mouse Button Rleased
            if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
            {
               //
               if (mouseButtonState[0] != UP)
               {
                  mouseButtonState[0] = RELEASED;
               }
            }

            //Middle Mouse Button Pressed
            if (event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN)
            {
               //
               if (mouseButtonState[1] == UP || mouseButtonState[1] == RELEASED)
               {
                  mouseButtonState[1] = PRESSED;
               }
               else
               {
                  mouseButtonState[1] = DOWN;
               }
            }

            //Middle Mouse Button Rleased
            if (event.MouseInput.Event == EMIE_MMOUSE_LEFT_UP)
            {
               //
               if (mouseButtonState[1] != UP)
               {
                  mouseButtonState[1] = RELEASED;
               }
            }

            //Right Mouse Button Pressed
            if (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
            {
               //
               if (mouseButtonState[2] == UP || mouseButtonState[2] == RELEASED)
               {
                  mouseButtonState[2] = PRESSED;
               }
               else
               {
                  mouseButtonState[2] = DOWN;
               }
            }

            //Right Mouse Button Rleased
            if (event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP)
            {
               //
               if (mouseButtonState[2] != UP)
               {
                  mouseButtonState[2] = RELEASED;
               }
            }
         }


         eventprocessed = true;
      }


      return eventprocessed;
   }


   //////////////////////
   // Public functions
   //////////////////////
   public:

   float mouseWheel()
   {
      return mouse.wheel;
   }

   int mouseX()
   {
      return mouse.X;
   }

   int mouseY()
   {
      return mouse.Y;
   }

   bool leftMouseReleased()
   {
      if (mouseButtonState[0] == RELEASED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }
   bool leftMouseUp()
   {
      if (mouseButtonState[0] == RELEASED || mouseButtonState[0] == UP)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool leftMousePressed()
   {
      if (mouseButtonState[0] == PRESSED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool leftMouseDown()
   {
      if (mouseButtonState[0] == PRESSED || mouseButtonState[0] == DOWN)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool middleMouseReleased()
   {
      if (mouseButtonState[1] == RELEASED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }
   bool middleMouseUp()
   {
      if (mouseButtonState[1] == RELEASED || mouseButtonState[1] == UP)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool middleMousePressed()
   {
      if (mouseButtonState[1] == PRESSED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool middleMouseDown()
   {
      if (mouseButtonState[1] == PRESSED || mouseButtonState[1] == DOWN)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool rightMouseReleased()
   {
      if (mouseButtonState[2] == RELEASED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }
   bool rightMouseUp()
   {
      if (mouseButtonState[2] == RELEASED || mouseButtonState[2] == UP)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool rightMousePressed()
   {
      if (mouseButtonState[2] == PRESSED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool rightMouseDown()
   {
      if (mouseButtonState[2] == PRESSED || mouseButtonState[2] == DOWN)
      {
         return true;
      }
      else
      {
         return false;
      }
   }//

   bool keyPressed(char keycode)
   {
      if (keyState[keycode] == PRESSED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool keyDown(char keycode)
   {
      if (keyState[keycode] == DOWN || keyState[keycode] == PRESSED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool keyUp(char keycode)
   {
      if (keyState[keycode] == UP || keyState[keycode] == RELEASED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }

   bool keyReleased(char keycode)
   {
      if (keyState[keycode] == RELEASED)
      {
         return true;
      }
      else
      {
         return false;
      }
   }


   // This is used so that the Key States will not be changed during execution of your Main game loop.
   // Place this at the very START of your Main Loop
   void endEventProcess()
   {
      processState = ENDED;
   }

   // This is used so that the Key States will not be changed during execution of your Main game loop.
   // Place this function at the END of your Main Loop.
   void startEventProcess()
   {

      processState = STARTED;
      //Keyboard Key States
      for (int i = 0; i < KEY_KEY_CODES_COUNT; i++)
      {
         if (keyState[i] == RELEASED)
         {
            keyState[i] = UP;
         }

         if (keyState[i] == PRESSED)
         {
            keyState[i] = DOWN;
         }
      }
      //Mouse Button States
      for (int i = 0; i <= 2; i++)
      {
         if (mouseButtonState[i] == RELEASED)
         {
            mouseButtonState[i] = UP;
         }

         if (mouseButtonState[i] == PRESSED)
         {
            mouseButtonState[i] = DOWN;
         }
      }
      //Mouse Wheel state
      mouse.wheel = 0.0f;

   }

   void init()
   {
      //KeyBoard States.
      for (int i = 0; i <= KEY_KEY_CODES_COUNT; i++)
      {
         keyState[i] = UP;
      }
      //Mouse states
      for (int i = 0; i <= 2; i++)
      {
         mouseButtonState[i] = UP;
      }
      //Mouse X/Y coordenates.
      mouse.X = 0;
      mouse.Y = 0;
      mouse.wheel = 0.0f;
   }


};
/// ==========================================
/// END OF MastEventReceiver
/// ========================================== 
/*
The Event Receiver is not only capable of getting keyboard and
mouse input events, but also events of the graphical user interface 
(gui). There are events for almost everything: Button click, 
Listbox selection change, events that say that a element was hovered
and so on. To be able to react to some of these events, we create 
an event receiver. 
We only react to gui events, and if it's such an event, we get the
id of the caller (the gui element which caused the event) and get 
the pointer to the gui environment.
*/
//class MyEventReceiver : public IEventReceiver
//{
//public:
//	virtual bool OnEvent(SEvent event)
//	{
//		cout << event.EventType << endl;
////		if (event.EventType == EET_GUI_EVENT)
////		{
////			s32 id = event.GUIEvent.Caller->getID();
////			IGUIEnvironment* env = device->getGUIEnvironment();
////
////			switch(event.GUIEvent.EventType)
////			{
////
////			/*
////			If a scrollbar changed its scroll position, and it is 'our'
////			scrollbar (the one with id 104), then we change the 
////			transparency of all gui elements. This is a very easy task:
////			There is a skin object, in which all color settings are stored.
////			We simply go through all colors stored in the skin and change
////			their alpha value.
////			*/
////			case EGET_SCROLL_BAR_CHANGED:
////				if (id == 104)
////				{
////					s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
////					
////					for (u32 i=0; i<EGDC_COUNT ; ++i)
////					{
////						SColor col = env->getSkin()->getColor((EGUI_DEFAULT_COLOR)i);
////						col.setAlpha(pos);
////						env->getSkin()->setColor((EGUI_DEFAULT_COLOR)i, col);
////					}
////					
////				}
////				break;
////
////			/*
////			If a button was clicked, it could be one of 'our'
////			three buttons. If it is the first, we shut down the engine.
////			If it is the second, we create a little window with some 
////			text on it. We also add a string to the list box to log
////			what happened. And if it is the third button, we create
////			a file open dialog, and add also this as string to the list box.
////			That's all for the event receiver.
////			*/
////			case EGET_BUTTON_CLICKED:
////
////				if (id == 101)
////				{
////					device->closeDevice();
////					return true;
////				}
////
////				if (id == 102)
////				{
////					listbox->addItem(L"Window created");
////					cnt += 30;
////					if (cnt > 200) 
////						cnt = 0;
////
////					IGUIWindow* window = env->addWindow(
////						rect<s32>(100 + cnt, 100 + cnt, 300 + cnt, 200 + cnt), 
////						false, // modal?
////						L"Test window");
////
////					env->addStaticText(L"Please close me",  
////						rect<s32>(35,35,140,50),
////						true, // border?
////						false, // wordwrap?
////						window);
////
////					return true;
////				}
////
////				if (id == 103)
////				{
////					listbox->addItem(L"File open");
////					env->addFileOpenDialog(L"Please choose a file.");
////					return true;
////				}
////
////				break;
////			default:
////				break;
////			}
////		}
//
//		return false;
//	}
//};


/*
Ok, now for the more interesting part. First, create the 
Irrlicht device. As in some examples before, we ask the user which
driver he wants to use for this example:
*/
int main()
{
	// ask user for driver
	

	// create device and exit if creation failed

	IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D9, core::dimension2d<s32>(640, 480));

	if (device == 0)
		return 1; // could not create selected driver.

	/* The creation was successful, now we set the event receiver and
		store pointers to the driver and to the gui environment. */

	MastEventReceiver receiver;
	receiver.init();
	device->setEventReceiver(&receiver);
	device->setWindowCaption(L"Irrlicht Engine - User Interface Demo");

	video::IVideoDriver* driver = device->getVideoDriver();
	IGUIEnvironment* env = device->getGUIEnvironment();

	/*
	To make the font a little bit nicer, we load an external font
	and set it as the new default font in the skin. 
	To keep the standard font for tool tip text, we set it to
	the built-in font.
	*/

	IGUISkin* skin = env->getSkin();
	IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp");
	if (font)
		skin->setFont(font);

	skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);

	/*
	We add three buttons. The first one closes the engine. The second
	creates a window and the third opens a file open dialog. The third
	parameter is the id of the button, with which we can easily identify
	the button in the event receiver.
	*/	

	env->addButton(rect<s32>(10,210,110,210 + 32), 0, 101, L"Quit", L"Exits Program");
	env->addButton(rect<s32>(10,250,110,250 + 32), 0, 102, L"New Window", L"Launches a new Window");
	env->addButton(rect<s32>(10,290,110,290 + 32), 0, 103, L"File Open", L"Opens a file");

	/*
	Now, we add a static text and a scrollbar, which modifies the
	transparency of all gui elements. We set the maximum value of
	the scrollbar to 255, because that's the maximal value for 
	a color value.
	Then we create an other static text and a list box.
	*/

	env->addStaticText(L"Transparent Control:", rect<s32>(150,20,350,40), true);
	IGUIScrollBar* scrollbar = env->addScrollBar(true, rect<s32>(150, 45, 350, 60), 0, 104);
	scrollbar->setMax(255);

	// set scrollbar position to alpha value of an arbitrary element
	scrollbar->setPos(env->getSkin()->getColor(EGDC_WINDOW).getAlpha());

	env->addStaticText(L"Logging ListBox:", rect<s32>(50,80,250,100), true);
	listbox = env->addListBox(rect<s32>(50, 110, 250, 180));
	env->addEditBox(L"Editable Text", rect<s32>(350, 80, 550, 100));

	// add the engine logo
	env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"),
			position2d<int>(10,10));


	/*
	That's all, we only have to draw everything.
	*/

	while(device->run() && driver)
	if (device->isWindowActive())
	{
		receiver.endEventProcess();
		driver->beginScene(true, true, SColor(0,200,200,200));

		env->drawAll();
	
		driver->endScene();
		receiver.startEventProcess();
	}

	device->drop();

	return 0;
}
Just fooling around abit!
Post Reply