dolphin/Source/Core/Core/FreeLookManager.cpp
JosJuice 1315b54ffa InputCommon: Use distinct values for profile key
Because the last commit made us use separate folders for GCPad and
GCKey profiles, we should also use separate game INI keys for them.
Otherwise setting e.g. PadProfile1 in a game INI will make both GCPad
and GCKey try to load it, typically with one of them succeeding and the
other one showing a panic alert due to the profile not existing in its
folder.

Better do this breaking change for GCKeys in the same PR as the other
breaking change rather than later.
2024-02-04 17:55:08 +01:00

367 lines
12 KiB
C++

// Copyright 2020 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/FreeLookManager.h"
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/ScopeGuard.h"
#include "Core/Config/FreeLookSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/FreeLookConfig.h"
#include "InputCommon/ControlReference/ControlReference.h"
#include "InputCommon/ControllerEmu/ControlGroup/Buttons.h"
#include "InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.h"
#include "InputCommon/InputConfig.h"
#include "VideoCommon/FreeLookCamera.h"
#include "VideoCommon/OnScreenDisplay.h"
namespace
{
namespace MoveButtons
{
enum MoveButtons
{
Up,
Down,
Left,
Right,
Forward,
Backward,
};
}
namespace SpeedButtons
{
enum SpeedButtons
{
Decrease,
Increase,
Reset,
};
}
namespace OtherButtons
{
enum OtherButtons
{
ResetView,
};
}
namespace FieldOfViewButtons
{
enum FieldOfViewButtons
{
IncreaseX,
DecreaseX,
IncreaseY,
DecreaseY,
};
}
namespace GyroButtons
{
enum GyroButtons
{
PitchUp,
PitchDown,
RollLeft,
RollRight,
YawLeft,
YawRight,
};
}
} // namespace
FreeLookController::FreeLookController(const unsigned int index) : m_index(index)
{
using Translatability = ControllerEmu::Translatability;
groups.emplace_back(m_move_buttons = new ControllerEmu::Buttons(_trans("Move")));
m_move_buttons->AddInput(Translatability::Translate, _trans("Up"));
m_move_buttons->AddInput(Translatability::Translate, _trans("Down"));
m_move_buttons->AddInput(Translatability::Translate, _trans("Left"));
m_move_buttons->AddInput(Translatability::Translate, _trans("Right"));
m_move_buttons->AddInput(Translatability::Translate, _trans("Forward"));
m_move_buttons->AddInput(Translatability::Translate, _trans("Backward"));
groups.emplace_back(m_speed_buttons = new ControllerEmu::Buttons(_trans("Speed")));
m_speed_buttons->AddInput(Translatability::Translate, _trans("Decrease"));
m_speed_buttons->AddInput(Translatability::Translate, _trans("Increase"));
m_speed_buttons->AddInput(Translatability::Translate, _trans("Reset"));
groups.emplace_back(m_other_buttons = new ControllerEmu::Buttons(_trans("Other")));
m_other_buttons->AddInput(Translatability::Translate, _trans("Reset View"));
groups.emplace_back(m_fov_buttons = new ControllerEmu::Buttons(_trans("Field of View")));
m_fov_buttons->AddInput(Translatability::Translate, _trans("Increase X"));
m_fov_buttons->AddInput(Translatability::Translate, _trans("Decrease X"));
m_fov_buttons->AddInput(Translatability::Translate, _trans("Increase Y"));
m_fov_buttons->AddInput(Translatability::Translate, _trans("Decrease Y"));
groups.emplace_back(m_rotation_gyro = new ControllerEmu::IMUGyroscope(
_trans("Incremental Rotation"), _trans("Incremental Rotation")));
}
std::string FreeLookController::GetName() const
{
return std::string("FreeLook") + char('1' + m_index);
}
InputConfig* FreeLookController::GetConfig() const
{
return FreeLook::GetInputConfig();
}
void FreeLookController::LoadDefaults(const ControllerInterface& ciface)
{
EmulatedController::LoadDefaults(ciface);
#ifndef ANDROID
auto hotkey_string = [](std::vector<std::string> inputs) {
return "@(" + JoinStrings(inputs, "+") + ')';
};
m_move_buttons->SetControlExpression(MoveButtons::Up, hotkey_string({"Shift", "E"}));
m_move_buttons->SetControlExpression(MoveButtons::Down, hotkey_string({"Shift", "Q"}));
m_move_buttons->SetControlExpression(MoveButtons::Left, hotkey_string({"Shift", "A"}));
m_move_buttons->SetControlExpression(MoveButtons::Right, hotkey_string({"Shift", "D"}));
m_move_buttons->SetControlExpression(MoveButtons::Forward, hotkey_string({"Shift", "W"}));
m_move_buttons->SetControlExpression(MoveButtons::Backward, hotkey_string({"Shift", "S"}));
m_speed_buttons->SetControlExpression(SpeedButtons::Decrease, hotkey_string({"Shift", "`1`"}));
m_speed_buttons->SetControlExpression(SpeedButtons::Increase, hotkey_string({"Shift", "`2`"}));
m_speed_buttons->SetControlExpression(SpeedButtons::Reset, hotkey_string({"Shift", "F"}));
m_other_buttons->SetControlExpression(OtherButtons::ResetView, hotkey_string({"Shift", "R"}));
m_fov_buttons->SetControlExpression(FieldOfViewButtons::IncreaseX,
hotkey_string({"Shift", "`Axis Z+`"}));
m_fov_buttons->SetControlExpression(FieldOfViewButtons::DecreaseX,
hotkey_string({"Shift", "`Axis Z-`"}));
m_fov_buttons->SetControlExpression(FieldOfViewButtons::IncreaseY,
hotkey_string({"Shift", "`Axis Z+`"}));
m_fov_buttons->SetControlExpression(FieldOfViewButtons::DecreaseY,
hotkey_string({"Shift", "`Axis Z-`"}));
// Left Click
#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)");
#elif defined(__APPLE__)
m_rotation_gyro->SetControlExpression(GyroButtons::PitchUp,
"if(`Left Click`,`RelativeMouse Y-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::PitchDown,
"if(`Left Click`,`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
// Middle Click
#ifdef __APPLE__
m_rotation_gyro->SetControlExpression(GyroButtons::RollLeft,
"if(`Middle Click`,`RelativeMouse X-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::RollRight,
"if(`Middle Click`,`RelativeMouse X+` * 0.10, 0)");
#else
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)");
#endif
// Right Click
#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)");
#elif defined(__APPLE__)
m_rotation_gyro->SetControlExpression(GyroButtons::YawLeft,
"if(`Right Click`,`RelativeMouse X-` * 0.10, 0)");
m_rotation_gyro->SetControlExpression(GyroButtons::YawRight,
"if(`Right Click`,`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
#endif
}
ControllerEmu::ControlGroup* FreeLookController::GetGroup(FreeLookGroup group) const
{
switch (group)
{
case FreeLookGroup::Move:
return m_move_buttons;
case FreeLookGroup::Speed:
return m_speed_buttons;
case FreeLookGroup::FieldOfView:
return m_fov_buttons;
case FreeLookGroup::Other:
return m_other_buttons;
case FreeLookGroup::Rotation:
return m_rotation_gyro;
default:
return nullptr;
}
}
void FreeLookController::Update()
{
if (!g_freelook_camera.IsActive())
return;
auto* camera_controller = g_freelook_camera.GetController();
if (camera_controller->SupportsInput())
{
UpdateInput(static_cast<CameraControllerInput*>(camera_controller));
}
}
void FreeLookController::UpdateInput(CameraControllerInput* camera_controller)
{
const auto lock = GetStateLock();
// Preserve the old controller gate state
const auto old_gate = ControlReference::GetInputGate();
Common::ScopeGuard gate_guard{[old_gate] { ControlReference::SetInputGate(old_gate); }};
// Switch to the free look focus gate
Core::UpdateInputGate(!Config::Get(Config::FREE_LOOK_BACKGROUND_INPUT));
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);
camera_controller->Rotate(gyro_motion_quat);
if (m_move_buttons->controls[MoveButtons::Up]->GetState<bool>())
camera_controller->MoveVertical(-camera_controller->GetSpeed() * dt);
if (m_move_buttons->controls[MoveButtons::Down]->GetState<bool>())
camera_controller->MoveVertical(camera_controller->GetSpeed() * dt);
if (m_move_buttons->controls[MoveButtons::Left]->GetState<bool>())
camera_controller->MoveHorizontal(camera_controller->GetSpeed() * dt);
if (m_move_buttons->controls[MoveButtons::Right]->GetState<bool>())
camera_controller->MoveHorizontal(-camera_controller->GetSpeed() * dt);
if (m_move_buttons->controls[MoveButtons::Forward]->GetState<bool>())
camera_controller->MoveForward(camera_controller->GetSpeed() * dt);
if (m_move_buttons->controls[MoveButtons::Backward]->GetState<bool>())
camera_controller->MoveForward(-camera_controller->GetSpeed() * dt);
if (m_fov_buttons->controls[FieldOfViewButtons::IncreaseX]->GetState<bool>())
camera_controller->IncreaseFovX(camera_controller->GetFovStepSize() * dt);
if (m_fov_buttons->controls[FieldOfViewButtons::DecreaseX]->GetState<bool>())
camera_controller->IncreaseFovX(-1.0f * camera_controller->GetFovStepSize() * dt);
if (m_fov_buttons->controls[FieldOfViewButtons::IncreaseY]->GetState<bool>())
camera_controller->IncreaseFovY(camera_controller->GetFovStepSize() * dt);
if (m_fov_buttons->controls[FieldOfViewButtons::DecreaseY]->GetState<bool>())
camera_controller->IncreaseFovY(-1.0f * camera_controller->GetFovStepSize() * dt);
if (m_speed_buttons->controls[SpeedButtons::Decrease]->GetState<bool>())
camera_controller->ModifySpeed(camera_controller->GetSpeed() * -0.9 * dt);
if (m_speed_buttons->controls[SpeedButtons::Increase]->GetState<bool>())
camera_controller->ModifySpeed(camera_controller->GetSpeed() * 1.1 * dt);
if (m_speed_buttons->controls[SpeedButtons::Reset]->GetState<bool>())
camera_controller->ResetSpeed();
if (m_other_buttons->controls[OtherButtons::ResetView]->GetState<bool>())
camera_controller->Reset();
}
namespace FreeLook
{
static InputConfig s_config("FreeLookController", _trans("FreeLook"), "FreeLookController",
"FreeLookController");
InputConfig* GetInputConfig()
{
return &s_config;
}
void Shutdown()
{
s_config.UnregisterHotplugCallback();
s_config.ClearControllers();
}
void Initialize()
{
if (s_config.ControllersNeedToBeCreated())
{
s_config.CreateController<FreeLookController>(0);
}
s_config.RegisterHotplugCallback();
FreeLook::GetConfig().Refresh();
s_config.LoadConfig();
}
void LoadInputConfig()
{
s_config.LoadConfig();
}
bool IsInitialized()
{
return !s_config.ControllersNeedToBeCreated();
}
ControllerEmu::ControlGroup* GetInputGroup(int pad_num, FreeLookGroup group)
{
return static_cast<FreeLookController*>(s_config.GetController(pad_num))->GetGroup(group);
}
void UpdateInput()
{
for (int i = 0; i < s_config.GetControllerCount(); i++)
{
static_cast<FreeLookController*>(s_config.GetController(i))->Update();
}
}
} // namespace FreeLook