Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/avi_play/src/lib/event/event_handler.cc @ 6611

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

trunk: segfault prevention

File size: 9.9 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 "t_stack.h"
29
30using namespace std;
31
32
33/**
34 *  standard constructor
35*/
36EventHandler::EventHandler ()
37{
38  this->setClassID(CL_EVENT_HANDLER, "EventHandler");
39  this->setName("EventHandler");
40
41  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
42  SDL_InitSubSystem(SDL_INIT_EVENTTHREAD);
43  SDL_SetEventFilter(EventHandler::eventFilter);
44
45
46  /* now initialize them all to zero */
47  this->flush(ES_ALL);
48  this->withUNICODE(false);
49  this->grabEvents(false);
50
51  this->state = ES_GAME;
52  this->keyMapper = NULL;
53  this->stateStack = NULL;
54
55}
56
57
58/**
59 *  the singleton reference to this class
60*/
61EventHandler* EventHandler::singletonRef = NULL;
62
63
64/**
65 *  standard deconstructor
66
67*/
68EventHandler::~EventHandler ()
69{
70  for(int i = 0; i < ES_NUMBER; ++i)
71  {
72    for(int j = 0; j < EV_NUMBER; ++j)
73    {
74      if( this->listeners[i][j] != NULL)
75      {
76        PRINTF(2)("forgot to unsubscribe an EventListener!\n");// %s!\n", this->listeners[i][j]->getName());
77      }
78    }
79  }
80  delete this->stateStack;
81  delete this->keyMapper;
82
83  SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
84
85  EventHandler::singletonRef = NULL;
86}
87
88
89/**
90 *  initializes the event handler
91 *
92 * this has to be called before the use of the event handler
93*/
94void EventHandler::init(IniParser* iniParser)
95{
96  if (this->keyMapper == NULL)
97  {
98    this->keyMapper = new KeyMapper();
99    this->keyMapper->loadKeyBindings(iniParser);
100  }
101  if (this->stateStack == NULL)
102    this->stateStack = new tStack<short>;
103}
104
105/**
106 * pushes the current State in the State-stack, and selects state
107 * @param state the new State to set
108 */
109void EventHandler::pushState(elState state)
110{
111  if (likely(state != ES_NULL && state != ES_ALL && this->stateStack != NULL))
112  {
113    this->stateStack->push(this->state);
114    this->setState(state);
115  }
116  else
117  {
118    PRINTF(2)("unable to push State\n");
119  }
120}
121
122/**
123 * this removes the topmost stack-entry and select the underlying one
124 * @returns the next stack-entry
125 */
126elState EventHandler::popState()
127{
128  if (unlikely(this->stateStack == NULL))
129    return ES_NULL;
130  elState state = (elState)this->stateStack->pop();
131  if (state == ES_NULL)
132  {
133    PRINTF(2)("No more states availiable. (unable to pop state)\n");
134    return ES_NULL;
135  }
136  else
137  {
138    this->setState(state);
139    return state;
140  }
141}
142
143
144/**
145 *  subscribe to an event
146 * @param el: the event listener that wants to subscribe itself, the listener that will be called when the evetn occures
147 * @param state: for which the listener wants to receive events
148 * @param eventType: the event type that wants to be listened for.
149
150   This is one of the most important function of the EventHandler. If you would like to subscribe for more
151   than one state, you have to subscribe for each state again. If you want to subscribe for all states, use
152   state = ES_ALL, which will subscribe your listener for all states together.
153 */
154void EventHandler::subscribe(EventListener* el, elState state, int eventType)
155{
156  PRINTF(4)("Subscribing event type: %i\n", eventType);
157  if( state == ES_ALL )
158    {
159      for(unsigned int i = 0; i < ES_NUMBER; i++)
160        if( likely(this->listeners[i][eventType] == NULL))
161          this->listeners[i][eventType] = el;
162        else
163          PRINTF(2)("%s of class %s tried to subscribe to event %i @ state %i but this event has already been subscribed\n", el->getName(), el->getClassName(), eventType, state);
164    }
165  else
166    if( likely(this->listeners[state][eventType] == NULL))
167      {
168        this->listeners[state][eventType] = el;
169      }
170    else
171      PRINTF(2)("% of class %s tried to subscribe to event %i @ state %i but this event has already been subscribed\n", el->getName(), el->getClassName(), eventType, state);
172}
173
174
175/**
176 *  unsubscribe from the EventHandler
177 * @param state: the stat in which it has been subscribed
178 * @param eventType: the event, that shall be unsubscribed
179
180   if you want to unsubscribe an event listener from all subscribed events, just use the
181   unsubscribe(EventListener* el, elState state) function
182*/
183void EventHandler::unsubscribe(elState state, int eventType)
184{
185  PRINTF(4)("Unsubscribing event type nr: %i\n", eventType);
186  if (state == ES_ALL)
187    for (unsigned int i = 0; i < ES_NUMBER; i++)
188      this->listeners[i][eventType] = NULL;
189  else
190    this->listeners[state][eventType] = NULL;
191}
192
193
194/**
195 * unsubscribe all events from a specific listener
196 * @param el: the listener that wants to unsubscribe itself
197 * @param state: the state in which the events shall be unsubscribed
198
199*/
200void EventHandler::unsubscribe(EventListener* el, elState state)
201{
202  if( el == NULL || state >= ES_NUMBER)
203    return;
204  if( state == ES_ALL)
205    {
206      for(unsigned int i = 0; i < ES_NUMBER; i++)
207        {
208          for(unsigned int j = 0; j < EV_NUMBER; j++)
209            {
210              if( this->listeners[i][j] == el )
211                this->listeners[i][j] = NULL;
212            }
213        }
214    }
215  else
216    {
217      for(int j = 0; j < EV_NUMBER; j++)
218        {
219          if( this->listeners[state][j] == el )
220            this->listeners[state][j] = NULL;
221        }
222    }
223}
224
225
226/**
227 * flush all registered events
228 * @param state: a specific state
229*/
230void EventHandler::flush(elState state)
231{
232  if( state == ES_ALL)
233    {
234      for(int i = 0; i < ES_NUMBER; ++i)
235        {
236          for(int j = 0; j < EV_NUMBER; ++j)
237            {
238              this->listeners[i][j] = NULL;
239            }
240        }
241    }
242  else
243    {
244      for(int j = 0; j < EV_NUMBER; ++j)
245        {
246          this->listeners[state][j] = NULL;
247        }
248    }
249}
250
251
252void EventHandler::withUNICODE(bool enableUNICODE)
253{
254  SDL_EnableUNICODE(enableUNICODE);
255  this->bUNICODE = enableUNICODE;
256}
257
258void EventHandler::grabEvents(bool grabEvents)
259{
260  this->eventsGrabbed = grabEvents;
261  if(!grabEvents)
262    SDL_WM_GrabInput(SDL_GRAB_OFF);
263  else
264    ;//SDL_WM_GrabInput(SDL_GRAB_ON);
265}
266
267/**
268 *  core function of event handler: receives all events from SDL
269
270   The event from the SDL framework are collected here and distributed to all listeners.
271*/
272void EventHandler::process()
273{
274  SDL_Event event;
275  Event ev;
276  EventListener* listener = NULL;
277  while( SDL_PollEvent (&event))
278    {
279      switch( event.type)
280        {
281        case SDL_KEYDOWN:
282          ev.bPressed = true;
283          ev.type = event.key.keysym.sym;
284          if (unlikely(this->bUNICODE))
285              ev.x = event.key.keysym.unicode;
286          break;
287        case SDL_KEYUP:
288          ev.bPressed = false;
289          ev.type = event.key.keysym.sym;
290          if (unlikely(this->bUNICODE))
291            ev.x = event.key.keysym.unicode;
292          break;
293        case SDL_MOUSEMOTION:
294          ev.bPressed = false;
295          ev.type = EV_MOUSE_MOTION;
296          ev.x = event.motion.x;
297          ev.y = event.motion.y;
298          ev.xRel = event.motion.xrel;
299          ev.yRel = event.motion.yrel;
300          break;
301        case SDL_MOUSEBUTTONUP:
302          ev.bPressed = false;
303          ev.type = event.button.button + SDLK_LAST;
304          break;
305        case SDL_MOUSEBUTTONDOWN:
306          ev.bPressed = true;
307          ev.type = event.button.button + SDLK_LAST;
308          break;
309        case SDL_JOYAXISMOTION:
310          ev.bPressed = false;
311          ev.type = EV_JOY_AXIS_MOTION;
312          break;
313        case SDL_JOYBALLMOTION:
314          ev.bPressed = false;
315          ev.type = EV_JOY_BALL_MOTION;
316          break;
317        case SDL_JOYHATMOTION:
318          ev.bPressed = false;
319          ev.type = EV_JOY_HAT_MOTION;
320          break;
321        case SDL_JOYBUTTONDOWN:
322          ev.bPressed = true;
323          ev.type = EV_JOY_BUTTON;
324          break;
325        case SDL_JOYBUTTONUP:
326          ev.bPressed = true;
327          ev.type = EV_JOY_BUTTON;
328          break;
329        case SDL_VIDEORESIZE:
330          ev.resize = event.resize;
331          ev.type = EV_VIDEO_RESIZE;
332          break;
333        case SDL_QUIT:
334          ev.type = EV_MAIN_QUIT;
335          break;
336        default:
337          ev.type = EV_UNKNOWN;
338          break;
339        }
340
341      /* small debug routine: shows all events dispatched by the event handler */
342      PRINT(4)("\n==========================| EventHandler::process () |===\n");
343      PRINT(4)("=  Got Event nr %i, for state %i", ev.type, this->state);
344
345      listener = this->listeners[this->state][ev.type];
346      if( listener != NULL)
347        {
348          PRINT(4)("=  Event dispatcher msg: This event has been consumed\n");
349          PRINT(4)("=======================================================\n");
350          listener->process(ev);
351        }
352      else
353        {
354          PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
355          PRINT(4)("=======================================================\n");
356        }
357    }
358}
359
360
361int EventHandler::eventFilter(const SDL_Event *event)
362{
363  if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
364  {
365    printf("Not sending event to the WindowManager\n");
366
367    EventHandler::getInstance()->grabEvents(false);
368    return 0;
369  }
370  return 1;
371}
372
373/**
374 * outputs some nice information about the EventHandler
375 */
376void EventHandler::debug() const
377{
378  PRINT(0)("===============================\n");
379  PRINT(0)(" EventHandle Debug Information \n");
380  PRINT(0)("===============================\n");
381  for(int i = 0; i < ES_NUMBER; ++i)
382    for(int j = 0; j < EV_NUMBER; ++j)
383      if( this->listeners[i][j] != NULL)
384        PRINT(0)("Event %d of State %d subscribed to %s (%p)\n", j, i, this->listeners[i][j]->getName(), this->listeners[i][j]);
385  PRINT(0)("============================EH=\n");
386}
Note: See TracBrowser for help on using the repository browser.