Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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