mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-13 16:43:07 +00:00
Split sensors handling so the separate file
This commit is contained in:
parent
b72720f357
commit
15dc4d241d
5 changed files with 371 additions and 261 deletions
|
|
@ -25,7 +25,7 @@ add_openmw_dir (mwrender
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
inputmanagerimp
|
inputmanagerimp sensormanager
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwgui
|
add_openmw_dir (mwgui
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
|
#include "sensormanager.hpp"
|
||||||
|
|
||||||
namespace MWInput
|
namespace MWInput
|
||||||
{
|
{
|
||||||
InputManager::InputManager(
|
InputManager::InputManager(
|
||||||
|
|
@ -79,20 +81,10 @@ namespace MWInput
|
||||||
, mAttemptJump(false)
|
, mAttemptJump(false)
|
||||||
, mInvUiScalingFactor(1.f)
|
, mInvUiScalingFactor(1.f)
|
||||||
, mGamepadCursorSpeed(Settings::Manager::getFloat("gamepad cursor speed", "Input"))
|
, mGamepadCursorSpeed(Settings::Manager::getFloat("gamepad cursor speed", "Input"))
|
||||||
, mGyroXSpeed(0.f)
|
|
||||||
, mGyroYSpeed(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"))
|
|
||||||
, mFakeDeviceID(1)
|
, mFakeDeviceID(1)
|
||||||
, mGyroscope(nullptr)
|
|
||||||
{
|
{
|
||||||
mInputManager = new SDLUtil::InputWrapper(window, viewer, grab);
|
mInputManager = new SDLUtil::InputWrapper(window, viewer, grab);
|
||||||
mInputManager->setMouseEventCallback (this);
|
mInputManager->setMouseEventCallback (this);
|
||||||
mInputManager->setSensorEventCallback (this);
|
|
||||||
mInputManager->setKeyboardEventCallback (this);
|
mInputManager->setKeyboardEventCallback (this);
|
||||||
mInputManager->setWindowEventCallback(this);
|
mInputManager->setWindowEventCallback(this);
|
||||||
mInputManager->setControllerEventCallback(this);
|
mInputManager->setControllerEventCallback(this);
|
||||||
|
|
@ -149,8 +141,8 @@ namespace MWInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
correctGyroscopeAxes();
|
mSensorManager = new SensorManager();
|
||||||
updateSensors();
|
mInputManager->setSensorEventCallback (mSensorManager);
|
||||||
|
|
||||||
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
|
||||||
if (uiScale != 0.f)
|
if (uiScale != 0.f)
|
||||||
|
|
@ -168,17 +160,15 @@ namespace MWInput
|
||||||
// Enable all controls
|
// Enable all controls
|
||||||
for (std::map<std::string, bool>::iterator it = mControlSwitch.begin(); it != mControlSwitch.end(); ++it)
|
for (std::map<std::string, bool>::iterator it = mControlSwitch.begin(); it != mControlSwitch.end(); ++it)
|
||||||
it->second = true;
|
it->second = true;
|
||||||
|
|
||||||
|
mSensorManager->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
InputManager::~InputManager()
|
InputManager::~InputManager()
|
||||||
{
|
{
|
||||||
mInputBinder->save (mUserFile);
|
mInputBinder->save (mUserFile);
|
||||||
|
|
||||||
if (mGyroscope != nullptr)
|
delete mSensorManager;
|
||||||
{
|
|
||||||
SDL_SensorClose(mGyroscope);
|
|
||||||
mGyroscope = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete mInputBinder;
|
delete mInputBinder;
|
||||||
|
|
||||||
|
|
@ -187,112 +177,6 @@ namespace MWInput
|
||||||
delete mVideoWrapper;
|
delete mVideoWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputManager::GyroscopeAxis InputManager::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 InputManager::correctGyroscopeAxes()
|
|
||||||
{
|
|
||||||
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Treat setting from config as axes for landscape mode.
|
|
||||||
// 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.
|
|
||||||
mGyroHAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro horizontal axis", "Input"));
|
|
||||||
mGyroVAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro vertical axis", "Input"));
|
|
||||||
|
|
||||||
SDL_DisplayOrientation currentOrientation = SDL_GetDisplayOrientation(Settings::Manager::getInt("screen", "Video"));
|
|
||||||
switch (currentOrientation)
|
|
||||||
{
|
|
||||||
case SDL_ORIENTATION_UNKNOWN:
|
|
||||||
return;
|
|
||||||
case SDL_ORIENTATION_LANDSCAPE:
|
|
||||||
break;
|
|
||||||
case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
|
|
||||||
{
|
|
||||||
mGyroHAxis = GyroscopeAxis(-mGyroHAxis);
|
|
||||||
mGyroVAxis = GyroscopeAxis(-mGyroVAxis);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SDL_ORIENTATION_PORTRAIT:
|
|
||||||
{
|
|
||||||
GyroscopeAxis oldVAxis = mGyroVAxis;
|
|
||||||
mGyroVAxis = mGyroHAxis;
|
|
||||||
mGyroHAxis = GyroscopeAxis(-oldVAxis);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SDL_ORIENTATION_PORTRAIT_FLIPPED:
|
|
||||||
{
|
|
||||||
GyroscopeAxis oldVAxis = mGyroVAxis;
|
|
||||||
mGyroVAxis = GyroscopeAxis(-mGyroHAxis);
|
|
||||||
mGyroHAxis = oldVAxis;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::updateSensors()
|
|
||||||
{
|
|
||||||
if (Settings::Manager::getBool("enable gyroscope", "Input"))
|
|
||||||
{
|
|
||||||
int numSensors = SDL_NumSensors();
|
|
||||||
|
|
||||||
for (int i = 0; i < numSensors; ++i)
|
|
||||||
{
|
|
||||||
if (SDL_SensorGetDeviceType(i) == SDL_SENSOR_GYRO)
|
|
||||||
{
|
|
||||||
// It is unclear how to handle several enabled gyroscopes, so use the first one.
|
|
||||||
// Note: Android registers some gyroscope as two separate sensors, for non-wake-up mode and for wake-up mode.
|
|
||||||
if (mGyroscope != nullptr)
|
|
||||||
{
|
|
||||||
SDL_SensorClose(mGyroscope);
|
|
||||||
mGyroscope = nullptr;
|
|
||||||
mGyroXSpeed = mGyroYSpeed = 0.f;
|
|
||||||
mGyroUpdateTimer = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: SDL2 does not provide a way to configure a sensor update frequency so far.
|
|
||||||
SDL_Sensor *sensor = SDL_SensorOpen(i);
|
|
||||||
if (sensor == nullptr)
|
|
||||||
Log(Debug::Error) << "Couldn't open sensor " << SDL_SensorGetDeviceName(i) << ": " << SDL_GetError();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mGyroscope = sensor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mGyroscope != nullptr)
|
|
||||||
{
|
|
||||||
SDL_SensorClose(mGyroscope);
|
|
||||||
mGyroscope = nullptr;
|
|
||||||
mGyroXSpeed = mGyroYSpeed = 0.f;
|
|
||||||
mGyroUpdateTimer = 0.f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputManager::isWindowVisible()
|
bool InputManager::isWindowVisible()
|
||||||
{
|
{
|
||||||
return mWindowVisible;
|
return mWindowVisible;
|
||||||
|
|
@ -731,36 +615,8 @@ namespace MWInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mGyroXSpeed != 0.f || mGyroYSpeed != 0.f)
|
if (mSensorManager->update(dt, mGuiCursorEnabled, mControlSwitch["playerlooking"]))
|
||||||
{
|
resetIdleTime();
|
||||||
if (mGyroUpdateTimer > 0.5f)
|
|
||||||
{
|
|
||||||
// More than half of second passed since the last gyroscope update.
|
|
||||||
// A device more likely was disconnected or switched to the sleep mode.
|
|
||||||
// Reset current rotation speed and wait for update.
|
|
||||||
mGyroXSpeed = mGyroYSpeed = 0.f;
|
|
||||||
mGyroUpdateTimer = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mGuiCursorEnabled)
|
|
||||||
{
|
|
||||||
resetIdleTime();
|
|
||||||
|
|
||||||
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
|
|
||||||
if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && mControlSwitch["playerlooking"])
|
|
||||||
{
|
|
||||||
mPlayer->yaw(rot[2]);
|
|
||||||
mPlayer->pitch(rot[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mGyroUpdateTimer += dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable movement in Gui mode
|
// Disable movement in Gui mode
|
||||||
if (!(MWBase::Environment::get().getWindowManager()->isGuiMode()
|
if (!(MWBase::Environment::get().getWindowManager()->isGuiMode()
|
||||||
|
|
@ -957,27 +813,6 @@ namespace MWInput
|
||||||
if (it->first == "Input" && it->second == "camera sensitivity")
|
if (it->first == "Input" && it->second == "camera sensitivity")
|
||||||
mCameraSensitivity = Settings::Manager::getFloat("camera sensitivity", "Input");
|
mCameraSensitivity = Settings::Manager::getFloat("camera sensitivity", "Input");
|
||||||
|
|
||||||
if (it->first == "Input" && it->second == "gyro horizontal sensitivity")
|
|
||||||
mGyroHSensitivity = Settings::Manager::getFloat("gyro horizontal sensitivity", "Input");
|
|
||||||
|
|
||||||
if (it->first == "Input" && it->second == "gyro vertical sensitivity")
|
|
||||||
mGyroVSensitivity = Settings::Manager::getFloat("gyro vertical sensitivity", "Input");
|
|
||||||
|
|
||||||
if (it->first == "Input" && it->second == "enable gyroscope")
|
|
||||||
{
|
|
||||||
correctGyroscopeAxes();
|
|
||||||
updateSensors();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it->first == "Input" && it->second == "gyro horizontal axis")
|
|
||||||
correctGyroscopeAxes();
|
|
||||||
|
|
||||||
if (it->first == "Input" && it->second == "gyro vertical axis")
|
|
||||||
correctGyroscopeAxes();
|
|
||||||
|
|
||||||
if (it->first == "Input" && it->second == "gyro input threshold")
|
|
||||||
mGyroInputThreshold = Settings::Manager::getFloat("gyro input threshold", "Input");
|
|
||||||
|
|
||||||
if (it->first == "Input" && it->second == "grab cursor")
|
if (it->first == "Input" && it->second == "grab cursor")
|
||||||
mGrabCursor = Settings::Manager::getBool("grab cursor", "Input");
|
mGrabCursor = Settings::Manager::getBool("grab cursor", "Input");
|
||||||
|
|
||||||
|
|
@ -1006,6 +841,8 @@ namespace MWInput
|
||||||
Settings::Manager::getBool("fullscreen", "Video"),
|
Settings::Manager::getBool("fullscreen", "Video"),
|
||||||
Settings::Manager::getBool("window border", "Video"));
|
Settings::Manager::getBool("window border", "Video"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSensorManager->processChangedSettings(changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputManager::getControlSwitch (const std::string& sw)
|
bool InputManager::getControlSwitch (const std::string& sw)
|
||||||
|
|
@ -1131,57 +968,6 @@ namespace MWInput
|
||||||
mJoystickLastUsed = false;
|
mJoystickLastUsed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float InputManager::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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::displayOrientationChanged()
|
|
||||||
{
|
|
||||||
correctGyroscopeAxes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::sensorUpdated(const SDL_SensorEvent &arg)
|
|
||||||
{
|
|
||||||
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SDL_Sensor *sensor = SDL_SensorFromInstanceID(arg.which);
|
|
||||||
if (!sensor)
|
|
||||||
{
|
|
||||||
Log(Debug::Info) << "Couldn't get sensor for sensor event";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (SDL_SensorGetType(sensor))
|
|
||||||
{
|
|
||||||
case SDL_SENSOR_ACCEL:
|
|
||||||
break;
|
|
||||||
case SDL_SENSOR_GYRO:
|
|
||||||
{
|
|
||||||
mGyroXSpeed = getGyroAxisSpeed(mGyroHAxis, arg);
|
|
||||||
mGyroYSpeed = getGyroAxisSpeed(mGyroVAxis, arg);
|
|
||||||
mGyroUpdateTimer = 0.f;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputManager::mouseMoved(const SDLUtil::MouseMotionEvent &arg )
|
void InputManager::mouseMoved(const SDLUtil::MouseMotionEvent &arg )
|
||||||
{
|
{
|
||||||
mInputBinder->mouseMoved (arg);
|
mInputBinder->mouseMoved (arg);
|
||||||
|
|
@ -2235,4 +2021,9 @@ namespace MWInput
|
||||||
//MyGUI's buttons are 0 indexed
|
//MyGUI's buttons are 0 indexed
|
||||||
return MyGUI::MouseButton::Enum(button - 1);
|
return MyGUI::MouseButton::Enum(button - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputManager::setPlayer (MWWorld::Player* player)
|
||||||
|
{
|
||||||
|
mPlayer = player;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,11 @@
|
||||||
|
|
||||||
#include "../mwbase/inputmanager.hpp"
|
#include "../mwbase/inputmanager.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class SensorManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Player;
|
class Player;
|
||||||
|
|
@ -67,7 +72,6 @@ namespace MWInput
|
||||||
public MWBase::InputManager,
|
public MWBase::InputManager,
|
||||||
public SDLUtil::KeyListener,
|
public SDLUtil::KeyListener,
|
||||||
public SDLUtil::MouseListener,
|
public SDLUtil::MouseListener,
|
||||||
public SDLUtil::SensorListener,
|
|
||||||
public SDLUtil::WindowListener,
|
public SDLUtil::WindowListener,
|
||||||
public SDLUtil::ControllerListener,
|
public SDLUtil::ControllerListener,
|
||||||
public ICS::ChannelListener,
|
public ICS::ChannelListener,
|
||||||
|
|
@ -92,7 +96,7 @@ namespace MWInput
|
||||||
|
|
||||||
virtual void update(float dt, bool disableControls=false, bool disableEvents=false);
|
virtual void update(float dt, bool disableControls=false, bool disableEvents=false);
|
||||||
|
|
||||||
void setPlayer (MWWorld::Player* player) { mPlayer = player; }
|
void setPlayer (MWWorld::Player* player);
|
||||||
|
|
||||||
virtual void changeInputMode(bool guiMode);
|
virtual void changeInputMode(bool guiMode);
|
||||||
|
|
||||||
|
|
@ -115,7 +119,6 @@ namespace MWInput
|
||||||
|
|
||||||
virtual bool joystickLastUsed() {return mJoystickLastUsed;}
|
virtual bool joystickLastUsed() {return mJoystickLastUsed;}
|
||||||
|
|
||||||
public:
|
|
||||||
virtual void keyPressed(const SDL_KeyboardEvent &arg );
|
virtual void keyPressed(const SDL_KeyboardEvent &arg );
|
||||||
virtual void keyReleased( const SDL_KeyboardEvent &arg );
|
virtual void keyReleased( const SDL_KeyboardEvent &arg );
|
||||||
virtual void textInput (const SDL_TextInputEvent &arg);
|
virtual void textInput (const SDL_TextInputEvent &arg);
|
||||||
|
|
@ -126,9 +129,6 @@ namespace MWInput
|
||||||
|
|
||||||
virtual void mouseWheelMoved( const SDL_MouseWheelEvent &arg);
|
virtual void mouseWheelMoved( const SDL_MouseWheelEvent &arg);
|
||||||
|
|
||||||
virtual void sensorUpdated(const SDL_SensorEvent &arg);
|
|
||||||
virtual void displayOrientationChanged();
|
|
||||||
|
|
||||||
virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg);
|
virtual void buttonPressed(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg);
|
virtual void buttonReleased(int deviceID, const SDL_ControllerButtonEvent &arg);
|
||||||
virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg);
|
virtual void axisMoved(int deviceID, const SDL_ControllerAxisEvent &arg);
|
||||||
|
|
@ -168,17 +168,6 @@ namespace MWInput
|
||||||
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
virtual void readRecord(ESM::ESMReader& reader, uint32_t type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum GyroscopeAxis
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
X = 1,
|
|
||||||
Y = 2,
|
|
||||||
Z = 3,
|
|
||||||
Minus_X = -1,
|
|
||||||
Minus_Y = -2,
|
|
||||||
Minus_Z = -3
|
|
||||||
};
|
|
||||||
|
|
||||||
SDL_Window* mWindow;
|
SDL_Window* mWindow;
|
||||||
bool mWindowVisible;
|
bool mWindowVisible;
|
||||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||||
|
|
@ -235,17 +224,8 @@ namespace MWInput
|
||||||
float mInvUiScalingFactor;
|
float mInvUiScalingFactor;
|
||||||
float mGamepadCursorSpeed;
|
float mGamepadCursorSpeed;
|
||||||
|
|
||||||
float mGyroXSpeed;
|
SensorManager* mSensorManager;
|
||||||
float mGyroYSpeed;
|
|
||||||
float mGyroUpdateTimer;
|
|
||||||
|
|
||||||
float mGyroHSensitivity;
|
|
||||||
float mGyroVSensitivity;
|
|
||||||
GyroscopeAxis mGyroHAxis;
|
|
||||||
GyroscopeAxis mGyroVAxis;
|
|
||||||
float mGyroInputThreshold;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void convertMousePosForMyGUI(int& x, int& y);
|
void convertMousePosForMyGUI(int& x, int& y);
|
||||||
|
|
||||||
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button);
|
MyGUI::MouseButton sdlButtonToMyGUI(Uint8 button);
|
||||||
|
|
@ -263,15 +243,9 @@ namespace MWInput
|
||||||
bool gamepadToGuiControl(const SDL_ControllerAxisEvent &arg);
|
bool gamepadToGuiControl(const SDL_ControllerAxisEvent &arg);
|
||||||
|
|
||||||
void updateCursorMode();
|
void updateCursorMode();
|
||||||
void updateSensors();
|
|
||||||
void correctGyroscopeAxes();
|
|
||||||
GyroscopeAxis mapGyroscopeAxis(const std::string& axis);
|
|
||||||
|
|
||||||
bool checkAllowedToUseItems() const;
|
bool checkAllowedToUseItems() const;
|
||||||
|
|
||||||
float getGyroAxisSpeed(GyroscopeAxis axis, const SDL_SensorEvent &arg) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void toggleMainMenu();
|
void toggleMainMenu();
|
||||||
void toggleSpell();
|
void toggleSpell();
|
||||||
void toggleWeapon();
|
void toggleWeapon();
|
||||||
|
|
@ -296,9 +270,7 @@ namespace MWInput
|
||||||
void loadControllerDefaults(bool force = false);
|
void loadControllerDefaults(bool force = false);
|
||||||
|
|
||||||
int mFakeDeviceID; //As we only support one controller at a time, use a fake deviceID so we don't lose bindings when switching controllers
|
int mFakeDeviceID; //As we only support one controller at a time, use a fake deviceID so we don't lose bindings when switching controllers
|
||||||
SDL_Sensor* mGyroscope;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum Actions
|
enum Actions
|
||||||
{
|
{
|
||||||
// please add new actions at the bottom, in order to preserve the channel IDs in the key configuration files
|
// please add new actions at the bottom, in order to preserve the channel IDs in the key configuration files
|
||||||
|
|
|
||||||
274
apps/openmw/mwinput/sensormanager.cpp
Normal file
274
apps/openmw/mwinput/sensormanager.cpp
Normal file
|
|
@ -0,0 +1,274 @@
|
||||||
|
#include "sensormanager.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
SensorManager::SensorManager()
|
||||||
|
: mInvertX(Settings::Manager::getBool("invert x axis", "Input"))
|
||||||
|
, mInvertY(Settings::Manager::getBool("invert y axis", "Input"))
|
||||||
|
, mGyroXSpeed(0.f)
|
||||||
|
, mGyroYSpeed(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)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::init()
|
||||||
|
{
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
updateSensors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::clear()
|
||||||
|
{
|
||||||
|
mGyroXSpeed = 0.f;
|
||||||
|
mGyroYSpeed = 0.f;
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
SensorManager::~SensorManager()
|
||||||
|
{
|
||||||
|
if (mGyroscope != nullptr)
|
||||||
|
{
|
||||||
|
SDL_SensorClose(mGyroscope);
|
||||||
|
mGyroscope = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Treat setting from config as axes for landscape mode.
|
||||||
|
// 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.
|
||||||
|
mGyroHAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro horizontal axis", "Input"));
|
||||||
|
mGyroVAxis = mapGyroscopeAxis(Settings::Manager::getString("gyro vertical axis", "Input"));
|
||||||
|
|
||||||
|
SDL_DisplayOrientation currentOrientation = SDL_GetDisplayOrientation(Settings::Manager::getInt("screen", "Video"));
|
||||||
|
switch (currentOrientation)
|
||||||
|
{
|
||||||
|
case SDL_ORIENTATION_UNKNOWN:
|
||||||
|
return;
|
||||||
|
case SDL_ORIENTATION_LANDSCAPE:
|
||||||
|
break;
|
||||||
|
case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
|
||||||
|
{
|
||||||
|
mGyroHAxis = GyroscopeAxis(-mGyroHAxis);
|
||||||
|
mGyroVAxis = GyroscopeAxis(-mGyroVAxis);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDL_ORIENTATION_PORTRAIT:
|
||||||
|
{
|
||||||
|
GyroscopeAxis oldVAxis = mGyroVAxis;
|
||||||
|
mGyroVAxis = mGyroHAxis;
|
||||||
|
mGyroHAxis = GyroscopeAxis(-oldVAxis);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SDL_ORIENTATION_PORTRAIT_FLIPPED:
|
||||||
|
{
|
||||||
|
GyroscopeAxis oldVAxis = mGyroVAxis;
|
||||||
|
mGyroVAxis = GyroscopeAxis(-mGyroHAxis);
|
||||||
|
mGyroHAxis = oldVAxis;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::updateSensors()
|
||||||
|
{
|
||||||
|
if (Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
{
|
||||||
|
int numSensors = SDL_NumSensors();
|
||||||
|
|
||||||
|
for (int i = 0; i < numSensors; ++i)
|
||||||
|
{
|
||||||
|
if (SDL_SensorGetDeviceType(i) == SDL_SENSOR_GYRO)
|
||||||
|
{
|
||||||
|
// It is unclear how to handle several enabled gyroscopes, so use the first one.
|
||||||
|
// Note: Android registers some gyroscope as two separate sensors, for non-wake-up mode and for wake-up mode.
|
||||||
|
if (mGyroscope != nullptr)
|
||||||
|
{
|
||||||
|
SDL_SensorClose(mGyroscope);
|
||||||
|
mGyroscope = nullptr;
|
||||||
|
mGyroXSpeed = mGyroYSpeed = 0.f;
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: SDL2 does not provide a way to configure a sensor update frequency so far.
|
||||||
|
SDL_Sensor *sensor = SDL_SensorOpen(i);
|
||||||
|
if (sensor == nullptr)
|
||||||
|
Log(Debug::Error) << "Couldn't open sensor " << SDL_SensorGetDeviceName(i) << ": " << SDL_GetError();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mGyroscope = sensor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mGyroscope != nullptr)
|
||||||
|
{
|
||||||
|
SDL_SensorClose(mGyroscope);
|
||||||
|
mGyroscope = nullptr;
|
||||||
|
mGyroXSpeed = mGyroYSpeed = 0.f;
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
||||||
|
{
|
||||||
|
for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == "Input" && it->second == "invert x axis")
|
||||||
|
mInvertX = Settings::Manager::getBool("invert x axis", "Input");
|
||||||
|
|
||||||
|
if (it->first == "Input" && it->second == "invert y axis")
|
||||||
|
mInvertY = Settings::Manager::getBool("invert y axis", "Input");
|
||||||
|
|
||||||
|
if (it->first == "Input" && it->second == "gyro horizontal sensitivity")
|
||||||
|
mGyroHSensitivity = Settings::Manager::getFloat("gyro horizontal sensitivity", "Input");
|
||||||
|
|
||||||
|
if (it->first == "Input" && it->second == "gyro vertical sensitivity")
|
||||||
|
mGyroVSensitivity = Settings::Manager::getFloat("gyro vertical sensitivity", "Input");
|
||||||
|
|
||||||
|
if (it->first == "Input" && it->second == "enable gyroscope")
|
||||||
|
init();
|
||||||
|
|
||||||
|
if (it->first == "Input" && it->second == "gyro horizontal axis")
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
|
||||||
|
if (it->first == "Input" && it->second == "gyro vertical axis")
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
|
||||||
|
if (it->first == "Input" && it->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::displayOrientationChanged()
|
||||||
|
{
|
||||||
|
correctGyroscopeAxes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SensorManager::sensorUpdated(const SDL_SensorEvent &arg)
|
||||||
|
{
|
||||||
|
if (!Settings::Manager::getBool("enable gyroscope", "Input"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDL_Sensor *sensor = SDL_SensorFromInstanceID(arg.which);
|
||||||
|
if (!sensor)
|
||||||
|
{
|
||||||
|
Log(Debug::Info) << "Couldn't get sensor for sensor event";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (SDL_SensorGetType(sensor))
|
||||||
|
{
|
||||||
|
case SDL_SENSOR_ACCEL:
|
||||||
|
break;
|
||||||
|
case SDL_SENSOR_GYRO:
|
||||||
|
{
|
||||||
|
mGyroXSpeed = getGyroAxisSpeed(mGyroHAxis, arg);
|
||||||
|
mGyroYSpeed = getGyroAxisSpeed(mGyroVAxis, arg);
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SensorManager::update(float dt, bool isCursorEnabled, bool isTurningEnabled)
|
||||||
|
{
|
||||||
|
if (mGyroXSpeed == 0.f && mGyroYSpeed == 0.f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mGyroUpdateTimer > 0.5f)
|
||||||
|
{
|
||||||
|
// More than half of second passed since the last gyroscope update.
|
||||||
|
// A device more likely was disconnected or switched to the sleep mode.
|
||||||
|
// Reset current rotation speed and wait for update.
|
||||||
|
clear();
|
||||||
|
mGyroUpdateTimer = 0.f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGyroUpdateTimer += dt;
|
||||||
|
|
||||||
|
if (!isCursorEnabled)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot) && isTurningEnabled)
|
||||||
|
{
|
||||||
|
MWWorld::Player& player = MWBase::Environment::get().getWorld()->getPlayer();
|
||||||
|
player.yaw(rot[2]);
|
||||||
|
player.pitch(rot[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
73
apps/openmw/mwinput/sensormanager.hpp
Normal file
73
apps/openmw/mwinput/sensormanager.hpp
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef MWINPUT_MWSENSORMANAGER_H
|
||||||
|
#define MWINPUT_MWSENSORMANAGER_H
|
||||||
|
|
||||||
|
#include <SDL_sensor.h>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/sdlutil/events.hpp>
|
||||||
|
|
||||||
|
namespace SDLUtil
|
||||||
|
{
|
||||||
|
class InputWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Player;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWInput
|
||||||
|
{
|
||||||
|
class SensorManager : public SDLUtil::SensorListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SensorManager();
|
||||||
|
|
||||||
|
virtual ~SensorManager();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
bool update(float dt, bool isCursorEnabled, bool isTurningEnabled);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void sensorUpdated(const SDL_SensorEvent &arg);
|
||||||
|
virtual void displayOrientationChanged();
|
||||||
|
void processChangedSettings(const Settings::CategorySettingVector& changed);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum GyroscopeAxis
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
X = 1,
|
||||||
|
Y = 2,
|
||||||
|
Z = 3,
|
||||||
|
Minus_X = -1,
|
||||||
|
Minus_Y = -2,
|
||||||
|
Minus_Z = -3
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mInvertX;
|
||||||
|
bool mInvertY;
|
||||||
|
|
||||||
|
float mGyroXSpeed;
|
||||||
|
float mGyroYSpeed;
|
||||||
|
float mGyroUpdateTimer;
|
||||||
|
|
||||||
|
float mGyroHSensitivity;
|
||||||
|
float mGyroVSensitivity;
|
||||||
|
GyroscopeAxis mGyroHAxis;
|
||||||
|
GyroscopeAxis mGyroVAxis;
|
||||||
|
float mGyroInputThreshold;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void updateSensors();
|
||||||
|
void correctGyroscopeAxes();
|
||||||
|
GyroscopeAxis mapGyroscopeAxis(const std::string& axis);
|
||||||
|
float getGyroAxisSpeed(GyroscopeAxis axis, const SDL_SensorEvent &arg) const;
|
||||||
|
SDL_Sensor* mGyroscope;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Loading…
Reference in a new issue