Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/gui/src/lib/event/event_handler.cc @ 7900

Last change on this file since 7900 was 7898, checked in by bensch, 19 years ago

doxy-tags :) the most i can do at this time :)

File size: 12.1 KB
RevLine 
[4780]1/*
[4329]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
[4346]12   main-programmer: Patrick Boenzli
[4780]13   co-programmer:
[4329]14*/
15
[4346]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_EVENT
[4329]17
[4346]18#include "event_handler.h"
[4388]19
[4350]20#include "event_listener.h"
[4361]21#include "event.h"
[4388]22#include "key_mapper.h"
[4329]23
[4381]24#include "compiler.h"
25#include "debug.h"
[4873]26#include "class_list.h"
[4352]27
[7756]28#include <algorithm>
[4329]29
30/**
[7898]31 * @brief standard constructor
32 */
[4780]33EventHandler::EventHandler ()
[4329]34{
[5285]35  this->setClassID(CL_EVENT_HANDLER, "EventHandler");
36  this->setName("EventHandler");
37
[5236]38  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
39  SDL_InitSubSystem(SDL_INIT_EVENTTHREAD);
[5371]40  SDL_SetEventFilter(EventHandler::eventFilter);
[5236]41
[4350]42
[4355]43  /* now initialize them all to zero */
[7895]44  for (unsigned int i = 0; i < ES_NUMBER; i++)
45    this->bUNICODE[i] = false;
[5978]46  this->grabEvents(false);
[5291]47
[4407]48  this->state = ES_GAME;
[6802]49  this->eventsGrabbed = false;
[4329]50}
51
[4407]52
[4329]53/**
[7898]54 * @brief the singleton reference to this class
[4329]55*/
[4346]56EventHandler* EventHandler::singletonRef = NULL;
[4329]57
[4407]58
[4329]59/**
[7898]60 * @brief standard deconstructor
61 */
[4780]62EventHandler::~EventHandler ()
[4329]63{
[4817]64  for(int i = 0; i < ES_NUMBER; ++i)
65  {
[4866]66    for(int j = 0; j < EV_NUMBER; ++j)
[4817]67    {
[7756]68      if(!this->listeners[i][j].empty())
[4817]69      {
[5285]70        PRINTF(2)("forgot to unsubscribe an EventListener!\n");// %s!\n", this->listeners[i][j]->getName());
[4817]71      }
72    }
73  }
[5236]74  SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
75
[4866]76  EventHandler::singletonRef = NULL;
[4352]77}
[4329]78
[4352]79
[4450]80/**
[7898]81 * @brief initializes the event handler
[5285]82 *
83 * this has to be called before the use of the event handler
[4450]84*/
[7256]85void EventHandler::init()
[4407]86{
[7756]87  this->keyMapper.loadKeyBindings();
[4407]88}
89
[4450]90/**
[7895]91 * @param state: to which the event handler shall change
92 */
93void EventHandler::setState(elState state)
94{
[7897]95  /// When Changing the State, all the keys will be released.
96  /// This is done by sending each eventListener, that still
97  /// has an Event subscribed, a Release Event.
98  int keyCount;
99  Uint8 * pressedKeys = SDL_GetKeyState(&keyCount);
100  for (unsigned int i = 0; i < SDLK_LAST; i++)
101  {
102    if (pressedKeys[i])
103    {
104      Event ev;
105      ev.bPressed = false;
106      ev.type = i;
107      if (unlikely(this->bUNICODE[this->state]))
108        ev.x = i;
109      this->dispachEvent( ev );
110    }
111  }
112
[7895]113  this->state = state;
114  SDL_EnableUNICODE(this->bUNICODE[state]);
115};
116
117
118/**
[7898]119 * @brief pushes the current State in the State-stack, and selects state
[5388]120 * @param state the new State to set
121 */
122void EventHandler::pushState(elState state)
123{
[7164]124  if (likely(state != ES_NULL && state != ES_ALL ))
[5388]125  {
[7164]126    this->stateStack.push(this->state);
[5388]127    this->setState(state);
128  }
129  else
130  {
131    PRINTF(2)("unable to push State\n");
132  }
133}
134
135/**
[7898]136 * @brief this removes the topmost stack-entry and select the underlying one
[5388]137 * @returns the next stack-entry
138 */
139elState EventHandler::popState()
140{
[7166]141  if (stateStack.empty())
142    return ES_NULL;
[7164]143  elState state =  (elState)stateStack.top();
144  this->stateStack.pop();
[5388]145  if (state == ES_NULL)
146  {
147    PRINTF(2)("No more states availiable. (unable to pop state)\n");
148    return ES_NULL;
149  }
150  else
151  {
152    this->setState(state);
153    return state;
154  }
155}
156
157
158/**
[7756]159 * @brief subscribe to an event
[4836]160 * @param el: the event listener that wants to subscribe itself, the listener that will be called when the evetn occures
161 * @param state: for which the listener wants to receive events
162 * @param eventType: the event type that wants to be listened for.
[4450]163
164   This is one of the most important function of the EventHandler. If you would like to subscribe for more
165   than one state, you have to subscribe for each state again. If you want to subscribe for all states, use
166   state = ES_ALL, which will subscribe your listener for all states together.
[5291]167 */
[4405]168void EventHandler::subscribe(EventListener* el, elState state, int eventType)
[4354]169{
[4450]170  PRINTF(4)("Subscribing event type: %i\n", eventType);
[4407]171  if( state == ES_ALL )
[6771]172  {
173    for(unsigned int i = 0; i < ES_NUMBER; i++)
[7756]174      this->listeners[i][eventType].push_back(el);
[6771]175  }
176  else
[7756]177    this->listeners[state][eventType].push_back(el);
[4354]178}
179
180
[4450]181/**
[7756]182 * @brief unsubscribe from the EventHandler
[4836]183 * @param state: the stat in which it has been subscribed
184 * @param eventType: the event, that shall be unsubscribed
[7898]185 *
186 * if you want to unsubscribe an event listener from all subscribed events, just use the
187 * unsubscribe(EventListener* el, elState state) function
188 */
[7868]189void EventHandler::unsubscribe(EventListener* el, elState state, int eventType)
[4355]190{
[4450]191  PRINTF(4)("Unsubscribing event type nr: %i\n", eventType);
[5291]192  if (state == ES_ALL)
193    for (unsigned int i = 0; i < ES_NUMBER; i++)
[7868]194    {
195      std::vector<EventListener*>::iterator listener =
[7895]196        std::find(this->listeners[i][eventType].begin(),
197                  this->listeners[i][eventType].end(),
198                  el);
[7868]199      if (listener != this->listeners[i][eventType].end())
200        this->listeners[i][eventType].erase(listener);
201    }
[5291]202  else
[7868]203  {
204    std::vector<EventListener*>::iterator listener =
[7895]205      std::find(this->listeners[state][eventType].begin(),
206                this->listeners[state][eventType].end(),
207                el);
[7868]208    if (listener != this->listeners[state][eventType].end())
209      this->listeners[state][eventType].erase(listener);
210  }
[4355]211}
[4354]212
[4450]213
214/**
[7868]215 * @brief unsubscribe all events from a specific listener
[4836]216 * @param el: the listener that wants to unsubscribe itself
217 * @param state: the state in which the events shall be unsubscribed
[7868]218 */
[4450]219void EventHandler::unsubscribe(EventListener* el, elState state)
[4355]220{
[5291]221  if( el == NULL || state >= ES_NUMBER)
[4816]222    return;
[4364]223  if( state == ES_ALL)
[6771]224  {
225    for(unsigned int i = 0; i < ES_NUMBER; i++)
[4355]226    {
[6771]227      for(unsigned int j = 0; j < EV_NUMBER; j++)
228      {
[7756]229        std::vector<EventListener*>::iterator deller = std::find (this->listeners[i][j].begin(), this->listeners[i][j].end(), el);
230        if( deller != this->listeners[i][j].end())
231          this->listeners[i][j].erase(deller);
[6771]232      }
[4364]233    }
[6771]234  }
[4364]235  else
[6771]236  {
237    for(int j = 0; j < EV_NUMBER; j++)
[4364]238    {
[7756]239      std::vector<EventListener*>::iterator deller =  std::find (this->listeners[state][j].begin(), this->listeners[state][j].end(), el);
240      if( deller != this->listeners[state][j].end())
241        this->listeners[state][j].erase(deller);
[4355]242    }
[6771]243  }
[4355]244}
245
[7897]246/**
247 * @brief returns true if at state and eventType there is something subscribed.
248 * @param state the state to check in.
249 * @param eventType the eventtype to check.
250 * @returns true if a event is subscibed.
251 */
[7756]252bool EventHandler::isSubscribed(elState state, int eventType)
253{
254  return(listeners[state][eventType].empty()) ? false : true;
255};
[4450]256
[7756]257
258
[4450]259/**
[7898]260 * @brief flush all registered events
[4836]261 * @param state: a specific state
[4450]262*/
263void EventHandler::flush(elState state)
[4420]264{
265  if( state == ES_ALL)
[6771]266  {
267    for(int i = 0; i < ES_NUMBER; ++i)
[4420]268    {
[6771]269      for(int j = 0; j < EV_NUMBER; ++j)
270      {
[7756]271        this->listeners[i][j].clear();
[6771]272      }
[4420]273    }
[6771]274  }
[4420]275  else
[6771]276  {
277    for(int j = 0; j < EV_NUMBER; ++j)
[4420]278    {
[7756]279      this->listeners[state][j].clear();
[4420]280    }
[6771]281  }
[4420]282}
[4355]283
284
[7897]285/**
286 * @brief if the unicode characters should be recorded.
287 * @param state the State in whitch to set the new Value.
288 * @param enableUNICODE: enabled, or disabled.
289 */
[7895]290void EventHandler::withUNICODE(elState state, bool enableUNICODE)
[5786]291{
[7895]292  this->bUNICODE[state] = enableUNICODE;
293  if (this->state == state)
294    SDL_EnableUNICODE(enableUNICODE);
[5786]295}
296
[7897]297/**
298 * @brief grabs InputEvents.
299 * @param grabEvents if the Events should be grabbed(true) or released(false)
300 */
[5978]301void EventHandler::grabEvents(bool grabEvents)
302{
[6054]303  this->eventsGrabbed = grabEvents;
304  if(!grabEvents)
[6990]305  {
306    SDL_ShowCursor(SDL_ENABLE);
[6054]307    SDL_WM_GrabInput(SDL_GRAB_OFF);
[6990]308  }
[6054]309  else
[6990]310  {
[6813]311    SDL_WM_GrabInput(SDL_GRAB_ON);
[6990]312    SDL_ShowCursor(SDL_DISABLE);
313  }
[5978]314}
[5786]315
[7897]316
[4450]317/**
[7898]318 * @brief core function of event handler: receives all events from SDL
[7895]319 *
320 * The event from the SDL framework are collected here and distributed to all listeners.
321 */
[7897]322void EventHandler::process() const
[4355]323{
324  SDL_Event event;
[4361]325  Event ev;
[4407]326  EventListener* listener = NULL;
[4355]327  while( SDL_PollEvent (&event))
[6771]328  {
329    switch( event.type)
[4355]330    {
[6771]331      case SDL_KEYDOWN:
332        ev.bPressed = true;
333        ev.type = event.key.keysym.sym;
[7895]334        if (unlikely(this->bUNICODE[this->state]))
[6771]335          ev.x = event.key.keysym.unicode;
336        break;
337      case SDL_KEYUP:
338        ev.bPressed = false;
339        ev.type = event.key.keysym.sym;
[7895]340        if (unlikely(this->bUNICODE[this->state]))
[6771]341          ev.x = event.key.keysym.unicode;
342        break;
343      case SDL_MOUSEMOTION:
344        ev.bPressed = false;
345        ev.type = EV_MOUSE_MOTION;
346        ev.x = event.motion.x;
347        ev.y = event.motion.y;
348        ev.xRel = event.motion.xrel;
349        ev.yRel = event.motion.yrel;
350        break;
351      case SDL_MOUSEBUTTONUP:
352        ev.bPressed = false;
353        ev.type = event.button.button + SDLK_LAST;
354        break;
355      case SDL_MOUSEBUTTONDOWN:
356        ev.bPressed = true;
357        ev.type = event.button.button + SDLK_LAST;
358        break;
359      case SDL_JOYAXISMOTION:
360        ev.bPressed = false;
361        ev.type = EV_JOY_AXIS_MOTION;
362        break;
363      case SDL_JOYBALLMOTION:
364        ev.bPressed = false;
365        ev.type = EV_JOY_BALL_MOTION;
366        break;
367      case SDL_JOYHATMOTION:
368        ev.bPressed = false;
369        ev.type = EV_JOY_HAT_MOTION;
370        break;
371      case SDL_JOYBUTTONDOWN:
372        ev.bPressed = true;
373        ev.type = EV_JOY_BUTTON;
374        break;
375      case SDL_JOYBUTTONUP:
376        ev.bPressed = true;
377        ev.type = EV_JOY_BUTTON;
378        break;
379      case SDL_VIDEORESIZE:
380        ev.resize = event.resize;
381        ev.type = EV_VIDEO_RESIZE;
382        break;
383      case SDL_QUIT:
384        ev.type = EV_MAIN_QUIT;
385        break;
386      default:
387        ev.type = EV_UNKNOWN;
388        break;
389    }
[7897]390    this->dispachEvent(ev);
391  }
392}
[4362]393
[4780]394
[7897]395/**
396 * @brief dispaches an Event.
397 * @param event the Event to dispach.
398 */
399void EventHandler::dispachEvent(const Event& event) const
400{
401  /* small debug routine: shows all events dispatched by the event handler */
402  PRINT(4)("\n==========================| EventHandler::process () |===\n");
403  PRINT(4)("=  Got Event nr %i, for state %i\n", event.type, this->state);
404
405  /// setting a temporary state in case of an EventListener's process changes the state.
406  elState currentState = this->state;
407  for (unsigned int i = 0; i < this->listeners[currentState][event.type].size(); i++)
408  {
409    PRINT(4)("=  Event dispatcher msg: This event has been consumed\n");
410    PRINT(4)("=  Got Event nr %i, for state %i %s::%s\n", event.type, currentState, this->listeners[this->state][event.type][i]->getClassName(), this->listeners[currentState][event.type][i]->getName());
411    PRINT(4)("=======================================================\n");
412    this->listeners[currentState][event.type][i]->process(event);
[6771]413  }
[7897]414  /*    else
415  {
416        PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
417        PRINT(4)("=======================================================\n");
418  }*/
[4355]419}
[4388]420
[7897]421
422
[7895]423/**
424 * @brief An eventFilter.
425 * @param event the Event to be filtered.
426 * @returns 0 on filtered Event. 1 Otherwise.
427 */
[5237]428int EventHandler::eventFilter(const SDL_Event *event)
429{
[6802]430  if (likely(EventHandler::getInstance()->eventsGrabbed))
[5237]431  {
[6802]432    if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
433    {
434      PRINTF(3)("Not sending event to the WindowManager\n");
435      EventHandler::getInstance()->grabEvents(false);
436      return 0;
437    }
438  }
439  else
440  {
441    if (event->type == SDL_MOUSEBUTTONDOWN)
442    {
443      EventHandler::getInstance()->grabEvents( true);
444      return 0;
445    }
446  }
[6054]447
[5237]448  return 1;
449}
450
451/**
[7895]452 * @brief outputs some nice information about the EventHandler
[5237]453 */
[4872]454void EventHandler::debug() const
455{
456  PRINT(0)("===============================\n");
457  PRINT(0)(" EventHandle Debug Information \n");
458  PRINT(0)("===============================\n");
459  for(int i = 0; i < ES_NUMBER; ++i)
[7895]460  {
[4872]461    for(int j = 0; j < EV_NUMBER; ++j)
[7756]462      for (unsigned int evl = 0; evl < this->listeners[i][j].size(); evl++)
463        PRINT(0)("Event %d of State %d subscribed to %s (%p)\n", j, i, this->listeners[i][j][evl]->getName(), this->listeners[i][j][evl]);
[7895]464  }
[4872]465  PRINT(0)("============================EH=\n");
466}
Note: See TracBrowser for help on using the repository browser.