Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9744 was 9656, checked in by bensch, 18 years ago

orxonox/trunk: merged the proxy bache back with no conflicts

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