Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged the scriptengine back to the trunk

File size: 13.2 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.x = event.motion.x;
383        ev.y = event.motion.y;
384        ev.type = event.button.button + SDLK_LAST;
385        break;
386      case SDL_MOUSEBUTTONDOWN:
387        ev.bPressed = true;
388        ev.x = event.motion.x;
389        ev.y = event.motion.y;
390        ev.type = event.button.button + SDLK_LAST;
391        break;
392      case SDL_JOYAXISMOTION:
393        ev.bPressed = false;
394        ev.type = EV_JOY_AXIS_MOTION;
395        break;
396      case SDL_JOYBALLMOTION:
397        ev.bPressed = false;
398        ev.type = EV_JOY_BALL_MOTION;
399        break;
400      case SDL_JOYHATMOTION:
401        ev.bPressed = false;
402        ev.type = EV_JOY_HAT_MOTION;
403        break;
404      case SDL_JOYBUTTONDOWN:
405        ev.bPressed = true;
406        ev.type = EV_JOY_BUTTON;
407        break;
408      case SDL_JOYBUTTONUP:
409        ev.bPressed = true;
410        ev.type = EV_JOY_BUTTON;
411        break;
412      case SDL_ACTIVEEVENT:
413        ev.type = EV_WINDOW_FOCUS;
414        ev.bPressed = (event.active.gain != 0);
415        break;
416      case SDL_VIDEORESIZE:
417        ev.resize = event.resize;
418        ev.type = EV_VIDEO_RESIZE;
419        break;
420      case SDL_QUIT:
421        ev.type = EV_MAIN_QUIT;
422        break;
423      default:
424        ev.type = EV_UNKNOWN;
425        break;
426    }
427    this->dispachEvent(this->state, ev);
428  }
429}
430
431
432/**
433 * @brief dispaches an Event.
434 * @param event the Event to dispach.
435 */
436void EventHandler::dispachEvent(elState state, const Event& event) const
437{
438  /* small debug routine: shows all events dispatched by the event handler */
439  PRINT(4)("\n==========================| EventHandler::process () |===\n");
440  PRINT(4)("=  Got Event nr %i, for state %i\n", event.type, state);
441
442  /// setting a temporary state in case of an EventListener's process changes the state.
443  for (unsigned int i = 0; i < this->listeners[state][event.type].size(); i++)
444  {
445    PRINT(4)("=  Event dispatcher msg: This event has been consumed\n");
446    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]);
447    PRINT(4)("=======================================================\n");
448    this->listeners[state][event.type][i]->process(event);
449  }
450  /*    else
451  {
452        PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
453        PRINT(4)("=======================================================\n");
454  }*/
455}
456
457
458
459/**
460 * @brief An eventFilter.
461 * @param event the Event to be filtered.
462 * @returns 0 on filtered Event. 1 Otherwise.
463 */
464int EventHandler::eventFilter(const SDL_Event *event)
465{
466  if (likely(EventHandler::getInstance()->eventsGrabbed))
467  {
468    if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
469    {
470      PRINTF(3)("Not sending event to the WindowManager\n");
471      EventHandler::getInstance()->grabEvents(false);
472      return 0;
473    }
474  }
475  else
476  {
477    if (event->type == SDL_MOUSEBUTTONDOWN)
478    {
479      EventHandler::getInstance()->grabEvents( true);
480      return 1;
481    }
482  }
483
484  return 1;
485}
486
487/**
488 * @brief outputs some nice information about the EventHandler
489 */
490void EventHandler::debug() const
491{
492  PRINT(0)("===============================\n");
493  PRINT(0)(" EventHandle Debug Information \n");
494  PRINT(0)("===============================\n");
495  for(int i = 0; i < ES_NUMBER; ++i)
496  {
497    for(int j = 0; j < EV_NUMBER; ++j)
498      for (unsigned int evl = 0; evl < this->listeners[i][j].size(); evl++)
499        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]);
500  }
501  PRINT(0)("============================EH=\n");
502}
Note: See TracBrowser for help on using the repository browser.