eventmanager.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 #include <iostream>
00024 
00025 // 3rd party library includes
00026 
00027 // FIFE includes
00028 // These includes are split up in two parts, separated by one empty line
00029 // First block: files included from the FIFE root src directory
00030 // Second block: files included from the same folder
00031 #include "util/base/exception.h"
00032 #include "eventchannel/key/ec_key.h"
00033 #include "eventchannel/key/ec_keyevent.h"
00034 #include "eventchannel/key/ec_ikeyfilter.h"
00035 #include "eventchannel/mouse/ec_mouseevent.h"
00036 #include "eventchannel/command/ec_command.h"
00037 #include "eventchannel/trigger/ec_trigger.h"
00038 
00039 #include "eventmanager.h"
00040 
00041 namespace FIFE {
00042 
00043     EventManager::EventManager():
00044         m_commandlisteners(),
00045         m_keylisteners(),
00046         m_mouselisteners(),
00047         m_sdleventlisteners(),
00048         m_keystatemap(),
00049         m_keyfilter(0),
00050         m_mousestate(0),
00051         m_mostrecentbtn(MouseEvent::EMPTY)
00052     {
00053     }
00054 
00055     EventManager::~EventManager() {
00056     }
00057 
00058     template<typename T>
00059     void removeListener(std::deque<T>& vec, T& listener) {
00060         vec.push_back(listener);
00061     }
00062 
00063     template<typename T>
00064     void addListener(std::deque<T>& vec, T& listener) {
00065         vec.push_back(listener);
00066     }
00067 
00068     void EventManager::addCommandListener(ICommandListener* listener) {
00069         addListener<ICommandListener*>(m_pending_commandlisteners, listener);
00070     }
00071 
00072     void EventManager::addCommandListenerFront(ICommandListener* listener) {
00073         addListener<ICommandListener*>(m_pending_commandlisteners, listener);
00074     }
00075 
00076     void EventManager::removeCommandListener(ICommandListener* listener) {
00077         removeListener<ICommandListener*>(m_pending_cldeletions, listener);
00078     }
00079 
00080     void EventManager::addKeyListener(IKeyListener* listener) {
00081         addListener<IKeyListener*>(m_pending_keylisteners, listener);
00082     }
00083 
00084     void EventManager::addKeyListenerFront(IKeyListener* listener) {
00085         addListener<IKeyListener*>(m_pending_keylisteners_front, listener);
00086     }
00087 
00088     void EventManager::removeKeyListener(IKeyListener* listener) {
00089         removeListener<IKeyListener*>(m_pending_kldeletions, listener);
00090     }
00091 
00092     void EventManager::addMouseListener(IMouseListener* listener) {
00093         addListener<IMouseListener*>(m_pending_mouselisteners, listener);
00094     }
00095 
00096     void EventManager::addMouseListenerFront(IMouseListener* listener) {
00097         addListener<IMouseListener*>(m_pending_mouselisteners, listener);
00098     }
00099 
00100     void EventManager::removeMouseListener(IMouseListener* listener) {
00101         removeListener<IMouseListener*>(m_pending_mldeletions, listener);
00102     }
00103 
00104     void EventManager::addSdlEventListener(ISdlEventListener* listener) {
00105         addListener<ISdlEventListener*>(m_pending_sdleventlisteners, listener);
00106     }
00107 
00108     void EventManager::addSdlEventListenerFront(ISdlEventListener* listener) {
00109         addListener<ISdlEventListener*>(m_pending_sdleventlisteners, listener);
00110     }
00111 
00112     void EventManager::removeSdlEventListener(ISdlEventListener* listener) {
00113         removeListener<ISdlEventListener*>(m_pending_sdldeletions, listener);
00114     }
00115 
00116     void EventManager::dispatchCommand(Command& command) {
00117         if(!m_pending_commandlisteners.empty()) {
00118             std::deque<ICommandListener*>::iterator i = m_pending_commandlisteners.begin();
00119             while (i != m_pending_commandlisteners.end()) {
00120                 m_commandlisteners.push_back(*i);
00121                 ++i;
00122             }
00123             m_pending_commandlisteners.clear();
00124         }
00125 
00126         if(!m_pending_commandlisteners_front.empty()) {
00127             std::deque<ICommandListener*>::iterator i = m_pending_commandlisteners_front.begin();
00128             while (i != m_pending_commandlisteners_front.end()) {
00129                 m_commandlisteners.push_front(*i);
00130                 ++i;
00131             }
00132             m_pending_commandlisteners_front.clear();
00133         }
00134 
00135         if (!m_pending_cldeletions.empty()) {
00136             std::deque<ICommandListener*>::iterator i = m_pending_cldeletions.begin();
00137             while (i != m_pending_cldeletions.end()) {
00138                 std::deque<ICommandListener*>::iterator j = m_commandlisteners.begin();
00139                 while (j != m_commandlisteners.end()) {
00140                     if(*j == *i) {
00141                         m_commandlisteners.erase(j);
00142                         break;
00143                     }
00144                     ++j;
00145                 }
00146                 ++i;
00147             }
00148             m_pending_cldeletions.clear();
00149         }
00150 
00151         std::deque<ICommandListener*>::iterator i = m_commandlisteners.begin();
00152         while (i != m_commandlisteners.end()) {
00153             (*i)->onCommand(command);
00154             if (command.isConsumed()) {
00155                 break;
00156             }
00157             ++i;
00158         }
00159     }
00160 
00161     void EventManager::dispatchKeyEvent(KeyEvent& evt) {
00162         if(!m_pending_keylisteners.empty()) {
00163             std::deque<IKeyListener*>::iterator i = m_pending_keylisteners.begin();
00164             while (i != m_pending_keylisteners.end()) {
00165                 m_keylisteners.push_back(*i);
00166                 ++i;
00167             }
00168             m_pending_keylisteners.clear();
00169         }
00170 
00171         if(!m_pending_keylisteners_front.empty()) {
00172             std::deque<IKeyListener*>::iterator i = m_pending_keylisteners_front.begin();
00173             while (i != m_pending_keylisteners_front.end()) {
00174                 m_keylisteners.push_front(*i);
00175                 ++i;
00176             }
00177             m_pending_keylisteners_front.clear();
00178         }
00179 
00180         if (!m_pending_kldeletions.empty()) {
00181             std::deque<IKeyListener*>::iterator i = m_pending_kldeletions.begin();
00182             while (i != m_pending_kldeletions.end()) {
00183                 std::deque<IKeyListener*>::iterator j = m_keylisteners.begin();
00184                 while (j != m_keylisteners.end()) {
00185                     if(*j == *i) {
00186                         m_keylisteners.erase(j);
00187                         break;
00188                     }
00189                     ++j;
00190                 }
00191                 ++i;
00192             }
00193             m_pending_kldeletions.clear();
00194         }
00195 
00196         std::deque<IKeyListener*>::iterator i = m_keylisteners.begin();
00197         while (i != m_keylisteners.end()) {
00198             switch (evt.getType()) {
00199                 case KeyEvent::PRESSED:
00200                     (*i)->keyPressed(evt);
00201                     break;
00202                 case KeyEvent::RELEASED:
00203                     (*i)->keyReleased(evt);
00204                     break;
00205                 default:
00206                     break;
00207             }
00208             ++i;
00209         }
00210     }
00211 
00212     void EventManager::dispatchMouseEvent(MouseEvent& evt) {
00213         if(!m_pending_mouselisteners.empty()) {
00214             std::deque<IMouseListener*>::iterator i = m_pending_mouselisteners.begin();
00215             while (i != m_pending_mouselisteners.end()) {
00216                 m_mouselisteners.push_back(*i);
00217                 ++i;
00218             }
00219             m_pending_mouselisteners.clear();
00220         }
00221 
00222         if(!m_pending_mouselisteners_front.empty()) {
00223             std::deque<IMouseListener*>::iterator i = m_pending_mouselisteners_front.begin();
00224             while (i != m_pending_mouselisteners_front.end()) {
00225                 m_mouselisteners.push_front(*i);
00226                 ++i;
00227             }
00228             m_pending_mouselisteners_front.clear();
00229         }
00230 
00231         if (!m_pending_mldeletions.empty()) {
00232             std::deque<IMouseListener*>::iterator i = m_pending_mldeletions.begin();
00233             while (i != m_pending_mldeletions.end()) {
00234                 std::deque<IMouseListener*>::iterator j = m_mouselisteners.begin();
00235                 while (j != m_mouselisteners.end()) {
00236                     if(*j == *i) {
00237                         m_mouselisteners.erase(j);
00238                         break;
00239                     }
00240                     ++j;
00241                 }
00242                 ++i;
00243             }
00244             m_pending_mldeletions.clear();
00245         }
00246 
00247         std::deque<IMouseListener*>::iterator i = m_mouselisteners.begin();
00248         while (i != m_mouselisteners.end()) {
00249             switch (evt.getType()) {
00250                 case MouseEvent::MOVED:
00251                     (*i)->mouseMoved(evt);
00252                     break;
00253                 case MouseEvent::PRESSED:
00254                     (*i)->mousePressed(evt);
00255                     break;
00256                 case MouseEvent::RELEASED:
00257                     (*i)->mouseReleased(evt);
00258                     break;
00259                 case MouseEvent::WHEEL_MOVED_DOWN:
00260                     (*i)->mouseWheelMovedDown(evt);
00261                     break;
00262                 case MouseEvent::WHEEL_MOVED_UP:
00263                     (*i)->mouseWheelMovedUp(evt);
00264                     break;
00265                 case MouseEvent::CLICKED:
00266                     (*i)->mouseClicked(evt);
00267                     break;
00268                 case MouseEvent::ENTERED:
00269                     (*i)->mouseEntered(evt);
00270                     break;
00271                 case MouseEvent::EXITED:
00272                     (*i)->mouseExited(evt);
00273                     break;
00274                 case MouseEvent::DRAGGED:
00275                     (*i)->mouseDragged(evt);
00276                     break;
00277                 default:
00278                     break;
00279             }
00280             if (evt.isConsumed()) {
00281                 break;
00282             }
00283             ++i;
00284         }
00285     }
00286 
00287     bool EventManager::dispatchSdlEvent(SDL_Event& evt) {
00288         bool ret = false;
00289         if (!m_pending_sdleventlisteners.empty()) {
00290             std::deque<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners.begin();
00291             while(i != m_pending_sdleventlisteners.end()) {
00292                 m_sdleventlisteners.push_back(*i);
00293                 ++i;
00294             }
00295             m_pending_sdleventlisteners.clear();
00296         }
00297 
00298         if (!m_pending_sdleventlisteners_front.empty()) {
00299             std::deque<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners_front.begin();
00300             while(i != m_pending_sdleventlisteners_front.end()) {
00301                 m_sdleventlisteners.push_front(*i);
00302                 ++i;
00303             }
00304             m_pending_sdleventlisteners_front.clear();
00305         }
00306 
00307         if (!m_pending_sdldeletions.empty()) {
00308             std::deque<ISdlEventListener*>::iterator i = m_pending_sdldeletions.begin();
00309             while (i != m_pending_sdldeletions.end()) {
00310                 std::deque<ISdlEventListener*>::iterator j = m_sdleventlisteners.begin();
00311                 while (j != m_sdleventlisteners.end()) {
00312                     if(*j == *i) {
00313                         m_sdleventlisteners.erase(j);
00314                         break;
00315                     }
00316                     ++j;
00317                 }
00318                 ++i;
00319             }
00320             m_pending_sdldeletions.clear();
00321         }
00322 
00323         std::deque<ISdlEventListener*>::iterator i = m_sdleventlisteners.begin();
00324         while (i != m_sdleventlisteners.end()) {
00325             ret = ret || (*i)->onSdlEvent(evt);
00326             ++i;
00327         }
00328         return ret;
00329     }
00330 
00331     bool EventManager::combineEvents(SDL_Event& event1, const SDL_Event& event2) {
00332         if(event1.type == event2.type) {
00333             switch (event1.type) {
00334                 case SDL_MOUSEMOTION:
00335                     if(event1.motion.state == event2.motion.state) {
00336                         event1.motion.x = event2.motion.x;
00337                         event1.motion.y = event2.motion.y;
00338                         event1.motion.xrel += event2.motion.xrel;
00339                         event1.motion.yrel += event2.motion.yrel;
00340                         return true;
00341                     }
00342                     return false;
00343             }
00344         }
00345         return false;
00346     }
00347 
00348     void EventManager::processEvents() {
00349         // The double SDL_PollEvent calls don't throw away events,
00350         // but try to combine (mouse motion) events.
00351         SDL_Event event, next_event;
00352         bool has_next_event = SDL_PollEvent(&event);
00353         while (has_next_event) {
00354             has_next_event = SDL_PollEvent(&next_event);
00355             if(has_next_event && combineEvents(event, next_event))
00356                 continue;
00357 
00358             switch (event.type) {
00359                 case SDL_QUIT: {
00360                     Command cmd;
00361                     cmd.setSource(this);
00362                     cmd.setCommandType(CMD_QUIT_GAME);
00363                     dispatchCommand(cmd);
00364                     }
00365                     break;
00366 
00367                 case SDL_ACTIVEEVENT:
00368                     processActiveEvent(event);
00369                     break;
00370 
00371                 case SDL_KEYDOWN:
00372                 case SDL_KEYUP:
00373                     processKeyEvent(event);
00374                     break;
00375 
00376                 case SDL_MOUSEBUTTONUP:
00377                 case SDL_MOUSEMOTION:
00378                 case SDL_MOUSEBUTTONDOWN:
00379                     processMouseEvent(event);
00380                     break;
00381             }
00382             if(has_next_event)
00383                 event = next_event;
00384         }
00385         pollTriggers();
00386     }
00387 
00388     void EventManager::processActiveEvent(SDL_Event event) {
00389         if(dispatchSdlEvent(event))
00390             return;
00391 
00392         Command cmd;
00393         cmd.setSource(this);
00394         SDL_ActiveEvent actevt = event.active;
00395         if (actevt.state == SDL_APPMOUSEFOCUS)
00396         {
00397             if (actevt.gain)
00398                 cmd.setCommandType(CMD_MOUSE_FOCUS_GAINED);
00399             else
00400                 cmd.setCommandType(CMD_MOUSE_FOCUS_LOST);
00401         }
00402         else if (actevt.state == SDL_APPINPUTFOCUS)
00403         {
00404             if (actevt.gain)
00405                 cmd.setCommandType(CMD_INPUT_FOCUS_GAINED);
00406             else
00407                 cmd.setCommandType(CMD_INPUT_FOCUS_LOST);
00408         }
00409         else if (actevt.state == SDL_APPACTIVE)
00410         {
00411             if (actevt.gain)
00412                 cmd.setCommandType(CMD_APP_RESTORED);
00413             else
00414                 cmd.setCommandType(CMD_APP_ICONIFIED);
00415         }
00416         dispatchCommand(cmd);
00417     }
00418 
00419     void EventManager::processKeyEvent(SDL_Event event) {
00420         KeyEvent keyevt;
00421         keyevt.setSource(this);
00422         fillKeyEvent(event, keyevt);
00423         m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED);
00424 
00425         bool dispatchAsSdl = !keyevt.getKey().isFunctionKey();
00426         if( dispatchAsSdl && m_keyfilter ) {
00427             dispatchAsSdl = !m_keyfilter->isFiltered(keyevt);
00428         }
00429 
00430         if( dispatchAsSdl ) {
00431             if( dispatchSdlEvent(event) )
00432                 return;
00433         }
00434 
00435         dispatchKeyEvent(keyevt);
00436     }
00437 
00438     void EventManager::processMouseEvent(SDL_Event event) {
00439         if(dispatchSdlEvent(event))
00440             return;
00441 
00442         MouseEvent mouseevt;
00443         mouseevt.setSource(this);
00444         fillMouseEvent(event, mouseevt);
00445         fillModifiers(mouseevt);
00446         if (event.type == SDL_MOUSEBUTTONDOWN) {
00447             m_mousestate |= static_cast<int>(mouseevt.getButton());
00448             m_mostrecentbtn = mouseevt.getButton();
00449         } else if (event.type == SDL_MOUSEBUTTONUP) {
00450             m_mousestate &= ~static_cast<int>(mouseevt.getButton());
00451         }
00452         // fire scrollwheel events only once
00453         if (event.button.button == SDL_BUTTON_WHEELDOWN || event.button.button == SDL_BUTTON_WHEELUP) {
00454             if (event.type == SDL_MOUSEBUTTONUP) {
00455                 return;
00456             }
00457         }
00458         dispatchMouseEvent(mouseevt);
00459     }
00460 
00461 
00462     void EventManager::fillMouseEvent(const SDL_Event& sdlevt, MouseEvent& mouseevt) {
00463         mouseevt.setX(sdlevt.button.x);
00464         mouseevt.setY(sdlevt.button.y);
00465         mouseevt.setButton(MouseEvent::EMPTY);
00466         mouseevt.setType(MouseEvent::MOVED);
00467         if ((sdlevt.type == SDL_MOUSEBUTTONUP) || (sdlevt.type == SDL_MOUSEBUTTONDOWN)) {
00468             switch (sdlevt.button.button) {
00469                 case SDL_BUTTON_LEFT:
00470                     mouseevt.setButton(MouseEvent::LEFT);
00471                     break;
00472                 case SDL_BUTTON_RIGHT:
00473                     mouseevt.setButton(MouseEvent::RIGHT);
00474                     break;
00475                 case SDL_BUTTON_MIDDLE:
00476                     mouseevt.setButton(MouseEvent::MIDDLE);
00477                     break;
00478                 default:
00479                     mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
00480                     break;
00481             }
00482 
00483             if (sdlevt.type == SDL_MOUSEBUTTONUP ) {
00484                 mouseevt.setType(MouseEvent::RELEASED);
00485             } else {
00486                 mouseevt.setType(MouseEvent::PRESSED);
00487             }
00488 
00489             switch (sdlevt.button.button) {
00490                 case SDL_BUTTON_WHEELDOWN:
00491                     mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
00492                     break;
00493                 case SDL_BUTTON_WHEELUP:
00494                     mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
00495                     break;
00496                 default:
00497                     break;
00498             }
00499         }
00500         if ((mouseevt.getType() == MouseEvent::MOVED) && m_mousestate) {
00501             mouseevt.setType(MouseEvent::DRAGGED);
00502             mouseevt.setButton(m_mostrecentbtn);
00503         }
00504     }
00505 
00506     void EventManager::fillKeyEvent(const SDL_Event& sdlevt, KeyEvent& keyevt) {
00507         if (sdlevt.type == SDL_KEYDOWN) {
00508             keyevt.setType(KeyEvent::PRESSED);
00509         } else if (sdlevt.type == SDL_KEYUP) {
00510             keyevt.setType(KeyEvent::RELEASED);
00511         } else {
00512             throw EventException("Invalid event type in fillKeyEvent");
00513         }
00514         SDL_keysym keysym = sdlevt.key.keysym;
00515 
00516         keyevt.setShiftPressed(keysym.mod & KMOD_SHIFT);
00517         keyevt.setControlPressed(keysym.mod & KMOD_CTRL);
00518         keyevt.setAltPressed(keysym.mod & KMOD_ALT);
00519         keyevt.setMetaPressed(keysym.mod & KMOD_META);
00520         keyevt.setNumericPad(keysym.sym >= SDLK_KP0 && keysym.sym <= SDLK_KP_EQUALS);
00521         keyevt.setKey(Key(static_cast<Key::KeyType>(keysym.sym), keysym.unicode));
00522     }
00523 
00524     void EventManager::fillModifiers(InputEvent& evt) {
00525         evt.setAltPressed(m_keystatemap[Key::ALT_GR] |
00526             m_keystatemap[Key::LEFT_ALT] |
00527             m_keystatemap[Key::RIGHT_ALT]);
00528         evt.setControlPressed(m_keystatemap[Key::LEFT_CONTROL] |
00529             m_keystatemap[Key::RIGHT_CONTROL]);
00530         evt.setMetaPressed(m_keystatemap[Key::LEFT_META] |
00531             m_keystatemap[Key::RIGHT_META]);
00532         evt.setShiftPressed(m_keystatemap[Key::LEFT_SHIFT] |
00533             m_keystatemap[Key::RIGHT_SHIFT]);
00534     }
00535 
00536     EventSourceType EventManager::getEventSourceType() {
00537         return ES_ENGINE;
00538     }
00539 
00540     void EventManager::registerTrigger(Trigger& trigger){
00541         m_triggers.push_back(&trigger);
00542     }
00543 
00544     void EventManager::unregisterTrigger(Trigger& trigger){
00545         m_triggers.remove(&trigger);
00546     }
00547 
00548     void EventManager::pollTriggers(){
00549         for (std::list<Trigger*>::iterator it = m_triggers.begin(); it!=m_triggers.end(); ++it) {
00550             (*it)->pollTrigger();
00551         }
00552     }
00553 
00554     void EventManager::setKeyFilter(IKeyFilter* keyFilter) {
00555         m_keyfilter = keyFilter;
00556     }
00557 }