Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5914 was 5786, checked in by bensch, 19 years ago

orxonox/trunk: key-repeat in the Shell is smoother now

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