1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-04 02:41:19 +00:00
OpenMW/apps/openmw/mwinput/sensormanager.cpp
elsid dcd81d026f
Use settings values for Video settings
* Convert window mode, vsync mode into enums, screenshot type into a struct.
* Add missing doc for screenshot type.
2023-10-27 14:31:23 +02:00

180 lines
5.1 KiB
C++

#include "sensormanager.hpp"
#include <components/debug/debuglog.hpp>
#include <components/settings/values.hpp>
namespace MWInput
{
SensorManager::SensorManager()
: mRotation()
, mGyroValues()
, mGyroUpdateTimer(0.f)
, mGyroscope(nullptr)
{
init();
}
void SensorManager::init()
{
correctGyroscopeAxes();
updateSensors();
}
SensorManager::~SensorManager()
{
if (mGyroscope != nullptr)
{
SDL_SensorClose(mGyroscope);
mGyroscope = nullptr;
}
}
void SensorManager::correctGyroscopeAxes()
{
if (!Settings::input().mEnableGyroscope)
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.
mRotation = osg::Matrixf::identity();
float angle = 0;
SDL_DisplayOrientation currentOrientation = SDL_GetDisplayOrientation(Settings::video().mScreen);
switch (currentOrientation)
{
case SDL_ORIENTATION_UNKNOWN:
break;
case SDL_ORIENTATION_LANDSCAPE:
break;
case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
{
angle = osg::PIf;
break;
}
case SDL_ORIENTATION_PORTRAIT:
{
angle = -0.5 * osg::PIf;
break;
}
case SDL_ORIENTATION_PORTRAIT_FLIPPED:
{
angle = 0.5 * osg::PIf;
break;
}
}
mRotation.makeRotate(angle, osg::Vec3f(0, 0, 1));
}
void SensorManager::updateSensors()
{
if (Settings::input().mEnableGyroscope)
{
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;
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;
mGyroUpdateTimer = 0.f;
}
}
}
void SensorManager::processChangedSettings(const Settings::CategorySettingVector& changed)
{
for (const auto& setting : changed)
{
if (setting.first == "Input" && setting.second == "enable gyroscope")
init();
}
}
void SensorManager::displayOrientationChanged()
{
correctGyroscopeAxes();
}
void SensorManager::sensorUpdated(const SDL_SensorEvent& arg)
{
if (!Settings::input().mEnableGyroscope)
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:
{
osg::Vec3f gyro(arg.data[0], arg.data[1], arg.data[2]);
mGyroValues = mRotation * gyro;
mGyroUpdateTimer = 0.f;
break;
}
default:
break;
}
}
void SensorManager::update(float dt)
{
mGyroUpdateTimer += dt;
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.
mGyroValues = osg::Vec3f();
mGyroUpdateTimer = 0.f;
}
}
bool SensorManager::isGyroAvailable() const
{
return mGyroscope != nullptr;
}
std::array<float, 3> SensorManager::getGyroValues() const
{
return { mGyroValues.x(), mGyroValues.y(), mGyroValues.z() };
}
}