Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/atmospheric_engine/src/lib/event/event_handler.cc @ 7917

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

orxonox/trunk: Multiple Event Subscription Method
@patrick, do you approve of this, or do you think, that it is too much??

This is something i proposed some time ago, and it is nice, because one can overload the Commandos

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