Skip to content

Commit

Permalink
Control profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
iota97 committed Nov 14, 2022
1 parent 3f133be commit 8dbe935
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 22 deletions.
12 changes: 12 additions & 0 deletions Common/Data/Format/IniFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,18 @@ bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool de
}
}

bool IniFile::Get(const char* sectionName, const char* key, float* value, float defaultValue)
{
Section *section = GetSection(sectionName);
if (!section) {
*value = defaultValue;
return false;
} else {
return section->Get(key, value, defaultValue);
}
}



// Unit test. TODO: Move to the real unit test framework.
/*
Expand Down
1 change: 1 addition & 0 deletions Common/Data/Format/IniFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class IniFile {
bool Get(const char* sectionName, const char* key, uint32_t* value, uint32_t defaultValue = 0);
bool Get(const char* sectionName, const char* key, uint64_t* value, uint64_t defaultValue = 0);
bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false);
bool Get(const char* sectionName, const char* key, float* value, float defaultValue = 0.0f);
bool Get(const char* sectionName, const char* key, std::vector<std::string>& values);

template<typename T> bool GetIfExists(const char* sectionName, const char* key, T value)
Expand Down
115 changes: 100 additions & 15 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,21 +562,6 @@ static ConfigSetting generalSettings[] = {
ConfigSetting("GridView1", &g_Config.bGridView1, true),
ConfigSetting("GridView2", &g_Config.bGridView2, true),
ConfigSetting("GridView3", &g_Config.bGridView3, false),
ConfigSetting("RightAnalogUp", &g_Config.iRightAnalogUp, 0, true, true),
ConfigSetting("RightAnalogDown", &g_Config.iRightAnalogDown, 0, true, true),
ConfigSetting("RightAnalogLeft", &g_Config.iRightAnalogLeft, 0, true, true),
ConfigSetting("RightAnalogRight", &g_Config.iRightAnalogRight, 0, true, true),
ConfigSetting("RightAnalogPress", &g_Config.iRightAnalogPress, 0, true, true),
ConfigSetting("RightAnalogCustom", &g_Config.bRightAnalogCustom, false, true, true),
ConfigSetting("RightAnalogDisableDiagonal", &g_Config.bRightAnalogDisableDiagonal, false, true, true),
ConfigSetting("SwipeUp", &g_Config.iSwipeUp, 0, true, true),
ConfigSetting("SwipeDown", &g_Config.iSwipeDown, 0, true, true),
ConfigSetting("SwipeLeft", &g_Config.iSwipeLeft, 0, true, true),
ConfigSetting("SwipeRight", &g_Config.iSwipeRight, 0, true, true),
ConfigSetting("SwipeSensitivity", &g_Config.fSwipeSensitivity, 1.0f, true, true),
ConfigSetting("SwipeSmoothing", &g_Config.fSwipeSmoothing, 0.3f, true, true),
ConfigSetting("DoubleTapGesture", &g_Config.iDoubleTapGesture, 0, true, true),
ConfigSetting("GestureControlEnabled", &g_Config.bGestureControlEnabled, false, true, true),

// "default" means let emulator decide, "" means disable.
ConfigSetting("ReportingHost", &g_Config.sReportHost, "default"),
Expand Down Expand Up @@ -616,6 +601,7 @@ static ConfigSetting generalSettings[] = {
ConfigSetting("EnablePlugins", &g_Config.bLoadPlugins, true, true, true),

ReportedConfigSetting("IgnoreCompatSettings", &g_Config.sIgnoreCompatSettings, "", true, true),
ConfigSetting("SettingsVersion", &g_Config.uSettingsVersion, 0u, true, true), // Per game for game configs

ConfigSetting(false),
};
Expand Down Expand Up @@ -1089,6 +1075,23 @@ static ConfigSetting controlSettings[] = {
ConfigSetting("MouseSensitivity", &g_Config.fMouseSensitivity, 0.1f, true, true),
ConfigSetting("MouseSmoothing", &g_Config.fMouseSmoothing, 0.9f, true, true),

ConfigSetting("RightAnalogUp", &g_Config.iRightAnalogUp, 0, true, true),
ConfigSetting("RightAnalogDown", &g_Config.iRightAnalogDown, 0, true, true),
ConfigSetting("RightAnalogLeft", &g_Config.iRightAnalogLeft, 0, true, true),
ConfigSetting("RightAnalogRight", &g_Config.iRightAnalogRight, 0, true, true),
ConfigSetting("RightAnalogPress", &g_Config.iRightAnalogPress, 0, true, true),
ConfigSetting("RightAnalogCustom", &g_Config.bRightAnalogCustom, false, true, true),
ConfigSetting("RightAnalogDisableDiagonal", &g_Config.bRightAnalogDisableDiagonal, false, true, true),

ConfigSetting("SwipeUp", &g_Config.iSwipeUp, 0, true, true),
ConfigSetting("SwipeDown", &g_Config.iSwipeDown, 0, true, true),
ConfigSetting("SwipeLeft", &g_Config.iSwipeLeft, 0, true, true),
ConfigSetting("SwipeRight", &g_Config.iSwipeRight, 0, true, true),
ConfigSetting("SwipeSensitivity", &g_Config.fSwipeSensitivity, 1.0f, true, true),
ConfigSetting("SwipeSmoothing", &g_Config.fSwipeSmoothing, 0.3f, true, true),
ConfigSetting("DoubleTapGesture", &g_Config.iDoubleTapGesture, 0, true, true),
ConfigSetting("GestureControlEnabled", &g_Config.bGestureControlEnabled, false, true, true),

ConfigSetting("SystemControls", &g_Config.bSystemControls, true, true, false),

ConfigSetting(false),
Expand Down Expand Up @@ -1322,6 +1325,24 @@ void Config::UpdateIniLocation(const char *iniFileName, const char *controllerIn
controllerIniFilename_ = FindConfigFile(useControllerIniFilename ? controllerIniFilename : "controls.ini");
}

static void loadOldControlSettings(IniFile &iniFile) {
iniFile.GetIfExists("General", "RightAnalogUp", &g_Config.iRightAnalogUp);
iniFile.GetIfExists("General", "RightAnalogDown", &g_Config.iRightAnalogDown);
iniFile.GetIfExists("General", "RightAnalogLeft", &g_Config.iRightAnalogLeft);
iniFile.GetIfExists("General", "RightAnalogRight", &g_Config.iRightAnalogRight);
iniFile.GetIfExists("General", "RightAnalogPress", &g_Config.iRightAnalogPress);
iniFile.GetIfExists("General", "SwipeUp", &g_Config.iSwipeUp);
iniFile.GetIfExists("General", "SwipeDown", &g_Config.iSwipeDown);
iniFile.GetIfExists("General", "SwipeLeft", &g_Config.iSwipeLeft);
iniFile.GetIfExists("General", "SwipeRight", &g_Config.iSwipeRight);
iniFile.GetIfExists("General", "DoubleTapGesture", &g_Config.iDoubleTapGesture);
iniFile.GetIfExists("General", "SwipeSensitivity", &g_Config.fSwipeSensitivity);
iniFile.GetIfExists("General", "SwipeSmoothing", &g_Config.fSwipeSmoothing);
iniFile.GetIfExists("General", "RightAnalogCustom", &g_Config.bRightAnalogCustom);
iniFile.GetIfExists("General", "RightAnalogDisableDiagonal", &g_Config.bRightAnalogDisableDiagonal);
iniFile.GetIfExists("General", "GestureControlEnabled", &g_Config.bGestureControlEnabled);
}

void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
if (!bUpdatedInstanceCounter) {
InitInstanceCounter();
Expand Down Expand Up @@ -1419,6 +1440,12 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
ResetControlLayout();
}

if (g_Config.uSettingsVersion == 0) {
g_Config.uSettingsVersion = 1;

loadOldControlSettings(iniFile);
}

const char *gitVer = PPSSPP_GIT_VERSION;
Version installed(gitVer);
Version upgrade(upgradeVersion);
Expand Down Expand Up @@ -1488,6 +1515,58 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
INFO_LOG(LOADER, "Config loaded: '%s'", iniFilename_.c_str());
}

bool Config::SaveControllerProfile(uint32_t id) {
IniFile iniFile;
if (!iniFile.Load(controllerIniFilename_)) {
ERROR_LOG(LOADER, "Error saving controller profile - can't read ini '%s'", controllerIniFilename_.c_str());
return false;
}

Section *section = iniFile.GetOrCreateSection(StringFromFormat("ControlProfile%uSettings", id).c_str());
for (auto setting = controlSettings; setting->HasMore(); ++setting) {
setting->Set(section);
}

KeyMap::SaveToIni(iniFile, StringFromFormat("ControlProfile%uMapping", id).c_str());

if (!iniFile.Save(controllerIniFilename_)) {
ERROR_LOG(LOADER, "Error saving controller profile - can't write ini '%s'", controllerIniFilename_.c_str());
return false;
}

return true;
}

bool Config::ControllerProfileExist(uint32_t id) {
IniFile iniFile;
if (!iniFile.Load(controllerIniFilename_)) {
ERROR_LOG(LOADER, "Error checking controller profile - can't read ini '%s'", controllerIniFilename_.c_str());
return false;
}

return iniFile.HasSection(StringFromFormat("ControlProfile%uSettings", id).c_str());
}

bool Config::LoadControllerProfile(uint32_t id) {
IniFile iniFile;
if (!iniFile.Load(controllerIniFilename_)) {
ERROR_LOG(LOADER, "Error loading controller profile - can't read ini '%s'", controllerIniFilename_.c_str());
return false;
}

if (!iniFile.HasSection(StringFromFormat("ControlProfile%uSettings", id).c_str()))
return false;

Section *section = iniFile.GetOrCreateSection(StringFromFormat("ControlProfile%uSettings", id).c_str());
for (auto setting = controlSettings; setting->HasMore(); ++setting) {
setting->Get(section);
}

KeyMap::LoadFromIni(iniFile, StringFromFormat("ControlProfile%uMapping", id).c_str());

return true;
}

bool Config::Save(const char *saveReason) {
if (!IsFirstInstance()) {
// TODO: Should we allow saving config if started from a different directory?
Expand Down Expand Up @@ -1895,6 +1974,12 @@ bool Config::loadGameConfig(const std::string &pGameId, const std::string &title
}
});

if (g_Config.uSettingsVersion == 0) {
g_Config.uSettingsVersion = 1;

loadOldControlSettings(iniFile);
}

KeyMap::LoadFromIni(iniFile);
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct Config {
bool bEnableLogging;
bool bDumpDecryptedEboot;
bool bFullscreenOnDoubleclick;
uint32_t uSettingsVersion;

// These four are Win UI only
bool bPauseOnLostFocus;
Expand Down Expand Up @@ -519,6 +520,9 @@ struct Config {

void Load(const char *iniFileName = nullptr, const char *controllerIniFilename = nullptr);
bool Save(const char *saveReason);
bool SaveControllerProfile(uint32_t id);
bool LoadControllerProfile(uint32_t id);
bool ControllerProfileExist(uint32_t id);
void Reload();
void RestoreDefaults();

Expand Down
16 changes: 11 additions & 5 deletions Core/KeyMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,12 @@ const KeyMap_IntStrPair psp_button_names[] = {
{CTRL_VOL_DOWN, "Vol -"},
{CTRL_SCREEN, "Screen"},
{CTRL_NOTE, "Note"},

{VIRTKEY_CONTROLLER_PROFILE_1, "Load control profile 1"},
{VIRTKEY_CONTROLLER_PROFILE_2, "Load control profile 2"},
{VIRTKEY_CONTROLLER_PROFILE_3, "Load control profile 3"},
{VIRTKEY_CONTROLLER_PROFILE_4, "Load control profile 4"},
{VIRTKEY_CONTROLLER_PROFILE_5, "Load control profile 5"},
};

const int AXIS_BIND_NKCODE_START = 4000;
Expand Down Expand Up @@ -702,13 +708,13 @@ void RestoreDefault() {
}

// TODO: Make the ini format nicer.
void LoadFromIni(IniFile &file) {
void LoadFromIni(IniFile &file, const char *section) {
RestoreDefault();
if (!file.HasSection("ControlMapping")) {
if (!file.HasSection("ControlMapping")) { // Only on default section
return;
}

Section *controls = file.GetOrCreateSection("ControlMapping");
Section *controls = file.GetOrCreateSection(section);
for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
std::string value;
controls->Get(psp_button_names[i].name, &value, "");
Expand All @@ -735,8 +741,8 @@ void LoadFromIni(IniFile &file) {
UpdateNativeMenuKeys();
}

void SaveToIni(IniFile &file) {
Section *controls = file.GetOrCreateSection("ControlMapping");
void SaveToIni(IniFile &file, const char *section) {
Section *controls = file.GetOrCreateSection(section);

for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
std::vector<KeyDef> keys;
Expand Down
9 changes: 7 additions & 2 deletions Core/KeyMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ enum {
VIRTKEY_SPEED_ANALOG = 0x40000024,
VIRTKEY_VR_CAMERA_ADJUST = 0x40000025,
VIRTKEY_VR_CAMERA_RESET = 0x40000026,
VIRTKEY_CONTROLLER_PROFILE_1 = 0x40000027,
VIRTKEY_CONTROLLER_PROFILE_2 = 0x40000028,
VIRTKEY_CONTROLLER_PROFILE_3 = 0x40000029,
VIRTKEY_CONTROLLER_PROFILE_4 = 0x4000002A,
VIRTKEY_CONTROLLER_PROFILE_5 = 0x4000002B,
VIRTKEY_LAST,
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
};
Expand Down Expand Up @@ -146,8 +151,8 @@ namespace KeyMap {
bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction);
MappedAnalogAxes MappedAxesForDevice(int deviceId);

void LoadFromIni(IniFile &iniFile);
void SaveToIni(IniFile &iniFile);
void LoadFromIni(IniFile &iniFile, const char *section = "ControlMapping");
void SaveToIni(IniFile &iniFile, const char *section = "ControlMapping");

void SetDefaultKeyMap(DefaultMaps dmap, bool replace);

Expand Down
20 changes: 20 additions & 0 deletions UI/EmuScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,26 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) {
case VIRTKEY_SCREEN_ROTATION_HORIZONTAL180:
g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180;
break;
case VIRTKEY_CONTROLLER_PROFILE_1:
g_Config.LoadControllerProfile(1);
RecreateViews();
break;
case VIRTKEY_CONTROLLER_PROFILE_2:
g_Config.LoadControllerProfile(2);
RecreateViews();
break;
case VIRTKEY_CONTROLLER_PROFILE_3:
g_Config.LoadControllerProfile(3);
RecreateViews();
break;
case VIRTKEY_CONTROLLER_PROFILE_4:
g_Config.LoadControllerProfile(4);
RecreateViews();
break;
case VIRTKEY_CONTROLLER_PROFILE_5:
g_Config.LoadControllerProfile(5);
RecreateViews();
break;
}
}

Expand Down
58 changes: 58 additions & 0 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,11 @@ void GameSettingsScreen::CreateViews() {
controlsSettings->Add(new Choice(co->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping);
controlsSettings->Add(new Choice(co->T("Calibrate Analog Stick")))->OnClick.Handle(this, &GameSettingsScreen::OnCalibrateAnalogs);

controlsSettings->Add(new Choice(co->T("Control Profiles")))->OnClick.Add([=](EventParams &e) {
screenManager()->push(new ControllerProfileScreen());
return UI::EVENT_DONE;
});

#if defined(USING_WIN_UI)
controlsSettings->Add(new CheckBox(&g_Config.bSystemControls, co->T("Enable standard shortcut keys")));
controlsSettings->Add(new CheckBox(&g_Config.bGamepadOnlyFocused, co->T("Ignore gamepads when not focused")));
Expand Down Expand Up @@ -2279,3 +2284,56 @@ void GestureMappingScreen::CreateViews() {
vert->Add(new ItemHeader(co->T("Double tap")));
vert->Add(new PopupMultiChoice(&g_Config.iDoubleTapGesture, mc->T("Double tap button"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
}

void ControllerProfileScreen::CreateViews() {
using namespace UI;

auto co = GetI18NCategory("Controls");

root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
AddStandardBack(root_);
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false));
root_->Add(tabHolder);
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
tabHolder->AddTab(co->T("Profiles"), rightPanel);
LinearLayout *vert = rightPanel->Add(new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)));
vert->SetSpacing(0);

float leftSide = 40.0f;
if (dp_yres <= dp_xres * 1.1f) {
leftSide += 200.0f;
}
settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams(dp_xres - leftSide - 40.0f, WRAP_CONTENT, leftSide, dp_yres - 80.0f - 40.0f, NONE, NONE));
settingInfo_->SetBottomCutoff(dp_yres - 200.0f);
root_->Add(settingInfo_);

static constexpr int MAX_PROFILE = 5; // Should we have 5 with binding for fast selection and unlimited just to have them?
for (int i = 1; i <= MAX_PROFILE; ++i) {
vert->Add(new ItemHeader(ReplaceAll(co->T("Profile %1"), "%1", std::to_string(i))));

Choice *save = new Choice(co->T("Save current control settings"));
Choice *load = new Choice(co->T("Load control profile"));

load->OnClick.Add([=](EventParams &e) {
if (g_Config.LoadControllerProfile(i))
settingInfo_->Show(co->T("Control profile loaded"), e.v);

return UI::EVENT_CONTINUE;
});

save->OnClick.Add([=](EventParams &e) {
if (g_Config.SaveControllerProfile(i)) {
settingInfo_->Show(co->T("Control profile saved"), e.v);
load->SetEnabled(true);
}

return UI::EVENT_CONTINUE;
});

// Not a func to avoid Android slow IO problems
load->SetEnabled(g_Config.ControllerProfileExist(i));
vert->Add(save);
vert->Add(load);
}
}

9 changes: 9 additions & 0 deletions UI/GameSettingsScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,12 @@ class GestureMappingScreen : public UIDialogScreenWithBackground {

const char *tag() const override { return "GestureMapping"; }
};

class ControllerProfileScreen : public UIDialogScreenWithBackground {
public:
void CreateViews() override;

const char *tag() const override { return "ControllerProfile"; }
private:
SettingInfoMessage *settingInfo_;
};
Loading

0 comments on commit 8dbe935

Please sign in to comment.