diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 473291535..4c1bedb49 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -23,7 +23,9 @@ set(GAMEREND_HEADER mwrender/sky.hpp) source_group(apps\\openmw\\mwrender FILES ${GAMEREND} ${GAMEREND_HEADER}) -# set(GAMEINPUT) +set(GAMEINPUT + mwinput/inputmanager.cpp +) set(GAMEINPUT_HEADER mwinput/inputmanager.hpp) source_group(apps\\openmw\\mwinput FILES ${GAMEINPUT} ${GAMEINPUT_HEADER}) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index e46e58d94..0b336e26b 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -24,6 +24,8 @@ #include "mwworld/ptr.hpp" #include "mwworld/environment.hpp" +#include + void OMW::Engine::executeLocalScripts() { for (MWWorld::World::ScriptList::const_iterator iter ( diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp new file mode 100644 index 000000000..511c2519e --- /dev/null +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -0,0 +1,250 @@ +#include "inputmanager.hpp" + +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include "../mwrender/playerpos.hpp" + +#include +#include +#include +#include + +namespace MWInput +{ + enum Actions + { + A_Quit, // Exit the program + + A_Screenshot, // Take a screenshot + + A_Inventory, // Toggle inventory screen + + 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 InputImpl : public Ogre::FrameListener + { + OEngine::Input::DispatcherPtr disp; + OEngine::Render::OgreRenderer &ogre; + OEngine::Render::ExitListener exit; + Mangle::Input::OISDriver input; + OEngine::Input::Poller poller; + OEngine::Render::MouseLookEventPtr mouse; + OEngine::GUI::EventInjectorPtr guiEvents; + MWRender::PlayerPos &player; + MWGui::WindowManager &windows; + + // Count screenshots. + 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); + } + + // Switch between gui modes. Besides controlling the Gui windows + // this also makes sure input is directed to the right place + void setGuiMode(MWGui::GuiMode mode) + { + // Tell the GUI what to show (this also takes care of the mouse + // pointer) + windows.setMode(mode); + + // Are we in GUI mode now? + if(windows.isGuiMode()) + { + // Disable mouse look + mouse->setCamera(NULL); + + // Enable GUI events + guiEvents->enabled = true; + } + else + { + // Start mouse-looking again. TODO: This should also allow + // for other ways to disable mouselook, like paralyzation. + mouse->setCamera(player.getCamera()); + + // Disable GUI events + guiEvents->enabled = false; + } + } + + // Called when the user presses the button to toggle the inventory + // screen. + void toggleInventory() + { + using namespace MWGui; + + GuiMode mode = windows.getMode(); + + // Toggle between game mode and inventory mode + if(mode == GM_Game) + setGuiMode(GM_Inventory); + else if(mode == GM_Inventory) + setGuiMode(GM_Game); + + // .. but don't touch any other mode. + } + + public: + InputImpl(OEngine::Render::OgreRenderer &_ogre, + MWRender::PlayerPos &_player, + MWGui::WindowManager &_windows, + bool debug) + : ogre(_ogre), + exit(ogre.getWindow()), + input(ogre.getWindow(), !debug), + poller(input), + player(_player), + windows(_windows), + shotCount(0) + { + using namespace OEngine::Input; + using namespace OEngine::Render; + using namespace OEngine::GUI; + using namespace Mangle::Input; + using namespace OIS; + + disp = DispatcherPtr(new Dispatcher(A_LAST)); + + // Bind MW-specific functions + disp->funcs.bind(A_Quit, boost::bind(&ExitListener::exitNow, &exit), + "Quit program"); + disp->funcs.bind(A_Screenshot, boost::bind(&InputImpl::screenshot, this), + "Screenshot"); + disp->funcs.bind(A_Inventory, boost::bind(&InputImpl::toggleInventory, this), + "Toggle inventory screen"); + + + // Add the exit listener + ogre.getRoot()->addFrameListener(&exit); + // Add ourselves as a frame listener to catch movement keys + ogre.getRoot()->addFrameListener(this); + + // Set up the mouse handler and tell it about the player camera + mouse = MouseLookEventPtr(new MouseLookEvent(player.getCamera())); + + // This event handler pumps events into MyGUI + guiEvents = EventInjectorPtr(new EventInjector(windows.getGui())); + + // Hook 'mouse' and 'disp' up as event handlers into 'input' + // (the OIS driver and event source.) We do this through an + // EventList which dispatches the event to multiple handlers for + // us. + { + EventList *lst = new EventList; + input.setEvent(EventPtr(lst)); + lst->add(mouse,Event::EV_MouseMove); + lst->add(disp,Event::EV_KeyDown); + lst->add(guiEvents,Event::EV_ALL); + } + + // Start out in game mode + setGuiMode(MWGui::GM_Game); + + /********************************** + Key binding section + + The rest of this function has hard coded key bindings, and is + intended to be replaced by user defined bindings later. + **********************************/ + + // Key bindings for keypress events + + disp->bind(A_Quit, KC_Q); + disp->bind(A_Quit, KC_ESCAPE); + disp->bind(A_Screenshot, KC_SYSRQ); + disp->bind(A_Inventory, KC_I); + + // 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) + { + // Tell OIS to handle all input events + input.capture(); + + // Disable movement in Gui mode + if(windows.isGuiMode()) return true; + + 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; + } + }; + + MWInputManager::MWInputManager(OEngine::Render::OgreRenderer &ogre, + MWRender::PlayerPos &player, + MWGui::WindowManager &windows, + bool debug) + { + impl = new InputImpl(ogre,player,windows,debug); + } + + MWInputManager::~MWInputManager() + { + delete impl; + } +} diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index 59b5ad500..094b848ee 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -1,239 +1,44 @@ #ifndef _MWINPUT_MWINPUTMANAGER_H #define _MWINPUT_MWINPUTMANAGER_H -#include -#include +namespace OEngine +{ + namespace Render + { + class OgreRenderer; + } +} -#include +namespace MWRender +{ + class PlayerPos; +} -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include "../mwrender/playerpos.hpp" - -#include - -#include +namespace MWGui +{ + class WindowManager; +} namespace MWInput { - enum Actions - { - A_Quit, // Exit the program + // Forward declaration of the real implementation. + class InputImpl; - A_Screenshot, // Take a screenshot + /* Class that handles all input and key bindings for OpenMW. - A_Inventory, // Toggle inventory screen - - 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 + This class is just an interface. All the messy details are in + inputmanager.cpp. + */ + struct MWInputManager { - OEngine::Input::DispatcherPtr disp; - OEngine::Render::OgreRenderer &ogre; - OEngine::Render::ExitListener exit; - Mangle::Input::OISDriver input; - OEngine::Input::Poller poller; - OEngine::Render::MouseLookEventPtr mouse; - OEngine::GUI::EventInjectorPtr guiEvents; - MWRender::PlayerPos &player; - MWGui::WindowManager &windows; - - // Count screenshots. - 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); - } - - // Switch between gui modes. Besides controlling the Gui windows - // this also makes sure input is directed to the right place - void setGuiMode(MWGui::GuiMode mode) - { - // Tell the GUI what to show (this also takes care of the mouse - // pointer) - windows.setMode(mode); - - // Are we in GUI mode now? - if(windows.isGuiMode()) - { - // Disable mouse look - mouse->setCamera(NULL); - - // Enable GUI events - guiEvents->enabled = true; - } - else - { - // Start mouse-looking again. TODO: This should also allow - // for other ways to disable mouselook, like paralyzation. - mouse->setCamera(player.getCamera()); - - // Disable GUI events - guiEvents->enabled = false; - } - } - - // Called when the user presses the button to toggle the inventory - // screen. - void toggleInventory() - { - using namespace MWGui; - - GuiMode mode = windows.getMode(); - - // Toggle between game mode and inventory mode - if(mode == GM_Game) - setGuiMode(GM_Inventory); - else if(mode == GM_Inventory) - setGuiMode(GM_Game); - - // .. but don't touch any other mode. - } + InputImpl *impl; public: MWInputManager(OEngine::Render::OgreRenderer &_ogre, MWRender::PlayerPos &_player, MWGui::WindowManager &_windows, - bool debug) - : ogre(_ogre), - exit(ogre.getWindow()), - input(ogre.getWindow(), !debug), - poller(input), - player(_player), - windows(_windows), - shotCount(0) - { - using namespace OEngine::Input; - using namespace OEngine::Render; - using namespace OEngine::GUI; - using namespace Mangle::Input; - using namespace OIS; - - disp = DispatcherPtr(new Dispatcher(A_LAST)); - - // Bind MW-specific functions - disp->funcs.bind(A_Quit, boost::bind(&ExitListener::exitNow, &exit), - "Quit program"); - disp->funcs.bind(A_Screenshot, boost::bind(&MWInputManager::screenshot, this), - "Screenshot"); - disp->funcs.bind(A_Inventory, boost::bind(&MWInputManager::toggleInventory, this), - "Toggle inventory screen"); - - - // Add the exit listener - ogre.getRoot()->addFrameListener(&exit); - // Add ourselves as a frame listener to catch movement keys - ogre.getRoot()->addFrameListener(this); - - // Set up the mouse handler and tell it about the player camera - mouse = MouseLookEventPtr(new MouseLookEvent(player.getCamera())); - - // This event handler pumps events into MyGUI - guiEvents = EventInjectorPtr(new EventInjector(windows.getGui())); - - // Hook 'mouse' and 'disp' up as event handlers into 'input' - // (the OIS driver and event source.) We do this through an - // EventList which dispatches the event to multiple handlers for - // us. - { - EventList *lst = new EventList; - input.setEvent(EventPtr(lst)); - lst->add(mouse,Event::EV_MouseMove); - lst->add(disp,Event::EV_KeyDown); - lst->add(guiEvents,Event::EV_ALL); - } - - // Start out in game mode - setGuiMode(MWGui::GM_Game); - - /********************************** - Key binding section - - The rest of this function has hard coded key bindings, and is - intended to be replaced by user defined bindings later. - **********************************/ - - // Key bindings for keypress events - - disp->bind(A_Quit, KC_Q); - disp->bind(A_Quit, KC_ESCAPE); - disp->bind(A_Screenshot, KC_SYSRQ); - disp->bind(A_Inventory, KC_I); - - // 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) - { - // Tell OIS to handle all input events - input.capture(); - - // Disable movement in Gui mode - if(windows.isGuiMode()) return true; - - 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; - } + bool debug); + ~MWInputManager(); }; } #endif