Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: Quit Events are listened on.

  1. Quit-Button from the Windows Handler works
  2. ctrl-c also quits the game.

(smoothly)

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