Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/gui/src/lib/event/event_handler.cc @ 7897

Last change on this file since 7897 was 7897, checked in by bensch, 19 years ago

/ When Changing the State, all the keys will be released.

/ This is done by sending each eventListener, that still
/ has an Event subscribed, a Release Event.

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