Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/current_cd/src/lib/event/event_handler.cc @ 7238

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

orxonox/trunk: particles, player etc.

File size: 9.8 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  this->eventsGrabbed = false;
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 (likely(EventHandler::getInstance()->eventsGrabbed))
364  {
365    if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
366    {
367      PRINTF(3)("Not sending event to the WindowManager\n");
368      EventHandler::getInstance()->grabEvents(false);
369      return 0;
370    }
371  }
372  else
373  {
374    if (event->type == SDL_MOUSEBUTTONDOWN)
375    {
376      EventHandler::getInstance()->grabEvents( true);
377      return 0;
378    }
379  }
380
381  return 1;
382}
383
384/**
385 * outputs some nice information about the EventHandler
386 */
387void EventHandler::debug() const
388{
389  PRINT(0)("===============================\n");
390  PRINT(0)(" EventHandle Debug Information \n");
391  PRINT(0)("===============================\n");
392  for(int i = 0; i < ES_NUMBER; ++i)
393    for(int j = 0; j < EV_NUMBER; ++j)
394      if( this->listeners[i][j] != NULL)
395        PRINT(0)("Event %d of State %d subscribed to %s (%p)\n", j, i, this->listeners[i][j]->getName(), this->listeners[i][j]);
396  PRINT(0)("============================EH=\n");
397}
Note: See TracBrowser for help on using the repository browser.