Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: fixed a bug in the EventHandler, that resulted from multiple inputs or so…

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