initial Gamepad profiles support

This commit is contained in:
Mahmood - Zer0xFF 2020-02-25 18:47:50 +00:00
parent 8b21aca123
commit cce77fc4ab
10 changed files with 238 additions and 45 deletions

View file

@ -198,6 +198,8 @@ set(COMMON_SRC_FILES
FpUtils.h FpUtils.h
FrameDump.cpp FrameDump.cpp
FrameDump.h FrameDump.h
InputConfig.cpp
InputConfig.h
GenericMipsExecutor.h GenericMipsExecutor.h
gs/GsCachedArea.cpp gs/GsCachedArea.cpp
gs/GsCachedArea.h gs/GsCachedArea.h

46
Source/InputConfig.cpp Normal file
View file

@ -0,0 +1,46 @@
#include "AppConfig.h"
#include "InputConfig.h"
#include "PathUtils.h"
#define PROFILE_PATH ("inputprofiles")
CInputConfig::CInputConfig(const Framework::CConfig::PathType& path)
: CConfig(path)
{
}
bool CInputConfig::IsValidProfileName(std::string name)
{
static const std::string valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-";
for(auto c : name)
{
if(valid_chars.find(c) == std::string::npos)
{
return false;
}
}
return true;
}
std::unique_ptr<CInputConfig> CInputConfig::LoadProfile(std::string name)
{
auto path = GetProfilePath() / name;
path.replace_extension(".xml");
return std::make_unique<CInputConfig>(path);
}
Framework::CConfig::PathType CInputConfig::GetProfilePath()
{
auto profile_path = CAppConfig::GetBasePath() / PROFILE_PATH;
Framework::PathUtils::EnsurePathExists(profile_path);
return profile_path;
}
Framework::CConfig::PathType CInputConfig::GetProfile(std::string name)
{
auto profile_path = CAppConfig::GetBasePath() / PROFILE_PATH;
Framework::PathUtils::EnsurePathExists(profile_path);
profile_path /= name;
profile_path.replace_extension(".xml");
return profile_path;
}

17
Source/InputConfig.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include "Config.h"
#define DEFAULT_PROFILE ("default")
class CInputConfig : public Framework::CConfig
{
public:
CInputConfig(const Framework::CConfig::PathType& path);
virtual ~CInputConfig() = default;
static bool IsValidProfileName(std::string);
static CConfig::PathType GetProfilePath();
static CConfig::PathType GetProfile(std::string = DEFAULT_PROFILE);
static std::unique_ptr<CInputConfig> LoadProfile(std::string = DEFAULT_PROFILE);
};

View file

@ -98,23 +98,9 @@ static void SaveBindingTargetPreference(Framework::CConfig& config, const char*
} }
CInputBindingManager::CInputBindingManager() CInputBindingManager::CInputBindingManager()
: m_config(CAppConfig::GetInstance())
{ {
for(unsigned int pad = 0; pad < MAX_PADS; pad++) m_config = CInputConfig::LoadProfile();
{ Reload();
for(unsigned int button = 0; button < PS2::CControllerInfo::MAX_BUTTONS; button++)
{
auto prefBase = Framework::CConfig::MakePreferenceName(CONFIG_PREFIX, m_padPreferenceName[pad], PS2::CControllerInfo::m_buttonName[button]);
m_config.RegisterPreferenceInteger(Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDING_TYPE).c_str(), 0);
RegisterBindingTargetPreference(m_config, Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDINGTARGET1).c_str());
if(PS2::CControllerInfo::IsAxis(static_cast<PS2::CControllerInfo::BUTTON>(button)))
{
RegisterBindingTargetPreference(m_config, Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDINGTARGET2).c_str());
}
CPovHatBinding::RegisterPreferences(m_config, prefBase.c_str());
}
}
Load();
} }
bool CInputBindingManager::HasBindings() const bool CInputBindingManager::HasBindings() const
@ -174,15 +160,31 @@ void CInputBindingManager::OnInputEventReceived(const BINDINGTARGET& target, uin
} }
} }
void CInputBindingManager::Load() void CInputBindingManager::Reload()
{ {
for(unsigned int pad = 0; pad < MAX_PADS; pad++)
{
for(unsigned int button = 0; button < PS2::CControllerInfo::MAX_BUTTONS; button++)
{
auto prefBase = Framework::CConfig::MakePreferenceName(CONFIG_PREFIX, m_padPreferenceName[pad], PS2::CControllerInfo::m_buttonName[button]);
m_config->RegisterPreferenceInteger(Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDING_TYPE).c_str(), 0);
RegisterBindingTargetPreference(*m_config, Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDINGTARGET1).c_str());
if(PS2::CControllerInfo::IsAxis(static_cast<PS2::CControllerInfo::BUTTON>(button)))
{
RegisterBindingTargetPreference(*m_config, Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDINGTARGET2).c_str());
}
CPovHatBinding::RegisterPreferences(*m_config, prefBase.c_str());
}
}
for(unsigned int pad = 0; pad < MAX_PADS; pad++) for(unsigned int pad = 0; pad < MAX_PADS; pad++)
{ {
for(unsigned int button = 0; button < PS2::CControllerInfo::MAX_BUTTONS; button++) for(unsigned int button = 0; button < PS2::CControllerInfo::MAX_BUTTONS; button++)
{ {
BINDINGTYPE bindingType = BINDING_UNBOUND; BINDINGTYPE bindingType = BINDING_UNBOUND;
auto prefBase = Framework::CConfig::MakePreferenceName(CONFIG_PREFIX, m_padPreferenceName[pad], PS2::CControllerInfo::m_buttonName[button]); auto prefBase = Framework::CConfig::MakePreferenceName(CONFIG_PREFIX, m_padPreferenceName[pad], PS2::CControllerInfo::m_buttonName[button]);
bindingType = static_cast<BINDINGTYPE>(m_config.GetPreferenceInteger((prefBase + "." + std::string(CONFIG_BINDING_TYPE)).c_str())); bindingType = static_cast<BINDINGTYPE>(m_config->GetPreferenceInteger((prefBase + "." + std::string(CONFIG_BINDING_TYPE)).c_str()));
if(bindingType == BINDING_UNBOUND) continue; if(bindingType == BINDING_UNBOUND) continue;
BindingPtr binding; BindingPtr binding;
switch(bindingType) switch(bindingType)
@ -199,7 +201,7 @@ void CInputBindingManager::Load()
} }
if(binding) if(binding)
{ {
binding->Load(m_config, prefBase.c_str()); binding->Load(*m_config, prefBase.c_str());
} }
m_bindings[pad][button] = binding; m_bindings[pad][button] = binding;
} }
@ -207,6 +209,12 @@ void CInputBindingManager::Load()
ResetBindingValues(); ResetBindingValues();
} }
void CInputBindingManager::Load(std::string profile)
{
m_config = CInputConfig::LoadProfile(profile);
Reload();
}
void CInputBindingManager::Save() void CInputBindingManager::Save()
{ {
for(unsigned int pad = 0; pad < MAX_PADS; pad++) for(unsigned int pad = 0; pad < MAX_PADS; pad++)
@ -216,11 +224,11 @@ void CInputBindingManager::Save()
const auto& binding = m_bindings[pad][button]; const auto& binding = m_bindings[pad][button];
if(!binding) continue; if(!binding) continue;
auto prefBase = Framework::CConfig::MakePreferenceName(CONFIG_PREFIX, m_padPreferenceName[pad], PS2::CControllerInfo::m_buttonName[button]); auto prefBase = Framework::CConfig::MakePreferenceName(CONFIG_PREFIX, m_padPreferenceName[pad], PS2::CControllerInfo::m_buttonName[button]);
m_config.SetPreferenceInteger(Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDING_TYPE).c_str(), binding->GetBindingType()); m_config->SetPreferenceInteger(Framework::CConfig::MakePreferenceName(prefBase, CONFIG_BINDING_TYPE).c_str(), binding->GetBindingType());
binding->Save(m_config, prefBase.c_str()); binding->Save(*m_config, prefBase.c_str());
} }
} }
m_config.Save(); m_config->Save();
} }
const CInputBindingManager::CBinding* CInputBindingManager::GetBinding(uint32 pad, PS2::CControllerInfo::BUTTON button) const const CInputBindingManager::CBinding* CInputBindingManager::GetBinding(uint32 pad, PS2::CControllerInfo::BUTTON button) const

View file

@ -1,11 +1,13 @@
#pragma once #pragma once
#include "Config.h" #include "Config.h"
#include "InputConfig.h"
#include "ControllerInfo.h" #include "ControllerInfo.h"
#include "InputProvider.h" #include "InputProvider.h"
#include <array> #include <array>
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <string>
class CInputBindingManager class CInputBindingManager
{ {
@ -60,7 +62,8 @@ public:
void SetPovHatBinding(uint32, PS2::CControllerInfo::BUTTON, const BINDINGTARGET&, uint32); void SetPovHatBinding(uint32, PS2::CControllerInfo::BUTTON, const BINDINGTARGET&, uint32);
void SetSimulatedAxisBinding(uint32, PS2::CControllerInfo::BUTTON, const BINDINGTARGET&, const BINDINGTARGET&); void SetSimulatedAxisBinding(uint32, PS2::CControllerInfo::BUTTON, const BINDINGTARGET&, const BINDINGTARGET&);
void Load(); void Reload();
void Load(std::string);
void Save(); void Save();
private: private:
@ -149,6 +152,6 @@ private:
static uint32 m_buttonDefaultValue[PS2::CControllerInfo::MAX_BUTTONS]; static uint32 m_buttonDefaultValue[PS2::CControllerInfo::MAX_BUTTONS];
static const char* m_padPreferenceName[MAX_PADS]; static const char* m_padPreferenceName[MAX_PADS];
Framework::CConfig& m_config; std::unique_ptr<CInputConfig> m_config;
ProviderMap m_providers; ProviderMap m_providers;
}; };

View file

@ -6,10 +6,18 @@
#include <QFile> #include <QFile>
#include <QAbstractButton> #include <QAbstractButton>
#include <QPushButton> #include <QPushButton>
#include <QInputDialog>
#include "AppConfig.h"
#include "PreferenceDefs.h"
#include "PathUtils.h"
#include "bindingmodel.h" #include "bindingmodel.h"
#include "ControllerInfo.h" #include "ControllerInfo.h"
#include "inputeventselectiondialog.h" #include "inputeventselectiondialog.h"
#include "QStringUtils.h"
#include "filesystem_def.h"
#include <iostream>
ControllerConfigDialog::ControllerConfigDialog(CInputBindingManager* inputBindingManager, CInputProviderQtKey* qtKeyInputProvider, QWidget* parent) ControllerConfigDialog::ControllerConfigDialog(CInputBindingManager* inputBindingManager, CInputProviderQtKey* qtKeyInputProvider, QWidget* parent)
: QDialog(parent) : QDialog(parent)
@ -18,7 +26,23 @@ ControllerConfigDialog::ControllerConfigDialog(CInputBindingManager* inputBindin
, m_qtKeyInputProvider(qtKeyInputProvider) , m_qtKeyInputProvider(qtKeyInputProvider)
{ {
ui->setupUi(this); ui->setupUi(this);
std::string profile = CAppConfig::GetInstance().GetPreferenceString(PREF_INPUT_PAD1_PROFILE);
PrepareBindingsView(); PrepareBindingsView();
auto path = CInputConfig::GetProfilePath();
if(fs::is_directory(path))
{
for(auto& entry : fs::directory_iterator(path))
{
auto profile = Framework::PathUtils::GetNativeStringFromPath(entry.path().stem());
ui->comboBox->addItem(profile.c_str());
}
}
auto index = ui->comboBox->findText(profile.c_str());
if(index >= 0)
ui->comboBox->setCurrentIndex(index);
} }
ControllerConfigDialog::~ControllerConfigDialog() ControllerConfigDialog::~ControllerConfigDialog()
@ -43,10 +67,12 @@ void ControllerConfigDialog::on_buttonBox_clicked(QAbstractButton* button)
if(button == ui->buttonBox->button(QDialogButtonBox::Ok)) if(button == ui->buttonBox->button(QDialogButtonBox::Ok))
{ {
m_inputManager->Save(); m_inputManager->Save();
CAppConfig::GetInstance().Save();
} }
else if(button == ui->buttonBox->button(QDialogButtonBox::Apply)) else if(button == ui->buttonBox->button(QDialogButtonBox::Apply))
{ {
m_inputManager->Save(); m_inputManager->Save();
CAppConfig::GetInstance().Save();
} }
else if(button == ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)) else if(button == ui->buttonBox->button(QDialogButtonBox::RestoreDefaults))
{ {
@ -60,7 +86,7 @@ void ControllerConfigDialog::on_buttonBox_clicked(QAbstractButton* button)
} }
else if(button == ui->buttonBox->button(QDialogButtonBox::Cancel)) else if(button == ui->buttonBox->button(QDialogButtonBox::Cancel))
{ {
m_inputManager->Load(); m_inputManager->Reload();
} }
} }
@ -124,3 +150,58 @@ int ControllerConfigDialog::OpenBindConfigDialog(int index)
auto res = IESD.exec(); auto res = IESD.exec();
return res; return res;
} }
void ControllerConfigDialog::on_comboBox_currentIndexChanged(int index)
{
ui->delProfileButton->setEnabled(index > 0);
auto profile = ui->comboBox->itemText(index).toStdString();
m_inputManager->Load(profile.c_str());
CAppConfig::GetInstance().SetPreferenceString(PREF_INPUT_PAD1_PROFILE, profile.c_str());
static_cast<CBindingModel*>(ui->tableView->model())->Refresh();
}
void ControllerConfigDialog::on_addProfileButton_clicked()
{
std::string profile_name;
while(profile_name.empty())
{
bool ok_pressed = false;
QString name = QInputDialog::getText(this, tr("Enter Profile Name"), tr("Only letters, numbers and dash characters allowed.\nProfile name:"),
QLineEdit::Normal, "", &ok_pressed);
if(!ok_pressed)
return;
if(!name.isEmpty() && CInputConfig::IsValidProfileName(name.toStdString()))
profile_name = name.toStdString();
}
{
auto profile_path = CInputConfig::GetProfile(profile_name);
if(!fs::exists(profile_path))
{
ui->comboBox->addItem(profile_name.c_str());
}
auto index = ui->comboBox->findText(profile_name.c_str());
if(index >= 0)
ui->comboBox->setCurrentIndex(index);
}
}
void ControllerConfigDialog::on_delProfileButton_clicked()
{
auto name = ui->comboBox->currentText();
std::string profile_name = name.toStdString();
{
auto profile_path = CInputConfig::GetProfile(profile_name);
if(fs::exists(profile_path))
{
fs::remove(profile_path);
int index = ui->comboBox->currentIndex();
ui->comboBox->removeItem(index);
}
}
}

View file

@ -27,6 +27,10 @@ private slots:
void on_tableView_doubleClicked(const QModelIndex& index); void on_tableView_doubleClicked(const QModelIndex& index);
void on_ConfigAllButton_clicked(); void on_ConfigAllButton_clicked();
void on_comboBox_currentIndexChanged(int index);
void on_addProfileButton_clicked();
void on_delProfileButton_clicked();
private: private:
void PrepareBindingsView(); void PrepareBindingsView();
int OpenBindConfigDialog(int index); int OpenBindConfigDialog(int index);

View file

@ -3,3 +3,4 @@
#define PREFERENCE_AUDIO_ENABLEOUTPUT "audio.enableoutput" #define PREFERENCE_AUDIO_ENABLEOUTPUT "audio.enableoutput"
#define PREF_UI_PAUSEWHENFOCUSLOST "ui.pausewhenfocuslost" #define PREF_UI_PAUSEWHENFOCUSLOST "ui.pausewhenfocuslost"
#define PREF_VIDEO_GS_HANDLER "video.gshandler" #define PREF_VIDEO_GS_HANDLER "video.gshandler"
#define PREF_INPUT_PAD1_PROFILE "input.pad1.profile"

View file

@ -26,26 +26,6 @@
<string>Controller Manager</string> <string>Controller Manager</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="ConfigAllButton">
<property name="text">
<string>Config All</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="enabled"> <property name="enabled">
@ -83,6 +63,53 @@ QGroupBox::title {
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QPushButton" name="ConfigAllButton">
<property name="text">
<string>Config All</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Profile(s)</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QComboBox" name="comboBox">
</widget>
</item>
<item>
<widget class="QPushButton" name="addProfileButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="delProfileButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>

View file

@ -150,7 +150,10 @@ void MainWindow::InitVirtualMachine()
{ {
m_virtualMachine->CreatePadHandler(CPH_GenericInput::GetFactoryFunction()); m_virtualMachine->CreatePadHandler(CPH_GenericInput::GetFactoryFunction());
auto padHandler = static_cast<CPH_GenericInput*>(m_virtualMachine->GetPadHandler()); auto padHandler = static_cast<CPH_GenericInput*>(m_virtualMachine->GetPadHandler());
auto profile = CAppConfig::GetInstance().GetPreferenceString(PREF_INPUT_PAD1_PROFILE);
auto& bindingManager = padHandler->GetBindingManager(); auto& bindingManager = padHandler->GetBindingManager();
bindingManager.Load(profile);
//Create QtKeyInputProvider //Create QtKeyInputProvider
m_qtKeyInputProvider = std::make_shared<CInputProviderQtKey>(); m_qtKeyInputProvider = std::make_shared<CInputProviderQtKey>();
@ -642,6 +645,7 @@ void MainWindow::RegisterPreferences()
CAppConfig::GetInstance().RegisterPreferenceBoolean(PREFERENCE_AUDIO_ENABLEOUTPUT, true); CAppConfig::GetInstance().RegisterPreferenceBoolean(PREFERENCE_AUDIO_ENABLEOUTPUT, true);
CAppConfig::GetInstance().RegisterPreferenceBoolean(PREF_UI_PAUSEWHENFOCUSLOST, true); CAppConfig::GetInstance().RegisterPreferenceBoolean(PREF_UI_PAUSEWHENFOCUSLOST, true);
CAppConfig::GetInstance().RegisterPreferenceInteger(PREF_VIDEO_GS_HANDLER, SettingsDialog::GS_HANDLERS::OPENGL); CAppConfig::GetInstance().RegisterPreferenceInteger(PREF_VIDEO_GS_HANDLER, SettingsDialog::GS_HANDLERS::OPENGL);
CAppConfig::GetInstance().RegisterPreferenceString(PREF_INPUT_PAD1_PROFILE, "default");
} }
void MainWindow::focusOutEvent(QFocusEvent* event) void MainWindow::focusOutEvent(QFocusEvent* event)