Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/event/event_handler.cc @ 6990

Last change on this file since 6990 was 6990, checked in by bensch, 18 years ago

orxonox/trunk: better mouse capture now

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  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  {
263    SDL_ShowCursor(SDL_ENABLE);
264    SDL_WM_GrabInput(SDL_GRAB_OFF);
265  }
266  else
267  {
268    SDL_WM_GrabInput(SDL_GRAB_ON);
269    SDL_ShowCursor(SDL_DISABLE);
270  }
271}
272
273/**
274 *  core function of event handler: receives all events from SDL
275
276   The event from the SDL framework are collected here and distributed to all listeners.
277*/
278void EventHandler::process()
279{
280  SDL_Event event;
281  Event ev;
282  EventListener* listener = NULL;
283  while( SDL_PollEvent (&event))
284  {
285    switch( event.type)
286    {
287      case SDL_KEYDOWN:
288        ev.bPressed = true;
289        ev.type = event.key.keysym.sym;
290        if (unlikely(this->bUNICODE))
291          ev.x = event.key.keysym.unicode;
292        break;
293      case SDL_KEYUP:
294        ev.bPressed = false;
295        ev.type = event.key.keysym.sym;
296        if (unlikely(this->bUNICODE))
297          ev.x = event.key.keysym.unicode;
298        break;
299      case SDL_MOUSEMOTION:
300        ev.bPressed = false;
301        ev.type = EV_MOUSE_MOTION;
302        ev.x = event.motion.x;
303        ev.y = event.motion.y;
304        ev.xRel = event.motion.xrel;
305        ev.yRel = event.motion.yrel;
306        break;
307      case SDL_MOUSEBUTTONUP:
308        ev.bPressed = false;
309        ev.type = event.button.button + SDLK_LAST;
310        break;
311      case SDL_MOUSEBUTTONDOWN:
312        ev.bPressed = true;
313        ev.type = event.button.button + SDLK_LAST;
314        break;
315      case SDL_JOYAXISMOTION:
316        ev.bPressed = false;
317        ev.type = EV_JOY_AXIS_MOTION;
318        break;
319      case SDL_JOYBALLMOTION:
320        ev.bPressed = false;
321        ev.type = EV_JOY_BALL_MOTION;
322        break;
323      case SDL_JOYHATMOTION:
324        ev.bPressed = false;
325        ev.type = EV_JOY_HAT_MOTION;
326        break;
327      case SDL_JOYBUTTONDOWN:
328        ev.bPressed = true;
329        ev.type = EV_JOY_BUTTON;
330        break;
331      case SDL_JOYBUTTONUP:
332        ev.bPressed = true;
333        ev.type = EV_JOY_BUTTON;
334        break;
335      case SDL_VIDEORESIZE:
336        ev.resize = event.resize;
337        ev.type = EV_VIDEO_RESIZE;
338        break;
339      case SDL_QUIT:
340        ev.type = EV_MAIN_QUIT;
341        break;
342      default:
343        ev.type = EV_UNKNOWN;
344        break;
345    }
346
347    /* small debug routine: shows all events dispatched by the event handler */
348    PRINT(4)("\n==========================| EventHandler::process () |===\n");
349    PRINT(4)("=  Got Event nr %i, for state %i", ev.type, this->state);
350
351    listener = this->listeners[this->state][ev.type];
352    if( listener != NULL)
353    {
354      PRINT(4)("=  Event dispatcher msg: This event has been consumed\n");
355      PRINT(4)("=======================================================\n");
356      listener->process(ev);
357    }
358    else
359    {
360      PRINT(4)("=  Event dispatcher msg: This event has NOT been consumed\n");
361      PRINT(4)("=======================================================\n");
362    }
363  }
364}
365
366
367int EventHandler::eventFilter(const SDL_Event *event)
368{
369  if (likely(EventHandler::getInstance()->eventsGrabbed))
370  {
371    if (event->type == SDL_KEYDOWN &&  event->key.keysym.sym == SDLK_TAB && SDL_GetKeyState(NULL)[SDLK_LALT])
372    {
373      PRINTF(3)("Not sending event to the WindowManager\n");
374      EventHandler::getInstance()->grabEvents(false);
375      return 0;
376    }
377  }
378  else
379  {
380    if (event->type == SDL_MOUSEBUTTONDOWN)
381    {
382      EventHandler::getInstance()->grabEvents( true);
383      return 0;
384    }
385  }
386
387  return 1;
388}
389
390/**
391 * outputs some nice information about the EventHandler
392 */
393void EventHandler::debug() const
394{
395  PRINT(0)("===============================\n");
396  PRINT(0)(" EventHandle Debug Information \n");
397  PRINT(0)("===============================\n");
398  for(int i = 0; i < ES_NUMBER; ++i)
399    for(int j = 0; j < EV_NUMBER; ++j)
400      if( this->listeners[i][j] != NULL)
401        PRINT(0)("Event %d of State %d subscribed to %s (%p)\n", j, i, this->listeners[i][j]->getName(), this->listeners[i][j]);
402  PRINT(0)("============================EH=\n");
403}
Note: See TracBrowser for help on using the repository browser.