Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7875 was 7868, checked in by bensch, 19 years ago

trunk: merge Check in the Event-changes:
r7867 | bensch | 2006-05-26 13:19:46 +0200 (Fri, 26 May 2006) | 1 line

Events better subscribed


r7866 | bensch | 2006-05-26 13:11:10 +0200 (Fri, 26 May 2006) | 1 line

Events are subscribed at the EventListener, and not the EventHandler

File size: 10.7 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(EventListener* el, 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    {
179      std::vector<EventListener*>::iterator listener =
180         std::find(this->listeners[i][eventType].begin(),
181                   this->listeners[i][eventType].end(),
182                   el);
183      if (listener != this->listeners[i][eventType].end())
184        this->listeners[i][eventType].erase(listener);
185    }
186  else
187  {
188    std::vector<EventListener*>::iterator listener =
189        std::find(this->listeners[state][eventType].begin(),
190                  this->listeners[state][eventType].end(),
191                  el);
192    if (listener != this->listeners[state][eventType].end())
193      this->listeners[state][eventType].erase(listener);
194  }
195}
196
197
198/**
199 * @brief unsubscribe all events from a specific listener
200 * @param el: the listener that wants to unsubscribe itself
201 * @param state: the state in which the events shall be unsubscribed
202 */
203void EventHandler::unsubscribe(EventListener* el, elState state)
204{
205  if( el == NULL || state >= ES_NUMBER)
206    return;
207  if( state == ES_ALL)
208  {
209    for(unsigned int i = 0; i < ES_NUMBER; i++)
210    {
211      for(unsigned int j = 0; j < EV_NUMBER; j++)
212      {
213        std::vector<EventListener*>::iterator deller = std::find (this->listeners[i][j].begin(), this->listeners[i][j].end(), el);
214        if( deller != this->listeners[i][j].end())
215          this->listeners[i][j].erase(deller);
216      }
217    }
218  }
219  else
220  {
221    for(int j = 0; j < EV_NUMBER; j++)
222    {
223      std::vector<EventListener*>::iterator deller =  std::find (this->listeners[state][j].begin(), this->listeners[state][j].end(), el);
224      if( deller != this->listeners[state][j].end())
225        this->listeners[state][j].erase(deller);
226    }
227  }
228}
229
230bool EventHandler::isSubscribed(elState state, int eventType)
231{
232  return(listeners[state][eventType].empty()) ? false : true;
233};
234
235
236
237/**
238 * flush all registered events
239 * @param state: a specific state
240*/
241void EventHandler::flush(elState state)
242{
243  if( state == ES_ALL)
244  {
245    for(int i = 0; i < ES_NUMBER; ++i)
246    {
247      for(int j = 0; j < EV_NUMBER; ++j)
248      {
249        this->listeners[i][j].clear();
250      }
251    }
252  }
253  else
254  {
255    for(int j = 0; j < EV_NUMBER; ++j)
256    {
257      this->listeners[state][j].clear();
258    }
259  }
260}
261
262
263void EventHandler::withUNICODE(bool enableUNICODE)
264{
265  SDL_EnableUNICODE(enableUNICODE);
266  this->bUNICODE = 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 *  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))
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))
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", ev.type, this->state);
361
362
363    for (unsigned int i = 0; i < this->listeners[this->state][ev.type].size(); i++)
364    {
365      PRINT(4)("=  Event dispatcher msg: This event has been consumed\n");
366      PRINT(4)("=======================================================\n");
367      listeners[this->state][ev.type][i]->process(ev);
368    }
369    /*    else
370        {
371          PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
372          PRINT(4)("=======================================================\n");
373        }*/
374  }
375}
376
377
378int EventHandler::eventFilter(const SDL_Event *event)
379{
380  if (likely(EventHandler::getInstance()->eventsGrabbed))
381  {
382    if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
383    {
384      PRINTF(3)("Not sending event to the WindowManager\n");
385      EventHandler::getInstance()->grabEvents(false);
386      return 0;
387    }
388  }
389  else
390  {
391    if (event->type == SDL_MOUSEBUTTONDOWN)
392    {
393      EventHandler::getInstance()->grabEvents( true);
394      return 0;
395    }
396  }
397
398  return 1;
399}
400
401/**
402 * outputs some nice information about the EventHandler
403 */
404void EventHandler::debug() const
405{
406  PRINT(0)("===============================\n");
407  PRINT(0)(" EventHandle Debug Information \n");
408  PRINT(0)("===============================\n");
409  for(int i = 0; i < ES_NUMBER; ++i)
410    for(int j = 0; j < EV_NUMBER; ++j)
411      for (unsigned int evl = 0; evl < this->listeners[i][j].size(); evl++)
412        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]);
413  PRINT(0)("============================EH=\n");
414}
Note: See TracBrowser for help on using the repository browser.