/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Patrick Boenzli co-programmer: */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_EVENT #include "event_handler.h" #include "event_listener.h" #include "event.h" #include "key_mapper.h" #include "compiler.h" #include "debug.h" #include "class_list.h" using namespace std; /** * standard constructor */ EventHandler::EventHandler () { this->setClassID(CL_EVENT_HANDLER, "EventHandler"); this->listeners = new EventListener**[ES_NUMBER]; for(int i = 0; i < ES_NUMBER; ++i) this->listeners[i] = new EventListener*[EV_NUMBER]; /* now initialize them all to zero */ for(int i = 0; i < ES_NUMBER; ++i) { for(int j = 0; j < EV_NUMBER; ++j) { this->listeners[i][j] = NULL; } } this->state = ES_GAME; } /** * the singleton reference to this class */ EventHandler* EventHandler::singletonRef = NULL; /** * standard deconstructor */ EventHandler::~EventHandler () { for(int i = 0; i < ES_NUMBER; ++i) { for(int j = 0; j < EV_NUMBER; ++j) { if( this->listeners[i][j] != NULL) { PRINTF(2)("forgot to unsubscribe an EventListener %s!\n");//, this->listeners[i][j]->getName()); } } } delete this->keyMapper; EventHandler::singletonRef = NULL; } /** * initializes the event handler this has to be called before the use of the event handler */ void EventHandler::init(IniParser* iniParser) { this->keyMapper = new KeyMapper(); this->keyMapper->loadKeyBindings(iniParser); } /** * subscribe to an event * @param el: the event listener that wants to subscribe itself, the listener that will be called when the evetn occures * @param state: for which the listener wants to receive events * @param eventType: the event type that wants to be listened for. This is one of the most important function of the EventHandler. If you would like to subscribe for more than one state, you have to subscribe for each state again. If you want to subscribe for all states, use state = ES_ALL, which will subscribe your listener for all states together. * * @todo this can also be done with the & operator, and checking for states, just set the esState to 1,2,4,8, and then 15 is equal to ES_ALL */ void EventHandler::subscribe(EventListener* el, elState state, int eventType) { PRINTF(4)("Subscribing event type: %i\n", eventType); if( state == ES_ALL ) { for(int i = 0; i < ES_NUMBER; ++i) if( likely(this->listeners[state][eventType] == NULL)) this->listeners[i][eventType] = el; else PRINTF(1)("%s of class %s tried to subscribe to event %i @ state %i but this event has already been subscribed\n", el->getName(), el->getClassName(), eventType, state); } else if( likely(this->listeners[state][eventType] == NULL)) { this->listeners[state][eventType] = el; } else PRINTF(1)("% of class %s tried to subscribe to event %i @ state %i but this event has already been subscribed\n", el->getName(), el->getClassName(), eventType, state); } /** * unsubscribe from the EventHandler * @param state: the stat in which it has been subscribed * @param eventType: the event, that shall be unsubscribed if you want to unsubscribe an event listener from all subscribed events, just use the unsubscribe(EventListener* el, elState state) function */ void EventHandler::unsubscribe(elState state, int eventType) { PRINTF(4)("Unsubscribing event type nr: %i\n", eventType); this->listeners[state][eventType] = NULL; } /** * unsubscribe all events from a specific listener * @param el: the listener that wants to unsubscribe itself * @param state: the state in which the events shall be unsubscribed */ void EventHandler::unsubscribe(EventListener* el, elState state) { if( el == NULL) return; if( state == ES_ALL) { for(int i = 0; i < ES_NUMBER; ++i) { for(int j = 0; j < EV_NUMBER; ++j) { if( this->listeners[i][j] == el ) this->listeners[i][j] = NULL; } } } else { for(int j = 0; j < EV_NUMBER; ++j) { if( this->listeners[state][j] == el ) this->listeners[state][j] = NULL; } } } /** * flush all registered events * @param state: a specific state */ void EventHandler::flush(elState state) { if( state == ES_ALL) { for(int i = 0; i < ES_NUMBER; ++i) { for(int j = 0; j < EV_NUMBER; ++j) { this->listeners[i][j] = NULL; } } } else { for(int j = 0; j < EV_NUMBER; ++j) { this->listeners[state][j] = NULL; } } } /** * core function of event handler: receives all events from SDL The event from the SDL framework are collected here and distributed to all listeners. */ void EventHandler::process() { SDL_Event event; Event ev; EventListener* listener = NULL; while( SDL_PollEvent (&event)) { switch( event.type) { case SDL_KEYDOWN: ev.bPressed = true; ev.type = event.key.keysym.sym; break; case SDL_KEYUP: ev.bPressed = false; ev.type = event.key.keysym.sym; break; case SDL_MOUSEMOTION: ev.bPressed = false; ev.type = EV_MOUSE_MOTION; ev.x = event.motion.x; ev.y = event.motion.y; ev.xRel = event.motion.xrel; ev.yRel = event.motion.yrel; break; case SDL_MOUSEBUTTONUP: ev.bPressed = false; ev.type = event.button.button + SDLK_LAST; break; case SDL_MOUSEBUTTONDOWN: ev.bPressed = true; ev.type = event.button.button + SDLK_LAST; break; case SDL_JOYAXISMOTION: ev.bPressed = false; ev.type = EV_JOY_AXIS_MOTION; break; case SDL_JOYBALLMOTION: ev.bPressed = false; ev.type = EV_JOY_BALL_MOTION; break; case SDL_JOYHATMOTION: ev.bPressed = false; ev.type = EV_JOY_HAT_MOTION; break; case SDL_JOYBUTTONDOWN: ev.bPressed = true; ev.type = EV_JOY_BUTTON; break; case SDL_JOYBUTTONUP: ev.bPressed = true; ev.type = EV_JOY_BUTTON; break; case SDL_VIDEORESIZE: ev.resize = event.resize; ev.type = EV_VIDEO_RESIZE; break; default: ev.type = EV_UNKNOWN; break; } /* small debug routine: shows all events dispatched by the event handler */ PRINT(4)("\n==========================| EventHandler::process () |===\n"); PRINT(4)("= Got Event nr %i, for state %i", ev.type, this->state); //! @todo fix this debug code away */ //////////////////////////////////////////////////////////////// listener = this->listeners[this->state][ev.type]; if (!ClassList::exists(listener, CL_EVENT_LISTENER) && listener != NULL) { ClassList::debug(3, CL_EVENT_LISTENER); this->debug(); printf("ERROR THIS EVENT DOES NOT EXIST\n"); return; } //////////////////////////////////////////////////////////////// if( listener != NULL) { PRINT(4)("= Event dispatcher msg: This event has been consumed\n"); PRINT(4)("=======================================================\n"); listener->process(ev); } else { PRINT(4)("= Event dispatcher msg: This event has NOT been consumed\n"); PRINT(4)("=======================================================\n"); } } } void EventHandler::debug() const { PRINT(0)("===============================\n"); PRINT(0)(" EventHandle Debug Information \n"); PRINT(0)("===============================\n"); for(int i = 0; i < ES_NUMBER; ++i) { for(int j = 0; j < EV_NUMBER; ++j) { if( this->listeners[i][j] != NULL) { PRINT(0)("Event %d of State %d subscribed to %s (%p)\n", j, i, this->listeners[i][j]->getName(), this->listeners[i][j]); } } } PRINT(0)("============================EH=\n"); }