| 1 | = Event-Handler = |
| 2 | |
| 3 | Maintainer: Patrick Boenzli, boenzli at orxonox.ethz.ch |
| 4 | |
| 5 | == Overview == |
| 6 | |
| 7 | All files used for event handling are located in the {{{./src/util/event}}} directory. Here a short overview: |
| 8 | * {{{event_handler.{cc, h} }}} - this is where all the event handling is going on: signals from the SDL env are interpreted and transmitted to the registered event listener |
| 9 | * {{{event_listener.{cc, h} }}} - this is an abstract class. A class that extends it will have to implement all abstract functions ({{{process(...)}}}) and will be able to register itself to the EventHandler to receive events. |
| 10 | * {{{event.{cc, h} }}} - a small class representing an event, that has occured |
| 11 | * {{{key_mapper.{cc, h} }}} - a parser, that reads in the {{{orxonox.conf}}} file and translates the keynames to key-ids used in orxonox |
| 12 | * {{{key_names.{cc, h} }}} - a file containig all key names with key-ids |
| 13 | |
| 14 | == Usage == |
| 15 | The usage of the !EventHandler System is realy stright forward: consider a case, where you have a !PNode, that wants to receive some key-events: [[br]] |
| 16 | The {{{pilot_me.h}}} could look like this: |
| 17 | {{{ |
| 18 | #!cpp |
| 19 | #include "p_node.h" |
| 20 | #include "event_listener.h" |
| 21 | |
| 22 | class Event; // forward declaration of a Event class |
| 23 | |
| 24 | class PilotMe : public PNode, public EventListener // extending EventListener |
| 25 | { |
| 26 | PilotMe(); |
| 27 | virtual ~PilotMe(); |
| 28 | |
| 29 | void process(const Event &event); // abstract process class |
| 30 | |
| 31 | }; |
| 32 | }}} |
| 33 | The {{{pilot_me.cc}}} class could look like this: |
| 34 | {{{ |
| 35 | #!cpp |
| 36 | #include "pilot_me.h" |
| 37 | #include "event_listener.h" //the event listener interface |
| 38 | #include "event.h" //the event structure |
| 39 | |
| 40 | PilotMe::PilotMe() |
| 41 | { |
| 42 | EventHandler::getInstance()->subscribe(this, ES_GAME, SDLK_LEFT); //subscribe this class to the left-key |
| 43 | EventHandler::getInstance()->subscribe(this, ES_GAME, SDLK_RIGHT); //subscribe this class to the right-key |
| 44 | } |
| 45 | |
| 46 | PilotMe::~PilotMe() |
| 47 | { |
| 48 | EventHandler::getInstance()->unsubscribe(this); //just unsubscribe all subscribtions of this class |
| 49 | } |
| 50 | . |
| 51 | void PilotMe::process(const Event &event) |
| 52 | { |
| 53 | if( event.type == SDLK_LEFT) |
| 54 | { |
| 55 | if( event.bPressed == true) |
| 56 | // whatever you want to do, when the left button is pressed |
| 57 | else |
| 58 | // whatever you want to do, when the left button is released |
| 59 | } |
| 60 | else if( event.type == SDLK_RIGHT) |
| 61 | { |
| 62 | if( event.bPressed == true) |
| 63 | // whatever you want to do, when the right button is pressed |
| 64 | else |
| 65 | // whatever you want to do, when the right button is released |
| 66 | |
| 67 | } |
| 68 | } |
| 69 | }}} |
| 70 | As you have seen, the whole event-management system is very simple, let's review all the necessary steps: |
| 71 | 1. Extend {{{EventListener}}} with any class that want to receive events. |
| 72 | |
| 73 | 2. Implement the {{{void process(const Event &event);}}} function. |
| 74 | |
| 75 | 3. Subscribe for an event {{{EventHandler::subscribe(EventListener* el, elState state, int keyID)}}}.[[br]] You will find the complete list of all SDL Commands in the {{{usr/include/SDL/SDL_keysym.h}}} file. Orxonox has extended the list with some other events, that you will find in {{{./src/util/event/event_def.h}}}. The {{{elState}}} describes the state of the event handler: When the menu is displayed, there are is a diffrent key mapping than when you are playing the game. So this means that there are different states of the eventhandler: {{{ {ES_GAME, ES_MENU, ES_ALL} }}}. So if you subscribe to an event for the state {{{ES_GAME}}} this event will only shoot, if the eventhandler is in this state. |
| 76 | |
| 77 | 4. Don't forget to unsubscribe the event again via {{{EventHandler::unsubscribe(EventListener* el)}}}[[br]]. If you forget to do this, there will be a reference to an object that is probably not existent anymore, this will most certanly cause a segfault :D |
| 78 | |
| 79 | |
| 80 | == Advanced == |
| 81 | There is some more stuff to say :D. Its possible to define !KeyAliases in the {{{orxonox.conf}}} file. These aliases are wrapped in the {{{KeyMapper}}} class and are available from this class as static variables: Eg: |
| 82 | * {{{KeyMapper::PEV_UP}}} - is the Up Key defined in the config file |
| 83 | * {{{KeyMapper::PEV_FIRE1}}} - is the fire button defined in the config file |
| 84 | * {{{KeyMapper::PEV_VIEW0}}} - is the view nr zero key |
| 85 | * ... |
| 86 | To see the whole list (and to extend it) read the {{{./src/util/event/key_mapper.{cc, h}}}} files, they are very short. To subscribe to such an event, you can use the code from above and alter it just a little: |
| 87 | {{{ |
| 88 | #!c |
| 89 | //subscribe this class to the orxonox.conf left |
| 90 | EventHandler::getInstance()->subscribe(this, ES_GAME, KeyMapper::PEV_LEFT); |
| 91 | //subscribe this class to the orxonox.conf right |
| 92 | EventHandler::getInstance()->subscribe(this, ES_GAME, KeyMapper::PEV_RIGHT); |
| 93 | }}} |
| 94 | |
| 95 | == References == |
| 96 | To see more references, look at some source code files, eg: |
| 97 | * {{{./src/world_entities/camera.{cc, h} }}} - the camera can change the view by pressing some keys |
| 98 | * {{{./src/world_entities/player.{cc, h} }}} - the player shoots and changes location |