Keyboard events

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

bogas
Just popping in
Just popping in
Posts: 5
Joined: Thu Jun 19, 2008 11:40

Keyboard events

Postby bogas » Thu Jun 19, 2008 11:49

Hello everyone,

I am trying to make a simple navigation menu for my application. Simple buttons really. I managed to work out the mouse input events, but I am having a hard time to bind different key events to the buttons. I want to have Arrow Up and Arrow Down button navigation/selection and Enter to confirm, ESC to cancel. I read that there is no keyboard support in CEGUI, or any easy way to have it done, but the posts that i read were from 2 years back. How is it now, what is a suggested way of doing this? I could not find it in any tutorials (they concentrate on mouse input). If it helps, i use CEGUI + OGRE.
Last edited by bogas on Thu Jun 19, 2008 21:42, edited 1 time in total.

Jamarr
CEGUI MVP
CEGUI MVP
Posts: 812
Joined: Tue Jun 03, 2008 23:59
Location: USA

Postby Jamarr » Thu Jun 19, 2008 17:40

it's exactly the same as mouse input, so to speak. You inject your own keyboard events into cegui (http://www.cegui.org.uk/wiki/index.php/The_Beginner_Guide_to_Injecting_Inputs); cegui processes that input, and then sends out the appropriate events to the appropriate window/widget. If you subscribed to those events (http://www.cegui.org.uk/wiki/index.php/FAQ#What_is_the_correct_way_to_subscribe_for_an_event.3F) then cegui will call the function/method you subscribed with. The reason you can't find keyboard specific code is because all input/events are essentially handled the same way. You might also try looking at the API docs, as it provides information regarding the EventArgs object passed to your subscriber (http://www.cegui.org.uk/api_reference/classCEGUI_1_1KeyEventArgs.html).

bogas
Just popping in
Just popping in
Posts: 5
Joined: Thu Jun 19, 2008 11:40

Postby bogas » Sat Jun 21, 2008 14:28

Ok. I managed to get keyboard input into CEGUI, however my function that subscribes to the EventKeyUp does not allow me to check which key was released/pressed. When I change the function to

Code: Select all

bool MainMenuDlg::Window_OnKeyUp(const CEGUI::KeyEventArgs &args)


instead of

Code: Select all

bool MainMenuDlg::Window_OnKeyUp(const CEGUI::EventArgs &args)


I get an error:

Code: Select all

error C2661: 'CEGUI::SubscriberSlot::SubscriberSlot' : no overloaded function takes 2 arguments


It seems like it cannot have KeyEventArgs as an paramter. I am confused.

This is how I inject the event to CEGUI:

Code: Select all

bool InputHandler::keyReleased(const OIS::KeyEvent &evt) {
   if (evt.key == OIS::KC_ESCAPE)
      m_simulation->requestStateChange(SHUTDOWN);

   CEGUI::KeyEventArgs* keyEvent = new CEGUI::KeyEventArgs(CEGUI::WindowManager::getSingleton().getWindow("Main"));
   return m_pSystem->injectKeyUp(keyEvent->scancode);
}


And this is how i subscribe to it:

Code: Select all

CEGUI::PushButton* pMainWindow = (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("Main");
pMainWindow->subscribeEvent(CEGUI::PushButton::EventKeyUp, CEGUI::Event::Subscriber(&MainMenuDlg::Window_OnKeyUp, this));

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Postby CrazyEddie » Sun Jun 22, 2008 08:27

Hi,

you can cast the CEGUI::EventArgs structure to the 'real' type that the specific handler knows that it will be getting.

For example:

Code: Select all

bool MainMenuDlg::Window_OnKeyUp(const CEGUI::EventArgs &args)
{
    const CEGUI::KeyEventArgs& key_args = static_cast<const CEGUI::KeyEventArgs&>{args);

    // TODO: Your code here!
}


CE

Jamarr
CEGUI MVP
CEGUI MVP
Posts: 812
Joined: Tue Jun 03, 2008 23:59
Location: USA

Postby Jamarr » Mon Jun 23, 2008 17:44

CE is correct, you just need to cast the EventArg parameter to real type.

As far as your code to inject the keyboard input, it doesn't look like it's actually injecting the input. I can see you are taking a keyboard event from your input handler (OIS::KeyEvent), but you are handling that event inside the cegui->injector function; I suppose this is fine if you want some global-keybinds, but if you are trying to handle window/widget-specific events you should be handling this event in the callback function you defined when you subscribed to the event (in your case, Window_OnKeyUp).

Also, it doesn't appear that you are actually injecting anything into cegui. It looks like you are simply creating a fake keyboard event and injecting that into cegui. Generally you should be injecting the actual keyboard event (evt.key) into cegui; this way you can take advantage of any builtin functionality that cegui has for the different widgets. However, note that you may need to remap some of your keys to cegui keys before injecting them (I believe the Guild to Injecting Inputs describes this). For example:

Code: Select all

bool InputHandler::keyReleased(const OIS::KeyEvent &evt) {
   return m_pSystem->injectKeyUp(MyKeyToCeKey(evt.key));
}

bool MainMenuDlg::Window_OnKeyUp(const CEGUI::EventArgs &args)
{
   const CEGUI::KeyEventArgs& keyEvent = static_cast<const CEGUI::KeyEventArgs&>(args);

   if (CEGUI::Key::Escape == keyEvent.scancode)
      m_simulation->requestStateChange(SHUTDOWN);
}

bogas
Just popping in
Just popping in
Posts: 5
Joined: Thu Jun 19, 2008 11:40

Postby bogas » Mon Jun 23, 2008 23:27

Thanks for the help. It did work after changing the code according to your suggestion guys. That is how I do the conversion from OIS to CEGUI:

Code: Select all

bool InputHandler::keyReleased(const OIS::KeyEvent &evt) {

   if (evt.key == OIS::KC_ESCAPE)
   {
      m_simulation->requestStateChange(SHUTDOWN);
      return true;
   }

        // L stands for nothing, just an experiment
   if (evt.key == OIS::KC_L)
      return m_pSystem->injectKeyUp(CEGUI::Key::L);

   return m_pSystem->injectKeyUp(evt.key);
}


Is that what you meant Jamarr?

Even though it works now, I am still a little confused. I experimented more and found out that the following code also works fine:

Code: Select all

bool InputHandler::keyReleased(const OIS::KeyEvent &evt) {

   unsigned int ch = evt.text;

   if (evt.key == OIS::KC_ESCAPE)
   {
      m_simulation->requestStateChange(SHUTDOWN);
      return true;
   }

   //if (evt.key == OIS::KC_L)
   //   return m_pSystem->injectKeyUp(CEGUI::Key::L);

   m_pSystem->injectKeyUp(evt.key);
   return m_pSystem->injectChar(ch);
}


It is basically the same code as for keyPressed() function. This saves the conversion code, but according to the injectChar() description is not correct because it injects characters pressed rather than released. Any comment on that, that would help me better understand this?

Jamarr
CEGUI MVP
CEGUI MVP
Posts: 812
Joined: Tue Jun 03, 2008 23:59
Location: USA

Postby Jamarr » Tue Jun 24, 2008 18:21

Is there a particular reason why you decided to use a KeyUp event instead of KeyDown? You can't replicate key holding (key repeat) using the KeyUp events; using KeyDown events seem to be the general standard (at least in my experience).

Anyway, the way I use it is that I only use injectKeyDown()+injectKeyUp() for system-related keybinds (ex: esc, return, F1-F12, tab, backspace, delete, arrow keys, etc. etc.), and for all ascii/character related events I just use injectChar(). It works very well for my setup.

bogas
Just popping in
Just popping in
Posts: 5
Joined: Thu Jun 19, 2008 11:40

Postby bogas » Wed Jun 25, 2008 00:03

There is no reason behind it. I was just checking things out. And the way you and CE suggested to solve my problem works fine for me to. So in my application I will stick to that. Thanks again!


Return to “Help”

Who is online

Users browsing this forum: No registered users and 19 guests