GameSettings: Add per-game input bindings from profiles

This just affects the **bindings**. You will still have to set the
controller type per game if this is different from the global default.
This commit is contained in:
Connor McLaughlin
2020-10-04 18:20:18 +10:00
parent 7278f055cb
commit 0b858658ca
7 changed files with 92 additions and 4 deletions

View File

@ -977,7 +977,10 @@ bool CommonHostInterface::HandleHostMouseEvent(HostMouseButton button, bool pres
void CommonHostInterface::UpdateInputMap(SettingsInterface& si)
{
ClearInputMap();
UpdateControllerInputMap(si);
if (!UpdateControllerInputMapFromGameSettings())
UpdateControllerInputMap(si);
UpdateHotkeyInputMap(si);
}
@ -1677,6 +1680,19 @@ void CommonHostInterface::FindInputProfiles(const std::string& base_path, InputP
}
}
std::string CommonHostInterface::GetInputProfilePath(const char* name) const
{
std::string path = GetUserDirectoryRelativePath("inputprofiles" FS_OSPATH_SEPARATOR_STR "%s.ini", name);
if (FileSystem::FileExists(path.c_str()))
return path;
path = GetProgramDirectoryRelativePath("inputprofiles" FS_OSPATH_SEPARATOR_STR "%s.ini", name);
if (FileSystem::FileExists(path.c_str()))
return path;
return {};
}
void CommonHostInterface::ClearAllControllerBindings(SettingsInterface& si)
{
for (u32 controller_index = 1; controller_index <= NUM_CONTROLLER_AND_CARD_PORTS; controller_index++)
@ -2282,6 +2298,35 @@ void CommonHostInterface::ApplyGameSettings(bool display_osd_messages)
gs->ApplySettings(display_osd_messages);
}
bool CommonHostInterface::UpdateControllerInputMapFromGameSettings()
{
// this gets called while booting, so can't use valid
if (System::IsShutdown() || System::GetRunningCode().empty() || !g_settings.apply_game_settings)
return false;
const GameSettings::Entry* gs = m_game_list->GetGameSettings(System::GetRunningPath(), System::GetRunningCode());
if (!gs || gs->input_profile_name.empty())
return false;
std::string path = GetInputProfilePath(gs->input_profile_name.c_str());
if (path.empty())
{
AddFormattedOSDMessage(10.0f, TranslateString("OSDMessage", "Input profile '%s' cannot be found."),
gs->input_profile_name.c_str());
return false;
}
if (System::GetState() == System::State::Starting)
{
AddFormattedOSDMessage(5.0f, TranslateString("OSDMessage", "Using input profile '%s'."),
gs->input_profile_name.c_str());
}
INISettingsInterface si(std::move(path));
UpdateControllerInputMap(si);
return true;
}
std::string CommonHostInterface::GetCheatFileName() const
{
const std::string& title = System::GetRunningTitle();

View File

@ -233,6 +233,9 @@ protected:
/// Returns a list of all input profiles. first - name, second - path
InputProfileList GetInputProfileList() const;
/// Returns the path for an input profile.
std::string GetInputProfilePath(const char* name) const;
/// Applies the specified input profile.
void ApplyInputProfile(const char* profile_path, SettingsInterface& si);
@ -330,6 +333,7 @@ private:
void RegisterAudioHotkeys();
void FindInputProfiles(const std::string& base_path, InputProfileList* out_list) const;
void UpdateControllerInputMap(SettingsInterface& si);
bool UpdateControllerInputMapFromGameSettings();
void UpdateHotkeyInputMap(SettingsInterface& si);
void ClearAllControllerBindings(SettingsInterface& si);

View File

@ -115,7 +115,7 @@ private:
enum : u32
{
GAME_LIST_CACHE_SIGNATURE = 0x45434C47,
GAME_LIST_CACHE_VERSION = 11
GAME_LIST_CACHE_VERSION = 12
};
using DatabaseMap = std::unordered_map<std::string, GameListDatabaseEntry>;

View File

@ -121,7 +121,7 @@ bool Entry::LoadFromStream(ByteStream* stream)
!ReadOptionalFromStream(stream, &controller_2_type) || !ReadOptionalFromStream(stream, &memory_card_1_type) ||
!ReadOptionalFromStream(stream, &memory_card_2_type) ||
!ReadStringFromStream(stream, &memory_card_1_shared_path) ||
!ReadStringFromStream(stream, &memory_card_2_shared_path))
!ReadStringFromStream(stream, &memory_card_2_shared_path) || !ReadStringFromStream(stream, &input_profile_name))
{
return false;
}
@ -162,7 +162,7 @@ bool Entry::SaveToStream(ByteStream* stream) const
WriteOptionalToStream(stream, gpu_pgxp) && WriteOptionalToStream(stream, controller_1_type) &&
WriteOptionalToStream(stream, controller_2_type) && WriteOptionalToStream(stream, memory_card_1_type) &&
WriteOptionalToStream(stream, memory_card_2_type) && WriteStringToStream(stream, memory_card_1_shared_path) &&
WriteStringToStream(stream, memory_card_2_shared_path);
WriteStringToStream(stream, memory_card_2_shared_path) && WriteStringToStream(stream, input_profile_name);
}
static void ParseIniSection(Entry* entry, const char* section, const CSimpleIniA& ini)
@ -247,6 +247,9 @@ static void ParseIniSection(Entry* entry, const char* section, const CSimpleIniA
cvalue = ini.GetValue(section, "MemoryCard2SharedPath");
if (cvalue)
entry->memory_card_2_shared_path = cvalue;
cvalue = ini.GetValue(section, "InputProfileName");
if (cvalue)
entry->input_profile_name = cvalue;
}
static void StoreIniSection(const Entry& entry, const char* section, CSimpleIniA& ini)
@ -316,6 +319,8 @@ static void StoreIniSection(const Entry& entry, const char* section, CSimpleIniA
ini.SetValue(section, "MemoryCard1SharedPath", entry.memory_card_1_shared_path.c_str());
if (!entry.memory_card_2_shared_path.empty())
ini.SetValue(section, "MemoryCard2SharedPath", entry.memory_card_2_shared_path.c_str());
if (!entry.input_profile_name.empty())
ini.SetValue(section, "InputProfileName", entry.input_profile_name.c_str());
}
Database::Database() = default;

View File

@ -61,6 +61,7 @@ struct Entry
std::optional<MemoryCardType> memory_card_2_type;
std::string memory_card_1_shared_path;
std::string memory_card_2_shared_path;
std::string input_profile_name;
ALWAYS_INLINE bool HasTrait(Trait trait) const { return traits[static_cast<int>(trait)]; }
ALWAYS_INLINE void AddTrait(Trait trait) { traits[static_cast<int>(trait)] = true; }