FreelookManager: Add gyro to support either keyboard/gamepad binding or motion based controllers

This commit is contained in:
iwubcode 2021-03-11 00:40:24 -06:00
parent 80cf87158e
commit d53ab32506
2 changed files with 78 additions and 1 deletions

View File

@ -12,6 +12,7 @@
#include "Core/FreeLookConfig.h" #include "Core/FreeLookConfig.h"
#include "InputCommon/ControllerEmu/ControlGroup/Buttons.h" #include "InputCommon/ControllerEmu/ControlGroup/Buttons.h"
#include "InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.h"
#include "InputCommon/InputConfig.h" #include "InputCommon/InputConfig.h"
#include "VideoCommon/FreeLookCamera.h" #include "VideoCommon/FreeLookCamera.h"
@ -60,6 +61,19 @@ enum FieldOfViewButtons
DecreaseY, DecreaseY,
}; };
} }
namespace GyroButtons
{
enum GyroButtons
{
PitchUp,
PitchDown,
RollLeft,
RollRight,
YawLeft,
YawRight,
};
}
} // namespace } // namespace
FreeLookController::FreeLookController(const unsigned int index) : m_index(index) FreeLookController::FreeLookController(const unsigned int index) : m_index(index)
@ -89,6 +103,9 @@ FreeLookController::FreeLookController(const unsigned int index) : m_index(index
m_fov_buttons->AddInput(ControllerEmu::Translate, _trans("Decrease X")); m_fov_buttons->AddInput(ControllerEmu::Translate, _trans("Decrease X"));
m_fov_buttons->AddInput(ControllerEmu::Translate, _trans("Increase Y")); m_fov_buttons->AddInput(ControllerEmu::Translate, _trans("Increase Y"));
m_fov_buttons->AddInput(ControllerEmu::Translate, _trans("Decrease Y")); m_fov_buttons->AddInput(ControllerEmu::Translate, _trans("Decrease Y"));
groups.emplace_back(m_rotation_gyro = new ControllerEmu::IMUGyroscope(
_trans("Incremental Rotation"), _trans("Incremental Rotation")));
} }
std::string FreeLookController::GetName() const std::string FreeLookController::GetName() const
@ -125,6 +142,35 @@ void FreeLookController::LoadDefaults(const ControllerInterface& ciface)
hotkey_string({"Shift", "`Axis Z+`"})); hotkey_string({"Shift", "`Axis Z+`"}));
m_fov_buttons->SetControlExpression(FieldOfViewButtons::DecreaseY, m_fov_buttons->SetControlExpression(FieldOfViewButtons::DecreaseY,
hotkey_string({"Shift", "`Axis Z-`"})); hotkey_string({"Shift", "`Axis Z-`"}));
#if defined HAVE_X11 && HAVE_X11
m_rotation_gyro->SetControlExpression(GyroButtons::PitchUp,
"if(`Click 3`,`RelativeMouse Y-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::PitchDown,
"if(`Click 3`,`RelativeMouse Y+` * 0.10, 0)");
#else
m_rotation_gyro->SetControlExpression(GyroButtons::PitchUp,
"if(`Click 1`,`RelativeMouse Y-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::PitchDown,
"if(`Click 1`,`RelativeMouse Y+` * 0.10, 0)");
#endif
m_rotation_gyro->SetControlExpression(GyroButtons::RollLeft,
"if(`Click 2`,`RelativeMouse X-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::RollRight,
"if(`Click 2`,`RelativeMouse X+` * 0.10, 0)");
#if defined HAVE_X11 && HAVE_X11
m_rotation_gyro->SetControlExpression(GyroButtons::YawLeft,
"if(`Click 3`,`RelativeMouse X-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::YawRight,
"if(`Click 3`,`RelativeMouse X+` * 0.10, 0)");
#else
m_rotation_gyro->SetControlExpression(GyroButtons::YawLeft,
"if(`Click 1`,`RelativeMouse X-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::YawRight,
"if(`Click 1`,`RelativeMouse X+` * 0.10, 0)");
#endif
} }
ControllerEmu::ControlGroup* FreeLookController::GetGroup(FreeLookGroup group) const ControllerEmu::ControlGroup* FreeLookController::GetGroup(FreeLookGroup group) const
@ -139,6 +185,8 @@ ControllerEmu::ControlGroup* FreeLookController::GetGroup(FreeLookGroup group) c
return m_fov_buttons; return m_fov_buttons;
case FreeLookGroup::Other: case FreeLookGroup::Other:
return m_other_buttons; return m_other_buttons;
case FreeLookGroup::Rotation:
return m_rotation_gyro;
default: default:
return nullptr; return nullptr;
} }
@ -151,6 +199,28 @@ void FreeLookController::Update()
const auto lock = GetStateLock(); const auto lock = GetStateLock();
float dt = 1.0;
if (m_last_free_look_rotate_time)
{
using seconds = std::chrono::duration<float, std::ratio<1>>;
dt = std::chrono::duration_cast<seconds>(std::chrono::steady_clock::now() -
*m_last_free_look_rotate_time)
.count();
}
m_last_free_look_rotate_time = std::chrono::steady_clock::now();
const auto gyro_motion_rad_velocity =
m_rotation_gyro->GetState() ? *m_rotation_gyro->GetState() : Common::Vec3{};
// Due to gyroscope implementation we need to swap the yaw and roll values
// and because of the different axis used for Wii and the PS3 motion directions,
// we need to invert the yaw and roll as well
const Common::Vec3 gyro_motion_rad_velocity_converted{
gyro_motion_rad_velocity.x, gyro_motion_rad_velocity.z * -1, gyro_motion_rad_velocity.y * -1};
const auto gyro_motion_quat =
Common::Quaternion::RotateXYZ(gyro_motion_rad_velocity_converted * dt);
g_freelook_camera.Rotate(gyro_motion_quat);
if (m_move_buttons->controls[MoveButtons::Up]->GetState<bool>()) if (m_move_buttons->controls[MoveButtons::Up]->GetState<bool>())
g_freelook_camera.MoveVertical(-g_freelook_camera.GetSpeed()); g_freelook_camera.MoveVertical(-g_freelook_camera.GetSpeed());

View File

@ -4,6 +4,9 @@
#pragma once #pragma once
#include <chrono>
#include <optional>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "InputCommon/ControllerEmu/ControllerEmu.h" #include "InputCommon/ControllerEmu/ControllerEmu.h"
@ -13,6 +16,7 @@ namespace ControllerEmu
{ {
class ControlGroup; class ControlGroup;
class Buttons; class Buttons;
class IMUGyroscope;
} // namespace ControllerEmu } // namespace ControllerEmu
enum class FreeLookGroup enum class FreeLookGroup
@ -20,7 +24,8 @@ enum class FreeLookGroup
Move, Move,
Speed, Speed,
FieldOfView, FieldOfView,
Other Other,
Rotation,
}; };
namespace FreeLook namespace FreeLook
@ -52,6 +57,8 @@ private:
ControllerEmu::Buttons* m_speed_buttons; ControllerEmu::Buttons* m_speed_buttons;
ControllerEmu::Buttons* m_fov_buttons; ControllerEmu::Buttons* m_fov_buttons;
ControllerEmu::Buttons* m_other_buttons; ControllerEmu::Buttons* m_other_buttons;
ControllerEmu::IMUGyroscope* m_rotation_gyro;
const unsigned int m_index; const unsigned int m_index;
std::optional<std::chrono::steady_clock::time_point> m_last_free_look_rotate_time;
}; };