Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/event/event_handler.cc @ 9457

Last change on this file since 9457 was 9406, checked in by bensch, 18 years ago

orxonox/trunk: merged the proxy back

merged with commandsvn merge -r9346:HEAD https://svn.orxonox.net/orxonox/branches/proxy .

no conflicts

File size: 14.7 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
[8340]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"
[8148]23#include "key_names.h"
[4329]24
[4381]25#include "compiler.h"
26#include "debug.h"
[4873]27#include "class_list.h"
[4352]28
[7756]29#include <algorithm>
[4329]30
31/**
[7919]32 * @brief standard constructor
33 */
[4780]34EventHandler::EventHandler ()
[4329]35{
[5285]36  this->setClassID(CL_EVENT_HANDLER, "EventHandler");
37  this->setName("EventHandler");
38
[5236]39  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
40  SDL_InitSubSystem(SDL_INIT_EVENTTHREAD);
[5371]41  SDL_SetEventFilter(EventHandler::eventFilter);
[5236]42
[4350]43
[4355]44  /* now initialize them all to zero */
[7919]45  for (unsigned int i = 0; i < ES_NUMBER; i++)
46    this->bUNICODE[i] = false;
[5978]47  this->grabEvents(false);
[5291]48
[4407]49  this->state = ES_GAME;
[6802]50  this->eventsGrabbed = false;
[8743]51
52  this->keyState = SDL_GetKeyState(NULL);
[4329]53}
54
[4407]55
[4329]56/**
[7919]57 * @brief the singleton reference to this class
[4329]58*/
[4346]59EventHandler* EventHandler::singletonRef = NULL;
[4329]60
[4407]61
[4329]62/**
[7919]63 * @brief standard deconstructor
64 */
[4780]65EventHandler::~EventHandler ()
[4329]66{
[8148]67  bool forgotToUnsubscribe = false;
68
[4817]69  for(int i = 0; i < ES_NUMBER; ++i)
70  {
[4866]71    for(int j = 0; j < EV_NUMBER; ++j)
[4817]72    {
[7756]73      if(!this->listeners[i][j].empty())
[4817]74      {
[8148]75        if (!forgotToUnsubscribe)
76        {
77          forgotToUnsubscribe = true;
78          PRINTF(2)("forgot to unsubscribe an EventListener!\n");// %s!\n", this->listeners[i][j]->getName());
79        }
[4817]80      }
81    }
82  }
[8148]83
84  if (forgotToUnsubscribe)
85  {
86    PRINTF(2)("Listing still subscribed EventListeners\n");
87    PRINTF(2)("========================================\n");
88    this->debug();
89    PRINTF(2)("========================================\n");
90  }
91
[5236]92  SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
93
[4866]94  EventHandler::singletonRef = NULL;
[4352]95}
[4329]96
[4352]97
[4450]98/**
[7919]99 * @brief initializes the event handler
[5285]100 *
101 * this has to be called before the use of the event handler
[4450]102*/
[7256]103void EventHandler::init()
[4407]104{
[7756]105  this->keyMapper.loadKeyBindings();
[4407]106}
107
[4450]108/**
[7919]109 * @param state: to which the event handler shall change
110 */
111void EventHandler::setState(elState state)
112{
113  if (state == this->state)
114    return;
115
[8339]116  PRINTF(4)("Switching to State %s\n", EventHandler::ELStateToString(state).c_str());
117
[7919]118  /// When Changing the State, all the keys will be released.
119  /// This is done by sending each eventListener, that still
120  /// has an Event subscribed, a Release Event.
121  int keyCount;
122  Uint8 * pressedKeys = SDL_GetKeyState(&keyCount);
123  for (unsigned int i = 0; i < SDLK_LAST; i++)
124  {
125    if (pressedKeys[i])
126    {
127      Event ev;
128      ev.bPressed = false;
129      ev.type = i;
130      if (unlikely(this->bUNICODE[this->state]))
131        ev.x = i;
132      this->dispachEvent(this->state, ev );
133    }
134  }
135
136  // switching to the new State.
137  elState oldState = this->state;
138  this->state = state;
139
140  // in the End the Corresponding handler will be notified.
141  Event stateSwitchEvent;
142  stateSwitchEvent.type = EV_LEAVE_STATE;
143  this->dispachEvent(oldState, stateSwitchEvent);
144
145  SDL_EnableUNICODE(this->bUNICODE[state]);
146};
147
148
149/**
150 * @brief pushes the current State in the State-stack, and selects state
[5388]151 * @param state the new State to set
152 */
153void EventHandler::pushState(elState state)
154{
[7164]155  if (likely(state != ES_NULL && state != ES_ALL ))
[5388]156  {
[7164]157    this->stateStack.push(this->state);
[5388]158    this->setState(state);
159  }
160  else
161  {
162    PRINTF(2)("unable to push State\n");
163  }
164}
165
166/**
[7919]167 * @brief this removes the topmost stack-entry and select the underlying one
[5388]168 * @returns the next stack-entry
169 */
170elState EventHandler::popState()
171{
[7166]172  if (stateStack.empty())
173    return ES_NULL;
[7164]174  elState state =  (elState)stateStack.top();
175  this->stateStack.pop();
[5388]176  if (state == ES_NULL)
177  {
178    PRINTF(2)("No more states availiable. (unable to pop state)\n");
179    return ES_NULL;
180  }
181  else
182  {
183    this->setState(state);
184    return state;
185  }
186}
187
188
189/**
[7756]190 * @brief subscribe to an event
[4836]191 * @param el: the event listener that wants to subscribe itself, the listener that will be called when the evetn occures
192 * @param state: for which the listener wants to receive events
193 * @param eventType: the event type that wants to be listened for.
[4450]194
195   This is one of the most important function of the EventHandler. If you would like to subscribe for more
196   than one state, you have to subscribe for each state again. If you want to subscribe for all states, use
197   state = ES_ALL, which will subscribe your listener for all states together.
[5291]198 */
[4405]199void EventHandler::subscribe(EventListener* el, elState state, int eventType)
[4354]200{
[4450]201  PRINTF(4)("Subscribing event type: %i\n", eventType);
[4407]202  if( state == ES_ALL )
[6771]203  {
204    for(unsigned int i = 0; i < ES_NUMBER; i++)
[7919]205      if (!this->findListener( NULL, (elState)i, eventType, el))
206        this->listeners[i][eventType].push_back(el);
207      else
[7756]208      {
[9406]209        PRINTF(2)("%s::%s was already subscribed to state %d event %d\n", el->getClassCName(), el->getCName(), i, eventType);
[7756]210      }
[6771]211  }
212  else
[7756]213  {
[7919]214    if (!this->findListener( NULL, state, eventType, el))
215      this->listeners[state][eventType].push_back(el);
216    else
[4407]217    {
[9406]218      PRINTF(2)("%s::%s was already subscribed to state %d event %d\n", el->getClassCName(), el->getCName(), state, eventType);
[4407]219    }
[7756]220  }
[4354]221}
222
223
[4450]224/**
[7756]225 * @brief unsubscribe from the EventHandler
[4836]226 * @param state: the stat in which it has been subscribed
227 * @param eventType: the event, that shall be unsubscribed
[7919]228 *
229 * if you want to unsubscribe an event listener from all subscribed events, just use the
230 * unsubscribe(EventListener* el, elState state) function
231 */
[7868]232void EventHandler::unsubscribe(EventListener* el, elState state, int eventType)
[4355]233{
[4450]234  PRINTF(4)("Unsubscribing event type nr: %i\n", eventType);
[5291]235  if (state == ES_ALL)
236    for (unsigned int i = 0; i < ES_NUMBER; i++)
[7868]237    {
[7919]238      std::vector<EventListener*>::iterator listener;
239      if (this->findListener(&listener, (elState)i, eventType, el))
[7868]240        this->listeners[i][eventType].erase(listener);
241    }
[5291]242  else
[7868]243  {
[7919]244    std::vector<EventListener*>::iterator listener;
245    if (this->findListener(&listener, state, eventType, el))
[7868]246      this->listeners[state][eventType].erase(listener);
247  }
[4355]248}
[4354]249
[4450]250
251/**
[7868]252 * @brief unsubscribe all events from a specific listener
[4836]253 * @param el: the listener that wants to unsubscribe itself
254 * @param state: the state in which the events shall be unsubscribed
[7868]255 */
[4450]256void EventHandler::unsubscribe(EventListener* el, elState state)
[4355]257{
[7919]258  assert( el != NULL && state < ES_NUMBER);
[4364]259  if( state == ES_ALL)
[6771]260  {
261    for(unsigned int i = 0; i < ES_NUMBER; i++)
[4355]262    {
[6771]263      for(unsigned int j = 0; j < EV_NUMBER; j++)
264      {
[7756]265        std::vector<EventListener*>::iterator deller = std::find (this->listeners[i][j].begin(), this->listeners[i][j].end(), el);
266        if( deller != this->listeners[i][j].end())
267          this->listeners[i][j].erase(deller);
[6771]268      }
[4364]269    }
[6771]270  }
[4364]271  else
[6771]272  {
273    for(int j = 0; j < EV_NUMBER; j++)
[4364]274    {
[7756]275      std::vector<EventListener*>::iterator deller =  std::find (this->listeners[state][j].begin(), this->listeners[state][j].end(), el);
276      if( deller != this->listeners[state][j].end())
277        this->listeners[state][j].erase(deller);
[4355]278    }
[6771]279  }
[4355]280}
281
[7919]282/**
283 * @brief returns true if at state and eventType there is something subscribed.
284 * @param state the state to check in.
285 * @param eventType the eventtype to check.
286 * @returns true if a event is subscibed.
287 */
[7756]288bool EventHandler::isSubscribed(elState state, int eventType)
289{
290  return(listeners[state][eventType].empty()) ? false : true;
291};
[4450]292
[7756]293
294
[4450]295/**
[7919]296 * @brief flush all registered events
[4836]297 * @param state: a specific state
[4450]298*/
299void EventHandler::flush(elState state)
[4420]300{
301  if( state == ES_ALL)
[6771]302  {
303    for(int i = 0; i < ES_NUMBER; ++i)
[4420]304    {
[6771]305      for(int j = 0; j < EV_NUMBER; ++j)
306      {
[7756]307        this->listeners[i][j].clear();
[6771]308      }
[4420]309    }
[6771]310  }
[4420]311  else
[6771]312  {
313    for(int j = 0; j < EV_NUMBER; ++j)
[4420]314    {
[7756]315      this->listeners[state][j].clear();
[4420]316    }
[6771]317  }
[4420]318}
[4355]319
320
[7919]321bool EventHandler::findListener(std::vector<EventListener*>::iterator* it, elState state, int eventType, EventListener* listener)
[5786]322{
[7919]323  std::vector<EventListener*>::iterator findIterator =
324    std::find(this->listeners[state][eventType].begin(), this->listeners[state][eventType].end(), listener);
325  if (it != NULL)
326    *it = findIterator;
327  return ( findIterator != this->listeners[state][eventType].end());
328
[5786]329}
330
[7919]331
332
333/**
334 * @brief if the unicode characters should be recorded.
335 * @param state the State in whitch to set the new Value.
336 * @param enableUNICODE: enabled, or disabled.
337 */
338void EventHandler::withUNICODE(elState state, bool enableUNICODE)
339{
340  this->bUNICODE[state] = enableUNICODE;
341  if (this->state == state)
342    SDL_EnableUNICODE(enableUNICODE);
343}
344
345/**
346 * @brief grabs InputEvents.
347 * @param grabEvents if the Events should be grabbed(true) or released(false)
348 */
[5978]349void EventHandler::grabEvents(bool grabEvents)
350{
[6054]351  this->eventsGrabbed = grabEvents;
352  if(!grabEvents)
[6990]353  {
354    SDL_ShowCursor(SDL_ENABLE);
[6054]355    SDL_WM_GrabInput(SDL_GRAB_OFF);
[6990]356  }
[6054]357  else
[6990]358  {
[8992]359     SDL_WM_GrabInput(SDL_GRAB_ON);
360     SDL_ShowCursor(SDL_DISABLE);
[6990]361  }
[5978]362}
[5786]363
[7919]364
365
[4450]366/**
[7919]367 * @brief core function of event handler: receives all events from SDL
368 *
369 * The event from the SDL framework are collected here and distributed to all listeners.
370 */
371void EventHandler::process() const
[4355]372{
373  SDL_Event event;
[4361]374  Event ev;
[4355]375  while( SDL_PollEvent (&event))
[6771]376  {
377    switch( event.type)
[4355]378    {
[6771]379      case SDL_KEYDOWN:
380        ev.bPressed = true;
381        ev.type = event.key.keysym.sym;
[7919]382        if (unlikely(this->bUNICODE[this->state]))
[6771]383          ev.x = event.key.keysym.unicode;
384        break;
385      case SDL_KEYUP:
386        ev.bPressed = false;
387        ev.type = event.key.keysym.sym;
[7919]388        if (unlikely(this->bUNICODE[this->state]))
[6771]389          ev.x = event.key.keysym.unicode;
390        break;
391      case SDL_MOUSEMOTION:
392        ev.bPressed = false;
393        ev.type = EV_MOUSE_MOTION;
394        ev.x = event.motion.x;
395        ev.y = event.motion.y;
396        ev.xRel = event.motion.xrel;
397        ev.yRel = event.motion.yrel;
398        break;
399      case SDL_MOUSEBUTTONUP:
400        ev.bPressed = false;
[8035]401        ev.x = event.motion.x;
402        ev.y = event.motion.y;
[6771]403        ev.type = event.button.button + SDLK_LAST;
404        break;
405      case SDL_MOUSEBUTTONDOWN:
406        ev.bPressed = true;
[8035]407        ev.x = event.motion.x;
408        ev.y = event.motion.y;
[6771]409        ev.type = event.button.button + SDLK_LAST;
410        break;
411      case SDL_JOYAXISMOTION:
412        ev.bPressed = false;
413        ev.type = EV_JOY_AXIS_MOTION;
414        break;
415      case SDL_JOYBALLMOTION:
416        ev.bPressed = false;
417        ev.type = EV_JOY_BALL_MOTION;
418        break;
419      case SDL_JOYHATMOTION:
420        ev.bPressed = false;
421        ev.type = EV_JOY_HAT_MOTION;
422        break;
423      case SDL_JOYBUTTONDOWN:
424        ev.bPressed = true;
425        ev.type = EV_JOY_BUTTON;
426        break;
427      case SDL_JOYBUTTONUP:
428        ev.bPressed = true;
429        ev.type = EV_JOY_BUTTON;
430        break;
[7919]431      case SDL_ACTIVEEVENT:
432        ev.type = EV_WINDOW_FOCUS;
433        ev.bPressed = (event.active.gain != 0);
434        break;
[6771]435      case SDL_VIDEORESIZE:
436        ev.resize = event.resize;
437        ev.type = EV_VIDEO_RESIZE;
438        break;
439      case SDL_QUIT:
440        ev.type = EV_MAIN_QUIT;
441        break;
442      default:
443        ev.type = EV_UNKNOWN;
444        break;
445    }
[7919]446    this->dispachEvent(this->state, ev);
447  }
448}
[4362]449
[4780]450
[7919]451/**
452 * @brief dispaches an Event.
453 * @param event the Event to dispach.
454 */
455void EventHandler::dispachEvent(elState state, const Event& event) const
456{
457  /* small debug routine: shows all events dispatched by the event handler */
458  PRINT(4)("\n==========================| EventHandler::process () |===\n");
459  PRINT(4)("=  Got Event nr %i, for state %i\n", event.type, state);
[7756]460
[7919]461  /// setting a temporary state in case of an EventListener's process changes the state.
462  for (unsigned int i = 0; i < this->listeners[state][event.type].size(); i++)
463  {
464    PRINT(4)("=  Event dispatcher msg: This event has been consumed\n");
[9406]465    PRINT(4)("=  Got Event nr %i, for state %i (%d registered) to %s::%s(%p)\n",
466      event.type,
467      i, state,
468      this->listeners[state][event.type][i]->getClassCName(),
469      this->listeners[state][event.type][i]->getCName(),
470      this->listeners[state][event.type][i]);
[7919]471    PRINT(4)("=======================================================\n");
472    this->listeners[state][event.type][i]->process(event);
[6771]473  }
[7919]474  /*    else
475  {
476        PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
477        PRINT(4)("=======================================================\n");
478  }*/
[4355]479}
[4388]480
[5371]481
[7919]482
483/**
484 * @brief An eventFilter.
485 * @param event the Event to be filtered.
486 * @returns 0 on filtered Event. 1 Otherwise.
487 */
[5237]488int EventHandler::eventFilter(const SDL_Event *event)
489{
[6802]490  if (likely(EventHandler::getInstance()->eventsGrabbed))
[5237]491  {
[6802]492    if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
493    {
494      PRINTF(3)("Not sending event to the WindowManager\n");
495      EventHandler::getInstance()->grabEvents(false);
496      return 0;
497    }
498  }
499  else
500  {
501    if (event->type == SDL_MOUSEBUTTONDOWN)
502    {
503      EventHandler::getInstance()->grabEvents( true);
[8035]504      return 1;
[6802]505    }
506  }
[6054]507
[5237]508  return 1;
509}
510
[8148]511
[8623]512int EventHandler::releaseMouse(void* p)
513{
[9240]514  SDL_ShowCursor(SDL_ENABLE);
[8623]515  SDL_WM_GrabInput(SDL_GRAB_OFF);
516  return 0;
517}
518
519
[5237]520/**
[8148]521 * @param state The State to get the Name of.
522 * @returns the Name of the State.
523 */
524const std::string& EventHandler::ELStateToString(elState state)
525{
526  if (state < ES_NUMBER)
527    return EventHandler::stateNames[state];
528  else
529    return EventHandler::stateNames[5];
530}
531
532/**
533 * @param stateName the Name of the State to retrieve.
534 * @return the State given by the name
535 */
536elState EventHandler::StringToELState(const std::string& stateName)
537{
538  for (unsigned int i = 0 ; i < ES_NUMBER; i++)
539    if (stateName == EventHandler::stateNames[i])
540      return (elState)i;
541  return ES_NULL;
542}
543
544const std::string  EventHandler::stateNames[] =
545{
546  "game",
547  "game_menu",
548  "menu",
549  "shell",
550  "all",
551  "unknown",
552};
553
554
555/**
[7919]556 * @brief outputs some nice information about the EventHandler
[5237]557 */
[4872]558void EventHandler::debug() const
559{
560  PRINT(0)("===============================\n");
561  PRINT(0)(" EventHandle Debug Information \n");
562  PRINT(0)("===============================\n");
563  for(int i = 0; i < ES_NUMBER; ++i)
[7919]564  {
[4872]565    for(int j = 0; j < EV_NUMBER; ++j)
[7756]566      for (unsigned int evl = 0; evl < this->listeners[i][j].size(); evl++)
[8148]567        PRINT(0)("Event %s(%d) of State %s(%d) subscribed to %s (%p)\n",
568        EVToKeyName(j).c_str(), j,
569        ELStateToString((elState)i).c_str(), i,
[9406]570        this->listeners[i][j][evl]->getCName(), this->listeners[i][j][evl]);
[7919]571  }
[4872]572  PRINT(0)("============================EH=\n");
573}
Note: See TracBrowser for help on using the repository browser.