diff --git a/Core/Config.cpp b/Core/Config.cpp index e99f55bf13..eac033342f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -222,8 +222,8 @@ static int DefaultScreenRotation() { #endif } -#define SETTING(a, x) (const char *)&a, &a.x -#define SETTING_IDX(a, x, i) (const char *)&a, &a.x[i] +#define SETTING(a, x) &a, &a.x +#define SETTING_IDX(a, x, i) &a, &a.x[i] // All relative to g_Config. static const ConfigSetting generalSettings[] = { @@ -844,33 +844,17 @@ static const float defaultControlScale = 1.15f; static const ConfigTouchPos defaultTouchPosShow = { -1.0f, -1.0f, defaultControlScale, true }; static const ConfigTouchPos defaultTouchPosHide = { -1.0f, -1.0f, defaultControlScale, false }; +bool TouchControlConfig::ResetToDefault(std::string_view blockName) { + // We do this traditionally for now. + return false; +} + static const ConfigSetting touchControlSettings[] = { ConfigSetting("ShowTouchCross", SETTING(g_Config.touchControlsLandscape, bShowTouchCross), true, CfgFlag::PER_GAME), ConfigSetting("ShowTouchCircle", SETTING(g_Config.touchControlsLandscape, bShowTouchCircle), true, CfgFlag::PER_GAME), ConfigSetting("ShowTouchSquare", SETTING(g_Config.touchControlsLandscape, bShowTouchSquare), true, CfgFlag::PER_GAME), ConfigSetting("ShowTouchTriangle", SETTING(g_Config.touchControlsLandscape, bShowTouchTriangle), true, CfgFlag::PER_GAME), - ConfigSetting("Custom0Mapping", "Custom0Image", "Custom0Shape", "Custom0Toggle", "Custom0Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 0), {0, 0, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom1Mapping", "Custom1Image", "Custom1Shape", "Custom1Toggle", "Custom1Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 1), {0, 1, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom2Mapping", "Custom2Image", "Custom2Shape", "Custom2Toggle", "Custom2Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 2), {0, 2, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom3Mapping", "Custom3Image", "Custom3Shape", "Custom3Toggle", "Custom3Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 3), {0, 3, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom4Mapping", "Custom4Image", "Custom4Shape", "Custom4Toggle", "Custom4Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 4), {0, 4, 0, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom5Mapping", "Custom5Image", "Custom5Shape", "Custom5Toggle", "Custom5Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 5), {0, 0, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom6Mapping", "Custom6Image", "Custom6Shape", "Custom6Toggle", "Custom6Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 6), {0, 1, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom7Mapping", "Custom7Image", "Custom7Shape", "Custom7Toggle", "Custom7Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 7), {0, 2, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom8Mapping", "Custom8Image", "Custom8Shape", "Custom8Toggle", "Custom8Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 8), {0, 3, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom9Mapping", "Custom9Image", "Custom9Shape", "Custom9Toggle", "Custom9Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 9), {0, 4, 1, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom10Mapping", "Custom10Image", "Custom10Shape", "Custom10Toggle", "Custom10Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 10), {0, 0, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom11Mapping", "Custom11Image", "Custom11Shape", "Custom11Toggle", "Custom11Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 11), {0, 1, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom12Mapping", "Custom12Image", "Custom12Shape", "Custom12Toggle", "Custom12Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 12), {0, 2, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom13Mapping", "Custom13Image", "Custom13Shape", "Custom13Toggle", "Custom13Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 13), {0, 3, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom14Mapping", "Custom14Image", "Custom14Shape", "Custom14Toggle", "Custom14Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 14), {0, 4, 2, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom15Mapping", "Custom15Image", "Custom15Shape", "Custom15Toggle", "Custom15Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 15), {0, 0, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom16Mapping", "Custom16Image", "Custom16Shape", "Custom16Toggle", "Custom16Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 16), {0, 1, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom17Mapping", "Custom17Image", "Custom17Shape", "Custom17Toggle", "Custom17Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 17), {0, 2, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom18Mapping", "Custom18Image", "Custom18Shape", "Custom18Toggle", "Custom18Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 18), {0, 3, 9, false, false}, CfgFlag::PER_GAME), - ConfigSetting("Custom19Mapping", "Custom19Image", "Custom19Shape", "Custom19Toggle", "Custom19Repeat", SETTING_IDX(g_Config.touchControlsLandscape, CustomButton, 19), {0, 4, 9, false, false}, CfgFlag::PER_GAME), - // Combo keys are something else, but I don't want to break the config backwards compatibility so these will stay wrongly named. ConfigSetting("fcombo0X", "fcombo0Y", "comboKeyScale0", "ShowComboKey0", SETTING_IDX(g_Config.touchControlsLandscape, touchCustom, 0), defaultTouchPosHide, CfgFlag::PER_GAME), ConfigSetting("fcombo1X", "fcombo1Y", "comboKeyScale1", "ShowComboKey1", SETTING_IDX(g_Config.touchControlsLandscape, touchCustom, 1), defaultTouchPosHide, CfgFlag::PER_GAME), @@ -926,6 +910,27 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("ShowTouchControls", SETTING(g_Config, bShowTouchControls), &DefaultShowTouchControls, CfgFlag::PER_GAME), // ConfigSetting("KeyMapping", SETTING(g_Config, iMappingMap), 0), + ConfigSetting("Custom0Mapping", "Custom0Image", "Custom0Shape", "Custom0Toggle", "Custom0Repeat", SETTING_IDX(g_Config, CustomButton, 0), {0, 0, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom1Mapping", "Custom1Image", "Custom1Shape", "Custom1Toggle", "Custom1Repeat", SETTING_IDX(g_Config, CustomButton, 1), {0, 1, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom2Mapping", "Custom2Image", "Custom2Shape", "Custom2Toggle", "Custom2Repeat", SETTING_IDX(g_Config, CustomButton, 2), {0, 2, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom3Mapping", "Custom3Image", "Custom3Shape", "Custom3Toggle", "Custom3Repeat", SETTING_IDX(g_Config, CustomButton, 3), {0, 3, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom4Mapping", "Custom4Image", "Custom4Shape", "Custom4Toggle", "Custom4Repeat", SETTING_IDX(g_Config, CustomButton, 4), {0, 4, 0, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom5Mapping", "Custom5Image", "Custom5Shape", "Custom5Toggle", "Custom5Repeat", SETTING_IDX(g_Config, CustomButton, 5), {0, 0, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom6Mapping", "Custom6Image", "Custom6Shape", "Custom6Toggle", "Custom6Repeat", SETTING_IDX(g_Config, CustomButton, 6), {0, 1, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom7Mapping", "Custom7Image", "Custom7Shape", "Custom7Toggle", "Custom7Repeat", SETTING_IDX(g_Config, CustomButton, 7), {0, 2, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom8Mapping", "Custom8Image", "Custom8Shape", "Custom8Toggle", "Custom8Repeat", SETTING_IDX(g_Config, CustomButton, 8), {0, 3, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom9Mapping", "Custom9Image", "Custom9Shape", "Custom9Toggle", "Custom9Repeat", SETTING_IDX(g_Config, CustomButton, 9), {0, 4, 1, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom10Mapping", "Custom10Image", "Custom10Shape", "Custom10Toggle", "Custom10Repeat", SETTING_IDX(g_Config, CustomButton, 10), {0, 0, 2, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom11Mapping", "Custom11Image", "Custom11Shape", "Custom11Toggle", "Custom11Repeat", SETTING_IDX(g_Config, CustomButton, 11), {0, 1, 2, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom12Mapping", "Custom12Image", "Custom12Shape", "Custom12Toggle", "Custom12Repeat", SETTING_IDX(g_Config, CustomButton, 12), {0, 2, 2, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom13Mapping", "Custom13Image", "Custom13Shape", "Custom13Toggle", "Custom13Repeat", SETTING_IDX(g_Config, CustomButton, 13), {0, 3, 2, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom14Mapping", "Custom14Image", "Custom14Shape", "Custom14Toggle", "Custom14Repeat", SETTING_IDX(g_Config, CustomButton, 14), {0, 4, 2, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom15Mapping", "Custom15Image", "Custom15Shape", "Custom15Toggle", "Custom15Repeat", SETTING_IDX(g_Config, CustomButton, 15), {0, 0, 9, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom16Mapping", "Custom16Image", "Custom16Shape", "Custom16Toggle", "Custom16Repeat", SETTING_IDX(g_Config, CustomButton, 16), {0, 1, 9, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom17Mapping", "Custom17Image", "Custom17Shape", "Custom17Toggle", "Custom17Repeat", SETTING_IDX(g_Config, CustomButton, 17), {0, 2, 9, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom18Mapping", "Custom18Image", "Custom18Shape", "Custom18Toggle", "Custom18Repeat", SETTING_IDX(g_Config, CustomButton, 18), {0, 3, 9, false, false}, CfgFlag::PER_GAME), + ConfigSetting("Custom19Mapping", "Custom19Image", "Custom19Shape", "Custom19Toggle", "Custom19Repeat", SETTING_IDX(g_Config, CustomButton, 19), {0, 4, 9, false, false}, CfgFlag::PER_GAME), + #ifdef MOBILE_DEVICE ConfigSetting("TiltBaseAngleY", SETTING(g_Config, fTiltBaseAngleY), 0.9f, CfgFlag::PER_GAME), @@ -1192,9 +1197,11 @@ void Config::ReadAllSettings(const IniFile &iniFile) { // Not found? Try the fallback (to upgrade settings that have been moved from old sections). if (!section && !meta.fallbackSectionName.empty()) { section = iniFile.GetSection(meta.fallbackSectionName); + // NOTE: it's tempting to update the configBlock here, but that's not what we want to do! + // We just want to read from a different section in the ini file, we still want to read into + // the same configBlock. } // If section is still null, we'll handle that gracefully by resetting to defaults. - _dbg_assert_(configBlock); bool applyDefaultPerSetting = true; if (configBlock->ResetToDefault(meta.section)) { applyDefaultPerSetting = false; @@ -1731,6 +1738,9 @@ bool Config::LoadGameConfig(const std::string &gameId) { // Not found? Try the fallback (to upgrade settings that have been moved from old sections). if (!section && !meta.fallbackSectionName.empty()) { section = iniFile.GetSection(meta.fallbackSectionName); + // NOTE: it's tempting to update the configBlock here, but that's not what we want to do! + // We just want to read from a different section in the ini file, we still want to read into + // the same configBlock. } for (size_t j = 0; j < meta.settingsCount; j++) { meta.settings[j].ReadFromIniSection(configBlock, section, false); @@ -1875,7 +1885,7 @@ void PlayTimeTracker::Stop(const std::string &gameId) { void PlayTimeTracker::Load(const Section *section) { tracker_.clear(); - auto map = section->ToMap(); + const auto map = section->ToMap(); for (const auto &iter : map) { const std::string &value = iter.second; diff --git a/Core/Config.h b/Core/Config.h index a108cd7e0e..737bc9259c 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -64,13 +64,6 @@ private: struct ConfigSetting; -struct ConfigBlock { - virtual ~ConfigBlock() = default; - virtual bool CanResetToDefault() const { return false; } - // If a block returns false here (like Config itself does), resetting to default will happen by the old per-setting mechanism. - virtual bool ResetToDefault(std::string_view blockName) { return false; } -}; - struct ConfigSectionMeta { ConfigBlock *configBlock; const ConfigSetting *settings; @@ -99,18 +92,19 @@ struct DisplayLayoutConfig : public ConfigBlock { bool InternalRotationIsPortrait() const; bool CanResetToDefault() const override { return true; } bool ResetToDefault(std::string_view blockName) override; + size_t Size() const override { return sizeof(DisplayLayoutConfig); } // For sanity checks }; struct TouchControlConfig : public ConfigBlock { //space between PSP buttons //the PSP button's center (triangle, circle, square, cross) ConfigTouchPos touchActionButtonCenter; - float fActionButtonSpacing; + float fActionButtonSpacing = 0.0f; //radius of the D-pad (PSP cross) // int iDpadRadius; //the D-pad (PSP cross) position ConfigTouchPos touchDpad; - float fDpadSpacing; + float fDpadSpacing = 0.0f; ConfigTouchPos touchStartKey; ConfigTouchPos touchSelectKey; ConfigTouchPos touchFastForwardKey; @@ -125,12 +119,17 @@ struct TouchControlConfig : public ConfigBlock { float fLeftStickHeadScale = 1.0f; float fRightStickHeadScale = 1.0f; + bool bHideStickBackground = false; bool bShowTouchCircle = true; bool bShowTouchCross = true; bool bShowTouchTriangle = true; bool bShowTouchSquare = true; + + bool CanResetToDefault() const override { return true; } + bool ResetToDefault(std::string_view blockName) override; + size_t Size() const override { return sizeof(TouchControlConfig); } // For sanity checks }; struct Config : public ConfigBlock { @@ -138,7 +137,7 @@ public: Config(); ~Config(); - u32 sentinel = 13371337; // For memory corruption debugging, just set a data breakpoint. + size_t Size() const override { return sizeof(Config); } // Whether to save the config on close. bool bSaveSettings; @@ -729,6 +728,7 @@ private: std::string gameId_; PlayTimeTracker playTimeTracker_; + Path iniFilename_; Path controllerIniFilename_; Path searchPath_; diff --git a/Core/ConfigSettings.cpp b/Core/ConfigSettings.cpp index ab4358a59d..2434138ff0 100644 --- a/Core/ConfigSettings.cpp +++ b/Core/ConfigSettings.cpp @@ -14,6 +14,8 @@ bool ConfigSetting::perGame(void *ptr) { bool ConfigSetting::ReadFromIniSection(ConfigBlock *configBlock, const Section *section, bool applyDefaultIfMissing) const { char *owner = (char *)configBlock; + _dbg_assert_(offset_ >= 0 && offset_ < configBlock->Size()); + switch (type_) { case Type::TYPE_BOOL: { @@ -178,6 +180,7 @@ void ConfigSetting::WriteToIniSection(const ConfigBlock *configBlock, Section *s return; } _dbg_assert_(section); + _dbg_assert_(offset_ >= 0 && offset_ < configBlock->Size()); const char *owner = (const char *)configBlock; switch (type_) { @@ -235,6 +238,7 @@ void ConfigSetting::WriteToIniSection(const ConfigBlock *configBlock, Section *s bool ConfigSetting::RestoreToDefault(ConfigBlock *configBlock, bool log) const { // If the block supports resetting itself, don't allow per-setting resets. Shake them out with this assert. _dbg_assert_(!configBlock->CanResetToDefault()); + _dbg_assert_(offset_ >= 0 && offset_ < configBlock->Size()); const char *owner = (const char *)configBlock; switch (type_) { @@ -369,6 +373,8 @@ bool ConfigSetting::RestoreToDefault(ConfigBlock *configBlock, bool log) const { // Might be used to copy individual settings from defaulted blocks. Didn't end up using this for now. void ConfigSetting::CopyFromBlock(const ConfigBlock *other) { + _dbg_assert_(offset_ >= 0 && offset_ < other->Size()); + const char *otherOwner = (const char *)other; const char *thisOwner = (const char *)this; switch (type_) { @@ -392,8 +398,9 @@ void ConfigSetting::ReportSetting(const ConfigBlock *configBlock, UrlEncoder &da if (!Report()) return; + _dbg_assert_(offset_ >= 0 && offset_ < configBlock->Size()); const char *owner = (const char *)configBlock; - const std::string key = join(prefix, std::string(iniKey_)); + const std::string key = join(prefix, iniKey_); switch (type_) { case Type::TYPE_BOOL: return data.Add(key, *(const bool *)(owner + offset_)); diff --git a/Core/ConfigSettings.h b/Core/ConfigSettings.h index deb7f89671..a77c3b9921 100644 --- a/Core/ConfigSettings.h +++ b/Core/ConfigSettings.h @@ -2,6 +2,7 @@ #include #include + #include "Core/ConfigValues.h" class Path; @@ -67,121 +68,123 @@ struct ConfigSetting { CustomButtonDefaultCallback customButton; }; - ConfigSetting(std::string_view ini, const char *owner, bool *v, bool def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_BOOL), flags_(flags), offset_((const char *)v - owner) { + // The configBlock you pass in here is just to be able to calculate the offset of the setting within the block so it can be + // applied to other blocks. + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, bool *v, bool def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_BOOL), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.b = nullptr; default_.b = def; } - ConfigSetting(std::string_view ini, const char *owner, bool *v, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_BOOL), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, bool *v, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_BOOL), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.b = nullptr; default_.b = false; // unused with this constructor } - ConfigSetting(std::string_view ini, const char *owner, int *v, int def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, int *v, int def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.i = nullptr; default_.i = def; } - ConfigSetting(std::string_view ini, const char *owner, int *v, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, int *v, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.i = nullptr; default_.i = 0; // unused with this constructor } - ConfigSetting(std::string_view ini, const char *owner, int *v, int def, std::string (*transTo)(int), int (*transFrom)(const std::string &), CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), translateTo_(transTo), translateFrom_(transFrom), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, int *v, int def, std::string (*transTo)(int), int (*transFrom)(const std::string &), CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), translateTo_(transTo), translateFrom_(transFrom), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.i = nullptr; default_.i = def; } - ConfigSetting(std::string_view ini, const char *owner, uint32_t *v, uint32_t def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_UINT32), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, uint32_t *v, uint32_t def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_UINT32), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.u = nullptr; default_.u = def; } - ConfigSetting(std::string_view ini, const char *owner, uint64_t *v, uint64_t def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_UINT64), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, uint64_t *v, uint64_t def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_UINT64), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.lu = nullptr; default_.lu = def; } - ConfigSetting(std::string_view ini, const char *owner, float *v, float def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_FLOAT), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, float *v, float def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_FLOAT), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.f = nullptr; default_.f = def; } - ConfigSetting(std::string_view ini, const char *owner, float *v, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_FLOAT), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, float *v, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_FLOAT), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.f = nullptr; default_.f = 0.0f; } - ConfigSetting(std::string_view ini, const char *owner, std::string *v, const char *def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_STRING), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, std::string *v, const char *def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_STRING), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.s = nullptr; default_.s = def; } - ConfigSetting(std::string_view ini, const char *owner, std::vector *v, const std::vector *def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_STRING_VECTOR), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, std::vector *v, const std::vector *def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_STRING_VECTOR), flags_(flags), offset_((const char *)v - (const char *)configBlock) { default_.v = def; } - ConfigSetting(std::string_view ini, const char *owner, Path *v, const char *def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_PATH), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, Path *v, const char *def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_PATH), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.p = nullptr; default_.p = def; } - ConfigSetting(const char *iniX, const char *iniY, const char *iniScale, const char *iniShow, const char *owner, ConfigTouchPos *v, ConfigTouchPos def, CfgFlag flags) noexcept - : iniKey_(iniX), ini2_(iniY), ini3_(iniScale), ini4_(iniShow), type_(Type::TYPE_TOUCH_POS), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(const char *iniX, const char *iniY, const char *iniScale, const char *iniShow, ConfigBlock *configBlock, ConfigTouchPos *v, ConfigTouchPos def, CfgFlag flags) noexcept + : iniKey_(iniX), ini2_(iniY), ini3_(iniScale), ini4_(iniShow), type_(Type::TYPE_TOUCH_POS), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.touchPos = nullptr; default_.touchPos = def; } - ConfigSetting(const char *iniKey, const char *iniImage, const char *iniShape, const char *iniToggle, const char *iniRepeat, const char *owner, ConfigCustomButton *v, ConfigCustomButton def, CfgFlag flags) noexcept - : iniKey_(iniKey), ini2_(iniImage), ini3_(iniShape), ini4_(iniToggle), ini5_(iniRepeat), type_(Type::TYPE_CUSTOM_BUTTON), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(const char *iniKey, const char *iniImage, const char *iniShape, const char *iniToggle, const char *iniRepeat, ConfigBlock *configBlock, ConfigCustomButton *v, ConfigCustomButton def, CfgFlag flags) noexcept + : iniKey_(iniKey), ini2_(iniImage), ini3_(iniShape), ini4_(iniToggle), ini5_(iniRepeat), type_(Type::TYPE_CUSTOM_BUTTON), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.customButton = nullptr; default_.customButton = def; } - ConfigSetting(std::string_view ini, const char *owner, bool *v, BoolDefaultCallback def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_BOOL), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, bool *v, BoolDefaultCallback def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_BOOL), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.b = def; } - ConfigSetting(std::string_view ini, const char *owner, int *v, IntDefaultCallback def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, int *v, IntDefaultCallback def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.i = def; } - ConfigSetting(std::string_view ini, const char *owner, int *v, IntDefaultCallback def, std::string(*transTo)(int), int(*transFrom)(const std::string &), CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - owner), translateTo_(transTo), translateFrom_(transFrom) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, int *v, IntDefaultCallback def, std::string(*transTo)(int), int(*transFrom)(const std::string &), CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_INT), flags_(flags), offset_((const char *)v - (const char *)configBlock), translateTo_(transTo), translateFrom_(transFrom) { defaultCallback_.i = def; } - ConfigSetting(std::string_view ini, const char *owner, uint32_t *v, Uint32DefaultCallback def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_UINT32), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, uint32_t *v, Uint32DefaultCallback def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_UINT32), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.u = def; } - ConfigSetting(std::string_view ini, const char *owner, float *v, FloatDefaultCallback def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_FLOAT), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, float *v, FloatDefaultCallback def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_FLOAT), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.f = def; } - ConfigSetting(std::string_view ini, const char *owner, std::string *v, StringDefaultCallback def, CfgFlag flags) noexcept - : iniKey_(ini), type_(Type::TYPE_STRING), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view ini, ConfigBlock *configBlock, std::string *v, StringDefaultCallback def, CfgFlag flags) noexcept + : iniKey_(ini), type_(Type::TYPE_STRING), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.s = def; } - ConfigSetting(std::string_view iniX, const char *iniY, const char *iniScale, const char *iniShow, const char *owner, ConfigTouchPos *v, TouchPosDefaultCallback def, CfgFlag flags) noexcept - : iniKey_(iniX), ini2_(iniY), ini3_(iniScale), ini4_(iniShow), type_(Type::TYPE_TOUCH_POS), flags_(flags), offset_((const char *)v - owner) { + ConfigSetting(std::string_view iniX, const char *iniY, const char *iniScale, const char *iniShow, ConfigBlock *configBlock, ConfigTouchPos *v, TouchPosDefaultCallback def, CfgFlag flags) noexcept + : iniKey_(iniX), ini2_(iniY), ini3_(iniScale), ini4_(iniShow), type_(Type::TYPE_TOUCH_POS), flags_(flags), offset_((const char *)v - (const char *)configBlock) { defaultCallback_.touchPos = def; } diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index e5e98aae87..40f71f4e50 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -20,12 +20,21 @@ #include #include #include +#include #ifndef _MSC_VER #include #endif #include "Common/Common.h" #include "Common/CommonFuncs.h" +struct ConfigBlock { + virtual ~ConfigBlock() = default; + virtual bool CanResetToDefault() const { return false; } + // If a block returns false here (like Config itself does), resetting to default will happen by the old per-setting mechanism. + virtual bool ResetToDefault(std::string_view blockName) { return false; } + virtual size_t Size() const { return sizeof(ConfigBlock); } // For sanity checks +}; + constexpr int PSP_MODEL_FAT = 0; constexpr int PSP_MODEL_SLIM = 1; constexpr int PSP_DEFAULT_FIRMWARE = 660; @@ -48,11 +57,11 @@ int MultiplierToVolume100(float multiplier); float UIScaleFactorToMultiplier(int factor); struct ConfigTouchPos { - float x; - float y; - float scale; + float x = -1.0f; + float y = -1.0f; + float scale = 1.0f; // Note: Show is not used for all settings. - bool show; + bool show = true; }; struct ConfigCustomButton { diff --git a/UI/CustomButtonMappingScreen.cpp b/UI/CustomButtonMappingScreen.cpp index 40e4e87e32..4456a00831 100644 --- a/UI/CustomButtonMappingScreen.cpp +++ b/UI/CustomButtonMappingScreen.cpp @@ -132,11 +132,13 @@ void CustomButtonMappingScreen::CreateViews() { LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(120, FILL_PARENT)); auto di = GetI18NCategory(I18NCat::DIALOG); + TouchControlConfig &touch = g_Config.GetTouchControlsConfig(deviceOrientation_); + ConfigCustomButton *cfg = nullptr; bool *show = nullptr; memset(array, 0, sizeof(array)); cfg = &g_Config.CustomButton[id_]; - show = &g_Config.touchCustom[id_].show; + show = &touch.touchCustom[id_].show; for (int i = 0; i < ARRAY_SIZE(g_customKeyList); i++) array[i] = (0x01 == ((g_Config.CustomButton[id_].key >> i) & 0x01)); @@ -221,7 +223,7 @@ static uint64_t arrayToInt(const bool ary[ARRAY_SIZE(CustomKeyData::g_customKeyL } void CustomButtonMappingScreen::saveArray() { - if (id_ >= 0 && id_ < Config::CUSTOM_BUTTON_COUNT) { + if (id_ >= 0 && id_ < TouchControlConfig::CUSTOM_BUTTON_COUNT) { g_Config.CustomButton[id_].key = arrayToInt(array); } } diff --git a/UI/CustomButtonMappingScreen.h b/UI/CustomButtonMappingScreen.h index c85efa3f6f..2fa658b00e 100644 --- a/UI/CustomButtonMappingScreen.h +++ b/UI/CustomButtonMappingScreen.h @@ -26,7 +26,7 @@ namespace UI { class CustomButtonMappingScreen : public UIBaseDialogScreen { public: - CustomButtonMappingScreen(const Path &gamePath, int id) : UIBaseDialogScreen(gamePath), id_(id) {} + CustomButtonMappingScreen(DeviceOrientation deviceOrientation, const Path &gamePath, int id) : UIBaseDialogScreen(gamePath), deviceOrientation_(deviceOrientation), id_(id) {} const char *tag() const override { return "CustomButton"; } @@ -49,4 +49,6 @@ private: private: UI::CheckBox *checkbox_; }; + + DeviceOrientation deviceOrientation_; }; diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index d7996cb295..d6599c01c1 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -274,8 +274,8 @@ void DisplayLayoutScreen::CreateViews() { supportsInsets = true; #endif // Hide insets option if no insets, or OS too old. - if (supportsInsets && - (System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) != 0.0f || + if (supportsInsets && ( + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) != 0.0f || System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP) != 0.0f || System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT) != 0.0f || System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM) != 0.0f)) { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 9fbd2c96d7..da11c0159e 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1245,13 +1245,15 @@ void EmuScreen::CreateViews() { auto dev = GetI18NCategory(I18NCat::DEVELOPER); auto sc = GetI18NCategory(I18NCat::SCREEN); + TouchControlConfig &touch = g_Config.GetTouchControlsConfig(GetDeviceOrientation()); + const Bounds &bounds = screenManager()->getUIContext()->GetLayoutBounds(); - InitPadLayout(bounds.w, bounds.h); + InitPadLayout(&touch, bounds.w, bounds.h); // Devices without a back button like iOS need an on-screen touch back button. bool showPauseButton = !System_GetPropertyBool(SYSPROP_HAS_BACK_BUTTON) || g_Config.bShowTouchPause; - root_ = CreatePadLayout(bounds.w, bounds.h, &pauseTrigger_, showPauseButton, &controlMapper_); + root_ = CreatePadLayout(touch, bounds.w, bounds.h, &pauseTrigger_, showPauseButton, &controlMapper_); if (g_Config.bShowDeveloperMenu) { root_->Add(new Button(dev->T("DevMenu")))->OnClick.Handle(this, &EmuScreen::OnDevTools); } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 4a476064af..68bec6862f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -854,8 +854,10 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) CheckBox *touchGliding = controlsSettings->Add(new CheckBox(&g_Config.bTouchGliding, co->T("Keep first touched button pressed when dragging"))); touchGliding->SetEnabledPtr(&g_Config.bShowTouchControls); + TouchControlConfig &touch = g_Config.GetTouchControlsConfig(GetDeviceOrientation()); + // Hide stick background, useful when increasing the size - CheckBox *hideStickBackground = controlsSettings->Add(new CheckBox(&g_Config.bHideStickBackground, co->T("Hide touch analog stick background circle"))); + CheckBox *hideStickBackground = controlsSettings->Add(new CheckBox(&touch.bHideStickBackground, co->T("Hide touch analog stick background circle"))); hideStickBackground->SetEnabledPtr(&g_Config.bShowTouchControls); // Sticky D-pad. diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index f81f5eb4ea..a2fe339af4 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -460,9 +460,11 @@ void PSPStick::Draw(UIContext &dc) { float dx, dy; __CtrlPeekAnalog(stick_, &dx, &dy); - if (!g_Config.bHideStickBackground) + const TouchControlConfig &config = g_Config.GetTouchControlsConfig(g_display.GetDeviceOrientation()); + + if (!config.bHideStickBackground) dc.Draw()->DrawImage(bgImg_, stickX, stickY, 1.0f * scale_, colorBg, ALIGN_CENTER); - float headScale = stick_ ? g_Config.fRightStickHeadScale : g_Config.fLeftStickHeadScale; + float headScale = stick_ ? config.fRightStickHeadScale : config.fLeftStickHeadScale; if (dragPointerId_ != -1 && g_Config.iTouchButtonStyle == 2 && stickDownImg_ != stickImageIndex_) dc.Draw()->DrawImage(stickDownImg_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f * scale_ * headScale, downBg, ALIGN_CENTER); dc.Draw()->DrawImage(stickImageIndex_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f * scale_ * headScale, colorBg, ALIGN_CENTER); @@ -480,7 +482,8 @@ bool PSPStick::Touch(const TouchInput &input) { return retval; } if (input.flags & TOUCH_DOWN) { - float fac = 0.5f*(stick_ ? g_Config.fRightStickHeadScale : g_Config.fLeftStickHeadScale)-0.5f; + const TouchControlConfig &config = g_Config.GetTouchControlsConfig(g_display.GetDeviceOrientation()); + float fac = 0.5f * (stick_ ? config.fRightStickHeadScale : config.fLeftStickHeadScale)-0.5f; if (dragPointerId_ == -1 && bounds_.Expand(bounds_.w*fac, bounds_.h*fac).Contains(input.x, input.y)) { if (g_Config.bAutoCenterTouchAnalog) { centerX_ = input.x; @@ -569,11 +572,13 @@ void PSPCustomStick::Draw(UIContext &dc) { dx = posX_; dy = -posY_; - if (!g_Config.bHideStickBackground) + const TouchControlConfig &config = g_Config.GetTouchControlsConfig(g_display.GetDeviceOrientation()); + const float headScale = config.fRightStickHeadScale; + if (!config.bHideStickBackground) dc.Draw()->DrawImage(bgImg_, stickX, stickY, 1.0f * scale_, colorBg, ALIGN_CENTER); if (dragPointerId_ != -1 && g_Config.iTouchButtonStyle == 2 && stickDownImg_ != stickImageIndex_) - dc.Draw()->DrawImage(stickDownImg_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f*scale_*g_Config.fRightStickHeadScale, downBg, ALIGN_CENTER); - dc.Draw()->DrawImage(stickImageIndex_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f*scale_*g_Config.fRightStickHeadScale, colorBg, ALIGN_CENTER); + dc.Draw()->DrawImage(stickDownImg_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f * scale_ * headScale, downBg, ALIGN_CENTER); + dc.Draw()->DrawImage(stickImageIndex_, stickX + dx * stick_size_ * scale_, stickY - dy * stick_size_ * scale_, 1.0f * scale_ * headScale, colorBg, ALIGN_CENTER); } bool PSPCustomStick::Touch(const TouchInput &input) { @@ -589,7 +594,8 @@ bool PSPCustomStick::Touch(const TouchInput &input) { return false; } if (input.flags & TOUCH_DOWN) { - float fac = 0.5f*g_Config.fRightStickHeadScale-0.5f; + const TouchControlConfig &config = g_Config.GetTouchControlsConfig(g_display.GetDeviceOrientation()); + float fac = 0.5f * config.fRightStickHeadScale - 0.5f; if (dragPointerId_ == -1 && bounds_.Expand(bounds_.w*fac, bounds_.h*fac).Contains(input.x, input.y)) { if (g_Config.bAutoCenterTouchAnalog) { centerX_ = input.x; @@ -744,32 +750,32 @@ void PSPCustomStick::ProcessTouch(float x, float y, bool down) { } } -void InitPadLayout(float xres, float yres, float globalScale) { +void InitPadLayout(TouchControlConfig *config, float xres, float yres, float globalScale) { const float scale = globalScale; const int halfW = xres / 2; - auto initTouchPos = [=](ConfigTouchPos &touch, float x, float y) { - if (touch.x == -1.0f || touch.y == -1.0f) { - touch.x = x / xres; - touch.y = std::max(y, 20.0f * globalScale) / yres; - touch.scale = scale; + auto initTouchPos = [=](ConfigTouchPos *touch, float x, float y) { + if (touch->x == -1.0f || touch->y == -1.0f) { + touch->x = x / xres; + touch->y = std::max(y, 20.0f * globalScale) / yres; + touch->scale = scale; } }; // PSP buttons (triangle, circle, square, cross)--------------------- // space between the PSP buttons (triangle, circle, square and cross) - if (g_Config.fActionButtonSpacing < 0) { - g_Config.fActionButtonSpacing = 1.0f; + if (config->fActionButtonSpacing < 0) { + config->fActionButtonSpacing = 1.0f; } // Position of the circle button (the PSP circle button). It is the farthest to the left - float Action_button_spacing = g_Config.fActionButtonSpacing * baseActionButtonSpacing; + float Action_button_spacing = config->fActionButtonSpacing * baseActionButtonSpacing; int Action_button_center_X = xres - Action_button_spacing * 2; int Action_button_center_Y = yres - Action_button_spacing * 2; - if (g_Config.touchRightAnalogStick.show) { + if (config->touchRightAnalogStick.show) { Action_button_center_Y -= 150 * scale; } - initTouchPos(g_Config.touchActionButtonCenter, Action_button_center_X, Action_button_center_Y); + initTouchPos(&config->touchActionButtonCenter, Action_button_center_X, Action_button_center_Y); //D-PAD (up down left right) (aka PSP cross)---------------------------- //radius to the D-pad @@ -777,22 +783,22 @@ void InitPadLayout(float xres, float yres, float globalScale) { int D_pad_X = 2.5 * D_pad_Radius * scale; int D_pad_Y = yres - D_pad_Radius * scale; - if (g_Config.touchAnalogStick.show) { + if (config->touchAnalogStick.show) { D_pad_Y -= 200 * scale; } - initTouchPos(g_Config.touchDpad, D_pad_X, D_pad_Y); + initTouchPos(&config->touchDpad, D_pad_X, D_pad_Y); //analog stick------------------------------------------------------- //keep the analog stick right below the D pad int analog_stick_X = D_pad_X; int analog_stick_Y = yres - 80 * scale; - initTouchPos(g_Config.touchAnalogStick, analog_stick_X, analog_stick_Y); + initTouchPos(&config->touchAnalogStick, analog_stick_X, analog_stick_Y); //right analog stick------------------------------------------------- //keep the right analog stick right below the face buttons int right_analog_stick_X = Action_button_center_X; int right_analog_stick_Y = yres - 80 * scale; - initTouchPos(g_Config.touchRightAnalogStick, right_analog_stick_X, right_analog_stick_Y); + initTouchPos(&config->touchRightAnalogStick, right_analog_stick_X, right_analog_stick_Y); //select, start, throttle-------------------------------------------- //space between the bottom keys (space between select, start and un-throttle) @@ -810,15 +816,15 @@ void InitPadLayout(float xres, float yres, float globalScale) { int start_key_X = halfW + bottom_key_spacing * scale; int start_key_Y = yres - bottom_button_Y * scale; - initTouchPos(g_Config.touchStartKey, start_key_X, start_key_Y); + initTouchPos(&config->touchStartKey, start_key_X, start_key_Y); int select_key_X = halfW; int select_key_Y = yres - bottom_button_Y * scale; - initTouchPos(g_Config.touchSelectKey, select_key_X, select_key_Y); + initTouchPos(&config->touchSelectKey, select_key_X, select_key_Y); int fast_forward_key_X = halfW - bottom_key_spacing * scale; int fast_forward_key_Y = yres - bottom_button_Y * scale; - initTouchPos(g_Config.touchFastForwardKey, fast_forward_key_X, fast_forward_key_Y); + initTouchPos(&config->touchFastForwardKey, fast_forward_key_X, fast_forward_key_Y); // L and R------------------------------------------------------------ // Put them above the analog stick / above the buttons to the right. @@ -826,11 +832,11 @@ void InitPadLayout(float xres, float yres, float globalScale) { int l_key_X = 60 * scale; int l_key_Y = yres - 380 * scale; - initTouchPos(g_Config.touchLKey, l_key_X, l_key_Y); + initTouchPos(&config->touchLKey, l_key_X, l_key_Y); int r_key_X = xres - 60 * scale; int r_key_Y = l_key_Y; - initTouchPos(g_Config.touchRKey, r_key_X, r_key_Y); + initTouchPos(&config->touchRKey, r_key_X, r_key_Y); struct { float x; float y; } customButtonPositions[10] = { { 1.2f, 0.5f }, @@ -845,17 +851,17 @@ void InitPadLayout(float xres, float yres, float globalScale) { { -2.2f, 0.333f }, }; - for (int i = 0; i < Config::CUSTOM_BUTTON_COUNT; i++) { - float y_offset = (float)(i / 10) * 0.08333f; + for (int i = 0; i < TouchControlConfig::CUSTOM_BUTTON_COUNT; i++) { + const float y_offset = (float)(i / 10) * 0.08333f; int combo_key_X = halfW + bottom_key_spacing * scale * customButtonPositions[i % 10].x; int combo_key_Y = yres * (y_offset + customButtonPositions[i % 10].y); - initTouchPos(g_Config.touchCustom[i], combo_key_X, combo_key_Y); + initTouchPos(&config->touchCustom[i], combo_key_X, combo_key_Y); } } -UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPauseButton, ControlMapper* controllMapper) { +UI::ViewGroup *CreatePadLayout(const TouchControlConfig &config, float xres, float yres, bool *pause, bool showPauseButton, ControlMapper *controlMapper) { using namespace UI; AnchorLayout *root = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); @@ -872,7 +878,7 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau }; // Space between the PSP buttons (traingle, circle, square and cross) - const float actionButtonSpacing = g_Config.fActionButtonSpacing * baseActionButtonSpacing; + const float actionButtonSpacing = config.fActionButtonSpacing * baseActionButtonSpacing; // Position of the circle button (the PSP circle button). It is the farthest to the right. ButtonOffset circleOffset{ actionButtonSpacing, 0.0f }; ButtonOffset crossOffset{ 0.0f, actionButtonSpacing }; @@ -906,7 +912,7 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau _dbg_assert_(cfg.image < ARRAY_SIZE(customKeyImages)); // Note: cfg.shape and cfg.image are bounds-checked elsewhere. - auto aux = root->Add(new CustomButton(cfg.key, key, cfg.toggle, cfg.repeat, controllMapper, + auto aux = root->Add(new CustomButton(cfg.key, key, cfg.toggle, cfg.repeat, controlMapper, g_Config.iTouchButtonStyle == 0 ? customKeyShapes[cfg.shape].i : customKeyShapes[cfg.shape].l, customKeyShapes[cfg.shape].i, customKeyImages[cfg.image].i, touch.scale, customKeyShapes[cfg.shape].d, buttonLayoutParams(touch))); aux->SetAngle(customKeyImages[cfg.image].r, customKeyShapes[cfg.shape].r); @@ -921,19 +927,19 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau } // touchActionButtonCenter.show will always be true, since that's the default. - if (g_Config.bShowTouchCircle) - addPSPButton(CTRL_CIRCLE, "Circle button", roundImage, ImageID("I_ROUND"), ImageID("I_CIRCLE"), g_Config.touchActionButtonCenter, circleOffset); - if (g_Config.bShowTouchCross) - addPSPButton(CTRL_CROSS, "Cross button", roundImage, ImageID("I_ROUND"), ImageID("I_CROSS"), g_Config.touchActionButtonCenter, crossOffset); - if (g_Config.bShowTouchTriangle) - addPSPButton(CTRL_TRIANGLE, "Triangle button", roundImage, ImageID("I_ROUND"), ImageID("I_TRIANGLE"), g_Config.touchActionButtonCenter, triangleOffset); - if (g_Config.bShowTouchSquare) - addPSPButton(CTRL_SQUARE, "Square button", roundImage, ImageID("I_ROUND"), ImageID("I_SQUARE"), g_Config.touchActionButtonCenter, squareOffset); + if (config.bShowTouchCircle) + addPSPButton(CTRL_CIRCLE, "Circle button", roundImage, ImageID("I_ROUND"), ImageID("I_CIRCLE"), config.touchActionButtonCenter, circleOffset); + if (config.bShowTouchCross) + addPSPButton(CTRL_CROSS, "Cross button", roundImage, ImageID("I_ROUND"), ImageID("I_CROSS"), config.touchActionButtonCenter, crossOffset); + if (config.bShowTouchTriangle) + addPSPButton(CTRL_TRIANGLE, "Triangle button", roundImage, ImageID("I_ROUND"), ImageID("I_TRIANGLE"), config.touchActionButtonCenter, triangleOffset); + if (config.bShowTouchSquare) + addPSPButton(CTRL_SQUARE, "Square button", roundImage, ImageID("I_ROUND"), ImageID("I_SQUARE"), config.touchActionButtonCenter, squareOffset); - addPSPButton(CTRL_START, "Start button", rectImage, ImageID("I_RECT"), ImageID("I_START"), g_Config.touchStartKey); - addPSPButton(CTRL_SELECT, "Select button", rectImage, ImageID("I_RECT"), ImageID("I_SELECT"), g_Config.touchSelectKey); + addPSPButton(CTRL_START, "Start button", rectImage, ImageID("I_RECT"), ImageID("I_START"), config.touchStartKey); + addPSPButton(CTRL_SELECT, "Select button", rectImage, ImageID("I_RECT"), ImageID("I_SELECT"), config.touchSelectKey); - BoolButton *fastForward = addBoolButton(&PSP_CoreParameter().fastForward, "Fast-forward button", rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), g_Config.touchFastForwardKey); + BoolButton *fastForward = addBoolButton(&PSP_CoreParameter().fastForward, "Fast-forward button", rectImage, ImageID("I_RECT"), ImageID("I_ARROW"), config.touchFastForwardKey); if (fastForward) { fastForward->SetAngle(180.0f); fastForward->OnChange.Add([](UI::EventParams &e) { @@ -943,28 +949,28 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau }); } - addPSPButton(CTRL_LTRIGGER, "Left shoulder button", shoulderImage, ImageID("I_SHOULDER"), ImageID("I_L"), g_Config.touchLKey); - PSPButton *rTrigger = addPSPButton(CTRL_RTRIGGER, "Right shoulder button", shoulderImage, ImageID("I_SHOULDER"), ImageID("I_R"), g_Config.touchRKey); + addPSPButton(CTRL_LTRIGGER, "Left shoulder button", shoulderImage, ImageID("I_SHOULDER"), ImageID("I_L"), config.touchLKey); + PSPButton *rTrigger = addPSPButton(CTRL_RTRIGGER, "Right shoulder button", shoulderImage, ImageID("I_SHOULDER"), ImageID("I_R"), config.touchRKey); if (rTrigger) rTrigger->FlipImageH(true); - if (g_Config.touchDpad.show) { + if (config.touchDpad.show) { const ImageID dirImage = g_Config.iTouchButtonStyle ? ImageID("I_DIR_LINE") : ImageID("I_DIR"); - root->Add(new PSPDpad(dirImage, "D-pad", ImageID("I_DIR"), ImageID("I_ARROW"), g_Config.touchDpad.scale, g_Config.fDpadSpacing, buttonLayoutParams(g_Config.touchDpad))); + root->Add(new PSPDpad(dirImage, "D-pad", ImageID("I_DIR"), ImageID("I_ARROW"), config.touchDpad.scale, config.fDpadSpacing, buttonLayoutParams(config.touchDpad))); } - if (g_Config.touchAnalogStick.show) - root->Add(new PSPStick(stickBg, "Left analog stick", stickImage, ImageID("I_STICK"), 0, g_Config.touchAnalogStick.scale, buttonLayoutParams(g_Config.touchAnalogStick))); + if (config.touchAnalogStick.show) + root->Add(new PSPStick(stickBg, "Left analog stick", stickImage, ImageID("I_STICK"), 0, config.touchAnalogStick.scale, buttonLayoutParams(config.touchAnalogStick))); - if (g_Config.touchRightAnalogStick.show) { + if (config.touchRightAnalogStick.show) { if (g_Config.bRightAnalogCustom) - root->Add(new PSPCustomStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick))); + root->Add(new PSPCustomStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, config.touchRightAnalogStick.scale, buttonLayoutParams(config.touchRightAnalogStick))); else - root->Add(new PSPStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, g_Config.touchRightAnalogStick.scale, buttonLayoutParams(g_Config.touchRightAnalogStick))); + root->Add(new PSPStick(stickBg, "Right analog stick", stickImage, ImageID("I_STICK"), 1, config.touchRightAnalogStick.scale, buttonLayoutParams(config.touchRightAnalogStick))); } // Sanitize custom button images, while adding them. - for (int i = 0; i < Config::CUSTOM_BUTTON_COUNT; i++) { + for (int i = 0; i < TouchControlConfig::CUSTOM_BUTTON_COUNT; i++) { if (g_Config.CustomButton[i].shape >= ARRAY_SIZE(CustomKeyData::customKeyShapes)) { g_Config.CustomButton[i].shape = 0; } @@ -974,11 +980,12 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau char temp[64]; snprintf(temp, sizeof(temp), "Custom %d button", i + 1); - addCustomButton(g_Config.CustomButton[i], temp, g_Config.touchCustom[i]); + addCustomButton(g_Config.CustomButton[i], temp, config.touchCustom[i]); } - if (g_Config.bGestureControlEnabled) - root->Add(new GestureGamepad(controllMapper)); + if (g_Config.bGestureControlEnabled) { + root->Add(new GestureGamepad(controlMapper)); + } return root; } diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index eae73e47f4..3ca7724751 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -155,10 +155,11 @@ private: float posY_ = 0.0f; }; -//initializes the layout from Config. if a default layout does not exist, -//it sets up default values -void InitPadLayout(float xres, float yres, float globalScale = 1.15f); -UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPauseButton, ControlMapper* controllMapper); +struct TouchControlConfig; + +// Initializes the layout from Config. if a default layout does not exist, it sets up default values +void InitPadLayout(TouchControlConfig *config, float xres, float yres, float globalScale = 1.15f); +UI::ViewGroup *CreatePadLayout(const TouchControlConfig &config, float xres, float yres, bool *pause, bool showPauseButton, ControlMapper *controlMapper); const int D_pad_Radius = 50; const int baseActionButtonSpacing = 60; @@ -185,7 +186,7 @@ private: class GestureGamepad : public UI::View { public: - GestureGamepad(ControlMapper* controllMapper) : controlMapper_(controllMapper) {}; + explicit GestureGamepad(ControlMapper* controllMapper) : controlMapper_(controllMapper) {} bool Touch(const TouchInput &input) override; void Update() override; @@ -197,8 +198,8 @@ protected: float lastY_ = 0.0f; float deltaX_ = 0.0f; float deltaY_ = 0.0f; - float downX_; - float downY_; + float downX_ = 0.0f; + float downY_ = 0.0f; float lastTapRelease_ = 0.0f; float lastTouchDown_ = 0.0f; int dragPointerId_ = -1; diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index f18067024f..9c2e9e3095 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -349,7 +349,7 @@ class DragDropButton; class ControlLayoutView : public UI::AnchorLayout { public: ControlLayoutView(DeviceOrientation orientation, UI::LayoutParams *layoutParams) - : UI::AnchorLayout(layoutParams), orientation_(orientation) { + : UI::AnchorLayout(layoutParams), deviceOrientation_(orientation) { SetClip(true); } @@ -360,11 +360,14 @@ public: return !controls_.empty(); } - DragDropButton *pickedControl_ = nullptr; - DragDropButton *getPickedControl(const int x, const int y); - std::vector controls_; + int mode_ = 0; private: + DragDropButton *getPickedControl(const int x, const int y); + DragDropButton *pickedControl_ = nullptr; + + std::vector controls_; + // Touch down state for dragging float startObjectX_ = -1.0f; float startObjectY_ = -1.0f; @@ -373,8 +376,7 @@ private: float startScale_ = -1.0f; float startSpacing_ = -1.0f; - int mode_ = 0; - DeviceOrientation orientation_; + DeviceOrientation deviceOrientation_; }; static Point2D ClampTo(const Point2D &p, const Bounds &b) { @@ -471,10 +473,8 @@ void ControlLayoutView::CreateViews() { return; } - // Create all the views. - - TouchControlConfig &touch = g_Config.GetTouchControlsConfig(orientation_); - + // Create all the subviews. + TouchControlConfig &touch = g_Config.GetTouchControlsConfig(deviceOrientation_); if (touch.bShowTouchCircle || touch.bShowTouchCross || touch.bShowTouchTriangle || touch.bShowTouchSquare) { PSPActionButtons *actionButtons = new PSPActionButtons(touch.touchActionButtonCenter, "Action buttons", touch.fActionButtonSpacing, bounds); @@ -536,16 +536,16 @@ void ControlLayoutView::CreateViews() { for (int i = 0; i < TouchControlConfig::CUSTOM_BUTTON_COUNT; i++) { // Similar to GamepadEmu, we sanitize the images for valid values. - if (touch.CustomButton[i].shape >= ARRAY_SIZE(CustomKeyData::customKeyShapes)) { - touch.CustomButton[i].shape = 0; + if (g_Config.CustomButton[i].shape >= ARRAY_SIZE(CustomKeyData::customKeyShapes)) { + g_Config.CustomButton[i].shape = 0; } - if (touch.CustomButton[i].image >= ARRAY_SIZE(CustomKeyData::customKeyImages)) { - touch.CustomButton[i].image = 0; + if (g_Config.CustomButton[i].image >= ARRAY_SIZE(CustomKeyData::customKeyImages)) { + g_Config.CustomButton[i].image = 0; } char temp[64]; snprintf(temp, sizeof(temp), "Custom %d button", i); - addDragCustomKey(touch.touchCustom[i], temp, touch.CustomButton[i]); + addDragCustomKey(touch.touchCustom[i], temp, g_Config.CustomButton[i]); } for (size_t i = 0; i < controls_.size(); i++) { @@ -595,7 +595,7 @@ void TouchControlLayoutScreen::OnReset(UI::EventParams &e) { INFO_LOG(Log::G3D, "Resetting touch control layout"); g_Config.ResetControlLayout(); const Bounds &bounds = screenManager()->getUIContext()->GetBounds(); - InitPadLayout(bounds.w, bounds.h); + InitPadLayout(&g_Config.GetTouchControlsConfig(GetDeviceOrientation()), bounds.w, bounds.h); RecreateViews(); }; @@ -637,7 +637,7 @@ void TouchControlLayoutScreen::CreateViews() { // setup g_Config for button layout const Bounds &bounds = screenManager()->getUIContext()->GetBounds(); - InitPadLayout(bounds.w, bounds.h); + InitPadLayout(&g_Config.GetTouchControlsConfig(GetDeviceOrientation()), bounds.w, bounds.h); bool portrait = GetDeviceOrientation() == DeviceOrientation::Portrait; diff --git a/UI/TouchControlVisibilityScreen.cpp b/UI/TouchControlVisibilityScreen.cpp index 95aa90895d..1f0720bbcb 100644 --- a/UI/TouchControlVisibilityScreen.cpp +++ b/UI/TouchControlVisibilityScreen.cpp @@ -83,27 +83,29 @@ void TouchControlVisibilityScreen::CreateVisibilityTab(UI::LinearLayout *vert) { gridsettings.fillCells = true; GridLayout *grid = vert->Add(new GridLayoutList(gridsettings, new LayoutParams(FILL_PARENT, WRAP_CONTENT))); + TouchControlConfig &touch = g_Config.GetTouchControlsConfig(GetDeviceOrientation()); + toggles_.clear(); - toggles_.push_back({ "Circle", &g_Config.bShowTouchCircle, ImageID("I_CIRCLE"), nullptr }); - toggles_.push_back({ "Cross", &g_Config.bShowTouchCross, ImageID("I_CROSS"), nullptr }); - toggles_.push_back({ "Square", &g_Config.bShowTouchSquare, ImageID("I_SQUARE"), nullptr }); - toggles_.push_back({ "Triangle", &g_Config.bShowTouchTriangle, ImageID("I_TRIANGLE"), nullptr }); - toggles_.push_back({ "L", &g_Config.touchLKey.show, ImageID("I_L"), nullptr }); - toggles_.push_back({ "R", &g_Config.touchRKey.show, ImageID("I_R"), nullptr }); - toggles_.push_back({ "Start", &g_Config.touchStartKey.show, ImageID("I_START"), nullptr }); - toggles_.push_back({ "Select", &g_Config.touchSelectKey.show, ImageID("I_SELECT"), nullptr }); - toggles_.push_back({ "Dpad", &g_Config.touchDpad.show, ImageID::invalid(), nullptr }); - toggles_.push_back({ "Analog Stick", &g_Config.touchAnalogStick.show, ImageID::invalid(), nullptr }); - toggles_.push_back({ "Right Analog Stick", &g_Config.touchRightAnalogStick.show, ImageID::invalid(), [=](EventParams &e) { + toggles_.push_back({ "Circle", &touch.bShowTouchCircle, ImageID("I_CIRCLE"), nullptr }); + toggles_.push_back({ "Cross", &touch.bShowTouchCross, ImageID("I_CROSS"), nullptr }); + toggles_.push_back({ "Square", &touch.bShowTouchSquare, ImageID("I_SQUARE"), nullptr }); + toggles_.push_back({ "Triangle", &touch.bShowTouchTriangle, ImageID("I_TRIANGLE"), nullptr }); + toggles_.push_back({ "L", &touch.touchLKey.show, ImageID("I_L"), nullptr }); + toggles_.push_back({ "R", &touch.touchRKey.show, ImageID("I_R"), nullptr }); + toggles_.push_back({ "Start", &touch.touchStartKey.show, ImageID("I_START"), nullptr }); + toggles_.push_back({ "Select", &touch.touchSelectKey.show, ImageID("I_SELECT"), nullptr }); + toggles_.push_back({ "Dpad", &touch.touchDpad.show, ImageID::invalid(), nullptr }); + toggles_.push_back({ "Analog Stick", &touch.touchAnalogStick.show, ImageID::invalid(), nullptr }); + toggles_.push_back({ "Right Analog Stick", &touch.touchRightAnalogStick.show, ImageID::invalid(), [=](EventParams &e) { screenManager()->push(new RightAnalogMappingScreen(gamePath_)); }}); - toggles_.push_back({ "Fast-forward", &g_Config.touchFastForwardKey.show, ImageID::invalid(), nullptr }); + toggles_.push_back({ "Fast-forward", &touch.touchFastForwardKey.show, ImageID::invalid(), nullptr }); - for (int i = 0; i < Config::CUSTOM_BUTTON_COUNT; i++) { + for (int i = 0; i < TouchControlConfig::CUSTOM_BUTTON_COUNT; i++) { char temp[256]; snprintf(temp, sizeof(temp), "Custom %d", i + 1); - toggles_.push_back({ temp, &g_Config.touchCustom[i].show, ImageID::invalid(), [=](EventParams &e) { - screenManager()->push(new CustomButtonMappingScreen(gamePath_, i)); + toggles_.push_back({ temp, &touch.touchCustom[i].show, ImageID::invalid(), [=](EventParams &e) { + screenManager()->push(new CustomButtonMappingScreen(GetDeviceOrientation(), gamePath_, i)); } }); } @@ -148,6 +150,8 @@ void RightAnalogMappingScreen::CreateViews() { auto co = GetI18NCategory(I18NCat::CONTROLS); auto mc = GetI18NCategory(I18NCat::MAPPABLECONTROLS); + TouchControlConfig &touch = g_Config.GetTouchControlsConfig(GetDeviceOrientation()); + root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); Choice *back = new Choice(di->T("Back"), ImageID("I_NAVIGATE_BACK"), new AnchorLayoutParams(leftColumnWidth - 10, WRAP_CONTENT, 10, NONE, NONE, 10)); root_->Add(back)->OnClick.Handle(this, &UIScreen::OnBack); @@ -161,7 +165,7 @@ void RightAnalogMappingScreen::CreateViews() { static const char *rightAnalogButton[] = {"None", "L", "R", "Square", "Triangle", "Circle", "Cross", "D-pad up", "D-pad down", "D-pad left", "D-pad right", "Start", "Select", "RightAn.Up", "RightAn.Down", "RightAn.Left", "RightAn.Right", "An.Up", "An.Down", "An.Left", "An.Right"}; vert->Add(new ItemHeader(co->T("Analog Style"))); - vert->Add(new CheckBox(&g_Config.touchRightAnalogStick.show, co->T("Visible"))); + vert->Add(new CheckBox(&touch.touchRightAnalogStick.show, co->T("Visible"))); vert->Add(new CheckBox(&g_Config.bRightAnalogCustom, co->T("Use custom right analog"))); vert->Add(new CheckBox(&g_Config.bRightAnalogDisableDiagonal, co->T("Disable diagonal input")))->SetEnabledPtr(&g_Config.bRightAnalogCustom);