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
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
24#include "compiler.h"
25#include "debug.h"
26#include "class_list.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
52
53/**
54 * @brief the singleton reference to this class
55*/
56EventHandler* EventHandler::singletonRef = NULL;
57
58
59/**
60 * @brief standard deconstructor
61 */
62EventHandler::~EventHandler ()
63{
64  for(int i = 0; i < ES_NUMBER; ++i)
65  {
66    for(int j = 0; j < EV_NUMBER; ++j)
67    {
68      if(!this->listeners[i][j].empty())
69      {
70        PRINTF(2)("forgot to unsubscribe an EventListener!\n");// %s!\n", this->listeners[i][j]->getName());
71      }
72    }
73  }
74  SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
75
76  EventHandler::singletonRef = NULL;
77}
78
79
80/**
81 * @brief initializes the event handler
82 *
83 * this has to be called before the use of the event handler
84*/
85void EventHandler::init()
86{
87  this->keyMapper.loadKeyBindings();
88}
89
90/**
91 * @param state: to which the event handler shall change
92 */
93void EventHandler::setState(elState state)
94{
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
113  this->state = state;
114  SDL_EnableUNICODE(this->bUNICODE[state]);
115};
116
117
118/**
119 * @brief pushes the current State in the State-stack, and selects state
120 * @param state the new State to set
121 */
122void EventHandler::pushState(elState state)
123{
124  if (likely(state != ES_NULL && state != ES_ALL ))
125  {
126    this->stateStack.push(this->state);
127    this->setState(state);
128  }
129  else
130  {
131    PRINTF(2)("unable to push State\n");
132  }
133}
134
135/**
136 * @brief this removes the topmost stack-entry and select the underlying one
137 * @returns the next stack-entry
138 */
139elState EventHandler::popState()
140{
141  if (stateStack.empty())
142    return ES_NULL;
143  elState state =  (elState)stateStack.top();
144  this->stateStack.pop();
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/**
159 * @brief subscribe to an event
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.
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.
167 */
168void EventHandler::subscribe(EventListener* el, elState state, int eventType)
169{
170  PRINTF(4)("Subscribing event type: %i\n", eventType);
171  if( state == ES_ALL )
172  {
173    for(unsigned int i = 0; i < ES_NUMBER; i++)
174      this->listeners[i][eventType].push_back(el);
175  }
176  else
177    this->listeners[state][eventType].push_back(el);
178}
179
180
181/**
182 * @brief unsubscribe from the EventHandler
183 * @param state: the stat in which it has been subscribed
184 * @param eventType: the event, that shall be unsubscribed
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 */
189void EventHandler::unsubscribe(EventListener* el, elState state, int eventType)
190{
191  PRINTF(4)("Unsubscribing event type nr: %i\n", eventType);
192  if (state == ES_ALL)
193    for (unsigned int i = 0; i < ES_NUMBER; i++)
194    {
195      std::vector<EventListener*>::iterator listener =
196        std::find(this->listeners[i][eventType].begin(),
197                  this->listeners[i][eventType].end(),
198                  el);
199      if (listener != this->listeners[i][eventType].end())
200        this->listeners[i][eventType].erase(listener);
201    }
202  else
203  {
204    std::vector<EventListener*>::iterator listener =
205      std::find(this->listeners[state][eventType].begin(),
206                this->listeners[state][eventType].end(),
207                el);
208    if (listener != this->listeners[state][eventType].end())
209      this->listeners[state][eventType].erase(listener);
210  }
211}
212
213
214/**
215 * @brief unsubscribe all events from a specific listener
216 * @param el: the listener that wants to unsubscribe itself
217 * @param state: the state in which the events shall be unsubscribed
218 */
219void EventHandler::unsubscribe(EventListener* el, elState state)
220{
221  if( el == NULL || state >= ES_NUMBER)
222    return;
223  if( state == ES_ALL)
224  {
225    for(unsigned int i = 0; i < ES_NUMBER; i++)
226    {
227      for(unsigned int j = 0; j < EV_NUMBER; j++)
228      {
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);
232      }
233    }
234  }
235  else
236  {
237    for(int j = 0; j < EV_NUMBER; j++)
238    {
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);
242    }
243  }
244}
245
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 */
252bool EventHandler::isSubscribed(elState state, int eventType)
253{
254  return(listeners[state][eventType].empty()) ? false : true;
255};
256
257
258
259/**
260 * @brief flush all registered events
261 * @param state: a specific state
262*/
263void EventHandler::flush(elState state)
264{
265  if( state == ES_ALL)
266  {
267    for(int i = 0; i < ES_NUMBER; ++i)
268    {
269      for(int j = 0; j < EV_NUMBER; ++j)
270      {
271        this->listeners[i][j].clear();
272      }
273    }
274  }
275  else
276  {
277    for(int j = 0; j < EV_NUMBER; ++j)
278    {
279      this->listeners[state][j].clear();
280    }
281  }
282}
283
284
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 */
290void EventHandler::withUNICODE(elState state, bool enableUNICODE)
291{
292  this->bUNICODE[state] = enableUNICODE;
293  if (this->state == state)
294    SDL_EnableUNICODE(enableUNICODE);
295}
296
297/**
298 * @brief grabs InputEvents.
299 * @param grabEvents if the Events should be grabbed(true) or released(false)
300 */
301void EventHandler::grabEvents(bool grabEvents)
302{
303  this->eventsGrabbed = grabEvents;
304  if(!grabEvents)
305  {
306    SDL_ShowCursor(SDL_ENABLE);
307    SDL_WM_GrabInput(SDL_GRAB_OFF);
308  }
309  else
310  {
311    SDL_WM_GrabInput(SDL_GRAB_ON);
312    SDL_ShowCursor(SDL_DISABLE);
313  }
314}
315
316
317/**
318 * @brief core function of event handler: receives all events from SDL
319 *
320 * The event from the SDL framework are collected here and distributed to all listeners.
321 */
322void EventHandler::process() const
323{
324  SDL_Event event;
325  Event ev;
326  EventListener* listener = NULL;
327  while( SDL_PollEvent (&event))
328  {
329    switch( event.type)
330    {
331      case SDL_KEYDOWN:
332        ev.bPressed = true;
333        ev.type = event.key.keysym.sym;
334        if (unlikely(this->bUNICODE[this->state]))
335          ev.x = event.key.keysym.unicode;
336        break;
337      case SDL_KEYUP:
338        ev.bPressed = false;
339        ev.type = event.key.keysym.sym;
340        if (unlikely(this->bUNICODE[this->state]))
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    }
390    this->dispachEvent(ev);
391  }
392}
393
394
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);
413  }
414  /*    else
415  {
416        PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
417        PRINT(4)("=======================================================\n");
418  }*/
419}
420
421
422
423/**
424 * @brief An eventFilter.
425 * @param event the Event to be filtered.
426 * @returns 0 on filtered Event. 1 Otherwise.
427 */
428int EventHandler::eventFilter(const SDL_Event *event)
429{
430  if (likely(EventHandler::getInstance()->eventsGrabbed))
431  {
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  }
447
448  return 1;
449}
450
451/**
452 * @brief outputs some nice information about the EventHandler
453 */
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)
460  {
461    for(int j = 0; j < EV_NUMBER; ++j)
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]);
464  }
465  PRINT(0)("============================EH=\n");
466}
Note: See TracBrowser for help on using the repository browser.