#ifndef _MWINPUT_MWINPUTMANAGER_H #define _MWINPUT_MWINPUTMANAGER_H #include "components/engine/input/listener.hpp" #include "components/engine/input/dispatcher.hpp" #include "components/engine/input/poller.hpp" #include "boost/bind.hpp" #include "apps/openmw/mwrender/playerpos.hpp" #include "libs/platform/strings.h" namespace MWInput { enum Actions { A_Quit, // Exit the program A_Screenshot, // Take a screenshot A_MoveLeft, // Move player left / right A_MoveRight, A_MoveUp, // Move up / down A_MoveDown, A_MoveForward, // Forward / Backward A_MoveBackward, A_LAST // Marker for the last item }; // Class that handles all input and key bindings for OpenMW class MWInputManager : public Ogre::FrameListener { // Note: the order here is important. The OISManager must be // initialized before poller and listener. Input::Dispatcher disp; Render::OgreRenderer &ogre; Input::OISManager input; Input::Poller poller; Input::InputListener listener; MWRender::PlayerPos &player; // Count screenshots. TODO: We should move this functionality to // OgreRender or somewhere else. int shotCount; // Write screenshot to file. void screenshot() { // Find the first unused filename. // char buf[50]; do { snprintf(buf, 50, "screenshot%03d.png", shotCount++); } while (boost::filesystem::exists(buf)); ogre.screenshot(buf); } public: MWInputManager(Render::OgreRenderer &_ogre, MWRender::PlayerPos &_player, bool debug) : disp(A_LAST), ogre(_ogre), input(_ogre, debug), poller(input), listener(_ogre, input, disp), player(_player), shotCount(0) { using namespace Input; using namespace OIS; // Bind MW-specific functions disp.funcs.bind(A_Quit, boost::bind(&InputListener::exitNow, &listener), "Quit program"); disp.funcs.bind(A_Screenshot, boost::bind(&MWInputManager::screenshot, this), "Screenshot"); // Add ourselves as a frame listener, to catch movement keys ogre.getRoot()->addFrameListener(this); // Tell the input listener about the camera listener.setCamera(player.getCamera()); // Key bindings disp.bind(KC_Q, A_Quit); disp.bind(KC_ESCAPE, A_Quit); disp.bind(KC_SYSRQ, A_Screenshot); // Key bindings for polled keys // Arrow keys poller.bind(A_MoveLeft, KC_LEFT); poller.bind(A_MoveRight, KC_RIGHT); poller.bind(A_MoveForward, KC_UP); poller.bind(A_MoveBackward, KC_DOWN); // WASD keys poller.bind(A_MoveLeft, KC_A); poller.bind(A_MoveRight, KC_D); poller.bind(A_MoveForward, KC_W); poller.bind(A_MoveBackward, KC_S); // Use shift and ctrl for up and down poller.bind(A_MoveUp, KC_LSHIFT); poller.bind(A_MoveDown, KC_LCONTROL); } // Used to check for movement keys bool frameStarted(const Ogre::FrameEvent &evt) { float speed = 300 * evt.timeSinceLastFrame; float moveX = 0, moveY = 0, moveZ = 0; if(poller.isDown(A_MoveLeft)) moveX -= speed; if(poller.isDown(A_MoveRight)) moveX += speed; if(poller.isDown(A_MoveForward)) moveZ -= speed; if(poller.isDown(A_MoveBackward)) moveZ += speed; // TODO: These should be enabled for floating modes (like // swimming and levitation) and disabled for everything else. if(poller.isDown(A_MoveUp)) moveY += speed; if(poller.isDown(A_MoveDown)) moveY -= speed; if(moveX != 0 || moveY != 0 || moveZ != 0) player.moveRel(moveX, moveY, moveZ); return true; } }; } #endif