Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/resources/src/lib/event/event_handler.cc @ 7683

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

trunk: hups :)

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