diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp index 80b293f940..113f4db737 100644 --- a/Source/Core/Core/HotkeyManager.cpp +++ b/Source/Core/Core/HotkeyManager.cpp @@ -69,6 +69,9 @@ constexpr std::array s_hotkey_labels{{ _trans("Connect Wii Remote 4"), _trans("Connect Balance Board"), + _trans("Next Wii Remote Profile"), + _trans("Previous Wii Remote Profile"), + _trans("Toggle Crop"), _trans("Toggle Aspect Ratio"), _trans("Toggle EFB Copies"), @@ -255,6 +258,7 @@ constexpr std::array s_groups_info = { {_trans("Program Counter"), HK_SHOW_PC, HK_SET_PC}, {_trans("Breakpoint"), HK_BP_TOGGLE, HK_MBP_ADD}, {_trans("Wii"), HK_TRIGGER_SYNC_BUTTON, HK_BALANCEBOARD_CONNECT}, + {_trans("Controller Profile"), HK_NEXT_WIIMOTE_PROFILE, HK_PREV_WIIMOTE_PROFILE}, {_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_RESET}, diff --git a/Source/Core/Core/HotkeyManager.h b/Source/Core/Core/HotkeyManager.h index 8505412d16..8b639f59fd 100644 --- a/Source/Core/Core/HotkeyManager.h +++ b/Source/Core/Core/HotkeyManager.h @@ -67,6 +67,9 @@ enum Hotkey HK_WIIMOTE4_CONNECT, HK_BALANCEBOARD_CONNECT, + HK_NEXT_WIIMOTE_PROFILE, + HK_PREV_WIIMOTE_PROFILE, + HK_TOGGLE_CROP, HK_TOGGLE_AR, HK_TOGGLE_EFBCOPIES, @@ -166,6 +169,7 @@ enum HotkeyGroup : int HKGP_PC, HKGP_BREAKPOINT, HKGP_WII, + HKGP_CONTROLLER_PROFILE, HKGP_GRAPHICS_TOGGLES, HKGP_IR, HKGP_FREELOOK, diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 8ff38fe645..b7c3c5c12e 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -50,6 +50,7 @@ add_executable(dolphin-emu Config/Mapping/GCPadEmu.cpp Config/Mapping/GCPadWiiUConfigDialog.cpp Config/Mapping/Hotkey3D.cpp + Config/Mapping/HotkeyControllerProfile.cpp Config/Mapping/HotkeyDebugging.cpp Config/Mapping/HotkeyGeneral.cpp Config/Mapping/HotkeyGraphics.cpp diff --git a/Source/Core/DolphinQt/Config/Mapping/HotkeyControllerProfile.cpp b/Source/Core/DolphinQt/Config/Mapping/HotkeyControllerProfile.cpp new file mode 100644 index 0000000000..14ae68f749 --- /dev/null +++ b/Source/Core/DolphinQt/Config/Mapping/HotkeyControllerProfile.cpp @@ -0,0 +1,39 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/Mapping/HotkeyControllerProfile.h" + +#include +#include + +#include "Core/HotkeyManager.h" + +HotkeyControllerProfile::HotkeyControllerProfile(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void HotkeyControllerProfile::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget(CreateGroupBox(tr("Controller Profile"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_CONTROLLER_PROFILE))); + + setLayout(m_main_layout); +} + +InputConfig* HotkeyControllerProfile::GetConfig() +{ + return HotkeyManagerEmu::GetConfig(); +} + +void HotkeyControllerProfile::LoadSettings() +{ + HotkeyManagerEmu::LoadConfig(); +} + +void HotkeyControllerProfile::SaveSettings() +{ + HotkeyManagerEmu::GetConfig()->SaveConfig(); +} diff --git a/Source/Core/DolphinQt/Config/Mapping/HotkeyControllerProfile.h b/Source/Core/DolphinQt/Config/Mapping/HotkeyControllerProfile.h new file mode 100644 index 0000000000..04c5435b27 --- /dev/null +++ b/Source/Core/DolphinQt/Config/Mapping/HotkeyControllerProfile.h @@ -0,0 +1,26 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt/Config/Mapping/MappingWidget.h" + +class QHBoxLayout; + +class HotkeyControllerProfile final : public MappingWidget +{ + Q_OBJECT +public: + explicit HotkeyControllerProfile(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + // Main + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp index 48e5a5f0f2..5424888ef5 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp @@ -25,6 +25,7 @@ #include "DolphinQt/Config/Mapping/GCMicrophone.h" #include "DolphinQt/Config/Mapping/GCPadEmu.h" #include "DolphinQt/Config/Mapping/Hotkey3D.h" +#include "DolphinQt/Config/Mapping/HotkeyControllerProfile.h" #include "DolphinQt/Config/Mapping/HotkeyDebugging.h" #include "DolphinQt/Config/Mapping/HotkeyGeneral.h" #include "DolphinQt/Config/Mapping/HotkeyGraphics.h" @@ -310,6 +311,7 @@ void MappingWindow::SetMappingType(MappingWindow::Type type) AddWidget(tr("Debugging"), new HotkeyDebugging(this)); AddWidget(tr("Wii and Wii Remote"), new HotkeyWii(this)); + AddWidget(tr("Controller Profile"), new HotkeyControllerProfile(this)); AddWidget(tr("Graphics"), new HotkeyGraphics(this)); AddWidget(tr("3D"), new Hotkey3D(this)); AddWidget(tr("Save and Load State"), new HotkeyStates(this)); diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index b87180eb2d..db2d90c4b2 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -70,6 +70,7 @@ + @@ -203,6 +204,7 @@ + @@ -283,6 +285,7 @@ + diff --git a/Source/Core/DolphinQt/HotkeyScheduler.cpp b/Source/Core/DolphinQt/HotkeyScheduler.cpp index 4853fd4517..6f29aa8431 100644 --- a/Source/Core/DolphinQt/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt/HotkeyScheduler.cpp @@ -240,6 +240,11 @@ void HotkeyScheduler::Run() emit ConnectWiiRemote(wiimote_id); } + if (IsHotkey(HK_PREV_WIIMOTE_PROFILE)) + m_profile_cycler.PreviousWiimoteProfile(); + else if (IsHotkey(HK_NEXT_WIIMOTE_PROFILE)) + m_profile_cycler.NextWiimoteProfile(); + const auto show_msg = [](OSDMessage message) { if (g_renderer) g_renderer->ShowOSDMessage(message); diff --git a/Source/Core/DolphinQt/HotkeyScheduler.h b/Source/Core/DolphinQt/HotkeyScheduler.h index 673f6fcab7..998bda3a02 100644 --- a/Source/Core/DolphinQt/HotkeyScheduler.h +++ b/Source/Core/DolphinQt/HotkeyScheduler.h @@ -9,6 +9,7 @@ #include #include "Common/Flag.h" +#include "InputCommon/InputProfile.h" class HotkeyScheduler : public QObject { @@ -64,4 +65,6 @@ private: Common::Flag m_stop_requested; std::thread m_thread; + + InputProfile::ProfileCycler m_profile_cycler; }; diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index 99cf2f9679..a3ef2722d8 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(inputcommon InputConfig.cpp + InputProfile.cpp ControllerEmu/ControllerEmu.cpp ControllerEmu/Control/Control.cpp ControllerEmu/Control/Input.cpp diff --git a/Source/Core/InputCommon/InputCommon.vcxproj b/Source/Core/InputCommon/InputCommon.vcxproj index 84ad406de1..6d0efb2c91 100644 --- a/Source/Core/InputCommon/InputCommon.vcxproj +++ b/Source/Core/InputCommon/InputCommon.vcxproj @@ -71,6 +71,7 @@ 4200;%(DisableSpecificWarnings) + @@ -105,6 +106,7 @@ + diff --git a/Source/Core/InputCommon/InputCommon.vcxproj.filters b/Source/Core/InputCommon/InputCommon.vcxproj.filters index 600a77727d..c67333497c 100644 --- a/Source/Core/InputCommon/InputCommon.vcxproj.filters +++ b/Source/Core/InputCommon/InputCommon.vcxproj.filters @@ -110,6 +110,7 @@ ControllerInterface + @@ -202,6 +203,7 @@ ControllerInterface + diff --git a/Source/Core/InputCommon/InputConfig.cpp b/Source/Core/InputCommon/InputConfig.cpp index 2a5766fbbe..989c1bdce9 100644 --- a/Source/Core/InputCommon/InputConfig.cpp +++ b/Source/Core/InputCommon/InputConfig.cpp @@ -128,6 +128,11 @@ bool InputConfig::ControllersNeedToBeCreated() const return m_controllers.empty(); } +std::size_t InputConfig::GetControllerCount() const +{ + return m_controllers.size(); +} + bool InputConfig::IsControllerControlledByGamepadDevice(int index) const { if (static_cast(index) >= m_controllers.size()) diff --git a/Source/Core/InputCommon/InputConfig.h b/Source/Core/InputCommon/InputConfig.h index a993a412b1..004e4be8bb 100644 --- a/Source/Core/InputCommon/InputConfig.h +++ b/Source/Core/InputCommon/InputConfig.h @@ -38,6 +38,7 @@ public: std::string GetGUIName() const { return m_gui_name; } std::string GetProfileName() const { return m_profile_name; } + std::size_t GetControllerCount() const; private: std::vector> m_controllers; diff --git a/Source/Core/InputCommon/InputProfile.cpp b/Source/Core/InputCommon/InputProfile.cpp new file mode 100644 index 0000000000..87d8c5bcab --- /dev/null +++ b/Source/Core/InputCommon/InputProfile.cpp @@ -0,0 +1,100 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Common/FileSearch.h" +#include "Common/FileUtil.h" + +#include "Core/Core.h" +#include "Core/HW/Wiimote.h" +#include "Core/HotkeyManager.h" + +#include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "InputCommon/InputConfig.h" +#include "InputCommon/InputProfile.h" + +namespace InputProfile +{ + + namespace + { + constexpr int display_message_ms = 3000; + } + + std::vector ProfileCycler::GetProfilesForDevice(InputConfig* device_configuration) + { + const std::string device_profile_root_location(File::GetUserPath(D_CONFIG_IDX) + "Profiles/" + device_configuration->GetProfileName()); + return Common::DoFileSearch({ device_profile_root_location }, { ".ini" }); + } + + std::string ProfileCycler::GetProfile(CycleDirection cycle_direction, int& profile_index, const std::vector& profiles) + { + // update the index and bind it to the number of available strings + auto positive_modulo = [](int& i, int n) {i = (i % n + n) % n;}; + profile_index += static_cast(cycle_direction); + positive_modulo(profile_index, static_cast(profiles.size())); + + return profiles[profile_index]; + } + + void ProfileCycler::UpdateToProfile(const std::string& profile_filename, const std::vector& controllers) + { + std::string base; + SplitPath(profile_filename, nullptr, &base, nullptr); + + IniFile ini_file; + if (ini_file.Load(profile_filename)) + { + Core::DisplayMessage("Loading input profile: " + base, display_message_ms); + + for (auto* controller : controllers) + { + controller->LoadConfig(ini_file.GetOrCreateSection("Profile")); + controller->UpdateReferences(g_controller_interface); + } + } + else + { + Core::DisplayMessage("Unable to load input profile: " + base, display_message_ms); + } + } + + std::vector ProfileCycler::GetControllersForDevice(InputConfig* device_configuration) + { + const std::size_t size = device_configuration->GetControllerCount(); + + std::vector result(size); + + for (int i = 0; i < static_cast(size); i++) + { + result[i] = device_configuration->GetController(i); + } + + return result; + } + + void ProfileCycler::CycleProfile(CycleDirection cycle_direction, + InputConfig* device_configuration, int& profile_index) + { + const auto& profiles = GetProfilesForDevice(device_configuration); + if (profiles.empty()) + { + Core::DisplayMessage("No input profiles found", display_message_ms); + return; + } + const std::string profile = GetProfile(cycle_direction, profile_index, profiles); + + const auto& controllers = GetControllersForDevice(device_configuration); + UpdateToProfile(profile, controllers); + } + + void ProfileCycler::NextWiimoteProfile() + { + CycleProfile(CycleDirection::Forward, Wiimote::GetConfig(), m_wiimote_profile_index); + } + + void ProfileCycler::PreviousWiimoteProfile() + { + CycleProfile(CycleDirection::Backward, Wiimote::GetConfig(), m_wiimote_profile_index); + } +} diff --git a/Source/Core/InputCommon/InputProfile.h b/Source/Core/InputCommon/InputProfile.h new file mode 100644 index 0000000000..09b617c398 --- /dev/null +++ b/Source/Core/InputCommon/InputProfile.h @@ -0,0 +1,39 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +class InputConfig; + +namespace ControllerEmu +{ + class EmulatedController; +} + +#include +#include + +namespace InputProfile +{ + enum class CycleDirection : int + { + Forward = 1, + Backward = -1 + }; + + class ProfileCycler + { + public: + void NextWiimoteProfile(); + void PreviousWiimoteProfile(); + private: + void CycleProfile(CycleDirection cycle_direction, InputConfig* device_configuration, int& profile_index); + std::vector GetProfilesForDevice(InputConfig* device_configuration); + std::string GetProfile(CycleDirection cycle_direction, int& profile_index, const std::vector& profiles); + void UpdateToProfile(const std::string& profile_filename, const std::vector& controllers); + std::vector GetControllersForDevice(InputConfig* device_configuration); + + int m_wiimote_profile_index = 0; + }; +}