diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp index 8fc54fde06..a9c5844b48 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp @@ -112,12 +112,6 @@ void EmulatedController::SetDefaultDevice(ciface::Core::DeviceQualifier devq) } } -void EmulatedController::SetDynamicInputTextureManager( - InputCommon::DynamicInputTextureManager* dynamic_input_tex_config_manager) -{ - m_dynamic_input_tex_config_manager = dynamic_input_tex_config_manager; -} - void EmulatedController::LoadConfig(IniFile::Section* sec, const std::string& base) { std::string defdev = GetDefaultDevice().ToString(); @@ -129,11 +123,6 @@ void EmulatedController::LoadConfig(IniFile::Section* sec, const std::string& ba for (auto& cg : groups) cg->LoadConfig(sec, defdev, base); - - if (base.empty()) - { - GenerateTextures(sec); - } } void EmulatedController::SaveConfig(IniFile::Section* sec, const std::string& base) @@ -144,11 +133,6 @@ void EmulatedController::SaveConfig(IniFile::Section* sec, const std::string& ba for (auto& ctrlGroup : groups) ctrlGroup->SaveConfig(sec, defdev, base); - - if (base.empty()) - { - GenerateTextures(sec); - } } void EmulatedController::LoadDefaults(const ControllerInterface& ciface) @@ -163,12 +147,4 @@ void EmulatedController::LoadDefaults(const ControllerInterface& ciface) SetDefaultDevice(default_device_string); } } - -void EmulatedController::GenerateTextures(IniFile::Section* sec) -{ - if (m_dynamic_input_tex_config_manager) - { - m_dynamic_input_tex_config_manager->GenerateTextures(sec, GetName()); - } -} } // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h index 00f750088a..291e707f25 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h +++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h @@ -17,7 +17,6 @@ #include "Common/MathUtil.h" #include "InputCommon/ControlReference/ExpressionParser.h" #include "InputCommon/ControllerInterface/CoreDevice.h" -#include "InputCommon/DynamicInputTextureManager.h" class ControllerInterface; @@ -183,7 +182,6 @@ public: const ciface::Core::DeviceQualifier& GetDefaultDevice() const; void SetDefaultDevice(const std::string& device); void SetDefaultDevice(ciface::Core::DeviceQualifier devq); - void SetDynamicInputTextureManager(InputCommon::DynamicInputTextureManager*); void UpdateReferences(const ControllerInterface& devi); void UpdateSingleControlReference(const ControllerInterface& devi, ControlReference* ref); @@ -226,8 +224,6 @@ protected: void UpdateReferences(ciface::ExpressionParser::ControlEnvironment& env); private: - void GenerateTextures(IniFile::Section* sec); - InputCommon::DynamicInputTextureManager* m_dynamic_input_tex_config_manager = nullptr; ciface::Core::DeviceQualifier m_default_device; bool m_default_device_is_connected{false}; }; diff --git a/Source/Core/InputCommon/DynamicInputTextureManager.cpp b/Source/Core/InputCommon/DynamicInputTextureManager.cpp index 602edc608d..85e5cefe28 100644 --- a/Source/Core/InputCommon/DynamicInputTextureManager.cpp +++ b/Source/Core/InputCommon/DynamicInputTextureManager.cpp @@ -40,13 +40,13 @@ void DynamicInputTextureManager::Load() } } -void DynamicInputTextureManager::GenerateTextures(const IniFile::Section* sec, - const std::string& controller_name) +void DynamicInputTextureManager::GenerateTextures(const IniFile& file, + const std::vector& controller_names) { bool any_dirty = false; for (const auto& configuration : m_configuration) { - any_dirty |= configuration.GenerateTextures(sec, controller_name); + any_dirty |= configuration.GenerateTextures(file, controller_names); } if (any_dirty && g_renderer && Core::GetState() != Core::State::Starting) diff --git a/Source/Core/InputCommon/DynamicInputTextureManager.h b/Source/Core/InputCommon/DynamicInputTextureManager.h index debd82f83e..f0ac4351c6 100644 --- a/Source/Core/InputCommon/DynamicInputTextureManager.h +++ b/Source/Core/InputCommon/DynamicInputTextureManager.h @@ -21,7 +21,7 @@ public: DynamicInputTextureManager(); ~DynamicInputTextureManager(); void Load(); - void GenerateTextures(const IniFile::Section* sec, const std::string& controller_name); + void GenerateTextures(const IniFile& file, const std::vector& controller_names); private: std::vector m_configuration; diff --git a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp index b057abff2b..f7c1b647be 100644 --- a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp +++ b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.cpp @@ -87,48 +87,22 @@ Configuration::Configuration(const std::string& json_file) Configuration::~Configuration() = default; -bool Configuration::GenerateTextures(const IniFile::Section* sec, - const std::string& controller_name) const +bool Configuration::GenerateTextures(const IniFile& file, + const std::vector& controller_names) const { bool any_dirty = false; for (const auto& texture_data : m_dynamic_input_textures) { - any_dirty |= GenerateTexture(sec, controller_name, texture_data); + any_dirty |= GenerateTexture(file, controller_names, texture_data); } return any_dirty; } -bool Configuration::GenerateTexture(const IniFile::Section* sec, const std::string& controller_name, +bool Configuration::GenerateTexture(const IniFile& file, + const std::vector& controller_names, const Data& texture_data) const { - std::string device_name; - if (!sec->Get("Device", &device_name)) - { - return false; - } - - auto emulated_controls_iter = texture_data.m_emulated_controllers.find(controller_name); - if (emulated_controls_iter == texture_data.m_emulated_controllers.end()) - { - return false; - } - - bool device_found = true; - auto host_devices_iter = texture_data.m_host_devices.find(device_name); - if (host_devices_iter == texture_data.m_host_devices.end()) - { - // If we fail to find our exact device, - // it's possible the creator doesn't care (single player game) - // and has used a wildcard for any device - host_devices_iter = texture_data.m_host_devices.find(""); - - if (host_devices_iter == texture_data.m_host_devices.end()) - { - device_found = false; - } - } - // Two copies of the loaded texture // The first one is used as a fallback if a key or device isn't mapped // the second one is used as the final image to write to the textures directory @@ -136,61 +110,88 @@ bool Configuration::GenerateTexture(const IniFile::Section* sec, const std::stri auto image_to_write = original_image; bool dirty = false; - for (auto& [emulated_key, rects] : emulated_controls_iter->second) - { - // TODO: Remove this line when we move to C++20 - auto& rects_ref = rects; - auto apply_original = [&] { - for (const auto& rect : rects_ref) - { - CopyImageRegion(*original_image, *image_to_write, rect, rect); - dirty = true; - } - }; - if (!device_found) + for (const auto& controller_name : controller_names) + { + auto* sec = file.GetSection(controller_name); + if (!sec) { - // If we get here, that means the controller is set to a - // device not exposed to the pack - // We still apply the original image, in case the user - // switched devices and wants to see the changes - apply_original(); continue; } - std::string host_key; - sec->Get(emulated_key, &host_key); - - const auto input_image_iter = host_devices_iter->second.find(host_key); - if (input_image_iter == host_devices_iter->second.end()) + std::string device_name; + if (!sec->Get("Device", &device_name)) { - apply_original(); + continue; } - else + + auto emulated_controls_iter = texture_data.m_emulated_controllers.find(controller_name); + if (emulated_controls_iter == texture_data.m_emulated_controllers.end()) { - const auto host_key_image = LoadImage(m_base_path + input_image_iter->second); + continue; + } - for (const auto& rect : rects) + bool device_found = true; + auto host_devices_iter = texture_data.m_host_devices.find(device_name); + if (host_devices_iter == texture_data.m_host_devices.end()) + { + // If we fail to find our exact device, + // it's possible the creator doesn't care (single player game) + // and has used a wildcard for any device + host_devices_iter = texture_data.m_host_devices.find(""); + + if (host_devices_iter == texture_data.m_host_devices.end()) { - InputCommon::ImagePixelData pixel_data; - if (host_key_image->width == rect.GetWidth() && host_key_image->height == rect.GetHeight()) - { - pixel_data = *host_key_image; - } - else if (texture_data.m_preserve_aspect_ratio) - { - pixel_data = ResizeKeepAspectRatio(ResizeMode::Nearest, *host_key_image, rect.GetWidth(), - rect.GetHeight(), Pixel{0, 0, 0, 0}); - } - else - { - pixel_data = - Resize(ResizeMode::Nearest, *host_key_image, rect.GetWidth(), rect.GetHeight()); - } + device_found = false; + } + } - CopyImageRegion(pixel_data, *image_to_write, Rect{0, 0, rect.GetWidth(), rect.GetHeight()}, - rect); + for (auto& [emulated_key, rects] : emulated_controls_iter->second) + { + if (!device_found) + { + // If we get here, that means the controller is set to a + // device not exposed to the pack dirty = true; + continue; + } + + std::string host_key; + sec->Get(emulated_key, &host_key); + + const auto input_image_iter = host_devices_iter->second.find(host_key); + if (input_image_iter == host_devices_iter->second.end()) + { + dirty = true; + } + else + { + const auto host_key_image = LoadImage(m_base_path + input_image_iter->second); + + for (const auto& rect : rects) + { + InputCommon::ImagePixelData pixel_data; + if (host_key_image->width == rect.GetWidth() && + host_key_image->height == rect.GetHeight()) + { + pixel_data = *host_key_image; + } + else if (texture_data.m_preserve_aspect_ratio) + { + pixel_data = + ResizeKeepAspectRatio(ResizeMode::Nearest, *host_key_image, rect.GetWidth(), + rect.GetHeight(), Pixel{0, 0, 0, 0}); + } + else + { + pixel_data = + Resize(ResizeMode::Nearest, *host_key_image, rect.GetWidth(), rect.GetHeight()); + } + + CopyImageRegion(pixel_data, *image_to_write, + Rect{0, 0, rect.GetWidth(), rect.GetHeight()}, rect); + dirty = true; + } } } } diff --git a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h index 49e3a350f9..a406ebe6ad 100644 --- a/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h +++ b/Source/Core/InputCommon/DynamicInputTextures/DITConfiguration.h @@ -19,10 +19,11 @@ class Configuration public: explicit Configuration(const std::string& json_file); ~Configuration(); - bool GenerateTextures(const IniFile::Section* sec, const std::string& controller_name) const; + bool GenerateTextures(const IniFile& file, + const std::vector& controller_names) const; private: - bool GenerateTexture(const IniFile::Section* sec, const std::string& controller_name, + bool GenerateTexture(const IniFile& file, const std::vector& controller_names, const Data& texture_data) const; std::vector m_dynamic_input_textures; diff --git a/Source/Core/InputCommon/InputConfig.cpp b/Source/Core/InputCommon/InputConfig.cpp index 03d2874332..72b28b6d16 100644 --- a/Source/Core/InputCommon/InputConfig.cpp +++ b/Source/Core/InputCommon/InputConfig.cpp @@ -4,6 +4,7 @@ #include +#include "Common/Config/Config.h" #include "Common/FileUtil.h" #include "Common/IniFile.h" #include "Common/MsgHandler.h" @@ -101,6 +102,8 @@ bool InputConfig::LoadConfig(bool isGC) !inifile.GetSections().empty()) { int n = 0; + + std::vector controller_names; for (auto& controller : m_controllers) { IniFile::Section config; @@ -113,9 +116,8 @@ bool InputConfig::LoadConfig(bool isGC) controller->GetName() + "'", 6000); - IniFile profile_ini; - profile_ini.Load(profile[n]); - config = *profile_ini.GetOrCreateSection("Profile"); + inifile.Load(profile[n]); + config = *inifile.GetOrCreateSection("Profile"); } else { @@ -133,10 +135,13 @@ bool InputConfig::LoadConfig(bool isGC) controller->LoadConfig(&config); // Update refs controller->UpdateReferences(g_controller_interface); + controller_names.push_back(controller->GetName()); // Next profile n++; } + + m_dynamic_input_tex_config_manager.GenerateTextures(inifile, controller_names); return true; } else @@ -154,8 +159,14 @@ void InputConfig::SaveConfig() IniFile inifile; inifile.Load(ini_filename); + std::vector controller_names; for (auto& controller : m_controllers) + { controller->SaveConfig(inifile.GetOrCreateSection(controller->GetName())); + controller_names.push_back(controller->GetName()); + } + + m_dynamic_input_tex_config_manager.GenerateTextures(inifile, controller_names); inifile.Save(ini_filename); } @@ -195,11 +206,6 @@ void InputConfig::UnregisterHotplugCallback() g_controller_interface.UnregisterDevicesChangedCallback(m_hotplug_callback_handle); } -void InputConfig::OnControllerCreated(ControllerEmu::EmulatedController& controller) -{ - controller.SetDynamicInputTextureManager(&m_dynamic_input_tex_config_manager); -} - bool InputConfig::IsControllerControlledByGamepadDevice(int index) const { if (static_cast(index) >= m_controllers.size()) @@ -215,3 +221,14 @@ bool InputConfig::IsControllerControlledByGamepadDevice(int index) const || (controller.source == "DInput" && controller.name == "Keyboard Mouse")); // Windows Keyboard/Mouse } + +void InputConfig::GenerateControllerTextures(const IniFile& file) +{ + std::vector controller_names; + for (auto& controller : m_controllers) + { + controller_names.push_back(controller->GetName()); + } + + m_dynamic_input_tex_config_manager.GenerateTextures(file, controller_names); +} diff --git a/Source/Core/InputCommon/InputConfig.h b/Source/Core/InputCommon/InputConfig.h index 3d0a60dd73..29ec661f67 100644 --- a/Source/Core/InputCommon/InputConfig.h +++ b/Source/Core/InputCommon/InputConfig.h @@ -31,8 +31,7 @@ public: template void CreateController(Args&&... args) { - OnControllerCreated( - *m_controllers.emplace_back(std::make_unique(std::forward(args)...))); + m_controllers.emplace_back(std::make_unique(std::forward(args)...)); } ControllerEmu::EmulatedController* GetController(int index); @@ -48,8 +47,9 @@ public: void RegisterHotplugCallback(); void UnregisterHotplugCallback(); + void GenerateControllerTextures(const IniFile& file); + private: - void OnControllerCreated(ControllerEmu::EmulatedController& controller); ControllerInterface::HotplugCallbackHandle m_hotplug_callback_handle; std::vector> m_controllers; const std::string m_ini_name; diff --git a/Source/Core/InputCommon/InputProfile.cpp b/Source/Core/InputCommon/InputProfile.cpp index 9037d79044..c48d50dae3 100644 --- a/Source/Core/InputCommon/InputProfile.cpp +++ b/Source/Core/InputCommon/InputProfile.cpp @@ -73,7 +73,8 @@ std::string ProfileCycler::GetProfile(CycleDirection cycle_direction, int& profi } void ProfileCycler::UpdateToProfile(const std::string& profile_filename, - ControllerEmu::EmulatedController* controller) + ControllerEmu::EmulatedController* controller, + InputConfig* device_configuration) { std::string base; SplitPath(profile_filename, nullptr, &base, nullptr); @@ -86,6 +87,7 @@ void ProfileCycler::UpdateToProfile(const std::string& profile_filename, display_message_ms); controller->LoadConfig(ini_file.GetOrCreateSection("Profile")); controller->UpdateReferences(g_controller_interface); + device_configuration->GenerateControllerTextures(ini_file); } else { @@ -129,7 +131,7 @@ void ProfileCycler::CycleProfile(CycleDirection cycle_direction, InputConfig* de auto* controller = device_configuration->GetController(controller_index); if (controller) { - UpdateToProfile(profile, controller); + UpdateToProfile(profile, controller, device_configuration); } else { @@ -168,7 +170,7 @@ void ProfileCycler::CycleProfileForGame(CycleDirection cycle_direction, auto* controller = device_configuration->GetController(controller_index); if (controller) { - UpdateToProfile(profile, controller); + UpdateToProfile(profile, controller, device_configuration); } else { diff --git a/Source/Core/InputCommon/InputProfile.h b/Source/Core/InputCommon/InputProfile.h index 0f784d7a04..53da662870 100644 --- a/Source/Core/InputCommon/InputProfile.h +++ b/Source/Core/InputCommon/InputProfile.h @@ -45,7 +45,8 @@ private: const std::vector& profiles, InputConfig* device_configuration); void UpdateToProfile(const std::string& profile_filename, - ControllerEmu::EmulatedController* controller); + ControllerEmu::EmulatedController* controller, + InputConfig* device_configuration); std::string GetWiimoteInputProfilesForGame(int controller_index); int m_wiimote_profile_index = 0;