1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 04:49:54 +00:00
openmw-tes3mp/apps/openmw/mwinput/inputmanager.cpp

507 lines
15 KiB
C++
Raw Normal View History

2010-07-17 17:58:15 +00:00
#include "inputmanager.hpp"
#include <openengine/input/dispatcher.hpp>
#include <openengine/input/poller.hpp>
#include <openengine/gui/events.hpp>
#include <openengine/ogre/renderer.hpp>
#include "../mwgui/window_manager.hpp"
2010-07-17 17:58:15 +00:00
#include <mangle/input/servers/ois_driver.hpp>
#include <mangle/input/filters/eventlist.hpp>
#include <libs/platform/strings.h>
#include "mouselookevent.hpp"
#include "../engine.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/world.hpp"
2010-07-17 17:58:15 +00:00
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <OgreRoot.h>
#include <OIS/OIS.h>
namespace MWInput
{
enum Actions
{
A_Quit, // Exit the program
A_Screenshot, // Take a screenshot
A_Inventory, // Toggle inventory screen
2010-07-20 19:10:51 +00:00
A_Console, // Toggle console screen
2010-07-17 17:58:15 +00:00
A_MoveLeft, // Move player left / right
A_MoveRight,
A_MoveForward, // Forward / Backward
A_MoveBackward,
A_Activate,
2011-02-03 11:16:59 +00:00
A_Use, //Use weapon, spell, etc.
A_Jump,
2011-02-03 11:16:59 +00:00
A_AutoMove, //Toggle Auto-move forward
A_Rest, //Rest
A_Journal, //Journal
A_Weapon, //Draw/Sheath weapon
A_Spell, //Ready/Unready Casting
A_AlwaysRun, //Toggle Always Run
A_CycleSpellLeft, //cycling through spells
2011-01-09 21:42:38 +00:00
A_CycleSpellRight,
A_CycleWeaponLeft,//Cycling through weapons
A_CycleWeaponRight,
2011-02-03 11:16:59 +00:00
A_ToggleSneak, //Toggles Sneak, add Push-Sneak later
A_ToggleWalk, //Toggle Walking/Running
A_Crouch,
A_QuickSave,
A_QuickLoad,
A_QuickMenu,
A_GameMenu,
2012-04-08 10:26:59 +00:00
A_ToggleWeapon,
A_ToggleSpell,
2010-07-17 17:58:15 +00:00
A_LAST // Marker for the last item
};
// Class that handles all input and key bindings for OpenMW
2012-04-06 08:39:55 +00:00
class InputImpl
2010-07-17 17:58:15 +00:00
{
OEngine::Input::DispatcherPtr disp;
OEngine::Render::OgreRenderer &ogre;
Mangle::Input::OISDriver input;
OEngine::Input::Poller poller;
MouseLookEventPtr mouse;
2010-07-17 17:58:15 +00:00
OEngine::GUI::EventInjectorPtr guiEvents;
MWWorld::Player &player;
2010-07-17 17:58:15 +00:00
MWGui::WindowManager &windows;
OMW::Engine& mEngine;
2010-07-17 17:58:15 +00:00
bool mDragDrop;
std::map<std::string, bool> mControlSwitch;
/* InputImpl Methods */
public:
void adjustMouseRegion(int width, int height)
{
input.adjustMouseClippingSize(width, height);
}
private:
2012-04-08 10:37:59 +00:00
void toggleSpell()
{
if (windows.isGuiMode()) return;
2012-07-07 18:53:19 +00:00
MWMechanics::DrawState_ state = player.getDrawState();
if (state == MWMechanics::DrawState_Weapon || state == MWMechanics::DrawState_Nothing)
{
player.setDrawState(MWMechanics::DrawState_Spell);
std::cout << "Player has now readied his hands for spellcasting!\n";
}
else
{
player.setDrawState(MWMechanics::DrawState_Nothing);
std::cout << "Player does not have any kind of attack ready now.\n";
}
2012-04-08 10:37:59 +00:00
}
void toggleWeapon()
{
if (windows.isGuiMode()) return;
2012-07-07 18:53:19 +00:00
MWMechanics::DrawState_ state = player.getDrawState();
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
{
player.setDrawState(MWMechanics::DrawState_Weapon);
std::cout << "Player is now drawing his weapon.\n";
}
else
{
player.setDrawState(MWMechanics::DrawState_Nothing);
std::cout << "Player does not have any kind of attack ready now.\n";
}
2012-04-08 10:37:59 +00:00
}
2010-07-17 17:58:15 +00:00
void screenshot()
{
mEngine.screenshot();
2012-05-01 19:54:30 +00:00
std::vector<std::string> empty;
windows.messageBox ("Screenshot saved", empty);
2010-07-17 17:58:15 +00:00
}
/* toggleInventory() is called when the user presses the button to toggle the inventory screen. */
2010-07-17 17:58:15 +00:00
void toggleInventory()
{
2012-05-23 10:23:35 +00:00
using namespace MWGui;
2010-07-17 17:58:15 +00:00
2012-05-23 10:23:35 +00:00
if (mDragDrop)
return;
2012-05-23 10:23:35 +00:00
bool gameMode = !windows.isGuiMode();
2010-07-17 17:58:15 +00:00
2012-05-23 10:23:35 +00:00
// Toggle between game mode and inventory mode
if(gameMode)
windows.pushGuiMode(GM_Inventory);
else if(windows.getMode() == GM_Inventory)
windows.popGuiMode();
2010-07-17 17:58:15 +00:00
2012-05-23 10:23:35 +00:00
// .. but don't touch any other mode.
2010-07-17 17:58:15 +00:00
}
2010-07-20 19:10:51 +00:00
// Toggle console
void toggleConsole()
{
using namespace MWGui;
if (mDragDrop)
return;
2012-05-23 10:23:35 +00:00
bool gameMode = !windows.isGuiMode();
2010-07-20 19:10:51 +00:00
// Switch to console mode no matter what mode we are currently
// in, except of course if we are already in console mode
2012-05-23 10:23:35 +00:00
if (!gameMode)
{
if (windows.getMode() == GM_Console)
windows.popGuiMode();
else
windows.pushGuiMode(GM_Console);
}
else
windows.pushGuiMode(GM_Console);
2010-07-20 19:10:51 +00:00
}
void toggleJournal()
{
2012-05-23 10:23:35 +00:00
using namespace MWGui;
2012-05-23 10:23:35 +00:00
// Toggle between game mode and journal mode
bool gameMode = !windows.isGuiMode();
2012-05-23 10:23:35 +00:00
if(gameMode)
windows.pushGuiMode(GM_Journal);
else if(windows.getMode() == GM_Journal)
windows.popGuiMode();
// .. but don't touch any other mode.
}
void activate()
{
mEngine.activate();
}
2011-01-18 14:20:36 +00:00
void toggleAutoMove()
{
if (windows.isGuiMode()) return;
2011-02-03 11:16:59 +00:00
player.setAutoMove (!player.getAutoMove());
2011-01-18 14:20:36 +00:00
}
void toggleWalking()
{
if (windows.isGuiMode()) return;
2011-02-03 11:16:59 +00:00
player.toggleRunning();
}
void toggleMainMenu()
{
if (windows.isGuiMode () && windows.getMode () == MWGui::GM_MainMenu)
windows.removeGuiMode (MWGui::GM_MainMenu);
else
windows.pushGuiMode (MWGui::GM_MainMenu);
}
2010-07-20 19:10:51 +00:00
// Exit program now button (which is disabled in GUI mode)
void exitNow()
{
2011-02-03 11:16:59 +00:00
if(!windows.isGuiMode())
MWBase::Environment::get().getWorld()->exitNow();
2010-07-20 19:10:51 +00:00
}
2010-07-17 17:58:15 +00:00
public:
InputImpl(OEngine::Render::OgreRenderer &_ogre,
MWWorld::Player &_player,
2010-07-17 17:58:15 +00:00
MWGui::WindowManager &_windows,
bool debug,
OMW::Engine& engine)
2010-07-17 17:58:15 +00:00
: ogre(_ogre),
input(ogre.getWindow(), !debug),
poller(input),
player(_player),
windows(_windows),
mEngine (engine),
mDragDrop(false)
2010-07-17 17:58:15 +00:00
{
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
2010-07-20 19:10:51 +00:00
disp->funcs.bind(A_Quit, boost::bind(&InputImpl::exitNow, this),
2010-07-17 17:58:15 +00:00
"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");
2010-07-20 19:10:51 +00:00
disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this),
"Toggle console");
disp->funcs.bind(A_Journal, boost::bind(&InputImpl::toggleJournal, this),
"Toggle journal");
disp->funcs.bind(A_Activate, boost::bind(&InputImpl::activate, this),
"Activate");
2011-01-14 15:03:45 +00:00
disp->funcs.bind(A_AutoMove, boost::bind(&InputImpl::toggleAutoMove, this),
"Auto Move");
disp->funcs.bind(A_ToggleWalk, boost::bind(&InputImpl::toggleWalking, this),
"Toggle Walk/Run");
2012-04-08 10:37:59 +00:00
disp->funcs.bind(A_ToggleWeapon,boost::bind(&InputImpl::toggleWeapon,this),
"Draw Weapon");
disp->funcs.bind(A_ToggleSpell,boost::bind(&InputImpl::toggleSpell,this),
"Ready hands");
disp->funcs.bind(A_GameMenu, boost::bind(&InputImpl::toggleMainMenu, this),
"Toggle main menu");
2010-07-17 17:58:15 +00:00
mouse = MouseLookEventPtr(new MouseLookEvent());
2010-07-17 17:58:15 +00:00
// 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);
}
2012-08-09 09:29:13 +00:00
mControlSwitch["playercontrols"] = true;
mControlSwitch["playerfighting"] = true;
mControlSwitch["playerjumping"] = true;
mControlSwitch["playerlooking"] = true;
mControlSwitch["playermagic"] = true;
mControlSwitch["playerviewswitch"] = true;
mControlSwitch["vanitymode"] = true;
2012-05-23 10:23:35 +00:00
changeInputMode(false);
2010-07-17 17:58:15 +00:00
/**********************************
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
// NOTE: These keys do not require constant polling - use in conjuction with variables in loops.
2010-07-17 17:58:15 +00:00
disp->bind(A_Quit, KC_Q);
disp->bind(A_GameMenu, KC_ESCAPE);
2010-07-17 17:58:15 +00:00
disp->bind(A_Screenshot, KC_SYSRQ);
disp->bind(A_Inventory, KC_I);
2010-07-20 19:10:51 +00:00
disp->bind(A_Console, KC_F1);
disp->bind(A_Journal, KC_J);
disp->bind(A_Activate, KC_SPACE);
disp->bind(A_AutoMove, KC_Z);
disp->bind(A_ToggleSneak, KC_X);
disp->bind(A_ToggleWalk, KC_C);
2012-04-08 10:37:59 +00:00
disp->bind(A_ToggleWeapon,KC_F);
disp->bind(A_ToggleSpell,KC_R);
2010-07-17 17:58:15 +00:00
// Key bindings for polled keys
// NOTE: These keys are constantly being polled. Only add keys that must be checked each frame.
2010-07-17 17:58:15 +00:00
// 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);
poller.bind(A_Jump, KC_E);
poller.bind(A_Crouch, KC_LCONTROL);
2010-07-17 17:58:15 +00:00
}
void setDragDrop(bool dragDrop)
{
mDragDrop = dragDrop;
}
//NOTE: Used to check for movement keys
void update ()
2010-07-17 17:58:15 +00:00
{
2011-02-03 11:16:59 +00:00
// Tell OIS to handle all input events
input.capture();
// Update windows/gui as a result of input events
// For instance this could mean opening a new window/dialog,
// by doing this after the input events are handled we
// ensure that window/gui changes appear quickly while
// avoiding that window/gui changes does not happen in
// event callbacks (which may crash)
windows.update();
// Disable movement in Gui mode
2012-05-23 10:23:35 +00:00
if (windows.isGuiMode()) return;
2011-02-03 11:16:59 +00:00
// Configure player movement according to keyboard input. Actual movement will
// be done in the physics system.
if (mControlSwitch["playercontrols"]) {
if (poller.isDown(A_MoveLeft))
{
player.setAutoMove (false);
player.setLeftRight (1);
}
else if (poller.isDown(A_MoveRight))
{
player.setAutoMove (false);
player.setLeftRight (-1);
}
else
player.setLeftRight (0);
if (poller.isDown(A_MoveForward))
{
player.setAutoMove (false);
player.setForwardBackward (1);
}
else if (poller.isDown(A_MoveBackward))
{
player.setAutoMove (false);
player.setForwardBackward (-1);
}
else
player.setForwardBackward (0);
2012-08-09 07:10:18 +00:00
if (poller.isDown(A_Jump) && mControlSwitch["playerjumping"])
player.setUpDown (1);
else if (poller.isDown(A_Crouch))
player.setUpDown (-1);
else
player.setUpDown (0);
}
2010-07-17 17:58:15 +00:00
}
// Switch between gui modes. Besides controlling the Gui windows
// this also makes sure input is directed to the right place
2012-05-23 10:23:35 +00:00
void changeInputMode(bool guiMode)
{
// Are we in GUI mode now?
2012-05-23 10:23:35 +00:00
if(guiMode)
{
// Disable mouse look
mouse->disable();
// Enable GUI events
guiEvents->enabled = true;
}
else
{
// Start mouse-looking again if allowed.
if (mControlSwitch["playerlooking"]) {
mouse->enable();
}
// Disable GUI events
guiEvents->enabled = false;
}
}
void toggleControlSwitch(std::string sw, bool value)
{
if (mControlSwitch[sw] == value) {
return;
}
/// \note 7 switches at all, if-else is relevant
if (sw == "playercontrols" && !value) {
player.setLeftRight(0);
player.setForwardBackward(0);
player.setAutoMove(false);
2012-08-09 07:10:18 +00:00
player.setUpDown(0);
} else if (sw == "playerjumping" && !value) {
/// \fixme maybe crouching at this time
player.setUpDown(0);
} else if (sw == "playerlooking") {
if (value) {
mouse->enable();
} else {
mouse->disable();
}
}
mControlSwitch[sw] = value;
}
2010-07-17 17:58:15 +00:00
};
/***CONSTRUCTOR***/
2010-07-17 17:58:15 +00:00
MWInputManager::MWInputManager(OEngine::Render::OgreRenderer &ogre,
MWWorld::Player &player,
2010-07-17 17:58:15 +00:00
MWGui::WindowManager &windows,
bool debug,
OMW::Engine& engine)
2010-07-17 17:58:15 +00:00
{
impl = new InputImpl(ogre,player,windows,debug, engine);
2010-07-17 17:58:15 +00:00
}
/***DESTRUCTOR***/
2010-07-17 17:58:15 +00:00
MWInputManager::~MWInputManager()
{
delete impl;
}
void MWInputManager::update()
{
impl->update();
}
void MWInputManager::setDragDrop(bool dragDrop)
{
impl->setDragDrop(dragDrop);
}
2012-05-23 10:23:35 +00:00
void MWInputManager::changeInputMode(bool guiMode)
{
impl->changeInputMode(guiMode);
}
void MWInputManager::processChangedSettings(const Settings::CategorySettingVector& changed)
{
bool changeRes = false;
for (Settings::CategorySettingVector::const_iterator it = changed.begin();
it != changed.end(); ++it)
{
if (it->first == "Video" && (
it->second == "resolution x"
|| it->second == "resolution y"))
changeRes = true;
}
if (changeRes)
impl->adjustMouseRegion(Settings::Manager::getInt("resolution x", "Video"), Settings::Manager::getInt("resolution y", "Video"));
}
void MWInputManager::toggleControlSwitch(std::string sw, bool value)
{
impl->toggleControlSwitch(sw, value);
}
2010-07-17 17:58:15 +00:00
}