mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 11:09:43 +00:00
Merge branch 'support_controller_gyro' into 'master'
Support controller gyro Closes #6557 See merge request OpenMW/openmw!1571
This commit is contained in:
commit
fac47ce0b5
11 changed files with 254 additions and 145 deletions
|
@ -27,7 +27,7 @@ add_openmw_dir (mwrender
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
actions actionmanager bindingsmanager controllermanager controlswitch
|
actions actionmanager bindingsmanager controllermanager controlswitch
|
||||||
inputmanagerimp mousemanager keyboardmanager sensormanager
|
inputmanagerimp mousemanager keyboardmanager sensormanager gyromanager
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwgui
|
add_openmw_dir (mwgui
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <MyGUI_InputManager.h>
|
#include <MyGUI_InputManager.h>
|
||||||
#include <MyGUI_Widget.h>
|
#include <MyGUI_Widget.h>
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/sdlutil/sdlmappings.hpp>
|
#include <components/sdlutil/sdlmappings.hpp>
|
||||||
|
|
||||||
|
@ -32,6 +34,7 @@ namespace MWInput
|
||||||
, mActionManager(actionManager)
|
, mActionManager(actionManager)
|
||||||
, mMouseManager(mouseManager)
|
, mMouseManager(mouseManager)
|
||||||
, mJoystickEnabled (Settings::Manager::getBool("enable controller", "Input"))
|
, mJoystickEnabled (Settings::Manager::getBool("enable controller", "Input"))
|
||||||
|
, mGyroAvailable(false)
|
||||||
, mGamepadCursorSpeed(Settings::Manager::getFloat("gamepad cursor speed", "Input"))
|
, mGamepadCursorSpeed(Settings::Manager::getFloat("gamepad cursor speed", "Input"))
|
||||||
, mSneakToggleShortcutTimer(0.f)
|
, mSneakToggleShortcutTimer(0.f)
|
||||||
, mGamepadGuiCursorEnabled(true)
|
, mGamepadGuiCursorEnabled(true)
|
||||||
|
@ -287,6 +290,7 @@ namespace MWInput
|
||||||
void ControllerManager::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg)
|
void ControllerManager::controllerAdded(int deviceID, const SDL_ControllerDeviceEvent &arg)
|
||||||
{
|
{
|
||||||
mBindingsManager->controllerAdded(deviceID, arg);
|
mBindingsManager->controllerAdded(deviceID, arg);
|
||||||
|
enableGyroSensor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerManager::controllerRemoved(const SDL_ControllerDeviceEvent &arg)
|
void ControllerManager::controllerRemoved(const SDL_ControllerDeviceEvent &arg)
|
||||||
|
@ -399,4 +403,34 @@ namespace MWInput
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ControllerManager::enableGyroSensor()
|
||||||
|
{
|
||||||
|
mGyroAvailable = false;
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||||
|
SDL_GameController* cntrl = mBindingsManager->getControllerOrNull();
|
||||||
|
if (!cntrl)
|
||||||
|
return;
|
||||||
|
if (!SDL_GameControllerHasSensor(cntrl, SDL_SENSOR_GYRO))
|
||||||
|
return;
|
||||||
|
if (SDL_GameControllerSetSensorEnabled(cntrl, SDL_SENSOR_GYRO, SDL_TRUE) < 0)
|
||||||
|
return;
|
||||||
|
mGyroAvailable = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControllerManager::isGyroAvailable() const
|
||||||
|
{
|
||||||
|
return mGyroAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<float, 3> ControllerManager::getGyroValues() const
|
||||||
|
{
|
||||||
|
float gyro[3] = { 0.f };
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||||
|
SDL_GameController* cntrl = mBindingsManager->getControllerOrNull();
|
||||||
|
if (cntrl && mGyroAvailable)
|
||||||
|
SDL_GameControllerGetSensorData(cntrl, SDL_SENSOR_GYRO, gyro, 3);
|
||||||
|
#endif
|
||||||
|
return std::array<float, 3>({gyro[0], gyro[1], gyro[2]});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,16 +44,22 @@ namespace MWInput
|
||||||
float getAxisValue(SDL_GameControllerAxis axis) const; // returns value in range [-1, 1]
|
float getAxisValue(SDL_GameControllerAxis axis) const; // returns value in range [-1, 1]
|
||||||
bool isButtonPressed(SDL_GameControllerButton button) const;
|
bool isButtonPressed(SDL_GameControllerButton button) const;
|
||||||
|
|
||||||
|
bool isGyroAvailable() const;
|
||||||
|
std::array<float, 3> getGyroValues() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Return true if GUI consumes input.
|
// Return true if GUI consumes input.
|
||||||
bool gamepadToGuiControl(const SDL_ControllerButtonEvent &arg);
|
bool gamepadToGuiControl(const SDL_ControllerButtonEvent &arg);
|
||||||
bool gamepadToGuiControl(const SDL_ControllerAxisEvent &arg);
|
bool gamepadToGuiControl(const SDL_ControllerAxisEvent &arg);
|
||||||
|
|
||||||
|
void enableGyroSensor();
|
||||||
|
|
||||||
BindingsManager* mBindingsManager;
|
BindingsManager* mBindingsManager;
|
||||||
ActionManager* mActionManager;
|
ActionManager* mActionManager;
|
||||||
MouseManager* mMouseManager;
|
MouseManager* mMouseManager;
|
||||||
|
|
||||||
bool mJoystickEnabled;
|
bool mJoystickEnabled;
|
||||||
|
bool mGyroAvailable;
|
||||||
float mGamepadCursorSpeed;
|
float mGamepadCursorSpeed;
|
||||||
float mSneakToggleShortcutTimer;
|
float mSneakToggleShortcutTimer;
|
||||||
bool mGamepadGuiCursorEnabled;
|
bool mGamepadGuiCursorEnabled;
|
||||||
|
|
101
apps/openmw/mwinput/gyromanager.cpp
Normal file
101
apps/openmw/mwinput/gyromanager.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
#include "gyromanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
GyroManager::GyroscopeAxis GyroManager::gyroscopeAxisFromString(std::string_view s)
|
||||||
|
{
|
||||||
|
if (s == "x")
|
||||||
|
return GyroscopeAxis::X;
|
||||||
|
else if (s == "y")
|
||||||
|
return GyroscopeAxis::Y;
|
||||||
|
else if (s == "z")
|
||||||
|
return GyroscopeAxis::Z;
|
||||||
|
else if (s == "-x")
|
||||||
|
return GyroscopeAxis::Minus_X;
|
||||||
|
else if (s == "-y")
|
||||||
|
return GyroscopeAxis::Minus_Y;
|
||||||
|
else if (s == "-z")
|
||||||
|
return GyroscopeAxis::Minus_Z;
|
||||||
|
|
||||||
|
return GyroscopeAxis::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
GyroManager::GyroManager()
|
||||||
|
: mEnabled(Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
, mGuiCursorEnabled(true)
|
||||||
|
, mSensitivityH(Settings::Manager::getFloat("gyro horizontal sensitivity", "Input"))
|
||||||
|
, mSensitivityV(Settings::Manager::getFloat("gyro vertical sensitivity", "Input"))
|
||||||
|
, mInputThreshold(Settings::Manager::getFloat("gyro input threshold", "Input"))
|
||||||
|
, mAxisH(gyroscopeAxisFromString(Settings::Manager::getString("gyro horizontal axis", "Input")))
|
||||||
|
, mAxisV(gyroscopeAxisFromString(Settings::Manager::getString("gyro vertical axis", "Input")))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void GyroManager::update(float dt, std::array<float, 3> values) const
|
||||||
|
{
|
||||||
|
if (!mGuiCursorEnabled)
|
||||||
|
{
|
||||||
|
float gyroH = getAxisValue(mAxisH, values);
|
||||||
|
float gyroV = getAxisValue(mAxisV, values);
|
||||||
|
|
||||||
|
if (gyroH == 0.f && gyroV == 0.f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float rot[3];
|
||||||
|
rot[0] = -gyroV * dt * mSensitivityV;
|
||||||
|
rot[1] = 0.0f;
|
||||||
|
rot[2] = -gyroH * dt * mSensitivityH;
|
||||||
|
|
||||||
|
// Only actually turn player when we're not in vanity mode
|
||||||
|
bool playerLooking = MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking");
|
||||||
|
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && playerLooking)
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.yaw(-rot[2]);
|
||||||
|
player.pitch(-rot[0]);
|
||||||
|
}
|
||||||
|
else if (!playerLooking)
|
||||||
|
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GyroManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
||||||
|
{
|
||||||
|
for (const auto& setting : changed)
|
||||||
|
{
|
||||||
|
if (setting.first != "Input")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (setting.second == "enable gyroscope")
|
||||||
|
mEnabled = Settings::Manager::getBool("enable gyroscope", "Input");
|
||||||
|
else if (setting.second == "gyro horizontal sensitivity")
|
||||||
|
mSensitivityH = Settings::Manager::getFloat("gyro horizontal sensitivity", "Input");
|
||||||
|
else if (setting.second == "gyro vertical sensitivity")
|
||||||
|
mSensitivityV = Settings::Manager::getFloat("gyro vertical sensitivity", "Input");
|
||||||
|
else if (setting.second == "gyro input threshold")
|
||||||
|
mInputThreshold = Settings::Manager::getFloat("gyro input threshold", "Input");
|
||||||
|
else if (setting.second == "gyro horizontal axis")
|
||||||
|
mAxisH = gyroscopeAxisFromString(Settings::Manager::getString("gyro horizontal axis", "Input"));
|
||||||
|
else if (setting.second == "gyro vertical axis")
|
||||||
|
mAxisV = gyroscopeAxisFromString(Settings::Manager::getString("gyro vertical axis", "Input"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float GyroManager::getAxisValue(GyroscopeAxis axis, std::array<float, 3> values) const
|
||||||
|
{
|
||||||
|
if (axis == GyroscopeAxis::Unknown)
|
||||||
|
return 0;
|
||||||
|
float value = values[std::abs(axis) - 1];
|
||||||
|
if (axis < 0)
|
||||||
|
value *= -1;
|
||||||
|
if (std::abs(value) <= mInputThreshold)
|
||||||
|
value = 0;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
47
apps/openmw/mwinput/gyromanager.hpp
Normal file
47
apps/openmw/mwinput/gyromanager.hpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef MWINPUT_GYROMANAGER
|
||||||
|
#define MWINPUT_GYROMANAGER
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class GyroManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GyroManager();
|
||||||
|
|
||||||
|
bool isEnabled() const { return mEnabled; }
|
||||||
|
|
||||||
|
void update(float dt, std::array<float, 3> values) const;
|
||||||
|
|
||||||
|
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
|
void setGuiCursorEnabled(bool enabled) { mGuiCursorEnabled = enabled; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum GyroscopeAxis
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
X = 1,
|
||||||
|
Y = 2,
|
||||||
|
Z = 3,
|
||||||
|
Minus_X = -1,
|
||||||
|
Minus_Y = -2,
|
||||||
|
Minus_Z = -3
|
||||||
|
};
|
||||||
|
|
||||||
|
static GyroscopeAxis gyroscopeAxisFromString(std::string_view s);
|
||||||
|
|
||||||
|
bool mEnabled;
|
||||||
|
bool mGuiCursorEnabled;
|
||||||
|
float mSensitivityH;
|
||||||
|
float mSensitivityV;
|
||||||
|
float mInputThreshold;
|
||||||
|
GyroscopeAxis mAxisH;
|
||||||
|
GyroscopeAxis mAxisV;
|
||||||
|
|
||||||
|
float getAxisValue(GyroscopeAxis axis, std::array<float, 3> values) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MWINPUT_GYROMANAGER
|
|
@ -19,6 +19,7 @@
|
||||||
#include "keyboardmanager.hpp"
|
#include "keyboardmanager.hpp"
|
||||||
#include "mousemanager.hpp"
|
#include "mousemanager.hpp"
|
||||||
#include "sensormanager.hpp"
|
#include "sensormanager.hpp"
|
||||||
|
#include "gyromanager.hpp"
|
||||||
|
|
||||||
namespace MWInput
|
namespace MWInput
|
||||||
{
|
{
|
||||||
|
@ -51,6 +52,8 @@ namespace MWInput
|
||||||
|
|
||||||
mSensorManager = new SensorManager();
|
mSensorManager = new SensorManager();
|
||||||
mInputWrapper->setSensorEventCallback(mSensorManager);
|
mInputWrapper->setSensorEventCallback(mSensorManager);
|
||||||
|
|
||||||
|
mGyroManager = new GyroManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::clear()
|
void InputManager::clear()
|
||||||
|
@ -72,6 +75,8 @@ namespace MWInput
|
||||||
delete mBindingsManager;
|
delete mBindingsManager;
|
||||||
|
|
||||||
delete mInputWrapper;
|
delete mInputWrapper;
|
||||||
|
|
||||||
|
delete mGyroManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::setAttemptJump(bool jumping)
|
void InputManager::setAttemptJump(bool jumping)
|
||||||
|
@ -100,6 +105,17 @@ namespace MWInput
|
||||||
mMouseManager->update(dt);
|
mMouseManager->update(dt);
|
||||||
mSensorManager->update(dt);
|
mSensorManager->update(dt);
|
||||||
mActionManager->update(dt, controllerMove);
|
mActionManager->update(dt, controllerMove);
|
||||||
|
|
||||||
|
if (mGyroManager->isEnabled())
|
||||||
|
{
|
||||||
|
bool controllerAvailable = mControllerManager->isGyroAvailable();
|
||||||
|
bool sensorAvailable = mSensorManager->isGyroAvailable();
|
||||||
|
if (controllerAvailable || sensorAvailable)
|
||||||
|
{
|
||||||
|
mGyroManager->update(dt,
|
||||||
|
controllerAvailable ? mControllerManager->getGyroValues() : mSensorManager->getGyroValues());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::setDragDrop(bool dragDrop)
|
void InputManager::setDragDrop(bool dragDrop)
|
||||||
|
@ -116,7 +132,7 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
mControllerManager->setGuiCursorEnabled(guiMode);
|
mControllerManager->setGuiCursorEnabled(guiMode);
|
||||||
mMouseManager->setGuiCursorEnabled(guiMode);
|
mMouseManager->setGuiCursorEnabled(guiMode);
|
||||||
mSensorManager->setGuiCursorEnabled(guiMode);
|
mGyroManager->setGuiCursorEnabled(guiMode);
|
||||||
mMouseManager->setMouseLookEnabled(!guiMode);
|
mMouseManager->setMouseLookEnabled(!guiMode);
|
||||||
if (guiMode)
|
if (guiMode)
|
||||||
MWBase::Environment::get().getWindowManager()->showCrosshair(false);
|
MWBase::Environment::get().getWindowManager()->showCrosshair(false);
|
||||||
|
@ -130,6 +146,7 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
mMouseManager->processChangedSettings(changed);
|
mMouseManager->processChangedSettings(changed);
|
||||||
mSensorManager->processChangedSettings(changed);
|
mSensorManager->processChangedSettings(changed);
|
||||||
|
mGyroManager->processChangedSettings(changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputManager::getControlSwitch(std::string_view sw)
|
bool InputManager::getControlSwitch(std::string_view sw)
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace MWInput
|
||||||
class KeyboardManager;
|
class KeyboardManager;
|
||||||
class MouseManager;
|
class MouseManager;
|
||||||
class SensorManager;
|
class SensorManager;
|
||||||
|
class GyroManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class that provides a high-level API for game input
|
* @brief Class that provides a high-level API for game input
|
||||||
|
@ -128,6 +129,7 @@ namespace MWInput
|
||||||
KeyboardManager* mKeyboardManager;
|
KeyboardManager* mKeyboardManager;
|
||||||
MouseManager* mMouseManager;
|
MouseManager* mMouseManager;
|
||||||
SensorManager* mSensorManager;
|
SensorManager* mSensorManager;
|
||||||
|
GyroManager* mGyroManager;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,18 +11,10 @@
|
||||||
namespace MWInput
|
namespace MWInput
|
||||||
{
|
{
|
||||||
SensorManager::SensorManager()
|
SensorManager::SensorManager()
|
||||||
: mInvertX(Settings::Manager::getBool("invert x axis", "Input"))
|
: mRotation()
|
||||||
, mInvertY(Settings::Manager::getBool("invert y axis", "Input"))
|
, mGyroValues()
|
||||||
, mGyroXSpeed(0.f)
|
|
||||||
, mGyroYSpeed(0.f)
|
|
||||||
, mGyroUpdateTimer(0.f)
|
, mGyroUpdateTimer(0.f)
|
||||||
, mGyroHSensitivity(Settings::Manager::getFloat("gyro horizontal sensitivity", "Input"))
|
|
||||||
, mGyroVSensitivity(Settings::Manager::getFloat("gyro vertical sensitivity", "Input"))
|
|
||||||
, mGyroHAxis(GyroscopeAxis::Minus_X)
|
|
||||||
, mGyroVAxis(GyroscopeAxis::Y)
|
|
||||||
, mGyroInputThreshold(Settings::Manager::getFloat("gyro input threshold", "Input"))
|
|
||||||
, mGyroscope(nullptr)
|
, mGyroscope(nullptr)
|
||||||
, mGuiCursorEnabled(true)
|
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
@ -42,24 +34,6 @@ namespace MWInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SensorManager::GyroscopeAxis SensorManager::mapGyroscopeAxis(const std::string& axis)
|
|
||||||
{
|
|
||||||
if (axis == "x")
|
|
||||||
return GyroscopeAxis::X;
|
|
||||||
else if (axis == "y")
|
|
||||||
return GyroscopeAxis::Y;
|
|
||||||
else if (axis == "z")
|
|
||||||
return GyroscopeAxis::Z;
|
|
||||||
else if (axis == "-x")
|
|
||||||
return GyroscopeAxis::Minus_X;
|
|
||||||
else if (axis == "-y")
|
|
||||||
return GyroscopeAxis::Minus_Y;
|
|
||||||
else if (axis == "-z")
|
|
||||||
return GyroscopeAxis::Minus_Z;
|
|
||||||
|
|
||||||
return GyroscopeAxis::Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SensorManager::correctGyroscopeAxes()
|
void SensorManager::correctGyroscopeAxes()
|
||||||
{
|
{
|
||||||
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
@ -68,40 +42,36 @@ namespace MWInput
|
||||||
// Treat setting from config as axes for landscape mode.
|
// Treat setting from config as axes for landscape mode.
|
||||||
// If the device does not support orientation change, do nothing.
|
// If the device does not support orientation change, do nothing.
|
||||||
// Note: in is unclear how to correct axes for devices with non-standart Z axis direction.
|
// Note: in is unclear how to correct axes for devices with non-standart Z axis direction.
|
||||||
mGyroHAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro horizontal axis", "Input"));
|
|
||||||
mGyroVAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro vertical axis", "Input"));
|
mRotation = osg::Matrixf::identity();
|
||||||
|
|
||||||
|
float angle = 0;
|
||||||
|
|
||||||
SDL_DisplayOrientation currentOrientation = SDL_GetDisplayOrientation(Settings::Manager::getInt("screen", "Video"));
|
SDL_DisplayOrientation currentOrientation = SDL_GetDisplayOrientation(Settings::Manager::getInt("screen", "Video"));
|
||||||
switch (currentOrientation)
|
switch (currentOrientation)
|
||||||
{
|
{
|
||||||
case SDL_ORIENTATION_UNKNOWN:
|
case SDL_ORIENTATION_UNKNOWN:
|
||||||
return;
|
break;
|
||||||
case SDL_ORIENTATION_LANDSCAPE:
|
case SDL_ORIENTATION_LANDSCAPE:
|
||||||
break;
|
break;
|
||||||
case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
|
case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
|
||||||
{
|
{
|
||||||
mGyroHAxis = GyroscopeAxis(-mGyroHAxis);
|
angle = osg::PIf;
|
||||||
mGyroVAxis = GyroscopeAxis(-mGyroVAxis);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDL_ORIENTATION_PORTRAIT:
|
case SDL_ORIENTATION_PORTRAIT:
|
||||||
{
|
{
|
||||||
GyroscopeAxis oldVAxis = mGyroVAxis;
|
angle = -0.5 * osg::PIf;
|
||||||
mGyroVAxis = mGyroHAxis;
|
|
||||||
mGyroHAxis = GyroscopeAxis(-oldVAxis);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDL_ORIENTATION_PORTRAIT_FLIPPED:
|
case SDL_ORIENTATION_PORTRAIT_FLIPPED:
|
||||||
{
|
{
|
||||||
GyroscopeAxis oldVAxis = mGyroVAxis;
|
angle = 0.5 * osg::PIf;
|
||||||
mGyroVAxis = GyroscopeAxis(-mGyroHAxis);
|
|
||||||
mGyroHAxis = oldVAxis;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mRotation.makeRotate(angle, osg::Vec3f(0, 0, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SensorManager::updateSensors()
|
void SensorManager::updateSensors()
|
||||||
|
@ -119,7 +89,6 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
SDL_SensorClose(mGyroscope);
|
SDL_SensorClose(mGyroscope);
|
||||||
mGyroscope = nullptr;
|
mGyroscope = nullptr;
|
||||||
mGyroXSpeed = mGyroYSpeed = 0.f;
|
|
||||||
mGyroUpdateTimer = 0.f;
|
mGyroUpdateTimer = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +110,6 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
SDL_SensorClose(mGyroscope);
|
SDL_SensorClose(mGyroscope);
|
||||||
mGyroscope = nullptr;
|
mGyroscope = nullptr;
|
||||||
mGyroXSpeed = mGyroYSpeed = 0.f;
|
|
||||||
mGyroUpdateTimer = 0.f;
|
mGyroUpdateTimer = 0.f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,46 +119,8 @@ namespace MWInput
|
||||||
{
|
{
|
||||||
for (const auto& setting : changed)
|
for (const auto& setting : changed)
|
||||||
{
|
{
|
||||||
if (setting.first == "Input" && setting.second == "invert x axis")
|
|
||||||
mInvertX = Settings::Manager::getBool("invert x axis", "Input");
|
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "invert y axis")
|
|
||||||
mInvertY = Settings::Manager::getBool("invert y axis", "Input");
|
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "gyro horizontal sensitivity")
|
|
||||||
mGyroHSensitivity = Settings::Manager::getFloat("gyro horizontal sensitivity", "Input");
|
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "gyro vertical sensitivity")
|
|
||||||
mGyroVSensitivity = Settings::Manager::getFloat("gyro vertical sensitivity", "Input");
|
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "enable gyroscope")
|
if (setting.first == "Input" && setting.second == "enable gyroscope")
|
||||||
init();
|
init();
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "gyro horizontal axis")
|
|
||||||
correctGyroscopeAxes();
|
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "gyro vertical axis")
|
|
||||||
correctGyroscopeAxes();
|
|
||||||
|
|
||||||
if (setting.first == "Input" && setting.second == "gyro input threshold")
|
|
||||||
mGyroInputThreshold = Settings::Manager::getFloat("gyro input threshold", "Input");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float SensorManager::getGyroAxisSpeed(GyroscopeAxis axis, const SDL_SensorEvent &arg) const
|
|
||||||
{
|
|
||||||
switch (axis)
|
|
||||||
{
|
|
||||||
case GyroscopeAxis::X:
|
|
||||||
case GyroscopeAxis::Y:
|
|
||||||
case GyroscopeAxis::Z:
|
|
||||||
return std::abs(arg.data[0]) >= mGyroInputThreshold ? arg.data[axis-1] : 0.f;
|
|
||||||
case GyroscopeAxis::Minus_X:
|
|
||||||
case GyroscopeAxis::Minus_Y:
|
|
||||||
case GyroscopeAxis::Minus_Z:
|
|
||||||
return std::abs(arg.data[0]) >= mGyroInputThreshold ? -arg.data[std::abs(axis)-1] : 0.f;
|
|
||||||
default:
|
|
||||||
return 0.f;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,10 +147,9 @@ namespace MWInput
|
||||||
break;
|
break;
|
||||||
case SDL_SENSOR_GYRO:
|
case SDL_SENSOR_GYRO:
|
||||||
{
|
{
|
||||||
mGyroXSpeed = getGyroAxisSpeed(mGyroHAxis, arg);
|
osg::Vec3f gyro(arg.data[0], arg.data[1], arg.data[2]);
|
||||||
mGyroYSpeed = getGyroAxisSpeed(mGyroVAxis, arg);
|
mGyroValues = mRotation * gyro;
|
||||||
mGyroUpdateTimer = 0.f;
|
mGyroUpdateTimer = 0.f;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -230,41 +159,24 @@ namespace MWInput
|
||||||
|
|
||||||
void SensorManager::update(float dt)
|
void SensorManager::update(float dt)
|
||||||
{
|
{
|
||||||
if (mGyroXSpeed == 0.f && mGyroYSpeed == 0.f)
|
mGyroUpdateTimer += dt;
|
||||||
return;
|
|
||||||
|
|
||||||
if (mGyroUpdateTimer > 0.5f)
|
if (mGyroUpdateTimer > 0.5f)
|
||||||
{
|
{
|
||||||
// More than half of second passed since the last gyroscope update.
|
// More than half of second passed since the last gyroscope update.
|
||||||
// A device more likely was disconnected or switched to the sleep mode.
|
// A device more likely was disconnected or switched to the sleep mode.
|
||||||
// Reset current rotation speed and wait for update.
|
// Reset current rotation speed and wait for update.
|
||||||
mGyroXSpeed = 0.f;
|
mGyroValues = osg::Vec3f();
|
||||||
mGyroYSpeed = 0.f;
|
|
||||||
mGyroUpdateTimer = 0.f;
|
mGyroUpdateTimer = 0.f;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGyroUpdateTimer += dt;
|
|
||||||
|
|
||||||
if (!mGuiCursorEnabled)
|
|
||||||
{
|
|
||||||
float rot[3];
|
|
||||||
rot[0] = -mGyroYSpeed * dt * mGyroVSensitivity * 4 * (mInvertY ? -1 : 1);
|
|
||||||
rot[1] = 0.0f;
|
|
||||||
rot[2] = -mGyroXSpeed * dt * mGyroHSensitivity * 4 * (mInvertX ? -1 : 1);
|
|
||||||
|
|
||||||
// Only actually turn player when we're not in vanity mode
|
|
||||||
bool playerLooking = MWBase::Environment::get().getInputManager()->getControlSwitch("playerlooking");
|
|
||||||
if (!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && playerLooking)
|
|
||||||
{
|
|
||||||
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
|
||||||
player.yaw(-rot[2]);
|
|
||||||
player.pitch(-rot[0]);
|
|
||||||
}
|
|
||||||
else if (!playerLooking)
|
|
||||||
MWBase::Environment::get().getWorld()->disableDeferredPreviewRotation();
|
|
||||||
|
|
||||||
MWBase::Environment::get().getInputManager()->resetIdleTime();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SensorManager::isGyroAvailable() const
|
||||||
|
{
|
||||||
|
return mGyroscope != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<float, 3> SensorManager::getGyroValues() const
|
||||||
|
{
|
||||||
|
return { mGyroValues.x(), mGyroValues.y(), mGyroValues.z() };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include <SDL_sensor.h>
|
#include <SDL_sensor.h>
|
||||||
|
|
||||||
|
#include <osg/Matrixf>
|
||||||
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/sdlutil/events.hpp>
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
|
@ -33,41 +36,19 @@ namespace MWInput
|
||||||
void displayOrientationChanged() override;
|
void displayOrientationChanged() override;
|
||||||
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
void setGuiCursorEnabled(bool enabled) { mGuiCursorEnabled = enabled; }
|
bool isGyroAvailable() const;
|
||||||
|
std::array<float, 3> getGyroValues() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum GyroscopeAxis
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
X = 1,
|
|
||||||
Y = 2,
|
|
||||||
Z = 3,
|
|
||||||
Minus_X = -1,
|
|
||||||
Minus_Y = -2,
|
|
||||||
Minus_Z = -3
|
|
||||||
};
|
|
||||||
|
|
||||||
void updateSensors();
|
void updateSensors();
|
||||||
void correctGyroscopeAxes();
|
void correctGyroscopeAxes();
|
||||||
GyroscopeAxis mapGyroscopeAxis(const std::string& axis);
|
|
||||||
float getGyroAxisSpeed(GyroscopeAxis axis, const SDL_SensorEvent &arg) const;
|
|
||||||
|
|
||||||
bool mInvertX;
|
osg::Matrixf mRotation;
|
||||||
bool mInvertY;
|
osg::Vec3f mGyroValues;
|
||||||
|
|
||||||
float mGyroXSpeed;
|
|
||||||
float mGyroYSpeed;
|
|
||||||
float mGyroUpdateTimer;
|
float mGyroUpdateTimer;
|
||||||
|
|
||||||
float mGyroHSensitivity;
|
|
||||||
float mGyroVSensitivity;
|
|
||||||
GyroscopeAxis mGyroHAxis;
|
|
||||||
GyroscopeAxis mGyroVAxis;
|
|
||||||
float mGyroInputThreshold;
|
|
||||||
|
|
||||||
SDL_Sensor* mGyroscope;
|
SDL_Sensor* mGyroscope;
|
||||||
|
|
||||||
bool mGuiCursorEnabled;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -158,6 +158,11 @@ Enable the support of camera rotation based on the information supplied from the
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
Built-in (e. g. in a phone or tablet) and controller gyroscopes are supported. If both are present, controller gyroscope takes priority.
|
||||||
|
|
||||||
|
Note: controller gyroscopes are only supported when OpenMW is built with SDL 2.0.14 or higher,
|
||||||
|
and were tested only on Windows.
|
||||||
|
|
||||||
gyro horizontal axis
|
gyro horizontal axis
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -190,8 +195,8 @@ gyro input threshold
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
:Type: floating point
|
:Type: floating point
|
||||||
:Range: > 0
|
:Range: >=0
|
||||||
:Default: 0.01
|
:Default: 0.0
|
||||||
|
|
||||||
This setting determines the minimum value of the rotation that will be accepted.
|
This setting determines the minimum value of the rotation that will be accepted.
|
||||||
It allows to avoid crosshair oscillation due to gyroscope "noise".
|
It allows to avoid crosshair oscillation due to gyroscope "noise".
|
||||||
|
@ -209,6 +214,8 @@ This setting controls the overall gyroscope horizontal sensitivity.
|
||||||
The smaller this sensitivity is, the less visible effect the device rotation
|
The smaller this sensitivity is, the less visible effect the device rotation
|
||||||
will have on the horizontal camera rotation, and vice versa.
|
will have on the horizontal camera rotation, and vice versa.
|
||||||
|
|
||||||
|
Value of X means that rotating the device by 1 degree will cause the player to rotate by X degrees.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
gyro vertical sensitivity
|
gyro vertical sensitivity
|
||||||
|
@ -222,4 +229,6 @@ This setting controls the overall gyroscope vertical sensitivity.
|
||||||
The smaller this sensitivity is, the less visible effect the device
|
The smaller this sensitivity is, the less visible effect the device
|
||||||
rotation will have on the vertical camera rotation, and vice versa.
|
rotation will have on the vertical camera rotation, and vice versa.
|
||||||
|
|
||||||
|
Value of X means that rotating the device by 1 degree will cause the player to rotate by X degrees.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
|
@ -540,7 +540,7 @@ gyro horizontal axis = -x
|
||||||
gyro vertical axis = y
|
gyro vertical axis = y
|
||||||
|
|
||||||
# The minimum gyroscope movement that is able to rotate the camera.
|
# The minimum gyroscope movement that is able to rotate the camera.
|
||||||
gyro input threshold = 0.01
|
gyro input threshold = 0
|
||||||
|
|
||||||
# Horizontal camera axis sensitivity to gyroscope movement.
|
# Horizontal camera axis sensitivity to gyroscope movement.
|
||||||
gyro horizontal sensitivity = 1.0
|
gyro horizontal sensitivity = 1.0
|
||||||
|
|
Loading…
Reference in a new issue