From bce8041cce88926adf68c7b35b4e79d72420bb36 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Sat, 26 May 2018 17:19:13 -0500 Subject: [PATCH] Input: Allow per-game configuration to specify directories for input-profiles. If specified, the directories are searched recursively for inis --- Source/Core/InputCommon/InputConfig.cpp | 28 ++++++------- Source/Core/InputCommon/InputProfile.cpp | 50 +++++++++++++++--------- Source/Core/InputCommon/InputProfile.h | 5 ++- 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/Source/Core/InputCommon/InputConfig.cpp b/Source/Core/InputCommon/InputConfig.cpp index 1ba44c047e..ac74c0ea7e 100644 --- a/Source/Core/InputCommon/InputConfig.cpp +++ b/Source/Core/InputCommon/InputConfig.cpp @@ -15,6 +15,7 @@ #include "InputCommon/ControllerEmu/ControllerEmu.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" #include "InputCommon/InputConfig.h" +#include "InputCommon/InputProfile.h" InputConfig::InputConfig(const std::string& ini_name, const std::string& gui_name, const std::string& profile_name) @@ -56,22 +57,21 @@ bool InputConfig::LoadConfig(bool isGC) std::string profile_setting; if (control_section->Get(type + "Profile" + num[i], &profile_setting)) { - // Setting can contain commas, which means there are multiple profiles specified - // this is used for controller cycling - const auto& profile_options = SplitString(profile_setting, ','); + auto profiles = InputProfile::GetProfilesFromSetting( + profile_setting, File::GetUserPath(D_CONFIG_IDX) + path); + + if (profiles.empty()) + { + const std::string error = + "No profiles found for game setting '" + profile_setting + "'"; + // TODO: PanicAlert shouldn't be used for this. + PanicAlertT("%s", error.c_str()); + continue; + } // Use the first profile by default - profile[i] = profile_options[0]; - - if (File::Exists(File::GetUserPath(D_CONFIG_IDX) + path + profile[i] + ".ini")) - { - useProfile[i] = true; - } - else - { - // TODO: PanicAlert shouldn't be used for this. - PanicAlertT("Selected controller profile does not exist"); - } + profile[i] = profiles[0]; + useProfile[i] = true; } } } diff --git a/Source/Core/InputCommon/InputProfile.cpp b/Source/Core/InputCommon/InputProfile.cpp index 2ca7b46096..c78c1fbfd6 100644 --- a/Source/Core/InputCommon/InputProfile.cpp +++ b/Source/Core/InputCommon/InputProfile.cpp @@ -25,11 +25,37 @@ namespace constexpr int display_message_ms = 3000; } +std::vector GetProfilesFromSetting(const std::string& setting, const std::string& root) +{ + const auto& setting_choices = SplitString(setting, ','); + + std::vector result; + for (const std::string& setting_choice : setting_choices) + { + const std::string path = root + StripSpaces(setting_choice); + if (File::IsDirectory(path)) + { + const auto files_under_directory = Common::DoFileSearch({path}, {".ini"}, true); + result.insert(result.end(), files_under_directory.begin(), files_under_directory.end()); + } + else + { + const std::string file_path = path + ".ini"; + if (File::Exists(file_path)) + { + result.push_back(file_path); + } + } + } + + return result; +} + 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"}); + return Common::DoFileSearch({device_profile_root_location}, {".ini"}, true); } std::string ProfileCycler::GetProfile(CycleDirection cycle_direction, int& profile_index, @@ -66,29 +92,15 @@ void ProfileCycler::UpdateToProfile(const std::string& profile_filename, } } -std::vector ProfileCycler::GetProfilesFromSetting(const std::string& setting, - InputConfig* device_configuration) -{ - const auto& profiles = SplitString(setting, ','); - - const std::string device_profile_root_location(File::GetUserPath(D_CONFIG_IDX) + "Profiles/" + - device_configuration->GetProfileName()); - - std::vector result(profiles.size()); - std::transform(profiles.begin(), profiles.end(), result.begin(), - [&device_profile_root_location](const std::string& profile) { - return device_profile_root_location + "/" + StripSpaces(profile) + ".ini"; - }); - - return result; -} - std::vector ProfileCycler::GetMatchingProfilesFromSetting(const std::string& setting, const std::vector& profiles, InputConfig* device_configuration) { - const auto& profiles_from_setting = GetProfilesFromSetting(setting, device_configuration); + const std::string device_profile_root_location(File::GetUserPath(D_CONFIG_IDX) + "Profiles/" + + device_configuration->GetProfileName() + "/"); + + const auto& profiles_from_setting = GetProfilesFromSetting(setting, device_profile_root_location); if (profiles_from_setting.empty()) { return {}; diff --git a/Source/Core/InputCommon/InputProfile.h b/Source/Core/InputCommon/InputProfile.h index 503f2bafcc..ccb4fbf4db 100644 --- a/Source/Core/InputCommon/InputProfile.h +++ b/Source/Core/InputCommon/InputProfile.h @@ -16,6 +16,9 @@ class EmulatedController; namespace InputProfile { +std::vector GetProfilesFromSetting(const std::string& setting, + const std::string& root); + enum class CycleDirection : int { Forward = 1, @@ -36,8 +39,6 @@ private: void CycleProfileForGame(CycleDirection cycle_direction, InputConfig* device_configuration, int& profile_index, const std::string& setting, int controller_index); std::vector GetProfilesForDevice(InputConfig* device_configuration); - std::vector GetProfilesFromSetting(const std::string& setting, - InputConfig* device_configuration); std::string GetProfile(CycleDirection cycle_direction, int& profile_index, const std::vector& profiles); std::vector GetMatchingProfilesFromSetting(const std::string& setting,