Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/cr/src/lib/event/event_handler.cc @ 7930

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

orxonox/trunk: merged the gui branche back
merged with command:
https://svn.orxonox.net/orxonox/branches/gui
no conflicts

File size: 13.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  if (state == this->state)
96    return;
97
98  /// When Changing the State, all the keys will be released.
99  /// This is done by sending each eventListener, that still
100  /// has an Event subscribed, a Release Event.
101  int keyCount;
102  Uint8 * pressedKeys = SDL_GetKeyState(&keyCount);
103  for (unsigned int i = 0; i < SDLK_LAST; i++)
104  {
105    if (pressedKeys[i])
106    {
107      Event ev;
108      ev.bPressed = false;
109      ev.type = i;
110      if (unlikely(this->bUNICODE[this->state]))
111        ev.x = i;
112      this->dispachEvent(this->state, ev );
113    }
114  }
115
116  // switching to the new State.
117  elState oldState = this->state;
118  this->state = state;
119
120  // in the End the Corresponding handler will be notified.
121  Event stateSwitchEvent;
122  stateSwitchEvent.type = EV_LEAVE_STATE;
123  this->dispachEvent(oldState, stateSwitchEvent);
124
125  SDL_EnableUNICODE(this->bUNICODE[state]);
126};
127
128
129/**
130 * @brief pushes the current State in the State-stack, and selects state
131 * @param state the new State to set
132 */
133void EventHandler::pushState(elState state)
134{
135  if (likely(state != ES_NULL && state != ES_ALL ))
136  {
137    this->stateStack.push(this->state);
138    this->setState(state);
139  }
140  else
141  {
142    PRINTF(2)("unable to push State\n");
143  }
144}
145
146/**
147 * @brief this removes the topmost stack-entry and select the underlying one
148 * @returns the next stack-entry
149 */
150elState EventHandler::popState()
151{
152  if (stateStack.empty())
153    return ES_NULL;
154  elState state =  (elState)stateStack.top();
155  this->stateStack.pop();
156  if (state == ES_NULL)
157  {
158    PRINTF(2)("No more states availiable. (unable to pop state)\n");
159    return ES_NULL;
160  }
161  else
162  {
163    this->setState(state);
164    return state;
165  }
166}
167
168
169/**
170 * @brief subscribe to an event
171 * @param el: the event listener that wants to subscribe itself, the listener that will be called when the evetn occures
172 * @param state: for which the listener wants to receive events
173 * @param eventType: the event type that wants to be listened for.
174
175   This is one of the most important function of the EventHandler. If you would like to subscribe for more
176   than one state, you have to subscribe for each state again. If you want to subscribe for all states, use
177   state = ES_ALL, which will subscribe your listener for all states together.
178 */
179void EventHandler::subscribe(EventListener* el, elState state, int eventType)
180{
181  PRINTF(4)("Subscribing event type: %i\n", eventType);
182  if( state == ES_ALL )
183  {
184    for(unsigned int i = 0; i < ES_NUMBER; i++)
185      if (!this->findListener( NULL, (elState)i, eventType, el))
186        this->listeners[i][eventType].push_back(el);
187      else
188      {
189        PRINTF(2)("%s::%s was already subscribed to state %d event %d\n", el->getClassName(), el->getName(), i, eventType);
190      }
191  }
192  else
193  {
194    if (!this->findListener( NULL, state, eventType, el))
195      this->listeners[state][eventType].push_back(el);
196    else
197    {
198      PRINTF(2)("%s::%s was already subscribed to state %d event %d\n", el->getClassName(), el->getName(), state, eventType);
199    }
200  }
201}
202
203
204/**
205 * @brief unsubscribe from the EventHandler
206 * @param state: the stat in which it has been subscribed
207 * @param eventType: the event, that shall be unsubscribed
208 *
209 * if you want to unsubscribe an event listener from all subscribed events, just use the
210 * unsubscribe(EventListener* el, elState state) function
211 */
212void EventHandler::unsubscribe(EventListener* el, elState state, int eventType)
213{
214  PRINTF(4)("Unsubscribing event type nr: %i\n", eventType);
215  if (state == ES_ALL)
216    for (unsigned int i = 0; i < ES_NUMBER; i++)
217    {
218      std::vector<EventListener*>::iterator listener;
219      if (this->findListener(&listener, (elState)i, eventType, el))
220        this->listeners[i][eventType].erase(listener);
221    }
222  else
223  {
224    std::vector<EventListener*>::iterator listener;
225    if (this->findListener(&listener, state, eventType, el))
226      this->listeners[state][eventType].erase(listener);
227  }
228}
229
230
231/**
232 * @brief unsubscribe all events from a specific listener
233 * @param el: the listener that wants to unsubscribe itself
234 * @param state: the state in which the events shall be unsubscribed
235 */
236void EventHandler::unsubscribe(EventListener* el, elState state)
237{
238  assert( el != NULL && state < ES_NUMBER);
239  if( state == ES_ALL)
240  {
241    for(unsigned int i = 0; i < ES_NUMBER; i++)
242    {
243      for(unsigned int j = 0; j < EV_NUMBER; j++)
244      {
245        std::vector<EventListener*>::iterator deller = std::find (this->listeners[i][j].begin(), this->listeners[i][j].end(), el);
246        if( deller != this->listeners[i][j].end())
247          this->listeners[i][j].erase(deller);
248      }
249    }
250  }
251  else
252  {
253    for(int j = 0; j < EV_NUMBER; j++)
254    {
255      std::vector<EventListener*>::iterator deller =  std::find (this->listeners[state][j].begin(), this->listeners[state][j].end(), el);
256      if( deller != this->listeners[state][j].end())
257        this->listeners[state][j].erase(deller);
258    }
259  }
260}
261
262/**
263 * @brief returns true if at state and eventType there is something subscribed.
264 * @param state the state to check in.
265 * @param eventType the eventtype to check.
266 * @returns true if a event is subscibed.
267 */
268bool EventHandler::isSubscribed(elState state, int eventType)
269{
270  return(listeners[state][eventType].empty()) ? false : true;
271};
272
273
274
275/**
276 * @brief flush all registered events
277 * @param state: a specific state
278*/
279void EventHandler::flush(elState state)
280{
281  if( state == ES_ALL)
282  {
283    for(int i = 0; i < ES_NUMBER; ++i)
284    {
285      for(int j = 0; j < EV_NUMBER; ++j)
286      {
287        this->listeners[i][j].clear();
288      }
289    }
290  }
291  else
292  {
293    for(int j = 0; j < EV_NUMBER; ++j)
294    {
295      this->listeners[state][j].clear();
296    }
297  }
298}
299
300
301bool EventHandler::findListener(std::vector<EventListener*>::iterator* it, elState state, int eventType, EventListener* listener)
302{
303  std::vector<EventListener*>::iterator findIterator =
304    std::find(this->listeners[state][eventType].begin(), this->listeners[state][eventType].end(), listener);
305  if (it != NULL)
306    *it = findIterator;
307  return ( findIterator != this->listeners[state][eventType].end());
308
309}
310
311
312
313/**
314 * @brief if the unicode characters should be recorded.
315 * @param state the State in whitch to set the new Value.
316 * @param enableUNICODE: enabled, or disabled.
317 */
318void EventHandler::withUNICODE(elState state, bool enableUNICODE)
319{
320  this->bUNICODE[state] = enableUNICODE;
321  if (this->state == state)
322    SDL_EnableUNICODE(enableUNICODE);
323}
324
325/**
326 * @brief grabs InputEvents.
327 * @param grabEvents if the Events should be grabbed(true) or released(false)
328 */
329void EventHandler::grabEvents(bool grabEvents)
330{
331  this->eventsGrabbed = grabEvents;
332  if(!grabEvents)
333  {
334    SDL_ShowCursor(SDL_ENABLE);
335    SDL_WM_GrabInput(SDL_GRAB_OFF);
336  }
337  else
338  {
339    SDL_WM_GrabInput(SDL_GRAB_ON);
340    SDL_ShowCursor(SDL_DISABLE);
341  }
342}
343
344
345
346/**
347 * @brief core function of event handler: receives all events from SDL
348 *
349 * The event from the SDL framework are collected here and distributed to all listeners.
350 */
351void EventHandler::process() const
352{
353  SDL_Event event;
354  Event ev;
355  EventListener* listener = NULL;
356  while( SDL_PollEvent (&event))
357  {
358    switch( event.type)
359    {
360      case SDL_KEYDOWN:
361        ev.bPressed = true;
362        ev.type = event.key.keysym.sym;
363        if (unlikely(this->bUNICODE[this->state]))
364          ev.x = event.key.keysym.unicode;
365        break;
366      case SDL_KEYUP:
367        ev.bPressed = false;
368        ev.type = event.key.keysym.sym;
369        if (unlikely(this->bUNICODE[this->state]))
370          ev.x = event.key.keysym.unicode;
371        break;
372      case SDL_MOUSEMOTION:
373        ev.bPressed = false;
374        ev.type = EV_MOUSE_MOTION;
375        ev.x = event.motion.x;
376        ev.y = event.motion.y;
377        ev.xRel = event.motion.xrel;
378        ev.yRel = event.motion.yrel;
379        break;
380      case SDL_MOUSEBUTTONUP:
381        ev.bPressed = false;
382        ev.type = event.button.button + SDLK_LAST;
383        break;
384      case SDL_MOUSEBUTTONDOWN:
385        ev.bPressed = true;
386        ev.type = event.button.button + SDLK_LAST;
387        break;
388      case SDL_JOYAXISMOTION:
389        ev.bPressed = false;
390        ev.type = EV_JOY_AXIS_MOTION;
391        break;
392      case SDL_JOYBALLMOTION:
393        ev.bPressed = false;
394        ev.type = EV_JOY_BALL_MOTION;
395        break;
396      case SDL_JOYHATMOTION:
397        ev.bPressed = false;
398        ev.type = EV_JOY_HAT_MOTION;
399        break;
400      case SDL_JOYBUTTONDOWN:
401        ev.bPressed = true;
402        ev.type = EV_JOY_BUTTON;
403        break;
404      case SDL_JOYBUTTONUP:
405        ev.bPressed = true;
406        ev.type = EV_JOY_BUTTON;
407        break;
408      case SDL_ACTIVEEVENT:
409        ev.type = EV_WINDOW_FOCUS;
410        ev.bPressed = (event.active.gain != 0);
411        break;
412      case SDL_VIDEORESIZE:
413        ev.resize = event.resize;
414        ev.type = EV_VIDEO_RESIZE;
415        break;
416      case SDL_QUIT:
417        ev.type = EV_MAIN_QUIT;
418        break;
419      default:
420        ev.type = EV_UNKNOWN;
421        break;
422    }
423    this->dispachEvent(this->state, ev);
424  }
425}
426
427
428/**
429 * @brief dispaches an Event.
430 * @param event the Event to dispach.
431 */
432void EventHandler::dispachEvent(elState state, const Event& event) const
433{
434  /* small debug routine: shows all events dispatched by the event handler */
435  PRINT(4)("\n==========================| EventHandler::process () |===\n");
436  PRINT(4)("=  Got Event nr %i, for state %i\n", event.type, state);
437
438  /// setting a temporary state in case of an EventListener's process changes the state.
439  for (unsigned int i = 0; i < this->listeners[state][event.type].size(); i++)
440  {
441    PRINT(4)("=  Event dispatcher msg: This event has been consumed\n");
442    PRINT(4)("=  Got Event nr %i, for state %i (%d registered) to %s::%s(%p)\n", event.type, i, state, this->listeners[state][event.type][i]->getClassName(), this->listeners[state][event.type][i]->getName(), this->listeners[state][event.type][i]);
443    PRINT(4)("=======================================================\n");
444    this->listeners[state][event.type][i]->process(event);
445  }
446  /*    else
447  {
448        PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
449        PRINT(4)("=======================================================\n");
450  }*/
451}
452
453
454
455/**
456 * @brief An eventFilter.
457 * @param event the Event to be filtered.
458 * @returns 0 on filtered Event. 1 Otherwise.
459 */
460int EventHandler::eventFilter(const SDL_Event *event)
461{
462  if (likely(EventHandler::getInstance()->eventsGrabbed))
463  {
464    if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
465    {
466      PRINTF(3)("Not sending event to the WindowManager\n");
467      EventHandler::getInstance()->grabEvents(false);
468      return 0;
469    }
470  }
471  else
472  {
473    if (event->type == SDL_MOUSEBUTTONDOWN)
474    {
475      EventHandler::getInstance()->grabEvents( true);
476      return 0;
477    }
478  }
479
480  return 1;
481}
482
483/**
484 * @brief outputs some nice information about the EventHandler
485 */
486void EventHandler::debug() const
487{
488  PRINT(0)("===============================\n");
489  PRINT(0)(" EventHandle Debug Information \n");
490  PRINT(0)("===============================\n");
491  for(int i = 0; i < ES_NUMBER; ++i)
492  {
493    for(int j = 0; j < EV_NUMBER; ++j)
494      for (unsigned int evl = 0; evl < this->listeners[i][j].size(); evl++)
495        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]);
496  }
497  PRINT(0)("============================EH=\n");
498}
Note: See TracBrowser for help on using the repository browser.