Mercurial > fife-parpg
view engine/core/eventchannel/eventmanager.cpp @ 46:90005975cdbb
* Final LGPL switch step by adjusting the file headers
* Remaining issues (just slightly related to the unittest switch):
* No working unittest solution for msvc2005 yet
* Unittests not working with mingw + scons either though this seems hard to impossible to fix without an expert in this field
* sample_unit_test.cpp would need to get modified for unittest++; it still contains the old boost unittest code
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 13 Jul 2008 11:05:12 +0000 |
parents | e84dccee1bb7 |
children | 76fb866be8ea |
line wrap: on
line source
/*************************************************************************** * Copyright (C) 2005-2008 by the FIFE team * * http://www.fifengine.de * * This file is part of FIFE. * * * * FIFE is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ // Standard C++ library includes #include <iostream> // 3rd party library includes // FIFE includes // These includes are split up in two parts, separated by one empty line // First block: files included from the FIFE root src directory // Second block: files included from the same folder #include "util/base/exception.h" #include "eventchannel/key/ec_key.h" #include "eventchannel/key/ec_keyevent.h" #include "eventchannel/mouse/ec_mouseevent.h" #include "eventchannel/widget/ec_widgetevent.h" #include "eventchannel/command/ec_command.h" #include "eventchannel/trigger/ec_trigger.h" #include "eventmanager.h" namespace FIFE { EventManager::EventManager(): m_commandlisteners(), m_keylisteners(), m_mouselisteners(), m_sdleventlisteners(), m_widgetlisteners(), m_pending_widgetlisteners(), m_nonconsumablekeys(), m_keystatemap(), m_mousestate(0), m_mostrecentbtn(MouseEvent::EMPTY) { } EventManager::~EventManager() { } void EventManager::fillMouseEvent(const SDL_Event& sdlevt, MouseEvent& mouseevt) { mouseevt.setX(sdlevt.button.x); mouseevt.setY(sdlevt.button.y); mouseevt.setButton(MouseEvent::EMPTY); mouseevt.setType(MouseEvent::MOVED); if ((sdlevt.type == SDL_MOUSEBUTTONUP) || (sdlevt.type == SDL_MOUSEBUTTONDOWN)) { switch (sdlevt.button.button) { case SDL_BUTTON_LEFT: mouseevt.setButton(MouseEvent::LEFT); break; case SDL_BUTTON_RIGHT: mouseevt.setButton(MouseEvent::RIGHT); break; case SDL_BUTTON_MIDDLE: mouseevt.setButton(MouseEvent::MIDDLE); break; default: mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON); break; } if (sdlevt.type == SDL_MOUSEBUTTONUP ) { mouseevt.setType(MouseEvent::RELEASED); } else { mouseevt.setType(MouseEvent::PRESSED); } switch (sdlevt.button.button) { case SDL_BUTTON_WHEELDOWN: mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN); break; case SDL_BUTTON_WHEELUP: mouseevt.setType(MouseEvent::WHEEL_MOVED_UP); break; default: break; } } if ((mouseevt.getType() == MouseEvent::MOVED) && m_mousestate) { mouseevt.setType(MouseEvent::DRAGGED); mouseevt.setButton(m_mostrecentbtn); } } void EventManager::fillKeyEvent(const SDL_Event& sdlevt, KeyEvent& keyevt) { if (sdlevt.type == SDL_KEYDOWN) { keyevt.setType(KeyEvent::PRESSED); } else if (sdlevt.type == SDL_KEYUP) { keyevt.setType(KeyEvent::RELEASED); } else { throw EventException("Invalid event type in fillKeyEvent"); } keyevt.setShiftPressed(sdlevt.key.keysym.mod & KMOD_SHIFT); keyevt.setControlPressed(sdlevt.key.keysym.mod & KMOD_CTRL); keyevt.setAltPressed(sdlevt.key.keysym.mod & KMOD_ALT); keyevt.setMetaPressed(sdlevt.key.keysym.mod & KMOD_META); keyevt.setNumericPad(sdlevt.key.keysym.sym >= SDLK_KP0 && sdlevt.key.keysym.sym <= SDLK_KP_EQUALS); SDL_keysym keysym = sdlevt.key.keysym; Key::KeyType value = Key::INVALID_KEY; std::string repr(""); if (keysym.unicode < 255) { value = static_cast<Key::KeyType>(keysym.unicode); repr.push_back(value); } #define MAP_KEY(_orig, _new) case _orig: value = _new; repr = #_new; break; switch (keysym.sym) { MAP_KEY(SDLK_TAB, Key::TAB); MAP_KEY(SDLK_LALT, Key::LEFT_ALT); MAP_KEY(SDLK_RALT, Key::RIGHT_ALT); MAP_KEY(SDLK_LSHIFT, Key::LEFT_SHIFT); MAP_KEY(SDLK_RSHIFT, Key::RIGHT_SHIFT); MAP_KEY(SDLK_LCTRL, Key::LEFT_CONTROL); MAP_KEY(SDLK_RCTRL, Key::RIGHT_CONTROL); MAP_KEY(SDLK_BACKSPACE, Key::BACKSPACE); MAP_KEY(SDLK_PAUSE, Key::PAUSE); MAP_KEY(SDLK_ESCAPE, Key::ESCAPE); MAP_KEY(SDLK_DELETE, Key::DELETE_KEY); MAP_KEY(SDLK_INSERT, Key::INSERT); MAP_KEY(SDLK_HOME, Key::HOME); MAP_KEY(SDLK_END, Key::END); MAP_KEY(SDLK_PAGEUP, Key::PAGE_UP); MAP_KEY(SDLK_PRINT, Key::PRINT_SCREEN); MAP_KEY(SDLK_PAGEDOWN, Key::PAGE_DOWN); MAP_KEY(SDLK_F1, Key::F1); MAP_KEY(SDLK_F2, Key::F2); MAP_KEY(SDLK_F3, Key::F3); MAP_KEY(SDLK_F4, Key::F4); MAP_KEY(SDLK_F5, Key::F5); MAP_KEY(SDLK_F6, Key::F6); MAP_KEY(SDLK_F7, Key::F7); MAP_KEY(SDLK_F8, Key::F8); MAP_KEY(SDLK_F9, Key::F9); MAP_KEY(SDLK_F10, Key::F10); MAP_KEY(SDLK_F11, Key::F11); MAP_KEY(SDLK_F12, Key::F12); MAP_KEY(SDLK_F13, Key::F13); MAP_KEY(SDLK_F14, Key::F14); MAP_KEY(SDLK_F15, Key::F15); MAP_KEY(SDLK_NUMLOCK, Key::NUM_LOCK); MAP_KEY(SDLK_CAPSLOCK, Key::CAPS_LOCK); MAP_KEY(SDLK_SCROLLOCK, Key::SCROLL_LOCK); MAP_KEY(SDLK_RMETA, Key::RIGHT_META); MAP_KEY(SDLK_LMETA, Key::LEFT_META); MAP_KEY(SDLK_LSUPER, Key::LEFT_SUPER); MAP_KEY(SDLK_RSUPER, Key::RIGHT_SUPER); MAP_KEY(SDLK_MODE, Key::ALT_GR); MAP_KEY(SDLK_UP, Key::UP); MAP_KEY(SDLK_DOWN, Key::DOWN); MAP_KEY(SDLK_LEFT, Key::LEFT); MAP_KEY(SDLK_RIGHT, Key::RIGHT); MAP_KEY(SDLK_RETURN, Key::ENTER); MAP_KEY(SDLK_KP_ENTER, Key::ENTER); case SDLK_SPACE: // Special characters like ~ (tilde) ends up with the keysym.sym SDLK_SPACE which // without this check would be lost. The check is only valid on key down events in SDL. if (sdlevt.type == SDL_KEYUP || keysym.unicode == ' ') { value = Key::SPACE; } break; default: break; } if (!(keysym.mod & KMOD_NUM)) { switch (keysym.sym) { MAP_KEY(SDLK_KP0, Key::INSERT); MAP_KEY(SDLK_KP1, Key::END); MAP_KEY(SDLK_KP2, Key::DOWN); MAP_KEY(SDLK_KP3, Key::PAGE_DOWN); MAP_KEY(SDLK_KP4, Key::LEFT); MAP_KEY(SDLK_KP5, Key::INVALID_KEY); MAP_KEY(SDLK_KP6, Key::RIGHT); MAP_KEY(SDLK_KP7, Key::HOME); MAP_KEY(SDLK_KP8, Key::UP); MAP_KEY(SDLK_KP9, Key::PAGE_UP); default: break; } } keyevt.setKey(Key(value, repr)); } template<typename T> void removeListener(std::vector<T>& vec, T& listener) { vec.push_back(listener); } template<typename T> void addListener(std::vector<T>& vec, T& listener) { vec.push_back(listener); } void EventManager::addCommandListener(ICommandListener* listener) { addListener<ICommandListener*>(m_pending_commandlisteners, listener); } void EventManager::removeCommandListener(ICommandListener* listener) { removeListener<ICommandListener*>(m_pending_cldeletions, listener); } void EventManager::addKeyListener(IKeyListener* listener) { addListener<IKeyListener*>(m_pending_keylisteners, listener); } void EventManager::removeKeyListener(IKeyListener* listener) { removeListener<IKeyListener*>(m_pending_kldeletions, listener); } void EventManager::addMouseListener(IMouseListener* listener) { addListener<IMouseListener*>(m_pending_mouselisteners, listener); } void EventManager::removeMouseListener(IMouseListener* listener) { removeListener<IMouseListener*>(m_pending_mldeletions, listener); } void EventManager::addSdlEventListener(ISdlEventListener* listener) { addListener<ISdlEventListener*>(m_pending_sdleventlisteners, listener); } void EventManager::removeSdlEventListener(ISdlEventListener* listener) { removeListener<ISdlEventListener*>(m_pending_sdldeletions, listener); } void EventManager::addWidgetListener(IWidgetListener* listener) { addListener<IWidgetListener*>(m_pending_widgetlisteners, listener); } void EventManager::removeWidgetListener(IWidgetListener* listener) { removeListener<IWidgetListener*>(m_pending_wldeletions, listener); } void EventManager::dispatchCommand(Command& command) { if(!m_pending_commandlisteners.empty()) { std::vector<ICommandListener*>::iterator i = m_pending_commandlisteners.begin(); while (i != m_pending_commandlisteners.end()) { m_commandlisteners.push_back(*i); ++i; } m_pending_commandlisteners.clear(); } if (!m_pending_cldeletions.empty()) { std::vector<ICommandListener*>::iterator i = m_pending_cldeletions.begin(); while (i != m_pending_cldeletions.end()) { std::vector<ICommandListener*>::iterator j = m_commandlisteners.begin(); while (j != m_commandlisteners.end()) { if(*j == *i) { m_commandlisteners.erase(j); break; } ++j; } ++i; } m_pending_cldeletions.clear(); } std::vector<ICommandListener*>::iterator i = m_commandlisteners.begin(); while (i != m_commandlisteners.end()) { (*i)->onCommand(command); if (command.isConsumed()) { break; } ++i; } } void EventManager::dispatchKeyEvent(KeyEvent& evt) { bool nonconsumablekey = false; for (std::vector<int>::iterator it = m_nonconsumablekeys.begin(); it != m_nonconsumablekeys.end(); ++it) { if (*it == evt.getKey().getValue()) { nonconsumablekey = true; break; } } if(!m_pending_keylisteners.empty()) { std::vector<IKeyListener*>::iterator i = m_pending_keylisteners.begin(); while (i != m_pending_keylisteners.end()) { m_keylisteners.push_back(*i); ++i; } m_pending_keylisteners.clear(); } if (!m_pending_kldeletions.empty()) { std::vector<IKeyListener*>::iterator i = m_pending_kldeletions.begin(); while (i != m_pending_kldeletions.end()) { std::vector<IKeyListener*>::iterator j = m_keylisteners.begin(); while (j != m_keylisteners.end()) { if(*j == *i) { m_keylisteners.erase(j); break; } ++j; } ++i; } m_pending_kldeletions.clear(); } std::vector<IKeyListener*>::iterator i = m_keylisteners.begin(); while (i != m_keylisteners.end()) { switch (evt.getType()) { case KeyEvent::PRESSED: (*i)->keyPressed(evt); break; case KeyEvent::RELEASED: (*i)->keyReleased(evt); break; default: break; } if ((!nonconsumablekey) && (evt.isConsumed())) { break; } ++i; } } void EventManager::fillModifiers(InputEvent& evt) { evt.setAltPressed(m_keystatemap[Key::ALT_GR] | m_keystatemap[Key::LEFT_ALT] | m_keystatemap[Key::RIGHT_ALT]); evt.setControlPressed(m_keystatemap[Key::LEFT_CONTROL] | m_keystatemap[Key::RIGHT_CONTROL]); evt.setMetaPressed(m_keystatemap[Key::LEFT_META] | m_keystatemap[Key::RIGHT_META]); evt.setShiftPressed(m_keystatemap[Key::LEFT_SHIFT] | m_keystatemap[Key::RIGHT_SHIFT]); } void EventManager::dispatchMouseEvent(MouseEvent& evt) { if(!m_pending_mouselisteners.empty()) { std::vector<IMouseListener*>::iterator i = m_pending_mouselisteners.begin(); while (i != m_pending_mouselisteners.end()) { m_mouselisteners.push_back(*i); ++i; } m_pending_mouselisteners.clear(); } if (!m_pending_mldeletions.empty()) { std::vector<IMouseListener*>::iterator i = m_pending_mldeletions.begin(); while (i != m_pending_mldeletions.end()) { std::vector<IMouseListener*>::iterator j = m_mouselisteners.begin(); while (j != m_mouselisteners.end()) { if(*j == *i) { m_mouselisteners.erase(j); break; } ++j; } ++i; } m_pending_mldeletions.clear(); } std::vector<IMouseListener*>::iterator i = m_mouselisteners.begin(); while (i != m_mouselisteners.end()) { switch (evt.getType()) { case MouseEvent::MOVED: (*i)->mouseMoved(evt); break; case MouseEvent::PRESSED: (*i)->mousePressed(evt); break; case MouseEvent::RELEASED: (*i)->mouseReleased(evt); break; case MouseEvent::WHEEL_MOVED_DOWN: (*i)->mouseWheelMovedDown(evt); break; case MouseEvent::WHEEL_MOVED_UP: (*i)->mouseWheelMovedUp(evt); break; case MouseEvent::CLICKED: (*i)->mouseClicked(evt); break; case MouseEvent::ENTERED: (*i)->mouseEntered(evt); break; case MouseEvent::EXITED: (*i)->mouseExited(evt); break; case MouseEvent::DRAGGED: (*i)->mouseDragged(evt); break; default: break; } if (evt.isConsumed()) { break; } ++i; } } void EventManager::dispatchSdlEvent(SDL_Event& evt) { if (!m_pending_sdleventlisteners.empty()) { std::vector<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners.begin(); while(i != m_pending_sdleventlisteners.end()) { m_sdleventlisteners.push_back(*i); ++i; } m_pending_sdleventlisteners.clear(); } if (!m_pending_sdldeletions.empty()) { std::vector<ISdlEventListener*>::iterator i = m_pending_sdldeletions.begin(); while (i != m_pending_sdldeletions.end()) { std::vector<ISdlEventListener*>::iterator j = m_sdleventlisteners.begin(); while (j != m_sdleventlisteners.end()) { if(*j == *i) { m_sdleventlisteners.erase(j); break; } ++j; } ++i; } m_pending_sdldeletions.clear(); } std::vector<ISdlEventListener*>::iterator i = m_sdleventlisteners.begin(); while (i != m_sdleventlisteners.end()) { (*i)->onSdlEvent(evt); ++i; } } void EventManager::dispatchWidgetEvent(WidgetEvent& evt) { if(!m_pending_widgetlisteners.empty()) { std::vector<IWidgetListener*>::iterator i = m_pending_widgetlisteners.begin(); while (i != m_pending_widgetlisteners.end()) { m_widgetlisteners.push_back(*i); ++i; } m_pending_widgetlisteners.clear(); } if (!m_pending_wldeletions.empty()) { std::vector<IWidgetListener*>::iterator i = m_pending_wldeletions.begin(); while (i != m_pending_wldeletions.end()) { std::vector<IWidgetListener*>::iterator j = m_widgetlisteners.begin(); while (j != m_widgetlisteners.end()) { if(*j == *i) { m_widgetlisteners.erase(j); break; } ++j; } ++i; } m_pending_wldeletions.clear(); } std::vector<IWidgetListener*>::iterator i = m_widgetlisteners.begin(); while (i != m_widgetlisteners.end()) { (*i)->onWidgetAction(evt); if (evt.isConsumed()) { break; } ++i; } } void EventManager::onWidgetAction(WidgetEvent& evt) { dispatchWidgetEvent(evt); } void EventManager::processEvents(){ SDL_Event event; while (SDL_PollEvent(&event)) { dispatchSdlEvent(event); switch (event.type) { case SDL_QUIT: { Command cmd; cmd.setSource(this); cmd.setCommandType(CMD_QUIT_GAME); dispatchCommand(cmd); break; } case SDL_ACTIVEEVENT: break; case SDL_KEYDOWN: case SDL_KEYUP: { KeyEvent keyevt; keyevt.setSource(this); fillKeyEvent(event, keyevt); m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED); dispatchKeyEvent(keyevt); } break; case SDL_MOUSEBUTTONUP: case SDL_MOUSEMOTION: case SDL_MOUSEBUTTONDOWN: { MouseEvent mouseevt; mouseevt.setSource(this); fillMouseEvent(event, mouseevt); fillModifiers(mouseevt); if (event.type == SDL_MOUSEBUTTONDOWN) { m_mousestate |= static_cast<int>(mouseevt.getButton()); m_mostrecentbtn = mouseevt.getButton(); } else if (event.type == SDL_MOUSEBUTTONUP) { m_mousestate &= ~static_cast<int>(mouseevt.getButton()); } // fire scrollwheel events only once if (event.button.button == SDL_BUTTON_WHEELDOWN || event.button.button == SDL_BUTTON_WHEELUP) { if (event.type == SDL_MOUSEBUTTONUP) { break; } } dispatchMouseEvent(mouseevt); break; } } } pollTriggers(); } EventSourceType EventManager::getEventSourceType() { return ES_ENGINE; } void EventManager::setNonConsumableKeys(const std::vector<int>& keys) { m_nonconsumablekeys = keys; } std::vector<int> EventManager::getNonConsumableKeys() { return m_nonconsumablekeys; } void EventManager::registerTrigger(Trigger& trigger){ m_triggers.push_back(&trigger); } void EventManager::unregisterTrigger(Trigger& trigger){ m_triggers.remove(&trigger); } void EventManager::pollTriggers(){ for (std::list<Trigger*>::iterator it = m_triggers.begin(); it!=m_triggers.end(); ++it) { (*it)->pollTrigger(); } } }