You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/apps/openmw/mwinput/actionmanager.cpp

391 lines
13 KiB
C++

#include "actionmanager.hpp"
#include <MyGUI_InputManager.h>
#include <SDL_keyboard.h>
#include <components/settings/settings.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/inputmanager.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/statemanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/globals.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/actorutil.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "actions.hpp"
#include "bindingsmanager.hpp"
namespace MWInput
{
ActionManager::ActionManager(BindingsManager* bindingsManager,
osgViewer::ScreenCaptureHandler::CaptureOperation* screenCaptureOperation,
osg::ref_ptr<osgViewer::Viewer> viewer, osg::ref_ptr<osgViewer::ScreenCaptureHandler> screenCaptureHandler)
: mBindingsManager(bindingsManager)
, mViewer(std::move(viewer))
, mScreenCaptureHandler(std::move(screenCaptureHandler))
, mScreenCaptureOperation(screenCaptureOperation)
, mTimeIdle(0.f)
{
}
void ActionManager::update(float dt)
{
if (mBindingsManager->actionIsActive(A_MoveForward) || mBindingsManager->actionIsActive(A_MoveBackward)
|| mBindingsManager->actionIsActive(A_MoveLeft) || mBindingsManager->actionIsActive(A_MoveRight)
|| mBindingsManager->actionIsActive(A_Jump) || mBindingsManager->actionIsActive(A_Sneak)
|| mBindingsManager->actionIsActive(A_TogglePOV) || mBindingsManager->actionIsActive(A_ZoomIn)
|| mBindingsManager->actionIsActive(A_ZoomOut))
{
resetIdleTime();
}
else
mTimeIdle += dt;
}
void ActionManager::resetIdleTime()
{
mTimeIdle = 0.f;
}
void ActionManager::executeAction(int action)
{
MWBase::Environment::get().getLuaManager()->inputEvent({ MWBase::LuaManager::InputEvent::Action, action });
const auto inputManager = MWBase::Environment::get().getInputManager();
const auto windowManager = MWBase::Environment::get().getWindowManager();
// trigger action activated
switch (action)
{
case A_GameMenu:
toggleMainMenu();
break;
case A_Screenshot:
screenshot();
break;
case A_Inventory:
toggleInventory();
break;
case A_Console:
toggleConsole();
break;
case A_Activate:
inputManager->resetIdleTime();
activate();
break;
case A_MoveLeft:
case A_MoveRight:
case A_MoveForward:
case A_MoveBackward:
handleGuiArrowKey(action);
break;
case A_Journal:
toggleJournal();
break;
case A_Rest:
rest();
break;
case A_QuickKey1:
quickKey(1);
break;
case A_QuickKey2:
quickKey(2);
break;
case A_QuickKey3:
quickKey(3);
break;
case A_QuickKey4:
quickKey(4);
break;
case A_QuickKey5:
quickKey(5);
break;
case A_QuickKey6:
quickKey(6);
break;
case A_QuickKey7:
quickKey(7);
break;
case A_QuickKey8:
quickKey(8);
break;
case A_QuickKey9:
quickKey(9);
break;
case A_QuickKey10:
quickKey(10);
break;
case A_QuickKeysMenu:
showQuickKeysMenu();
break;
case A_ToggleHUD:
windowManager->toggleHud();
break;
case A_ToggleDebug:
windowManager->toggleDebugWindow();
break;
case A_TogglePostProcessorHUD:
windowManager->togglePostProcessorHud();
break;
case A_QuickSave:
quickSave();
break;
case A_QuickLoad:
quickLoad();
break;
case A_CycleSpellLeft:
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Magic))
MWBase::Environment::get().getWindowManager()->cycleSpell(false);
break;
case A_CycleSpellRight:
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Magic))
MWBase::Environment::get().getWindowManager()->cycleSpell(true);
break;
case A_CycleWeaponLeft:
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Inventory))
MWBase::Environment::get().getWindowManager()->cycleWeapon(false);
break;
case A_CycleWeaponRight:
if (checkAllowedToUseItems() && windowManager->isAllowed(MWGui::GW_Inventory))
MWBase::Environment::get().getWindowManager()->cycleWeapon(true);
break;
}
}
bool ActionManager::checkAllowedToUseItems() const
{
MWWorld::Ptr player = MWMechanics::getPlayer();
if (player.getClass().getNpcStats(player).isWerewolf())
{
// Cannot use items or spells while in werewolf form
MWBase::Environment::get().getWindowManager()->messageBox("#{sWerewolfRefusal}");
return false;
}
return true;
}
void ActionManager::screenshot()
{
const std::string& settingStr = Settings::Manager::getString("screenshot type", "Video");
bool regularScreenshot = settingStr.empty() || settingStr == "regular";
if (regularScreenshot)
{
mScreenCaptureHandler->setFramesToCapture(1);
mScreenCaptureHandler->captureNextFrame(*mViewer);
}
else
{
osg::ref_ptr<osg::Image> screenshot(new osg::Image);
if (MWBase::Environment::get().getWorld()->screenshot360(screenshot.get()))
{
(*mScreenCaptureOperation)(*(screenshot.get()), 0);
// FIXME: mScreenCaptureHandler->getCaptureOperation() causes crash for some reason
}
}
}
void ActionManager::toggleMainMenu()
{
if (MyGUI::InputManager::getInstance().isModalAny())
{
MWBase::Environment::get().getWindowManager()->exitCurrentModal();
return;
}
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
{
MWBase::Environment::get().getWindowManager()->toggleConsole();
return;
}
if (MWBase::Environment::get().getWindowManager()->isPostProcessorHudVisible())
{
MWBase::Environment::get().getWindowManager()->togglePostProcessorHud();
return;
}
if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) // No open GUIs, open up the MainMenu
{
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_MainMenu);
}
else // Close current GUI
{
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
}
}
void ActionManager::quickLoad()
{
if (!MyGUI::InputManager::getInstance().isModalAny())
MWBase::Environment::get().getStateManager()->quickLoad();
}
void ActionManager::quickSave()
{
if (!MyGUI::InputManager::getInstance().isModalAny())
MWBase::Environment::get().getStateManager()->quickSave();
}
void ActionManager::rest()
{
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
return;
if (!MWBase::Environment::get().getWindowManager()->getRestEnabled()
|| MWBase::Environment::get().getWindowManager()->isGuiMode())
return;
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Rest); // Open rest GUI
}
void ActionManager::toggleInventory()
{
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
return;
if (MyGUI::InputManager::getInstance().isModalAny())
return;
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
return;
// Toggle between game mode and inventory mode
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Inventory);
else
{
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
if (mode == MWGui::GM_Inventory || mode == MWGui::GM_Container)
MWBase::Environment::get().getWindowManager()->popGuiMode();
}
// .. but don't touch any other mode, except container.
}
void ActionManager::toggleConsole()
{
if (MyGUI::InputManager::getInstance().isModalAny())
return;
MWBase::Environment::get().getWindowManager()->toggleConsole();
}
void ActionManager::toggleJournal()
{
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
return;
if (MyGUI::InputManager::getInstance().isModalAny())
return;
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
if (windowManager->getMode() != MWGui::GM_Journal && windowManager->getMode() != MWGui::GM_MainMenu
&& windowManager->getMode() != MWGui::GM_Settings && windowManager->getJournalAllowed())
{
windowManager->pushGuiMode(MWGui::GM_Journal);
}
else if (windowManager->containsMode(MWGui::GM_Journal))
{
windowManager->removeGuiMode(MWGui::GM_Journal);
}
}
void ActionManager::quickKey(int index)
{
if (!MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols")
|| !MWBase::Environment::get().getInputManager()->getControlSwitch("playerfighting")
|| !MWBase::Environment::get().getInputManager()->getControlSwitch("playermagic"))
return;
if (!checkAllowedToUseItems())
return;
if (MWBase::Environment::get().getWorld()->getGlobalFloat(MWWorld::Globals::sCharGenState) != -1)
return;
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
MWBase::Environment::get().getWindowManager()->activateQuickKey(index);
}
void ActionManager::showQuickKeysMenu()
{
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_QuickKeysMenu)
{
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
return;
}
if (MWBase::Environment::get().getWorld()->getGlobalFloat(MWWorld::Globals::sCharGenState) != -1)
return;
if (!checkAllowedToUseItems())
return;
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_QuickKeysMenu);
}
void ActionManager::activate()
{
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
bool joystickUsed = MWBase::Environment::get().getInputManager()->joystickLastUsed();
if (!SDL_IsTextInputActive() && !mBindingsManager->isLeftOrRightButton(A_Activate, joystickUsed))
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Return, 0, false);
}
else if (MWBase::Environment::get().getInputManager()->getControlSwitch("playercontrols"))
{
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
player.activate();
}
}
bool ActionManager::isSneaking() const
{
const MWBase::Environment& env = MWBase::Environment::get();
return env.getMechanicsManager()->isSneaking(env.getWorld()->getPlayer().getPlayer());
}
void ActionManager::handleGuiArrowKey(int action)
{
bool joystickUsed = MWBase::Environment::get().getInputManager()->joystickLastUsed();
// This is currently keyboard-specific code
// TODO: see if GUI controls can be refactored into a single function
if (joystickUsed)
return;
if (SDL_IsTextInputActive())
return;
if (mBindingsManager->isLeftOrRightButton(action, joystickUsed))
return;
MyGUI::KeyCode key;
switch (action)
{
case A_MoveLeft:
key = MyGUI::KeyCode::ArrowLeft;
break;
case A_MoveRight:
key = MyGUI::KeyCode::ArrowRight;
break;
case A_MoveForward:
key = MyGUI::KeyCode::ArrowUp;
break;
case A_MoveBackward:
default:
key = MyGUI::KeyCode::ArrowDown;
break;
}
MWBase::Environment::get().getWindowManager()->injectKeyPress(key, 0, false);
}
}