FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
eventmanager.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2008 by the FIFE team *
3  * http://www.fifengine.de *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <iostream>
24 
25 // 3rd party library includes
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 #include "util/base/exception.h"
32 #include "eventchannel/key/ec_key.h"
33 #include "eventchannel/key/ec_keyevent.h"
34 #include "eventchannel/key/ec_ikeyfilter.h"
35 #include "eventchannel/mouse/ec_mouseevent.h"
36 #include "eventchannel/command/ec_command.h"
37 
38 #include "eventmanager.h"
39 
40 namespace FIFE {
41 
43  m_commandlisteners(),
44  m_keylisteners(),
45  m_mouselisteners(),
46  m_sdleventlisteners(),
47  m_keystatemap(),
48  m_keyfilter(0),
49  m_mousestate(0),
50  m_mostrecentbtn(MouseEvent::EMPTY)
51  {
52  }
53 
55  }
56 
57  template<typename T>
58  void removeListener(std::deque<T>& vec, T& listener) {
59  vec.push_back(listener);
60  }
61 
62  template<typename T>
63  void addListener(std::deque<T>& vec, T& listener) {
64  vec.push_back(listener);
65  }
66 
68  addListener<ICommandListener*>(m_pending_commandlisteners, listener);
69  }
70 
72  addListener<ICommandListener*>(m_pending_commandlisteners, listener);
73  }
74 
76  removeListener<ICommandListener*>(m_pending_cldeletions, listener);
77  }
78 
80  addListener<IKeyListener*>(m_pending_keylisteners, listener);
81  }
82 
84  addListener<IKeyListener*>(m_pending_keylisteners_front, listener);
85  }
86 
88  removeListener<IKeyListener*>(m_pending_kldeletions, listener);
89  }
90 
92  addListener<IMouseListener*>(m_pending_mouselisteners, listener);
93  }
94 
96  addListener<IMouseListener*>(m_pending_mouselisteners, listener);
97  }
98 
100  removeListener<IMouseListener*>(m_pending_mldeletions, listener);
101  }
102 
104  addListener<ISdlEventListener*>(m_pending_sdleventlisteners, listener);
105  }
106 
108  addListener<ISdlEventListener*>(m_pending_sdleventlisteners, listener);
109  }
110 
112  removeListener<ISdlEventListener*>(m_pending_sdldeletions, listener);
113  }
114 
116  if(!m_pending_commandlisteners.empty()) {
117  std::deque<ICommandListener*>::iterator i = m_pending_commandlisteners.begin();
118  while (i != m_pending_commandlisteners.end()) {
119  m_commandlisteners.push_back(*i);
120  ++i;
121  }
122  m_pending_commandlisteners.clear();
123  }
124 
125  if(!m_pending_commandlisteners_front.empty()) {
126  std::deque<ICommandListener*>::iterator i = m_pending_commandlisteners_front.begin();
127  while (i != m_pending_commandlisteners_front.end()) {
128  m_commandlisteners.push_front(*i);
129  ++i;
130  }
131  m_pending_commandlisteners_front.clear();
132  }
133 
134  if (!m_pending_cldeletions.empty()) {
135  std::deque<ICommandListener*>::iterator i = m_pending_cldeletions.begin();
136  while (i != m_pending_cldeletions.end()) {
137  std::deque<ICommandListener*>::iterator j = m_commandlisteners.begin();
138  while (j != m_commandlisteners.end()) {
139  if(*j == *i) {
140  m_commandlisteners.erase(j);
141  break;
142  }
143  ++j;
144  }
145  ++i;
146  }
147  m_pending_cldeletions.clear();
148  }
149 
150  std::deque<ICommandListener*>::iterator i = m_commandlisteners.begin();
151  while (i != m_commandlisteners.end()) {
152  (*i)->onCommand(command);
153  if (command.isConsumed()) {
154  break;
155  }
156  ++i;
157  }
158  }
159 
160  void EventManager::dispatchKeyEvent(KeyEvent& evt) {
161  if(!m_pending_keylisteners.empty()) {
162  std::deque<IKeyListener*>::iterator i = m_pending_keylisteners.begin();
163  while (i != m_pending_keylisteners.end()) {
164  m_keylisteners.push_back(*i);
165  ++i;
166  }
167  m_pending_keylisteners.clear();
168  }
169 
170  if(!m_pending_keylisteners_front.empty()) {
171  std::deque<IKeyListener*>::iterator i = m_pending_keylisteners_front.begin();
172  while (i != m_pending_keylisteners_front.end()) {
173  m_keylisteners.push_front(*i);
174  ++i;
175  }
176  m_pending_keylisteners_front.clear();
177  }
178 
179  if (!m_pending_kldeletions.empty()) {
180  std::deque<IKeyListener*>::iterator i = m_pending_kldeletions.begin();
181  while (i != m_pending_kldeletions.end()) {
182  std::deque<IKeyListener*>::iterator j = m_keylisteners.begin();
183  while (j != m_keylisteners.end()) {
184  if(*j == *i) {
185  m_keylisteners.erase(j);
186  break;
187  }
188  ++j;
189  }
190  ++i;
191  }
192  m_pending_kldeletions.clear();
193  }
194 
195  std::deque<IKeyListener*>::iterator i = m_keylisteners.begin();
196  while (i != m_keylisteners.end()) {
197  switch (evt.getType()) {
198  case KeyEvent::PRESSED:
199  (*i)->keyPressed(evt);
200  break;
201  case KeyEvent::RELEASED:
202  (*i)->keyReleased(evt);
203  break;
204  default:
205  break;
206  }
207  ++i;
208  }
209  }
210 
211  void EventManager::dispatchMouseEvent(MouseEvent& evt) {
212  if(!m_pending_mouselisteners.empty()) {
213  std::deque<IMouseListener*>::iterator i = m_pending_mouselisteners.begin();
214  while (i != m_pending_mouselisteners.end()) {
215  m_mouselisteners.push_back(*i);
216  ++i;
217  }
218  m_pending_mouselisteners.clear();
219  }
220 
221  if(!m_pending_mouselisteners_front.empty()) {
222  std::deque<IMouseListener*>::iterator i = m_pending_mouselisteners_front.begin();
223  while (i != m_pending_mouselisteners_front.end()) {
224  m_mouselisteners.push_front(*i);
225  ++i;
226  }
227  m_pending_mouselisteners_front.clear();
228  }
229 
230  if (!m_pending_mldeletions.empty()) {
231  std::deque<IMouseListener*>::iterator i = m_pending_mldeletions.begin();
232  while (i != m_pending_mldeletions.end()) {
233  std::deque<IMouseListener*>::iterator j = m_mouselisteners.begin();
234  while (j != m_mouselisteners.end()) {
235  if(*j == *i) {
236  m_mouselisteners.erase(j);
237  break;
238  }
239  ++j;
240  }
241  ++i;
242  }
243  m_pending_mldeletions.clear();
244  }
245 
246  std::deque<IMouseListener*>::iterator i = m_mouselisteners.begin();
247  while (i != m_mouselisteners.end()) {
248  switch (evt.getType()) {
249  case MouseEvent::MOVED:
250  (*i)->mouseMoved(evt);
251  break;
252  case MouseEvent::PRESSED:
253  (*i)->mousePressed(evt);
254  break;
255  case MouseEvent::RELEASED:
256  (*i)->mouseReleased(evt);
257  break;
258  case MouseEvent::WHEEL_MOVED_DOWN:
259  (*i)->mouseWheelMovedDown(evt);
260  break;
261  case MouseEvent::WHEEL_MOVED_UP:
262  (*i)->mouseWheelMovedUp(evt);
263  break;
264  case MouseEvent::CLICKED:
265  (*i)->mouseClicked(evt);
266  break;
267  case MouseEvent::ENTERED:
268  (*i)->mouseEntered(evt);
269  break;
270  case MouseEvent::EXITED:
271  (*i)->mouseExited(evt);
272  break;
273  case MouseEvent::DRAGGED:
274  (*i)->mouseDragged(evt);
275  break;
276  default:
277  break;
278  }
279  if (evt.isConsumed()) {
280  break;
281  }
282  ++i;
283  }
284  }
285 
286  bool EventManager::dispatchSdlEvent(SDL_Event& evt) {
287  bool ret = false;
288  if (!m_pending_sdleventlisteners.empty()) {
289  std::deque<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners.begin();
290  while(i != m_pending_sdleventlisteners.end()) {
291  m_sdleventlisteners.push_back(*i);
292  ++i;
293  }
294  m_pending_sdleventlisteners.clear();
295  }
296 
297  if (!m_pending_sdleventlisteners_front.empty()) {
298  std::deque<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners_front.begin();
299  while(i != m_pending_sdleventlisteners_front.end()) {
300  m_sdleventlisteners.push_front(*i);
301  ++i;
302  }
303  m_pending_sdleventlisteners_front.clear();
304  }
305 
306  if (!m_pending_sdldeletions.empty()) {
307  std::deque<ISdlEventListener*>::iterator i = m_pending_sdldeletions.begin();
308  while (i != m_pending_sdldeletions.end()) {
309  std::deque<ISdlEventListener*>::iterator j = m_sdleventlisteners.begin();
310  while (j != m_sdleventlisteners.end()) {
311  if(*j == *i) {
312  m_sdleventlisteners.erase(j);
313  break;
314  }
315  ++j;
316  }
317  ++i;
318  }
319  m_pending_sdldeletions.clear();
320  }
321 
322  std::deque<ISdlEventListener*>::iterator i = m_sdleventlisteners.begin();
323  while (i != m_sdleventlisteners.end()) {
324  ret = ret || (*i)->onSdlEvent(evt);
325  ++i;
326  }
327  return ret;
328  }
329 
330  bool EventManager::combineEvents(SDL_Event& event1, const SDL_Event& event2) {
331  if(event1.type == event2.type) {
332  switch (event1.type) {
333  case SDL_MOUSEMOTION:
334  if(event1.motion.state == event2.motion.state) {
335  event1.motion.x = event2.motion.x;
336  event1.motion.y = event2.motion.y;
337  event1.motion.xrel += event2.motion.xrel;
338  event1.motion.yrel += event2.motion.yrel;
339  return true;
340  }
341  return false;
342  }
343  }
344  return false;
345  }
346 
348  // The double SDL_PollEvent calls don't throw away events,
349  // but try to combine (mouse motion) events.
350  SDL_Event event, next_event;
351  bool has_next_event = SDL_PollEvent(&event);
352  while (has_next_event) {
353  has_next_event = SDL_PollEvent(&next_event);
354  if(has_next_event && combineEvents(event, next_event))
355  continue;
356 
357  switch (event.type) {
358  case SDL_QUIT: {
359  Command cmd;
360  cmd.setSource(this);
361  cmd.setCommandType(CMD_QUIT_GAME);
362  dispatchCommand(cmd);
363  }
364  break;
365 
366  case SDL_ACTIVEEVENT:
367  processActiveEvent(event);
368  break;
369 
370  case SDL_KEYDOWN:
371  case SDL_KEYUP:
372  processKeyEvent(event);
373  break;
374 
375  case SDL_MOUSEBUTTONUP:
376  case SDL_MOUSEMOTION:
377  case SDL_MOUSEBUTTONDOWN:
378  processMouseEvent(event);
379  break;
380  }
381  if(has_next_event)
382  event = next_event;
383  }
384  }
385 
386  void EventManager::processActiveEvent(SDL_Event event) {
387  if(dispatchSdlEvent(event))
388  return;
389 
390  Command cmd;
391  cmd.setSource(this);
392  SDL_ActiveEvent actevt = event.active;
393  if (actevt.state == SDL_APPMOUSEFOCUS)
394  {
395  if (actevt.gain)
396  cmd.setCommandType(CMD_MOUSE_FOCUS_GAINED);
397  else
398  cmd.setCommandType(CMD_MOUSE_FOCUS_LOST);
399  }
400  else if (actevt.state == SDL_APPINPUTFOCUS)
401  {
402  if (actevt.gain)
403  cmd.setCommandType(CMD_INPUT_FOCUS_GAINED);
404  else
405  cmd.setCommandType(CMD_INPUT_FOCUS_LOST);
406  }
407  else if (actevt.state == SDL_APPACTIVE)
408  {
409  if (actevt.gain)
410  cmd.setCommandType(CMD_APP_RESTORED);
411  else
412  cmd.setCommandType(CMD_APP_ICONIFIED);
413  }
414  dispatchCommand(cmd);
415  }
416 
417  void EventManager::processKeyEvent(SDL_Event event) {
418  KeyEvent keyevt;
419  keyevt.setSource(this);
420  fillKeyEvent(event, keyevt);
421  m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED);
422 
423  bool dispatchAsSdl = !keyevt.getKey().isFunctionKey();
424  if( dispatchAsSdl && m_keyfilter ) {
425  dispatchAsSdl = !m_keyfilter->isFiltered(keyevt);
426  }
427 
428  if( dispatchAsSdl ) {
429  if( dispatchSdlEvent(event) )
430  return;
431  }
432 
433  dispatchKeyEvent(keyevt);
434  }
435 
436  void EventManager::processMouseEvent(SDL_Event event) {
437  if(dispatchSdlEvent(event))
438  return;
439 
440  MouseEvent mouseevt;
441  mouseevt.setSource(this);
442  fillMouseEvent(event, mouseevt);
443  fillModifiers(mouseevt);
444  if (event.type == SDL_MOUSEBUTTONDOWN) {
445  m_mousestate |= static_cast<int>(mouseevt.getButton());
446  m_mostrecentbtn = mouseevt.getButton();
447  } else if (event.type == SDL_MOUSEBUTTONUP) {
448  m_mousestate &= ~static_cast<int>(mouseevt.getButton());
449  }
450  // fire scrollwheel events only once
451  if (event.button.button == SDL_BUTTON_WHEELDOWN || event.button.button == SDL_BUTTON_WHEELUP) {
452  if (event.type == SDL_MOUSEBUTTONUP) {
453  return;
454  }
455  }
456  dispatchMouseEvent(mouseevt);
457  }
458 
459 
460  void EventManager::fillMouseEvent(const SDL_Event& sdlevt, MouseEvent& mouseevt) {
461  mouseevt.setX(sdlevt.button.x);
462  mouseevt.setY(sdlevt.button.y);
463  mouseevt.setButton(MouseEvent::EMPTY);
464  mouseevt.setType(MouseEvent::MOVED);
465  if ((sdlevt.type == SDL_MOUSEBUTTONUP) || (sdlevt.type == SDL_MOUSEBUTTONDOWN)) {
466  switch (sdlevt.button.button) {
467  case SDL_BUTTON_LEFT:
468  mouseevt.setButton(MouseEvent::LEFT);
469  break;
470  case SDL_BUTTON_RIGHT:
471  mouseevt.setButton(MouseEvent::RIGHT);
472  break;
473  case SDL_BUTTON_MIDDLE:
474  mouseevt.setButton(MouseEvent::MIDDLE);
475  break;
476  default:
477  mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
478  break;
479  }
480 
481  if (sdlevt.type == SDL_MOUSEBUTTONUP ) {
482  mouseevt.setType(MouseEvent::RELEASED);
483  } else {
484  mouseevt.setType(MouseEvent::PRESSED);
485  }
486 
487  switch (sdlevt.button.button) {
488  case SDL_BUTTON_WHEELDOWN:
489  mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
490  break;
491  case SDL_BUTTON_WHEELUP:
492  mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
493  break;
494  default:
495  break;
496  }
497  }
498  if ((mouseevt.getType() == MouseEvent::MOVED) && m_mousestate) {
499  mouseevt.setType(MouseEvent::DRAGGED);
500  mouseevt.setButton(m_mostrecentbtn);
501  }
502  }
503 
504  void EventManager::fillKeyEvent(const SDL_Event& sdlevt, KeyEvent& keyevt) {
505  if (sdlevt.type == SDL_KEYDOWN) {
506  keyevt.setType(KeyEvent::PRESSED);
507  } else if (sdlevt.type == SDL_KEYUP) {
508  keyevt.setType(KeyEvent::RELEASED);
509  } else {
510  throw EventException("Invalid event type in fillKeyEvent");
511  }
512  SDL_keysym keysym = sdlevt.key.keysym;
513 
514  keyevt.setShiftPressed(keysym.mod & KMOD_SHIFT);
515  keyevt.setControlPressed(keysym.mod & KMOD_CTRL);
516  keyevt.setAltPressed(keysym.mod & KMOD_ALT);
517  keyevt.setMetaPressed(keysym.mod & KMOD_META);
518  keyevt.setNumericPad(keysym.sym >= SDLK_KP0 && keysym.sym <= SDLK_KP_EQUALS);
519  keyevt.setKey(Key(static_cast<Key::KeyType>(keysym.sym), keysym.unicode));
520  }
521 
522  void EventManager::fillModifiers(InputEvent& evt) {
523  evt.setAltPressed(m_keystatemap[Key::ALT_GR] |
524  m_keystatemap[Key::LEFT_ALT] |
525  m_keystatemap[Key::RIGHT_ALT]);
526  evt.setControlPressed(m_keystatemap[Key::LEFT_CONTROL] |
527  m_keystatemap[Key::RIGHT_CONTROL]);
528  evt.setMetaPressed(m_keystatemap[Key::LEFT_META] |
529  m_keystatemap[Key::RIGHT_META]);
530  evt.setShiftPressed(m_keystatemap[Key::LEFT_SHIFT] |
531  m_keystatemap[Key::RIGHT_SHIFT]);
532  }
533 
535  return ES_ENGINE;
536  }
537 
538  void EventManager::setKeyFilter(IKeyFilter* keyFilter) {
539  m_keyfilter = keyFilter;
540  }
541 }