diff --git a/Common/UI/PopupScreens.cpp b/Common/UI/PopupScreens.cpp index a8715591d1..cb737cc348 100644 --- a/Common/UI/PopupScreens.cpp +++ b/Common/UI/PopupScreens.cpp @@ -10,6 +10,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/System/System.h" #include "Common/System/Request.h" +#include "Core/ConfigSettings.h" namespace UI { @@ -199,6 +200,14 @@ void PopupSliderChoiceFloat::SetFormat(std::string_view fmt) { } } +bool PopupSliderChoiceFloat::perGame() const { + return ConfigSetting::perGame(value_); +} + +bool PopupSliderChoice::perGame() const { + return ConfigSetting::perGame(value_); +} + EventReturn PopupSliderChoice::HandleClick(EventParams &e) { restoreFocus_ = HasFocus(); @@ -644,7 +653,13 @@ void AbstractChoiceWithValueDisplay::Draw(UIContext &dc) { dc.MeasureTextRect(dc.theme->uiFont, scale, scale, valueText, availBounds, &w, &h, ALIGN_RIGHT | ALIGN_VCENTER | FLAG_WRAP_TEXT); textPadding_.right = w + paddingX; + if (perGame()) { + textPadding_.left = 30; + } Choice::Draw(dc); + if (perGame()) { + dc.Draw()->DrawImage(ImageID("I_GEAR"), bounds_.x + 22, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); + } int imagePadding = 0; if (rightIconImage_.isValid()) { imagePadding = bounds_.h; diff --git a/Common/UI/PopupScreens.h b/Common/UI/PopupScreens.h index 1eab264abf..9251beb9c8 100644 --- a/Common/UI/PopupScreens.h +++ b/Common/UI/PopupScreens.h @@ -297,6 +297,7 @@ public: protected: std::string ValueText() const override; + bool perGame() const override; private: EventReturn HandleClick(EventParams &e); @@ -335,6 +336,7 @@ public: protected: std::string ValueText() const override; + bool perGame() const override; private: EventReturn HandleClick(EventParams &e); diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index 0ee17eaa82..b18a5707b4 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -18,6 +18,7 @@ #include "Common/TimeUtil.h" #include "Common/StringUtils.h" #include "Common/Log.h" +#include "Core/ConfigSettings.h" namespace UI { @@ -798,6 +799,10 @@ void CheckBox::Draw(UIContext &dc) { if (!text_.empty()) { Bounds textBounds(bounds_.x + paddingX, bounds_.y, availWidth, bounds_.h); + if (ConfigSetting::perGame(toggle_)) { + dc.Draw()->DrawImage(ImageID("I_GEAR"), bounds_.x + 22, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_CENTER); + textBounds.x += 30; + } dc.DrawTextRectSqueeze(text_, textBounds, style.fgColor, ALIGN_VCENTER | FLAG_WRAP_TEXT); } dc.Draw()->DrawImage(image, bounds_.x2() - paddingX, bounds_.centerY(), 1.0f, style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER); diff --git a/Common/UI/View.h b/Common/UI/View.h index c39cd4538a..f17552c154 100644 --- a/Common/UI/View.h +++ b/Common/UI/View.h @@ -829,6 +829,7 @@ public: } protected: virtual std::string ValueText() const = 0; + virtual bool perGame() const { return false; } float CalculateValueScale(const UIContext &dc, std::string_view valueText, float availWidth) const; diff --git a/Core/ConfigSettings.cpp b/Core/ConfigSettings.cpp index 49bc12f486..7739a1cb88 100644 --- a/Core/ConfigSettings.cpp +++ b/Core/ConfigSettings.cpp @@ -4,6 +4,16 @@ #include "Core/ConfigSettings.h" #include "Core/ConfigValues.h" +#include "Core/Config.h" + +std::unordered_map& ConfigSetting::getPtrLUT() { + static std::unordered_map lut; + return lut; +} + +bool ConfigSetting::perGame(void* ptr) { + return g_Config.bGameSpecific && ConfigSetting::getPtrLUT().count(ptr) > 0 && ConfigSetting::getPtrLUT()[ptr]->PerGame(); +} bool ConfigSetting::Get(const Section *section) const { switch (type_) { diff --git a/Core/ConfigSettings.h b/Core/ConfigSettings.h index 6d6ce2864c..7cf71d475e 100644 --- a/Core/ConfigSettings.h +++ b/Core/ConfigSettings.h @@ -1,7 +1,7 @@ #pragma once #include - +#include #include "Core/ConfigValues.h" class Path; @@ -79,6 +79,7 @@ struct ConfigSetting { ptr_.b = v; cb_.b = nullptr; default_.b = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, int *v, int def, CfgFlag flags = CfgFlag::DEFAULT) @@ -86,6 +87,7 @@ struct ConfigSetting { ptr_.i = v; cb_.i = nullptr; default_.i = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, int *v, int def, std::string(*transTo)(int), int (*transFrom)(const std::string &), CfgFlag flags = CfgFlag::DEFAULT) @@ -93,6 +95,7 @@ struct ConfigSetting { ptr_.i = v; cb_.i = nullptr; default_.i = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, uint32_t *v, uint32_t def, CfgFlag flags = CfgFlag::DEFAULT) @@ -100,6 +103,7 @@ struct ConfigSetting { ptr_.u = v; cb_.u = nullptr; default_.u = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, uint64_t *v, uint64_t def, CfgFlag flags = CfgFlag::DEFAULT) @@ -107,6 +111,7 @@ struct ConfigSetting { ptr_.lu = v; cb_.lu = nullptr; default_.lu = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, float *v, float def, CfgFlag flags = CfgFlag::DEFAULT) @@ -114,6 +119,7 @@ struct ConfigSetting { ptr_.f = v; cb_.f = nullptr; default_.f = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, std::string *v, const char *def, CfgFlag flags = CfgFlag::DEFAULT) @@ -121,13 +127,15 @@ struct ConfigSetting { ptr_.s = v; cb_.s = nullptr; default_.s = def; + getPtrLUT()[v] = this; } - ConfigSetting(const char *ini, Path *p, const char *def, CfgFlag flags = CfgFlag::DEFAULT) + ConfigSetting(const char *ini, Path *v, const char *def, CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(ini), type_(TYPE_PATH), flags_(flags) { - ptr_.p = p; + ptr_.p = v; cb_.p = nullptr; default_.p = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *iniX, const char *iniY, const char *iniScale, const char *iniShow, ConfigTouchPos *v, ConfigTouchPos def, CfgFlag flags = CfgFlag::DEFAULT) @@ -135,6 +143,7 @@ struct ConfigSetting { ptr_.touchPos = v; cb_.touchPos = nullptr; default_.touchPos = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *iniKey, const char *iniImage, const char *iniShape, const char *iniToggle, const char *iniRepeat, ConfigCustomButton *v, ConfigCustomButton def, CfgFlag flags = CfgFlag::DEFAULT) @@ -142,48 +151,56 @@ struct ConfigSetting { ptr_.customButton = v; cb_.customButton = nullptr; default_.customButton = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, bool *v, BoolDefaultCallback def, CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(ini), type_(TYPE_BOOL), flags_(flags) { ptr_.b = v; cb_.b = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, int *v, IntDefaultCallback def, CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(ini), type_(TYPE_INT), flags_(flags) { ptr_.i = v; cb_.i = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, int *v, IntDefaultCallback def, std::string(*transTo)(int), int(*transFrom)(const std::string &), CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(ini), type_(TYPE_INT), flags_(flags), translateTo_(transTo), translateFrom_(transFrom) { ptr_.i = v; cb_.i = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, uint32_t *v, Uint32DefaultCallback def, CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(ini), type_(TYPE_UINT32), flags_(flags) { ptr_.u = v; cb_.u = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, float *v, FloatDefaultCallback def, CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(ini), type_(TYPE_FLOAT), flags_(flags) { ptr_.f = v; cb_.f = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *ini, std::string *v, StringDefaultCallback def, CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(ini), type_(TYPE_STRING), flags_(flags) { ptr_.s = v; cb_.s = def; + getPtrLUT()[v] = this; } ConfigSetting(const char *iniX, const char *iniY, const char *iniScale, const char *iniShow, ConfigTouchPos *v, TouchPosDefaultCallback def, CfgFlag flags = CfgFlag::DEFAULT) : iniKey_(iniX), ini2_(iniY), ini3_(iniScale), ini4_(iniShow), type_(TYPE_TOUCH_POS), flags_(flags) { ptr_.touchPos = v; cb_.touchPos = def; + getPtrLUT()[v] = this; } // Should actually be called ReadFromIni or something. @@ -210,6 +227,8 @@ struct ConfigSetting { const Type type_; + static bool perGame(void* ptr); + private: CfgFlag flags_; SettingPtr ptr_; @@ -219,6 +238,8 @@ private: // We only support transform for ints. std::string (*translateTo_)(int) = nullptr; int (*translateFrom_)(const std::string &) = nullptr; + + static std::unordered_map& getPtrLUT(); }; struct ConfigSectionSettings {