Subscribing to global 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

LearnerPlates
Just popping in
Just popping in
Posts: 20
Joined: Mon Jun 08, 2009 06:05

Subscribing to global keyboard events?

Postby LearnerPlates » Tue Sep 08, 2009 08:47

I've browsed the forums and tutorials for more information on this, but I can't find exactly what I'm looking for. How would I go about subscribing to a global keyboard event in CEGUI?

I am injecting the keyboard input from OIS, but I don't know what to do from there. I've read this thread, but I'm confused - do keyboard events really need to be subscribed to a specific widget? The "global event set" is mentioned here - can I use that instead? If so, what is the correct syntax for subscribing an event? This line in the code on that page

Code: Select all

CEGUI::GlobalEventSet::getSingleton( ).subscribeEvent( CEGUI::Window::EventNamespace + "/" + CEGUI::Window::EventActivated, CEGUI::Event::Subscriber(&UserInterface::keyboardEvent) );
gives me a compiler error (error C2064: term does not evaluate to a function taking 1 arguments c:\program files\ogresdk\include\cegui\ceguifunctorcopyslot.h), and besides I don't really understand its first parameter.

I'd really like to know what the "correct" way of doing this is - thanks for any help, and sorry if this is a lame question!

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

Re: Subscribing to global keyboard events?

Postby CrazyEddie » Tue Sep 08, 2009 09:41

Hi,

I don't especially understand why you want to subscribe to these events globally - CEGUI is very window centric. For truly 'global' access to the input events, you have access to the source of the events, since you're injecting them in the first place :)

You can subscribe to the global event set, though depending on various things, including the version of the code and the particular set of bugs your version has, you may end up with >1 call of the handler for a single input event.

To address the compile error:

Code: Select all

CEGUI::Event::Subscriber(&UserInterface::keyboardEvent)

attempts to subscribe a member function to handle the event, but you have not included an the instance object that is to have the function invoked. If the class containing the function is the same as the one making the subscription, you just need to add the 'this' pointer, like so:

Code: Select all

CEGUI::Event::Subscriber(&UserInterface::keyboardEvent, this)

If the classes are not the same, then you need to provide a pointer to an object of the appropriate type (UserInterface).

CE.

LearnerPlates
Just popping in
Just popping in
Posts: 20
Joined: Mon Jun 08, 2009 06:05

Re: Subscribing to global keyboard events?

Postby LearnerPlates » Tue Sep 08, 2009 10:33

Thanks so much for your help, CE! So, I guess the "correct" way for me to go about this would be simply to pass a message to my class when OIS picks up the keyboard event rather than trying to handle it through CEGUI. Makes sense. :) I still might experiment a bit with the global event set, though.

Oh, I can't believe I didn't realise what was happening with that code! Maybe the example on that page was written using an older version of the library? Cheers for the assistance. :)

LearnerPlates
Just popping in
Just popping in
Posts: 20
Joined: Mon Jun 08, 2009 06:05

Re: Subscribing to global keyboard events?

Postby LearnerPlates » Tue Sep 08, 2009 11:24

Argh, have I done something really stupid? I've browsed all the threads I can find on global events and I'm not sure why this

Code: Select all

CEGUI::GlobalEventSet::getSingleton().subscribeEvent( CEGUI::Window::EventNamespace + "/" + CEGUI::Window::EventKeyDown, CEGUI::Event::Subscriber(&UserInterface::keyboardEvent, this) );
doesn't work (my keyboardEvent function is never called).

I'm mostly going off what I read in this thread - otherwise, I don't properly understand what subscribeEvent wants for its first parameter. :( If this is clearly documented somewhere please let me know...

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

Re: Subscribing to global keyboard events?

Postby Jamarr » Tue Sep 08, 2009 16:27

It would help if we knew exactly what you where trying to do? I really cannot see any need for someone to subscribe to global input events through CEGUI because you already have access to that input when you inject it into CEGUI.
If somebody helps you by replying to your thread, upvote him/her as a thanks! Make sure to include your CEGUI.log and everything you tried when posting! And remember that we are not magicians!

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

Re: Subscribing to global keyboard events?

Postby CrazyEddie » Wed Sep 09, 2009 08:37

Perhaps a daft question, but are you injecting key down events? (not characters, but actual key down / key up pairs?).

CE.

LearnerPlates
Just popping in
Just popping in
Posts: 20
Joined: Mon Jun 08, 2009 06:05

Re: Subscribing to global keyboard events?

Postby LearnerPlates » Tue Sep 15, 2009 07:54

I'm trying to pass a keyboard event from my OIS key listener to my CEGUI-based interface class. I inject the event into CEGUI like so:

Code: Select all

bool keyPressed(const OIS::KeyEvent &arg)
{
      CEGUI::System *sys = CEGUI::System::getSingletonPtr();
      sys->injectKeyDown(arg.key);
}


Then try to subscribe within the class like so:

Code: Select all

CEGUI::GlobalEventSet::getSingleton().subscribeEvent( CEGUI::Window::EventNamespace + "/" + CEGUI::Window::EventKeyDown, CEGUI::Event::Subscriber(&UserInterface::keyboardEvent, this) );


I want a keypress to call my keyboardEvent( const CEGUI::EventArgs &e ), where I will then switch the scancode to see what key has been pressed and call appropriate code from there. At the moment, my keyboardEvent function is never called. :(

Code: Select all

I really cannot see any need for someone to subscribe to global input events through CEGUI because you already have access to that input when you inject it into CEGUI.


I see your point, but surely the global event functionality was added to CEGUI for a reason...? :?:

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

Re: Subscribing to global keyboard events?

Postby CrazyEddie » Tue Sep 15, 2009 09:20

surely the global event functionality was added to CEGUI for a reason...?

Yes, it was added so a person could get event notifications without needing to individually subscribe handlers to every window - or other object - they create.

CrazyEddie wrote:Perhaps a daft question, but are you injecting key down events? (not characters, but actual key down / key up pairs?).

This is important because if you're not, you will not get events fired. If you subscribe a handler globally to some other event, does that work? (I know you want keys, but it's a test to ensure there's not some other underlying cause).

CE.

LearnerPlates
Just popping in
Just popping in
Posts: 20
Joined: Mon Jun 08, 2009 06:05

Re: Subscribing to global keyboard events?

Postby LearnerPlates » Tue Sep 15, 2009 10:23

Yes, it was added so a person could get event notifications without needing to individually subscribe handlers to every window - or other object - they create.

Do you mean so that every instance of a particular type of window/widget is subscribed to one function? Thus what I'm trying to achieve is not actually what it was designed for?

Perhaps a daft question, but are you injecting key down events? (not characters, but actual key down / key up pairs?).

Now I'm confused... isn't that what I'm doing here?
sys->injectKeyDown(arg.key);


If you subscribe a handler globally to some other event, does that work?

Weird... I just tried it with EventMouseButtonDown and it worked fine, but it doesn't work with EventKeyDown, which I'm injecting in the same way (from an OIS mouse/key listener). :?

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

Re: Subscribing to global keyboard events?

Postby CrazyEddie » Tue Sep 15, 2009 10:48

LearnerPlates wrote:Do you mean so that every instance of a particular type of window/widget is subscribed to one function? Thus what I'm trying to achieve is not actually what it was designed for?

If you're asking whether internally we subscribe the event to every window, then no, that's not what happens. So long as there's a window of some kind to receive the initial input from CEGUI::System, the event will fire - but there has to be a window (hence the use of the window event namespace) - which means so long as this criteria is met, what you're trying to do should be fine.

LearnerPlates wrote:
Perhaps a daft question, but are you injecting key down events? (not characters, but actual key down / key up pairs?).

Now I'm confused... isn't that what I'm doing here?
sys->injectKeyDown(arg.key);

Sorry, I'd missed the fact you'd posted that :oops: Yes, this is correct. Have you added some debugging spew to confirm that the code is ever called?

CE.

LearnerPlates
Just popping in
Just popping in
Posts: 20
Joined: Mon Jun 08, 2009 06:05

Re: Subscribing to global keyboard events?

Postby LearnerPlates » Tue Sep 15, 2009 12:27

Thanks very much for the explanation - that makes sense now. :)

And yes, debugging spew (and a break point!) confirm the inject code is definitely called...

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

Re: Subscribing to global keyboard events?

Postby CrazyEddie » Tue Sep 15, 2009 12:39

Hi, very odd.

Which version of the code is this? And are there any particular window types you're using. I'm mainly asking since I spotted a SNAFU in the editboxes for v0-7.

CE.

LearnerPlates
Just popping in
Just popping in
Posts: 20
Joined: Mon Jun 08, 2009 06:05

Re: Subscribing to global keyboard events?

Postby LearnerPlates » Tue Sep 15, 2009 13:32

I'm using version 0.6.2 of the code, and at the moment I'm only using StaticText, StaticImage, Button and ImageButton. I feel sure the mess-up must be on my end, though...

Wow, now I'm really confused. I tried pressing a key at various points in the code with a breakpoint on my keyboardEvent function to see if it was ever getting called:
I initialised the CEGUI stuff (which is where I subscribe to the GlobalEventSet), pressed Esc - nothing.
Clicked a Button, pressed Esc - nothing.
Clicked an ImageButton, pressed Esc - the function was called!
Pressed Esc again - the function was called again (and every time thereafter).

There is absolutely nothing special happening in the code called when I click the ImageButton (I even tried commenting it all out and the effect was the same), so I'm very puzzled by this... I do change .layout sheets several times before getting to the ImageButton - could this be affecting it?


Edit: Hmmm, it seems that if I click on either the root window or an ImageButton (thereby changing the focus, I guess?) before hitting a key, the subscribed function is called. After I click on a Button, though, the function is no longer called when I press a key. Is there some way I can remedy this?

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

Re: Subscribing to global keyboard events?

Postby Jamarr » Tue Sep 15, 2009 14:59

LearnerPlates wrote:
Yes, it was added so a person could get event notifications without needing to individually subscribe handlers to every window - or other object - they create.

Do you mean so that every instance of a particular type of window/widget is subscribed to one function? Thus what I'm trying to achieve is not actually what it was designed for?


In a sense, yes. As CE mentioned this is not how it works internally, but the end result is similar. Say you want to play some sound-effect whenever a window is closed...instead of subscribing to every single window you simply subscribe to the global event.

It sounds like what you are trying to do is simply forward the input from your input-system to your game-system. But you are currently going through a middle man, CEGUI, for no apparent reason. This is why I asked what exactly are you trying to do. There are perfectly logical reasons to use the global event system, but it sounds like to me you are simply trying to pass all input to your game-system. I say this because your second post in this thread leads me to believe that.

If you just want to pass your input to your game, then you are making it more complicated than it needs to be. Just pass it on to your game after injecting it into CEGUI. Additionally, the CEGUI::System::inject* methods return a result telling you weather or not the event triggered any action in the GUI. Typically you would only pass the input onto your game-system if it was not used by the GUI.
If somebody helps you by replying to your thread, upvote him/her as a thanks! Make sure to include your CEGUI.log and everything you tried when posting! And remember that we are not magicians!

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

Re: Subscribing to global keyboard events?

Postby CrazyEddie » Tue Sep 15, 2009 18:27

Since there are clearly issues here that, at least without some closer analysis, I can't explain, I will put it down to the fact that these events are more 'input' orientated, whereas the global event set is more about 'output' events. Yes, this is a lame 'cop out' answer, but there it is...

However. If you're dead set on using CEGUI based events for whatever reason, there is nothing stopping you from firing your own custom event on the global event set. For example, in your injection code, you might add something like this:

Code: Select all

bool keyPressed(const OIS::KeyEvent &arg)
{
    CEGUI::KeyEventArgs custom_args(0);
    custom_args.scancode = (CEGUI::Key::Scan)arg.key;
    CEGUI::GlobalEventSet::getSingleton().fireEvent( "MyCustomEventName", custom_args );

    // if you want, you might examine the 'handled' state here, and decide whether to inject into CEGUI
    // for example,
    //    if ( custom_args.handled )
    //        return true;

    CEGUI::System *sys = CEGUI::System::getSingletonPtr();
    sys->injectKeyDown(arg.key);
}

Then subscribe to the event "MyCustomEventName" on the global event set. This will give you exactly what you want, and you have total control over when it's triggered (since you're triggering it) and how to deal with what happens afterwards.

HTH

CE.


Return to “Help”

Who is online

Users browsing this forum: No registered users and 24 guests