diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h index a1d87800f4..d1ef058228 100644 --- a/Source/Core/Common/CommonPaths.h +++ b/Source/Core/Common/CommonPaths.h @@ -87,6 +87,7 @@ #define DEBUGGER_CONFIG "Debugger.ini" #define LOGGER_CONFIG "Logger.ini" #define DUALSHOCKUDPCLIENT_CONFIG "DSUClient.ini" +#define FREELOOK_CONFIG "FreeLook.ini" // Files in the directory returned by GetUserPath(D_LOGS_IDX) #define MAIN_LOG "dolphin.log" diff --git a/Source/Core/Common/Config/Enums.h b/Source/Core/Common/Config/Enums.h index 831726ae1e..5c75a01893 100644 --- a/Source/Core/Common/Config/Enums.h +++ b/Source/Core/Common/Config/Enums.h @@ -31,6 +31,7 @@ enum class System Logger, Debugger, DualShockUDPClient, + FreeLook, }; constexpr std::array SEARCH_ORDER{{ diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index 0d41395209..0a58c2417f 100644 --- a/Source/Core/Common/FileUtil.cpp +++ b/Source/Core/Common/FileUtil.cpp @@ -866,6 +866,7 @@ static void RebuildUserDirectories(unsigned int dir_index) s_user_paths[F_LOGGERCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + LOGGER_CONFIG; s_user_paths[F_DUALSHOCKUDPCLIENTCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + DUALSHOCKUDPCLIENT_CONFIG; + s_user_paths[F_FREELOOKCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + FREELOOK_CONFIG; s_user_paths[F_MAINLOG_IDX] = s_user_paths[D_LOGS_IDX] + MAIN_LOG; s_user_paths[F_MEM1DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM1_DUMP; s_user_paths[F_MEM2DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM2_DUMP; diff --git a/Source/Core/Common/FileUtil.h b/Source/Core/Common/FileUtil.h index 7e0b2e6990..d4d909695b 100644 --- a/Source/Core/Common/FileUtil.h +++ b/Source/Core/Common/FileUtil.h @@ -72,6 +72,7 @@ enum F_MEMORYWATCHERSOCKET_IDX, F_WIISDCARD_IDX, F_DUALSHOCKUDPCLIENTCONFIG_IDX, + F_FREELOOKCONFIG_IDX, NUM_PATH_INDICES }; diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 03c87e6db3..ccdc3268ae 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -17,6 +17,10 @@ add_library(core CoreTiming.h DSPEmulator.cpp DSPEmulator.h + FreeLookConfig.cpp + FreeLookConfig.h + FreeLookManager.cpp + FreeLookManager.h GeckoCodeConfig.cpp GeckoCodeConfig.h GeckoCode.cpp @@ -58,6 +62,8 @@ add_library(core Boot/ElfReader.cpp Boot/ElfReader.h Boot/ElfTypes.h + Config/FreeLookSettings.cpp + Config/FreeLookSettings.h Config/GraphicsSettings.cpp Config/GraphicsSettings.h Config/MainSettings.cpp diff --git a/Source/Core/Core/Config/FreeLookSettings.cpp b/Source/Core/Core/Config/FreeLookSettings.cpp new file mode 100644 index 0000000000..5f69b4c390 --- /dev/null +++ b/Source/Core/Core/Config/FreeLookSettings.cpp @@ -0,0 +1,21 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/Config/FreeLookSettings.h" +#include "Core/FreeLookConfig.h" + +#include + +#include "Common/Config/Config.h" + +namespace Config +{ +// Configuration Information +const Info FREE_LOOK_ENABLED{{System::FreeLook, "General", "Enabled"}, false}; + +// FreeLook.Controller1 +const Info FL1_CONTROL_TYPE{{System::FreeLook, "Camera1", "ControlType"}, + FreeLook::ControlType::SixAxis}; + +} // namespace Config diff --git a/Source/Core/Core/Config/FreeLookSettings.h b/Source/Core/Core/Config/FreeLookSettings.h new file mode 100644 index 0000000000..d17ecbe456 --- /dev/null +++ b/Source/Core/Core/Config/FreeLookSettings.h @@ -0,0 +1,23 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Common/Config/Config.h" + +namespace FreeLook +{ +enum class ControlType : int; +} + +namespace Config +{ +// Configuration Information + +extern const Info FREE_LOOK_ENABLED; + +// FreeLook.Controller1 +extern const Info FL1_CONTROL_TYPE; + +} // namespace Config diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp index d6f1f633dd..506d9062d5 100644 --- a/Source/Core/Core/Config/GraphicsSettings.cpp +++ b/Source/Core/Core/Config/GraphicsSettings.cpp @@ -42,9 +42,6 @@ const Info GFX_CACHE_HIRES_TEXTURES{{System::GFX, "Settings", "CacheHiresT const Info GFX_DUMP_EFB_TARGET{{System::GFX, "Settings", "DumpEFBTarget"}, false}; const Info GFX_DUMP_XFB_TARGET{{System::GFX, "Settings", "DumpXFBTarget"}, false}; const Info GFX_DUMP_FRAMES_AS_IMAGES{{System::GFX, "Settings", "DumpFramesAsImages"}, false}; -const Info GFX_FREE_LOOK{{System::GFX, "Settings", "FreeLook"}, false}; -const Info GFX_FREE_LOOK_CONTROL_TYPE{ - {System::GFX, "Settings", "FreeLookControlType"}, FreelookControlType::SixAxis}; const Info GFX_USE_FFV1{{System::GFX, "Settings", "UseFFV1"}, false}; const Info GFX_DUMP_FORMAT{{System::GFX, "Settings", "DumpFormat"}, "avi"}; const Info GFX_DUMP_CODEC{{System::GFX, "Settings", "DumpCodec"}, ""}; diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h index 228c2af3b9..75bcb227e0 100644 --- a/Source/Core/Core/Config/GraphicsSettings.h +++ b/Source/Core/Core/Config/GraphicsSettings.h @@ -43,8 +43,6 @@ extern const Info GFX_CACHE_HIRES_TEXTURES; extern const Info GFX_DUMP_EFB_TARGET; extern const Info GFX_DUMP_XFB_TARGET; extern const Info GFX_DUMP_FRAMES_AS_IMAGES; -extern const Info GFX_FREE_LOOK; -extern const Info GFX_FREE_LOOK_CONTROL_TYPE; extern const Info GFX_USE_FFV1; extern const Info GFX_DUMP_FORMAT; extern const Info GFX_DUMP_CODEC; diff --git a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp index f54e2ac9f5..65b46ec4bd 100644 --- a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp @@ -90,6 +90,7 @@ const std::map system_to_ini = { {Config::System::Logger, F_LOGGERCONFIG_IDX}, {Config::System::Debugger, F_DEBUGGERCONFIG_IDX}, {Config::System::DualShockUDPClient, F_DUALSHOCKUDPCLIENTCONFIG_IDX}, + {Config::System::FreeLook, F_FREELOOKCONFIG_IDX}, }; // INI layer configuration loader diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index a8d25a4bdc..fcb5eb0f4e 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -16,8 +16,9 @@ namespace ConfigLoaders { bool IsSettingSaveable(const Config::Location& config_location) { - for (Config::System system : {Config::System::SYSCONF, Config::System::GFX, - Config::System::DualShockUDPClient, Config::System::Logger}) + for (Config::System system : + {Config::System::SYSCONF, Config::System::GFX, Config::System::DualShockUDPClient, + Config::System::Logger, Config::System::FreeLook}) { if (config_location.system == system) return true; diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index b4d0de38d1..e942677efc 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -43,6 +43,7 @@ #include "Core/CoreTiming.h" #include "Core/DSPEmulator.h" #include "Core/FifoPlayer/FifoPlayer.h" +#include "Core/FreeLookManager.h" #include "Core/HLE/HLE.h" #include "Core/HW/CPU.h" #include "Core/HW/DSP.h" @@ -83,7 +84,6 @@ #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/VideoBackendBase.h" -#include "VideoCommon/VideoConfig.h" #ifdef ANDROID #include "jni/AndroidCommon/IDCache.h" @@ -485,6 +485,15 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi NetPlay::SetupWiimotes(); } + if (init_controllers) + { + FreeLook::Initialize(); + } + else + { + FreeLook::LoadInputConfig(); + } + Common::ScopeGuard controller_guard{[init_controllers, init_wiimotes] { if (!init_controllers) return; @@ -495,6 +504,8 @@ static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi Wiimote::Shutdown(); } + FreeLook::Shutdown(); + ResetRumble(); Keyboard::Shutdown(); diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index f672f088d1..c772229835 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -25,6 +25,7 @@ + @@ -83,6 +84,8 @@ + + @@ -386,6 +389,7 @@ + @@ -436,6 +440,8 @@ + + diff --git a/Source/Core/Core/FreeLookConfig.cpp b/Source/Core/Core/FreeLookConfig.cpp new file mode 100644 index 0000000000..f58a9e893b --- /dev/null +++ b/Source/Core/Core/FreeLookConfig.cpp @@ -0,0 +1,48 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/FreeLookConfig.h" +#include "Core/Config/FreeLookSettings.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" + +namespace FreeLook +{ +static Config s_config; +static Config s_active_config; +static bool s_has_registered_callback = false; + +Config& GetConfig() +{ + return s_config; +} + +const Config& GetActiveConfig() +{ + return s_active_config; +} + +void UpdateActiveConfig() +{ + s_active_config = s_config; +} + +Config::Config() +{ + camera_config.control_type = ControlType::SixAxis; + enabled = false; +} + +void Config::Refresh() +{ + if (!s_has_registered_callback) + { + ::Config::AddConfigChangedCallback([] { Core::RunAsCPUThread([] { s_config.Refresh(); }); }); + s_has_registered_callback = true; + } + + camera_config.control_type = ::Config::Get(::Config::FL1_CONTROL_TYPE); + enabled = ::Config::Get(::Config::FREE_LOOK_ENABLED); +} +} // namespace FreeLook diff --git a/Source/Core/Core/FreeLookConfig.h b/Source/Core/Core/FreeLookConfig.h new file mode 100644 index 0000000000..f012bde3e8 --- /dev/null +++ b/Source/Core/Core/FreeLookConfig.h @@ -0,0 +1,41 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +// IMPORTANT: UI etc should modify the value returned by FreeLook::GetConfig(). +// Free Look code should read from the value returned by FreeLook::GetActiveConfig(). +// The reason for this is to get rid of race conditions etc when the +// configuration changes in the middle of a frame. + +#pragma once + +namespace FreeLook +{ +enum class ControlType : int +{ + SixAxis, + FPS, + Orbital +}; + +struct CameraConfig +{ + ControlType control_type; +}; + +// NEVER inherit from this class. +struct Config final +{ + Config(); + void Refresh(); + + CameraConfig camera_config; + bool enabled; +}; + +Config& GetConfig(); +const Config& GetActiveConfig(); + +// Called every frame. +void UpdateActiveConfig(); +} // namespace FreeLook diff --git a/Source/Core/Core/FreeLookManager.cpp b/Source/Core/Core/FreeLookManager.cpp new file mode 100644 index 0000000000..6914b09fdb --- /dev/null +++ b/Source/Core/Core/FreeLookManager.cpp @@ -0,0 +1,247 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/FreeLookManager.h" + +#include "Common/Common.h" +#include "Common/CommonTypes.h" +#include "Common/Config/Config.h" + +#include "Core/ConfigManager.h" +#include "Core/FreeLookConfig.h" + +#include "InputCommon/ControllerEmu/ControlGroup/Buttons.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 + +FreeLookController::FreeLookController(const unsigned int index) : m_index(index) +{ + groups.emplace_back(m_move_buttons = new ControllerEmu::Buttons(_trans("Move"))); + + m_move_buttons->AddInput(ControllerEmu::Translate, _trans("Up")); + m_move_buttons->AddInput(ControllerEmu::Translate, _trans("Down")); + m_move_buttons->AddInput(ControllerEmu::Translate, _trans("Left")); + m_move_buttons->AddInput(ControllerEmu::Translate, _trans("Right")); + m_move_buttons->AddInput(ControllerEmu::Translate, _trans("Forward")); + m_move_buttons->AddInput(ControllerEmu::Translate, _trans("Backward")); + + groups.emplace_back(m_speed_buttons = new ControllerEmu::Buttons(_trans("Speed"))); + + m_speed_buttons->AddInput(ControllerEmu::Translate, _trans("Decrease")); + m_speed_buttons->AddInput(ControllerEmu::Translate, _trans("Increase")); + m_speed_buttons->AddInput(ControllerEmu::Translate, _trans("Reset")); + + groups.emplace_back(m_other_buttons = new ControllerEmu::Buttons(_trans("Other"))); + + m_other_buttons->AddInput(ControllerEmu::Translate, _trans("Reset View")); + + groups.emplace_back(m_fov_buttons = new ControllerEmu::Buttons(_trans("Field of View"))); + + m_fov_buttons->AddInput(ControllerEmu::Translate, _trans("Increase 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("Decrease Y")); +} + +std::string FreeLookController::GetName() const +{ + return std::string("FreeLook") + char('1' + m_index); +} + +void FreeLookController::LoadDefaults(const ControllerInterface& ciface) +{ + EmulatedController::LoadDefaults(ciface); + + auto hotkey_string = [](std::vector 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-`"})); +} + +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; + default: + return nullptr; + } +} + +void FreeLookController::Update() +{ + if (!g_freelook_camera.IsActive()) + return; + + if (m_move_buttons->controls[MoveButtons::Up]->GetState()) + g_freelook_camera.MoveVertical(-g_freelook_camera.GetSpeed()); + + if (m_move_buttons->controls[MoveButtons::Down]->GetState()) + g_freelook_camera.MoveVertical(g_freelook_camera.GetSpeed()); + + if (m_move_buttons->controls[MoveButtons::Left]->GetState()) + g_freelook_camera.MoveHorizontal(g_freelook_camera.GetSpeed()); + + if (m_move_buttons->controls[MoveButtons::Right]->GetState()) + g_freelook_camera.MoveHorizontal(-g_freelook_camera.GetSpeed()); + + if (m_move_buttons->controls[MoveButtons::Forward]->GetState()) + g_freelook_camera.MoveForward(g_freelook_camera.GetSpeed()); + + if (m_move_buttons->controls[MoveButtons::Backward]->GetState()) + g_freelook_camera.MoveForward(-g_freelook_camera.GetSpeed()); + + if (m_fov_buttons->controls[FieldOfViewButtons::IncreaseX]->GetState()) + g_freelook_camera.IncreaseFovX(g_freelook_camera.GetFovStepSize()); + + if (m_fov_buttons->controls[FieldOfViewButtons::DecreaseX]->GetState()) + g_freelook_camera.IncreaseFovX(-1.0f * g_freelook_camera.GetFovStepSize()); + + if (m_fov_buttons->controls[FieldOfViewButtons::IncreaseY]->GetState()) + g_freelook_camera.IncreaseFovY(g_freelook_camera.GetFovStepSize()); + + if (m_fov_buttons->controls[FieldOfViewButtons::DecreaseY]->GetState()) + g_freelook_camera.IncreaseFovY(-1.0f * g_freelook_camera.GetFovStepSize()); + + if (m_speed_buttons->controls[SpeedButtons::Decrease]->GetState()) + g_freelook_camera.ModifySpeed(1.0f / 1.1f); + + if (m_speed_buttons->controls[SpeedButtons::Increase]->GetState()) + g_freelook_camera.ModifySpeed(1.1f); + + if (m_speed_buttons->controls[SpeedButtons::Reset]->GetState()) + g_freelook_camera.ResetSpeed(); + + if (m_other_buttons->controls[OtherButtons::ResetView]->GetState()) + g_freelook_camera.Reset(); +} + +namespace FreeLook +{ +static InputConfig s_config("FreeLookController", _trans("FreeLook"), "FreeLookController"); +InputConfig* GetInputConfig() +{ + return &s_config; +} + +void Shutdown() +{ + s_config.UnregisterHotplugCallback(); + + s_config.ClearControllers(); +} + +void Initialize() +{ + if (s_config.ControllersNeedToBeCreated()) + { + s_config.CreateController(0); + } + + s_config.RegisterHotplugCallback(); + + FreeLook::GetConfig().Refresh(); + + s_config.LoadConfig(true); +} + +void LoadInputConfig() +{ + s_config.LoadConfig(true); +} + +bool IsInitialized() +{ + return !s_config.ControllersNeedToBeCreated(); +} + +ControllerEmu::ControlGroup* GetInputGroup(int pad_num, FreeLookGroup group) +{ + return static_cast(s_config.GetController(pad_num))->GetGroup(group); +} + +void UpdateInput() +{ + for (int i = 0; i < s_config.GetControllerCount(); i++) + { + static_cast(s_config.GetController(i))->Update(); + } +} + +} // namespace FreeLook diff --git a/Source/Core/Core/FreeLookManager.h b/Source/Core/Core/FreeLookManager.h new file mode 100644 index 0000000000..a74d26271f --- /dev/null +++ b/Source/Core/Core/FreeLookManager.h @@ -0,0 +1,57 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Common/CommonTypes.h" +#include "InputCommon/ControllerEmu/ControllerEmu.h" + +class InputConfig; + +namespace ControllerEmu +{ +class ControlGroup; +class Buttons; +} // namespace ControllerEmu + +enum class FreeLookGroup +{ + Move, + Speed, + FieldOfView, + Other +}; + +namespace FreeLook +{ +void Shutdown(); +void Initialize(); +void LoadInputConfig(); +bool IsInitialized(); +void UpdateInput(); + +InputConfig* GetInputConfig(); +ControllerEmu::ControlGroup* GetInputGroup(int pad_num, FreeLookGroup group); + +} // namespace FreeLook + +class FreeLookController final : public ControllerEmu::EmulatedController +{ +public: + explicit FreeLookController(unsigned int index); + + std::string GetName() const override; + void LoadDefaults(const ControllerInterface& ciface) override; + + ControllerEmu::ControlGroup* GetGroup(FreeLookGroup group) const; + void Update(); + +private: + ControllerEmu::Buttons* m_move_buttons; + ControllerEmu::Buttons* m_speed_buttons; + ControllerEmu::Buttons* m_fov_buttons; + ControllerEmu::Buttons* m_other_buttons; + + const unsigned int m_index; +}; diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp index 747be5212d..f9c02e02e9 100644 --- a/Source/Core/Core/HotkeyManager.cpp +++ b/Source/Core/Core/HotkeyManager.cpp @@ -24,7 +24,7 @@ #include "InputCommon/GCPadStatus.h" // clang-format off -constexpr std::array s_hotkey_labels{{ +constexpr std::array s_hotkey_labels{{ _trans("Open"), _trans("Change Disc"), _trans("Eject Disc"), @@ -117,21 +117,7 @@ constexpr std::array s_hotkey_labels{{ // i18n: IR stands for internal resolution _trans("Decrease IR"), - _trans("Freelook Decrease Speed"), - _trans("Freelook Increase Speed"), - _trans("Freelook Reset Speed"), - _trans("Freelook Move Up"), - _trans("Freelook Move Down"), - _trans("Freelook Move Left"), - _trans("Freelook Move Right"), - _trans("Freelook Zoom In"), - _trans("Freelook Zoom Out"), - _trans("Freelook Reset"), _trans("Freelook Toggle"), - _trans("Freelook Increase Field of View X"), - _trans("Freelook Decrease Field of View X"), - _trans("Freelook Increase Field of View Y"), - _trans("Freelook Decrease Field of View Y"), _trans("Toggle 3D Side-by-Side"), _trans("Toggle 3D Top-Bottom"), @@ -339,7 +325,7 @@ constexpr std::array s_groups_info = { {_trans("Controller Profile 4"), HK_NEXT_WIIMOTE_PROFILE_4, HK_PREV_GAME_WIIMOTE_PROFILE_4}, {_trans("Graphics Toggles"), HK_TOGGLE_CROP, HK_TOGGLE_TEXTURES}, {_trans("Internal Resolution"), HK_INCREASE_IR, HK_DECREASE_IR}, - {_trans("Freelook"), HK_FREELOOK_DECREASE_SPEED, HK_FREELOOK_DECREASE_FOV_Y}, + {_trans("Freelook"), HK_FREELOOK_TOGGLE, HK_FREELOOK_TOGGLE}, // i18n: Stereoscopic 3D {_trans("3D"), HK_TOGGLE_STEREO_SBS, HK_TOGGLE_STEREO_ANAGLYPH}, // i18n: Stereoscopic 3D @@ -446,22 +432,6 @@ void HotkeyManager::LoadDefaults(const ControllerInterface& ciface) set_key_expression(HK_TOGGLE_THROTTLE, "Tab"); #endif - // Freelook - set_key_expression(HK_FREELOOK_DECREASE_SPEED, hotkey_string({"Shift", "`1`"})); - set_key_expression(HK_FREELOOK_INCREASE_SPEED, hotkey_string({"Shift", "`2`"})); - set_key_expression(HK_FREELOOK_RESET_SPEED, hotkey_string({"Shift", "F"})); - set_key_expression(HK_FREELOOK_UP, hotkey_string({"Shift", "E"})); - set_key_expression(HK_FREELOOK_DOWN, hotkey_string({"Shift", "Q"})); - set_key_expression(HK_FREELOOK_LEFT, hotkey_string({"Shift", "A"})); - set_key_expression(HK_FREELOOK_RIGHT, hotkey_string({"Shift", "D"})); - set_key_expression(HK_FREELOOK_ZOOM_IN, hotkey_string({"Shift", "W"})); - set_key_expression(HK_FREELOOK_ZOOM_OUT, hotkey_string({"Shift", "S"})); - set_key_expression(HK_FREELOOK_RESET, hotkey_string({"Shift", "R"})); - set_key_expression(HK_FREELOOK_INCREASE_FOV_X, hotkey_string({"Shift", "`Axis Z+`"})); - set_key_expression(HK_FREELOOK_DECREASE_FOV_X, hotkey_string({"Shift", "`Axis Z-`"})); - set_key_expression(HK_FREELOOK_INCREASE_FOV_Y, hotkey_string({"Shift", "`Axis Z+`"})); - set_key_expression(HK_FREELOOK_DECREASE_FOV_Y, hotkey_string({"Shift", "`Axis Z-`"})); - // Savestates for (int i = 0; i < 8; i++) { diff --git a/Source/Core/Core/HotkeyManager.h b/Source/Core/Core/HotkeyManager.h index 8029199647..8bce8f86fe 100644 --- a/Source/Core/Core/HotkeyManager.h +++ b/Source/Core/Core/HotkeyManager.h @@ -101,21 +101,7 @@ enum Hotkey HK_INCREASE_IR, HK_DECREASE_IR, - HK_FREELOOK_DECREASE_SPEED, - HK_FREELOOK_INCREASE_SPEED, - HK_FREELOOK_RESET_SPEED, - HK_FREELOOK_UP, - HK_FREELOOK_DOWN, - HK_FREELOOK_LEFT, - HK_FREELOOK_RIGHT, - HK_FREELOOK_ZOOM_IN, - HK_FREELOOK_ZOOM_OUT, - HK_FREELOOK_RESET, HK_FREELOOK_TOGGLE, - HK_FREELOOK_INCREASE_FOV_X, - HK_FREELOOK_DECREASE_FOV_X, - HK_FREELOOK_INCREASE_FOV_Y, - HK_FREELOOK_DECREASE_FOV_Y, HK_TOGGLE_STEREO_SBS, HK_TOGGLE_STEREO_TAB, diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 70c28a6b7b..84fce4f471 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -constexpr u32 STATE_VERSION = 124; // Last changed in PR 9097 +constexpr u32 STATE_VERSION = 125; // Last changed in PR 8867 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list, diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index e0d21f0754..6bc5e7fa77 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -71,6 +71,10 @@ add_executable(dolphin-emu Config/ControllersWindow.h Config/FilesystemWidget.cpp Config/FilesystemWidget.h + Config/FreeLookWidget.cpp + Config/FreeLookWidget.h + Config/FreeLookWindow.cpp + Config/FreeLookWindow.h Config/GameConfigEdit.cpp Config/GameConfigEdit.h Config/GameConfigHighlighter.cpp @@ -112,6 +116,8 @@ add_executable(dolphin-emu Config/LogConfigWidget.h Config/LogWidget.cpp Config/LogWidget.h + Config/Mapping/FreeLookGeneral.cpp + Config/Mapping/FreeLookGeneral.h Config/Mapping/GCKeyboardEmu.cpp Config/Mapping/GCKeyboardEmu.h Config/Mapping/GCMicrophone.cpp diff --git a/Source/Core/DolphinQt/Config/FreeLookWidget.cpp b/Source/Core/DolphinQt/Config/FreeLookWidget.cpp new file mode 100644 index 0000000000..dec4493ca9 --- /dev/null +++ b/Source/Core/DolphinQt/Config/FreeLookWidget.cpp @@ -0,0 +1,112 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/FreeLookWidget.h" + +#include +#include +#include +#include +#include + +#include "Core/Config/FreeLookSettings.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" + +#include "DolphinQt/Config/Graphics/GraphicsChoice.h" +#include "DolphinQt/Config/Mapping/MappingWindow.h" +#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h" +#include "DolphinQt/Settings.h" + +FreeLookWidget::FreeLookWidget(QWidget* parent) : QWidget(parent) +{ + CreateLayout(); + LoadSettings(); + ConnectWidgets(); +} + +void FreeLookWidget::CreateLayout() +{ + auto* layout = new QVBoxLayout(); + + m_enable_freelook = new ToolTipCheckBox(tr("Enable")); + m_enable_freelook->setChecked(Config::Get(Config::FREE_LOOK_ENABLED)); + m_enable_freelook->SetDescription( + tr("Allows manipulation of the in-game camera.

If unsure, " + "leave this unchecked.")); + m_freelook_controller_configure_button = new QPushButton(tr("Configure Controller")); + + m_freelook_control_type = new GraphicsChoice({tr("Six Axis"), tr("First Person"), tr("Orbital")}, + Config::FL1_CONTROL_TYPE); + m_freelook_control_type->SetTitle(tr("Free Look Control Type")); + m_freelook_control_type->SetDescription(tr( + "Changes the in-game camera type during Free Look.

" + "Six Axis: Offers full camera control on all axes, akin to moving a spacecraft in zero " + "gravity. This is the most powerful Free Look option but is the most challenging to use.
" + "
" + "First Person: Controls the free camera similarly to a first person video game. The camera " + "can rotate and travel, but roll is impossible. Easy to use, but limiting.

" + "Orbital: Rotates the free camera around the original camera. Has no lateral movement, only " + "rotation and you may zoom up to the camera's origin point.")); + + auto* description = + new QLabel(tr("Free Look allows for manipulation of the in-game camera. " + "Different camera types are available from the dropdown.

" + "For detailed instructions, " + "" + "refer to this page.")); + description->setTextFormat(Qt::RichText); + description->setWordWrap(true); + description->setTextInteractionFlags(Qt::TextBrowserInteraction); + description->setOpenExternalLinks(true); + + auto* hlayout = new QHBoxLayout(); + hlayout->addWidget(new QLabel(tr("Camera 1"))); + hlayout->addWidget(m_freelook_control_type); + hlayout->addWidget(m_freelook_controller_configure_button); + + layout->addWidget(m_enable_freelook); + layout->addLayout(hlayout); + layout->addWidget(description); + + setLayout(layout); +} + +void FreeLookWidget::ConnectWidgets() +{ + connect(m_freelook_controller_configure_button, &QPushButton::clicked, this, + &FreeLookWidget::OnFreeLookControllerConfigured); + connect(m_enable_freelook, &QCheckBox::clicked, this, &FreeLookWidget::SaveSettings); + connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { + const QSignalBlocker blocker(this); + LoadSettings(); + }); +} + +void FreeLookWidget::OnFreeLookControllerConfigured() +{ + if (m_freelook_controller_configure_button != QObject::sender()) + return; + const int index = 0; + MappingWindow* window = new MappingWindow(this, MappingWindow::Type::MAPPING_FREELOOK, index); + window->setAttribute(Qt::WA_DeleteOnClose, true); + window->setWindowModality(Qt::WindowModality::WindowModal); + window->show(); +} + +void FreeLookWidget::LoadSettings() +{ + const bool checked = Config::Get(Config::FREE_LOOK_ENABLED); + m_enable_freelook->setChecked(checked); + m_freelook_control_type->setEnabled(checked); + m_freelook_controller_configure_button->setEnabled(checked); +} + +void FreeLookWidget::SaveSettings() +{ + const bool checked = m_enable_freelook->isChecked(); + Config::SetBaseOrCurrent(Config::FREE_LOOK_ENABLED, checked); + m_freelook_control_type->setEnabled(checked); + m_freelook_controller_configure_button->setEnabled(checked); +} diff --git a/Source/Core/DolphinQt/Config/FreeLookWidget.h b/Source/Core/DolphinQt/Config/FreeLookWidget.h new file mode 100644 index 0000000000..c517406a6c --- /dev/null +++ b/Source/Core/DolphinQt/Config/FreeLookWidget.h @@ -0,0 +1,30 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class GraphicsChoice; +class QPushButton; +class ToolTipCheckBox; + +class FreeLookWidget final : public QWidget +{ + Q_OBJECT +public: + explicit FreeLookWidget(QWidget* parent); + +private: + void CreateLayout(); + void ConnectWidgets(); + + void OnFreeLookControllerConfigured(); + void LoadSettings(); + void SaveSettings(); + + ToolTipCheckBox* m_enable_freelook; + GraphicsChoice* m_freelook_control_type; + QPushButton* m_freelook_controller_configure_button; +}; diff --git a/Source/Core/DolphinQt/Config/FreeLookWindow.cpp b/Source/Core/DolphinQt/Config/FreeLookWindow.cpp new file mode 100644 index 0000000000..8e9845aeef --- /dev/null +++ b/Source/Core/DolphinQt/Config/FreeLookWindow.cpp @@ -0,0 +1,31 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/FreeLookWindow.h" + +#include +#include +#include +#include + +#include "DolphinQt/Config/FreeLookWidget.h" + +FreeLookWindow::FreeLookWindow(QWidget* parent) : QDialog(parent) +{ + CreateMainLayout(); + + setWindowTitle(tr("Free Look Settings")); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); +} + +void FreeLookWindow::CreateMainLayout() +{ + m_button_box = new QDialogButtonBox(QDialogButtonBox::Close); + connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); + + auto* main_layout = new QVBoxLayout(); + main_layout->addWidget(new FreeLookWidget(this)); + main_layout->addWidget(m_button_box); + setLayout(main_layout); +} diff --git a/Source/Core/DolphinQt/Config/FreeLookWindow.h b/Source/Core/DolphinQt/Config/FreeLookWindow.h new file mode 100644 index 0000000000..5424c528a6 --- /dev/null +++ b/Source/Core/DolphinQt/Config/FreeLookWindow.h @@ -0,0 +1,21 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class QDialogButtonBox; + +class FreeLookWindow final : public QDialog +{ + Q_OBJECT +public: + explicit FreeLookWindow(QWidget* parent); + +private: + void CreateMainLayout(); + + QDialogButtonBox* m_button_box; +}; diff --git a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp index d91c7ee8c5..16ebd14dc9 100644 --- a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp @@ -80,19 +80,6 @@ void AdvancedWidget::CreateWidgets() utility_layout->addWidget(m_dump_efb_target, 1, 1); - // Freelook - auto* freelook_box = new QGroupBox(tr("Free Look")); - auto* freelook_layout = new QGridLayout(); - freelook_box->setLayout(freelook_layout); - - m_enable_freelook = new GraphicsBool(tr("Enable"), Config::GFX_FREE_LOOK); - m_freelook_control_type = new GraphicsChoice({tr("Six Axis"), tr("First Person"), tr("Orbital")}, - Config::GFX_FREE_LOOK_CONTROL_TYPE); - - freelook_layout->addWidget(m_enable_freelook, 0, 0); - freelook_layout->addWidget(new QLabel(tr("Control Type:")), 1, 0); - freelook_layout->addWidget(m_freelook_control_type, 1, 1); - // Texture dumping auto* texture_dump_box = new QGroupBox(tr("Texture Dumping")); auto* texture_dump_layout = new QGridLayout(); @@ -155,7 +142,6 @@ void AdvancedWidget::CreateWidgets() main_layout->addWidget(debugging_box); main_layout->addWidget(utility_box); - main_layout->addWidget(freelook_box); main_layout->addWidget(texture_dump_box); main_layout->addWidget(dump_box); main_layout->addWidget(misc_box); @@ -170,7 +156,6 @@ void AdvancedWidget::ConnectWidgets() connect(m_load_custom_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); connect(m_dump_use_ffv1, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); connect(m_enable_prog_scan, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); - connect(m_enable_freelook, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); connect(m_dump_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings); } @@ -180,8 +165,6 @@ void AdvancedWidget::LoadSettings() m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1)); m_enable_prog_scan->setChecked(Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN)); - - m_freelook_control_type->setEnabled(Config::Get(Config::GFX_FREE_LOOK)); m_dump_mip_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES)); m_dump_base_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES)); } @@ -192,8 +175,6 @@ void AdvancedWidget::SaveSettings() m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1)); Config::SetBase(Config::SYSCONF_PROGRESSIVE_SCAN, m_enable_prog_scan->isChecked()); - - m_freelook_control_type->setEnabled(Config::Get(Config::GFX_FREE_LOOK)); m_dump_mip_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES)); m_dump_base_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES)); } @@ -268,22 +249,6 @@ void AdvancedWidget::AddDescriptions() QT_TR_NOOP("Encodes frame dumps using the FFV1 codec.

If " "unsure, leave this unchecked."); #endif - static const char TR_FREE_LOOK_DESCRIPTION[] = QT_TR_NOOP( - "Allows manipulation of the in-game camera. Move the mouse while holding the right button " - "to pan or middle button to roll.

Use the WASD keys while holding SHIFT to move " - "the " - "camera. Press SHIFT+2 to increase speed or SHIFT+1 to decrease speed. Press SHIFT+R " - "to reset the camera or SHIFT+F to reset the speed.

If unsure, " - "leave this unchecked."); - static const char TR_FREE_LOOK_CONTROL_TYPE_DESCRIPTION[] = QT_TR_NOOP( - "Changes the in-game camera type during freelook.

" - "Six Axis: Offers full camera control on all axes, akin to moving a spacecraft in zero " - "gravity. This is the most powerful freelook option but is the most challenging to use.

" - "First Person: Controls the free camera similarly to a first person video game. The camera " - "can rotate and travel, but roll is impossible. Easy to use, but limiting.

" - "Orbital: Rotates the free camera around the original camera. Has no lateral movement, only " - "rotation and you may zoom up to the camera's origin point."); static const char TR_CROPPING_DESCRIPTION[] = QT_TR_NOOP( "Crops the picture from its native aspect ratio to 4:3 or " "16:9.

If unsure, leave this unchecked."); @@ -330,9 +295,6 @@ void AdvancedWidget::AddDescriptions() #endif m_enable_cropping->SetDescription(tr(TR_CROPPING_DESCRIPTION)); m_enable_prog_scan->SetDescription(tr(TR_PROGRESSIVE_SCAN_DESCRIPTION)); - m_enable_freelook->SetDescription(tr(TR_FREE_LOOK_DESCRIPTION)); - m_freelook_control_type->SetTitle(tr("Free Look Control Type")); - m_freelook_control_type->SetDescription(tr(TR_FREE_LOOK_CONTROL_TYPE_DESCRIPTION)); m_backend_multithreading->SetDescription(tr(TR_BACKEND_MULTITHREADING_DESCRIPTION)); #ifdef _WIN32 m_borderless_fullscreen->SetDescription(tr(TR_BORDERLESS_FULLSCREEN_DESCRIPTION)); diff --git a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h index a73d9ae1de..180df811b0 100644 --- a/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h +++ b/Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h @@ -42,8 +42,6 @@ private: GraphicsBool* m_dump_efb_target; GraphicsBool* m_disable_vram_copies; GraphicsBool* m_load_custom_textures; - GraphicsBool* m_enable_freelook; - GraphicsChoice* m_freelook_control_type; // Texture dumping GraphicsBool* m_dump_textures; diff --git a/Source/Core/DolphinQt/Config/Mapping/FreeLookGeneral.cpp b/Source/Core/DolphinQt/Config/Mapping/FreeLookGeneral.cpp new file mode 100644 index 0000000000..7fcd8bb63b --- /dev/null +++ b/Source/Core/DolphinQt/Config/Mapping/FreeLookGeneral.cpp @@ -0,0 +1,48 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/Mapping/FreeLookGeneral.h" + +#include +#include + +#include "Core/FreeLookManager.h" +#include "InputCommon/InputConfig.h" + +FreeLookGeneral::FreeLookGeneral(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void FreeLookGeneral::CreateMainLayout() +{ + auto* layout = new QGridLayout; + + layout->addWidget( + CreateGroupBox(tr("Move"), FreeLook::GetInputGroup(GetPort(), FreeLookGroup::Move)), 0, 0); + layout->addWidget( + CreateGroupBox(tr("Speed"), FreeLook::GetInputGroup(GetPort(), FreeLookGroup::Speed)), 0, 1); + layout->addWidget(CreateGroupBox(tr("Field of View"), + FreeLook::GetInputGroup(GetPort(), FreeLookGroup::FieldOfView)), + 0, 2); + layout->addWidget( + CreateGroupBox(tr("Other"), FreeLook::GetInputGroup(GetPort(), FreeLookGroup::Other)), 0, 3); + + setLayout(layout); +} + +void FreeLookGeneral::LoadSettings() +{ + FreeLook::LoadInputConfig(); +} + +void FreeLookGeneral::SaveSettings() +{ + FreeLook::GetInputConfig()->SaveConfig(); +} + +InputConfig* FreeLookGeneral::GetConfig() +{ + return FreeLook::GetInputConfig(); +} diff --git a/Source/Core/DolphinQt/Config/Mapping/FreeLookGeneral.h b/Source/Core/DolphinQt/Config/Mapping/FreeLookGeneral.h new file mode 100644 index 0000000000..d867db6793 --- /dev/null +++ b/Source/Core/DolphinQt/Config/Mapping/FreeLookGeneral.h @@ -0,0 +1,21 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt/Config/Mapping/MappingWidget.h" + +class FreeLookGeneral final : public MappingWidget +{ + Q_OBJECT +public: + explicit FreeLookGeneral(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); +}; diff --git a/Source/Core/DolphinQt/Config/Mapping/HotkeyGraphics.cpp b/Source/Core/DolphinQt/Config/Mapping/HotkeyGraphics.cpp index 9114322bce..1212142379 100644 --- a/Source/Core/DolphinQt/Config/Mapping/HotkeyGraphics.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/HotkeyGraphics.cpp @@ -18,12 +18,12 @@ void HotkeyGraphics::CreateMainLayout() { m_main_layout = new QGridLayout(); - m_main_layout->addWidget( - CreateGroupBox(tr("Freelook"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_FREELOOK)), 0, 0, -1, 1); - m_main_layout->addWidget(CreateGroupBox(tr("Graphics Toggles"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_GRAPHICS_TOGGLES)), - 0, 1); + 0, 0, -1, 1); + + m_main_layout->addWidget( + CreateGroupBox(tr("FreeLook"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_FREELOOK)), 0, 1); m_main_layout->addWidget( CreateGroupBox(tr("Internal Resolution"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_IR)), 1, 1); diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp index d433d27247..c079bd6b59 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp @@ -21,6 +21,7 @@ #include "Common/IniFile.h" #include "Common/StringUtil.h" +#include "DolphinQt/Config/Mapping/FreeLookGeneral.h" #include "DolphinQt/Config/Mapping/GCKeyboardEmu.h" #include "DolphinQt/Config/Mapping/GCMicrophone.h" #include "DolphinQt/Config/Mapping/GCPadEmu.h" @@ -82,7 +83,7 @@ void MappingWindow::CreateDevicesLayout() m_devices_combo = new QComboBox(); m_devices_refresh = new QPushButton(tr("Refresh")); - m_devices_combo->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + m_devices_combo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_devices_refresh->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_devices_layout->addWidget(m_devices_combo); @@ -428,6 +429,13 @@ void MappingWindow::SetMappingType(MappingWindow::Type type) setWindowTitle(tr("Hotkey Settings")); break; } + case Type::MAPPING_FREELOOK: + { + widget = new FreeLookGeneral(this); + AddWidget(tr("General"), widget); + setWindowTitle(tr("Free Look Controller %1").arg(GetPort() + 1)); + } + break; default: return; } diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h index c98ce900a1..520cdc2f68 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h @@ -42,7 +42,9 @@ public: // Wii MAPPING_WIIMOTE_EMU, // Hotkeys - MAPPING_HOTKEYS + MAPPING_HOTKEYS, + // Freelook + MAPPING_FREELOOK, }; explicit MappingWindow(QWidget* parent, Type type, int port_num); diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index de63050059..840233cc5e 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -55,6 +55,8 @@ + + @@ -75,6 +77,7 @@ + @@ -223,6 +226,8 @@ + + @@ -243,6 +248,7 @@ + diff --git a/Source/Core/DolphinQt/HotkeyScheduler.cpp b/Source/Core/DolphinQt/HotkeyScheduler.cpp index 1377dd6e48..1805d1e4db 100644 --- a/Source/Core/DolphinQt/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt/HotkeyScheduler.cpp @@ -15,10 +15,12 @@ #include "Common/Config/Config.h" #include "Common/Thread.h" +#include "Core/Config/FreeLookSettings.h" #include "Core/Config/GraphicsSettings.h" #include "Core/Config/UISettings.h" #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "Core/FreeLookManager.h" #include "Core/Host.h" #include "Core/HotkeyManager.h" #include "Core/IOS/IOS.h" @@ -30,7 +32,6 @@ #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" -#include "VideoCommon/FreeLookCamera.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/VertexShaderManager.h" @@ -537,57 +538,15 @@ void HotkeyScheduler::Run() Config::SetCurrent(Config::GFX_STEREO_CONVERGENCE, std::min(stereo_convergence + 5, Config::GFX_STEREO_CONVERGENCE_MAXIMUM)); - // Freelook - static float fl_speed = 1.0; - + // Free Look if (IsHotkey(HK_FREELOOK_TOGGLE)) { - const bool new_value = !Config::Get(Config::GFX_FREE_LOOK); - Config::SetCurrent(Config::GFX_FREE_LOOK, new_value); - OSD::AddMessage(StringFromFormat("Freelook: %s", new_value ? "Enabled" : "Disabled")); + const bool new_value = !Config::Get(Config::FREE_LOOK_ENABLED); + Config::SetCurrent(Config::FREE_LOOK_ENABLED, new_value); + OSD::AddMessage(StringFromFormat("Free Look: %s", new_value ? "Enabled" : "Disabled")); } - if (IsHotkey(HK_FREELOOK_DECREASE_SPEED, true)) - fl_speed /= 1.1f; - - if (IsHotkey(HK_FREELOOK_INCREASE_SPEED, true)) - fl_speed *= 1.1f; - - if (IsHotkey(HK_FREELOOK_RESET_SPEED, true)) - fl_speed = 1.0; - - if (IsHotkey(HK_FREELOOK_UP, true)) - g_freelook_camera.MoveVertical(-fl_speed); - - if (IsHotkey(HK_FREELOOK_DOWN, true)) - g_freelook_camera.MoveVertical(fl_speed); - - if (IsHotkey(HK_FREELOOK_LEFT, true)) - g_freelook_camera.MoveHorizontal(fl_speed); - - if (IsHotkey(HK_FREELOOK_RIGHT, true)) - g_freelook_camera.MoveHorizontal(-fl_speed); - - if (IsHotkey(HK_FREELOOK_ZOOM_IN, true)) - g_freelook_camera.Zoom(fl_speed); - - if (IsHotkey(HK_FREELOOK_ZOOM_OUT, true)) - g_freelook_camera.Zoom(-fl_speed); - - if (IsHotkey(HK_FREELOOK_INCREASE_FOV_X, true)) - g_freelook_camera.IncreaseFovX(g_freelook_camera.GetFovStepSize()); - - if (IsHotkey(HK_FREELOOK_DECREASE_FOV_X, true)) - g_freelook_camera.IncreaseFovX(-1.0f * g_freelook_camera.GetFovStepSize()); - - if (IsHotkey(HK_FREELOOK_INCREASE_FOV_Y, true)) - g_freelook_camera.IncreaseFovY(g_freelook_camera.GetFovStepSize()); - - if (IsHotkey(HK_FREELOOK_DECREASE_FOV_Y, true)) - g_freelook_camera.IncreaseFovY(-1.0f * g_freelook_camera.GetFovStepSize()); - - if (IsHotkey(HK_FREELOOK_RESET, true)) - g_freelook_camera.Reset(); + FreeLook::UpdateInput(); // Savestates for (u32 i = 0; i < State::NUM_STATES; i++) diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 54deeb47c6..b54687828d 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -41,6 +41,7 @@ #include "Core/Config/NetplaySettings.h" #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "Core/FreeLookManager.h" #include "Core/HW/DVD/DVDInterface.h" #include "Core/HW/GCKeyboard.h" #include "Core/HW/GCPad.h" @@ -62,6 +63,7 @@ #include "DolphinQt/AboutDialog.h" #include "DolphinQt/CheatsManager.h" #include "DolphinQt/Config/ControllersWindow.h" +#include "DolphinQt/Config/FreeLookWindow.h" #include "DolphinQt/Config/Graphics/GraphicsWindow.h" #include "DolphinQt/Config/LogConfigWidget.h" #include "DolphinQt/Config/LogWidget.h" @@ -302,6 +304,7 @@ void MainWindow::InitControllers() Pad::Initialize(); Keyboard::Initialize(); Wiimote::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES); + FreeLook::Initialize(); m_hotkey_scheduler = new HotkeyScheduler(); m_hotkey_scheduler->Start(); @@ -315,6 +318,9 @@ void MainWindow::InitControllers() Keyboard::LoadConfig(); Keyboard::GetConfig()->SaveConfig(); + + FreeLook::LoadInputConfig(); + FreeLook::GetInputConfig()->SaveConfig(); } void MainWindow::ShutdownControllers() @@ -325,6 +331,7 @@ void MainWindow::ShutdownControllers() Keyboard::Shutdown(); Wiimote::Shutdown(); HotkeyManagerEmu::Shutdown(); + FreeLook::Shutdown(); g_controller_interface.Shutdown(); m_hotkey_scheduler->deleteLater(); @@ -479,6 +486,7 @@ void MainWindow::ConnectMenuBar() connect(m_menu_bar, &MenuBar::ConfigureAudio, this, &MainWindow::ShowAudioWindow); connect(m_menu_bar, &MenuBar::ConfigureControllers, this, &MainWindow::ShowControllersWindow); connect(m_menu_bar, &MenuBar::ConfigureHotkeys, this, &MainWindow::ShowHotkeyDialog); + connect(m_menu_bar, &MenuBar::ConfigureFreelook, this, &MainWindow::ShowFreeLookWindow); // Tools connect(m_menu_bar, &MenuBar::ShowMemcardManager, this, &MainWindow::ShowMemcardManager); @@ -1101,6 +1109,19 @@ void MainWindow::ShowControllersWindow() m_controllers_window->activateWindow(); } +void MainWindow::ShowFreeLookWindow() +{ + if (!m_freelook_window) + { + m_freelook_window = new FreeLookWindow(this); + InstallHotkeyFilter(m_freelook_window); + } + + m_freelook_window->show(); + m_freelook_window->raise(); + m_freelook_window->activateWindow(); +} + void MainWindow::ShowSettingsWindow() { if (!m_settings_window) diff --git a/Source/Core/DolphinQt/MainWindow.h b/Source/Core/DolphinQt/MainWindow.h index 8f69bd6c8e..bd9da7651c 100644 --- a/Source/Core/DolphinQt/MainWindow.h +++ b/Source/Core/DolphinQt/MainWindow.h @@ -23,6 +23,7 @@ class ControllersWindow; class DiscordHandler; class DragEnterEvent; class FIFOPlayerWindow; +class FreeLookWindow; class GameList; class GCTASInputWindow; class GraphicsWindow; @@ -147,6 +148,7 @@ private: void ShowAudioWindow(); void ShowControllersWindow(); void ShowGraphicsWindow(); + void ShowFreeLookWindow(); void ShowAboutDialog(); void ShowHotkeyDialog(); void ShowNetPlaySetupDialog(); @@ -213,6 +215,7 @@ private: GraphicsWindow* m_graphics_window = nullptr; FIFOPlayerWindow* m_fifo_window = nullptr; MappingWindow* m_hotkey_window = nullptr; + FreeLookWindow* m_freelook_window = nullptr; HotkeyScheduler* m_hotkey_scheduler; NetPlayDialog* m_netplay_dialog; diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index 94c322e8e8..3869fcf8e5 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -528,6 +528,7 @@ void MenuBar::AddOptionsMenu() m_controllers_action = options_menu->addAction(tr("&Controller Settings"), this, &MenuBar::ConfigureControllers); options_menu->addAction(tr("&Hotkey Settings"), this, &MenuBar::ConfigureHotkeys); + options_menu->addAction(tr("&Free Look Settings"), this, &MenuBar::ConfigureFreelook); options_menu->addSeparator(); diff --git a/Source/Core/DolphinQt/MenuBar.h b/Source/Core/DolphinQt/MenuBar.h index b42a661813..c0364edbd9 100644 --- a/Source/Core/DolphinQt/MenuBar.h +++ b/Source/Core/DolphinQt/MenuBar.h @@ -91,6 +91,7 @@ signals: void ConfigureAudio(); void ConfigureControllers(); void ConfigureHotkeys(); + void ConfigureFreelook(); // View void ShowList(); diff --git a/Source/Core/DolphinQt/RenderWidget.cpp b/Source/Core/DolphinQt/RenderWidget.cpp index 8200b0b9f0..6be674526a 100644 --- a/Source/Core/DolphinQt/RenderWidget.cpp +++ b/Source/Core/DolphinQt/RenderWidget.cpp @@ -181,7 +181,7 @@ bool RenderWidget::event(QEvent* event) break; } case QEvent::MouseMove: - if (g_Config.bFreeLook) + if (g_freelook_camera.IsActive()) OnFreeLookMouseMove(static_cast(event)); [[fallthrough]]; diff --git a/Source/Core/VideoCommon/FreeLookCamera.cpp b/Source/Core/VideoCommon/FreeLookCamera.cpp index 7a15674da2..f3123e5cb6 100644 --- a/Source/Core/VideoCommon/FreeLookCamera.cpp +++ b/Source/Core/VideoCommon/FreeLookCamera.cpp @@ -12,25 +12,24 @@ #include "Common/MathUtil.h" #include "Common/ChunkFile.h" -#include "Core/Config/GraphicsSettings.h" #include "Core/ConfigManager.h" #include "Core/Core.h" + #include "VideoCommon/VideoCommon.h" -#include "VideoCommon/VideoConfig.h" FreeLookCamera g_freelook_camera; namespace { -std::string to_string(FreelookControlType type) +std::string to_string(FreeLook::ControlType type) { switch (type) { - case FreelookControlType::SixAxis: + case FreeLook::ControlType::SixAxis: return "Six Axis"; - case FreelookControlType::FPS: + case FreeLook::ControlType::FPS: return "First Person"; - case FreelookControlType::Orbital: + case FreeLook::ControlType::Orbital: return "Orbital"; } @@ -54,7 +53,7 @@ public: m_mat = Common::Matrix44::Translate(Common::Vec3{amt, 0, 0}) * m_mat; } - void Zoom(float amt) override + void MoveForward(float amt) override { m_mat = Common::Matrix44::Translate(Common::Vec3{0, 0, amt}) * m_mat; } @@ -97,7 +96,7 @@ public: m_position += right * amt; } - void Zoom(float amt) override + void MoveForward(float amt) override { Common::Vec3 forward{m_rotate_mat.data[8], m_rotate_mat.data[9], m_rotate_mat.data[10]}; m_position += forward * amt; @@ -150,7 +149,7 @@ public: void MoveHorizontal(float) override {} - void Zoom(float amt) override + void MoveForward(float amt) override { m_distance += -1 * amt; m_distance = std::clamp(m_distance, 0.0f, m_distance); @@ -176,22 +175,22 @@ private: }; } // namespace -void FreeLookCamera::SetControlType(FreelookControlType type) +void FreeLookCamera::SetControlType(FreeLook::ControlType type) { if (m_current_type && *m_current_type == type) { return; } - if (type == FreelookControlType::SixAxis) + if (type == FreeLook::ControlType::SixAxis) { m_camera_controller = std::make_unique(); } - else if (type == FreelookControlType::Orbital) + else if (type == FreeLook::ControlType::Orbital) { m_camera_controller = std::make_unique(); } - else + else if (type == FreeLook::ControlType::FPS) { m_camera_controller = std::make_unique(); } @@ -221,9 +220,9 @@ void FreeLookCamera::MoveHorizontal(float amt) m_dirty = true; } -void FreeLookCamera::Zoom(float amt) +void FreeLookCamera::MoveForward(float amt) { - m_camera_controller->Zoom(amt); + m_camera_controller->MoveForward(amt); m_dirty = true; } @@ -258,10 +257,26 @@ void FreeLookCamera::Reset() m_dirty = true; } +void FreeLookCamera::ModifySpeed(float multiplier) +{ + m_speed *= multiplier; +} + +void FreeLookCamera::ResetSpeed() +{ + m_speed = 1.0f; +} + +float FreeLookCamera::GetSpeed() const +{ + return m_speed; +} + void FreeLookCamera::DoState(PointerWrap& p) { if (p.mode == PointerWrap::MODE_WRITE || p.mode == PointerWrap::MODE_MEASURE) { + p.Do(m_speed); p.Do(m_current_type); p.Do(m_fov_x); p.Do(m_fov_y); @@ -273,6 +288,7 @@ void FreeLookCamera::DoState(PointerWrap& p) else { const auto old_type = m_current_type; + p.Do(m_speed); p.Do(m_current_type); p.Do(m_fov_x); p.Do(m_fov_y); @@ -303,3 +319,8 @@ void FreeLookCamera::SetClean() { m_dirty = false; } + +bool FreeLookCamera::IsActive() const +{ + return FreeLook::GetActiveConfig().enabled; +} diff --git a/Source/Core/VideoCommon/FreeLookCamera.h b/Source/Core/VideoCommon/FreeLookCamera.h index 0a35e20972..4db1ad68c1 100644 --- a/Source/Core/VideoCommon/FreeLookCamera.h +++ b/Source/Core/VideoCommon/FreeLookCamera.h @@ -8,7 +8,7 @@ #include #include "Common/Matrix.h" -#include "VideoCommon/VideoConfig.h" +#include "Core/FreeLookConfig.h" class PointerWrap; @@ -29,7 +29,7 @@ public: virtual void MoveVertical(float amt) = 0; virtual void MoveHorizontal(float amt) = 0; - virtual void Zoom(float amt) = 0; + virtual void MoveForward(float amt) = 0; virtual void Rotate(const Common::Vec3& amt) = 0; @@ -41,14 +41,13 @@ public: class FreeLookCamera { public: - void SetControlType(FreelookControlType type); + void SetControlType(FreeLook::ControlType type); Common::Matrix44 GetView(); Common::Vec2 GetFieldOfView() const; void MoveVertical(float amt); void MoveHorizontal(float amt); - - void Zoom(float amt); + void MoveForward(float amt); void Rotate(const Common::Vec3& amt); @@ -63,14 +62,22 @@ public: bool IsDirty() const; void SetClean(); + void ModifySpeed(float multiplier); + void ResetSpeed(); + float GetSpeed() const; + + bool IsActive() const; + private: bool m_dirty = false; float m_fov_x = 1.0f; float m_fov_y = 1.0f; - std::optional m_current_type; + std::optional m_current_type; std::unique_ptr m_camera_controller; float m_fov_step_size = 0.025f; + float m_speed = 1.0f; + bool m_enabled = true; }; extern FreeLookCamera g_freelook_camera; diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 02deb3a8b1..8cc777d173 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -45,6 +45,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/FifoPlayer/FifoRecorder.h" +#include "Core/FreeLookConfig.h" #include "Core/HW/SystemTimers.h" #include "Core/HW/VideoInterface.h" #include "Core/Host.h" @@ -105,6 +106,7 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height, float backbuffer MAX_XFB_HEIGHT} { UpdateActiveConfig(); + FreeLook::UpdateActiveConfig(); UpdateDrawRectangle(); CalculateTargetSize(); @@ -402,11 +404,9 @@ void Renderer::CheckForConfigChanges() const bool old_bbox = g_ActiveConfig.bBBoxEnable; UpdateActiveConfig(); + FreeLook::UpdateActiveConfig(); - if (g_ActiveConfig.bFreeLook) - { - g_freelook_camera.SetControlType(g_ActiveConfig.iFreelookControlType); - } + g_freelook_camera.SetControlType(FreeLook::GetActiveConfig().camera_config.control_type); // Update texture cache settings with any changed options. g_texture_cache->OnConfigChanged(g_ActiveConfig); diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index 04cb3b2f6f..9c82d9b431 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -112,7 +112,6 @@ void VertexShaderManager::Init() bViewportChanged = false; bTexMtxInfoChanged = false; bLightingConfigChanged = false; - g_freelook_camera.SetControlType(Config::Get(Config::GFX_FREE_LOOK_CONTROL_TYPE)); std::memset(static_cast(&xfmem), 0, sizeof(xfmem)); constants = {}; @@ -357,7 +356,7 @@ void VertexShaderManager::SetConstants() case GX_PERSPECTIVE: { const Common::Vec2 fov = - g_ActiveConfig.bFreeLook ? g_freelook_camera.GetFieldOfView() : Common::Vec2{1, 1}; + g_freelook_camera.IsActive() ? g_freelook_camera.GetFieldOfView() : Common::Vec2{1, 1}; g_fProjectionMatrix[0] = rawProjection[0] * g_ActiveConfig.fAspectRatioHackW * fov.x; g_fProjectionMatrix[1] = 0.0f; g_fProjectionMatrix[2] = rawProjection[1] * g_ActiveConfig.fAspectRatioHackW * fov.x; @@ -420,7 +419,7 @@ void VertexShaderManager::SetConstants() auto corrected_matrix = s_viewportCorrection * Common::Matrix44::FromArray(g_fProjectionMatrix); - if (g_ActiveConfig.bFreeLook && xfmem.projection.type == GX_PERSPECTIVE) + if (g_freelook_camera.IsActive() && xfmem.projection.type == GX_PERSPECTIVE) corrected_matrix *= g_freelook_camera.GetView(); memcpy(constants.projection.data(), corrected_matrix.data.data(), 4 * sizeof(float4)); diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index b0ab912e6c..9ed9a599e4 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -92,8 +92,6 @@ void VideoConfig::Refresh() bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET); bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET); bDumpFramesAsImages = Config::Get(Config::GFX_DUMP_FRAMES_AS_IMAGES); - bFreeLook = Config::Get(Config::GFX_FREE_LOOK); - iFreelookControlType = Config::Get(Config::GFX_FREE_LOOK_CONTROL_TYPE); bUseFFV1 = Config::Get(Config::GFX_USE_FFV1); sDumpFormat = Config::Get(Config::GFX_DUMP_FORMAT); sDumpCodec = Config::Get(Config::GFX_DUMP_CODEC); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index dacb286ada..6c328c864b 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -51,13 +51,6 @@ enum class ShaderCompilationMode : int AsynchronousSkipRendering }; -enum class FreelookControlType : int -{ - SixAxis, - FPS, - Orbital -}; - // NEVER inherit from this class. struct VideoConfig final { @@ -115,8 +108,6 @@ struct VideoConfig final std::string sDumpFormat; std::string sDumpPath; bool bInternalResolutionFrameDumps; - bool bFreeLook; - FreelookControlType iFreelookControlType; bool bBorderlessFullscreen; bool bEnableGPUTextureDecoding; int iBitrateKbps;