diff --git a/UnleashedRecomp/cfg/config.h b/UnleashedRecomp/cfg/config.h index cff597d6..9d0704b0 100644 --- a/UnleashedRecomp/cfg/config.h +++ b/UnleashedRecomp/cfg/config.h @@ -37,6 +37,7 @@ public: CONFIG_DEFINE_CALLBACK("Video", float, ResolutionScale, 1.0f, { def->NameLocale = &g_ResolutionScale_locale; + def->DescLocale = &g_ResolutionScale_desc_locale; def->Value = std::clamp(def->Value, 0.25f, 2.0f); }); diff --git a/UnleashedRecomp/cfg/config_detail.cpp b/UnleashedRecomp/cfg/config_detail.cpp index 0e74cba0..b8edf28a 100644 --- a/UnleashedRecomp/cfg/config_detail.cpp +++ b/UnleashedRecomp/cfg/config_detail.cpp @@ -10,8 +10,8 @@ ConfigDef::ConfigDef(std::string section, std::string name, T defaultValue) : // CONFIG_DEFINE_LOCALISED template -ConfigDef::ConfigDef(std::string section, std::string name, std::unordered_map* nameLocale, T defaultValue) - : Section(section), Name(name), NameLocale(nameLocale), DefaultValue(defaultValue) +ConfigDef::ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, CONFIG_LOCALE* descLocale, T defaultValue) + : Section(section), Name(name), NameLocale(nameLocale), DescLocale(descLocale), DefaultValue(defaultValue) { Config::Definitions.emplace_back(this); } @@ -29,8 +29,8 @@ ConfigDef::ConfigDef(std::string section, std::string name, T defaultValue, s // CONFIG_DEFINE_ENUM_LOCALISED template -ConfigDef::ConfigDef(std::string section, std::string name, std::unordered_map* nameLocale, T defaultValue, std::unordered_map* enumTemplate, std::unordered_map>* enumLocale) - : Section(section), Name(name), NameLocale(nameLocale), DefaultValue(defaultValue), EnumTemplate(enumTemplate), EnumLocale(enumLocale) +ConfigDef::ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, CONFIG_LOCALE* descLocale, T defaultValue, std::unordered_map* enumTemplate, CONFIG_ENUM_LOCALE(T)* enumLocale) + : Section(section), Name(name), NameLocale(nameLocale), DescLocale(descLocale), DefaultValue(defaultValue), EnumTemplate(enumTemplate), EnumLocale(enumLocale) { for (const auto& pair : *EnumTemplate) EnumTemplateReverse[pair.second] = pair.first; @@ -46,6 +46,27 @@ ConfigDef::ConfigDef(std::string section, std::string name, T defaultValue, s Config::Definitions.emplace_back(this); } +template +std::string ConfigDef::GetDescription() const +{ + if (!DescLocale) + return ""; + + if (!DescLocale->count(Config::Language)) + { + if (DescLocale->count(ELanguage::English)) + { + return DescLocale->at(ELanguage::English); + } + else + { + return ""; + } + } + + return DescLocale->at(Config::Language); +} + template std::string ConfigDef::GetNameLocalised() const { @@ -71,7 +92,7 @@ template std::string ConfigDef::GetValueLocalised() const { auto language = Config::Language; - std::unordered_map>* locale = nullptr; + CONFIG_ENUM_LOCALE(T)* locale = nullptr; if constexpr (std::is_enum_v) { diff --git a/UnleashedRecomp/cfg/config_detail.h b/UnleashedRecomp/cfg/config_detail.h index 7cf75299..f3c36d07 100644 --- a/UnleashedRecomp/cfg/config_detail.h +++ b/UnleashedRecomp/cfg/config_detail.h @@ -8,13 +8,13 @@ inline static ConfigDef name{section, #name, defaultValue}; #define CONFIG_DEFINE_LOCALISED(section, type, name, defaultValue) \ - inline static ConfigDef name{section, #name, &g_##name##_locale, defaultValue}; + inline static ConfigDef name{section, #name, &g_##name##_locale, &g_##name##_desc_locale, defaultValue}; #define CONFIG_DEFINE_ENUM(section, type, name, defaultValue) \ inline static ConfigDef name{section, #name, defaultValue, &g_##type##_template}; #define CONFIG_DEFINE_ENUM_LOCALISED(section, type, name, defaultValue) \ - inline static ConfigDef name{section, #name, &g_##name##_locale, defaultValue, &g_##type##_template, &g_##type##_locale}; + inline static ConfigDef name{section, #name, &g_##name##_locale, &g_##name##_desc_locale, defaultValue, &g_##type##_template, &g_##type##_locale}; #define CONFIG_DEFINE_CALLBACK(section, type, name, defaultValue, readCallback) \ inline static ConfigDef name{section, #name, defaultValue, [](ConfigDef* def) readCallback}; @@ -22,8 +22,8 @@ #define CONFIG_DEFINE_ENUM_TEMPLATE(type) \ inline static std::unordered_map g_##type##_template = -#define CONFIG_GET_DEFAULT(name) Config::name.DefaultValue -#define CONFIG_SET_DEFAULT(name) Config::name.MakeDefault(); +#define CONFIG_LOCALE std::unordered_map +#define CONFIG_ENUM_LOCALE(type) std::unordered_map> #define WINDOWPOS_CENTRED 0x2FFF0000 @@ -169,8 +169,9 @@ public: virtual void MakeDefault() = 0; virtual std::string_view GetSection() const = 0; virtual std::string_view GetName() const = 0; + virtual std::string GetDescription() const = 0; virtual std::string GetNameLocalised() const = 0; - virtual void* GetValue() = 0; + virtual const void* GetValue() const = 0; virtual std::string GetValueLocalised() const = 0; virtual std::string GetDefinition(bool withSection = false) const = 0; virtual std::string ToString(bool strWithQuotes = true) const = 0; @@ -182,25 +183,26 @@ class ConfigDef : public IConfigDef public: std::string Section{}; std::string Name{}; - std::unordered_map* NameLocale; + CONFIG_LOCALE* NameLocale; + CONFIG_LOCALE* DescLocale; T DefaultValue{}; T Value{ DefaultValue }; std::unordered_map* EnumTemplate; std::map EnumTemplateReverse{}; - std::unordered_map>* EnumLocale; + CONFIG_ENUM_LOCALE(T)* EnumLocale; std::function*)> ReadCallback; // CONFIG_DEFINE ConfigDef(std::string section, std::string name, T defaultValue); // CONFIG_DEFINE_LOCALISED - ConfigDef(std::string section, std::string name, std::unordered_map* nameLocale, T defaultValue); + ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, CONFIG_LOCALE* descLocale, T defaultValue); // CONFIG_DEFINE_ENUM ConfigDef(std::string section, std::string name, T defaultValue, std::unordered_map* enumTemplate); // CONFIG_DEFINE_ENUM_LOCALISED - ConfigDef(std::string section, std::string name, std::unordered_map* nameLocale, T defaultValue, std::unordered_map* enumTemplate, std::unordered_map>* enumLocale); + ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, CONFIG_LOCALE* descLocale, T defaultValue, std::unordered_map* enumTemplate, CONFIG_ENUM_LOCALE(T)* enumLocale); // CONFIG_DEFINE_CALLBACK ConfigDef(std::string section, std::string name, T defaultValue, std::function*)> readCallback); @@ -246,9 +248,11 @@ public: return Name; } + std::string GetDescription() const override; + std::string GetNameLocalised() const override; - void* GetValue() override + const void* GetValue() const override { return &Value; } diff --git a/UnleashedRecomp/cfg/config_locale.h b/UnleashedRecomp/cfg/config_locale.h index 0db8a278..1287b666 100644 --- a/UnleashedRecomp/cfg/config_locale.h +++ b/UnleashedRecomp/cfg/config_locale.h @@ -5,9 +5,15 @@ #define CONFIG_DEFINE_LOCALE(name) \ inline static std::unordered_map g_##name##_locale = +#define CONFIG_DEFINE_DESCRIPTION_LOCALE(name) \ + inline static std::unordered_map g_##name##_desc_locale = + #define CONFIG_DEFINE_ENUM_LOCALE(type) \ inline static std::unordered_map> g_##type##_locale = +#define CONFIG_DEFINE_ENUM_DESCRIPTION_LOCALE(type) \ + inline static std::unordered_map> g_##type##_desc_locale = + CONFIG_DEFINE_ENUM_LOCALE(bool) { { @@ -33,11 +39,16 @@ CONFIG_DEFINE_ENUM_LOCALE(bool) CONFIG_DEFINE_LOCALE(Language) { { ELanguage::English, "Language" }, - { ELanguage::Japanese, "言語" }, - { ELanguage::German, "Sprache" }, - { ELanguage::French, "Langue" }, - { ELanguage::Spanish, "Idioma" }, - { ELanguage::Italian, "Lingua" } + { ELanguage::Japanese, "言語" }, + { ELanguage::German, "Sprache" }, + { ELanguage::French, "Langue" }, + { ELanguage::Spanish, "Idioma" }, + { ELanguage::Italian, "Lingua" } +}; + +CONFIG_DEFINE_DESCRIPTION_LOCALE(Language) +{ + { ELanguage::English, "The language used for text and logos." } }; CONFIG_DEFINE_ENUM_LOCALE(ELanguage) @@ -60,24 +71,49 @@ CONFIG_DEFINE_LOCALE(Hints) { ELanguage::English, "Hints" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(Hints) +{ + { ELanguage::English, "Determines whether to show hint rings in stages." } +}; + CONFIG_DEFINE_LOCALE(ControlTutorial) { { ELanguage::English, "Control Tutorial" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(ControlTutorial) +{ + { ELanguage::English, "Determines whether to show controller hints in stages." } +}; + CONFIG_DEFINE_LOCALE(SaveScoreAtCheckpoints) { { ELanguage::English, "Save Score at Checkpoints" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(SaveScoreAtCheckpoints) +{ + { ELanguage::English, "Determines whether to save your score when reaching checkpoints.\n\nUpon respawning, your last checkpoint score will be restored." } +}; + CONFIG_DEFINE_LOCALE(UnleashOutOfControlDrain) { - { ELanguage::English, "Decrease Unleash Gauge whilst Out Of Control" } + { ELanguage::English, "Deplete Unleash Gauge whilst Out Of Control" } +}; + +CONFIG_DEFINE_DESCRIPTION_LOCALE(UnleashOutOfControlDrain) +{ + { ELanguage::English, "Determines whether to continue depleting the Unleash gauge whilst the player is locked in place during transitions." } }; CONFIG_DEFINE_LOCALE(WerehogHubTransformVideo) { - { ELanguage::English, "Werehog Transformation Video" } + { ELanguage::English, "Werehog Transformation Cutscene" } +}; + +CONFIG_DEFINE_DESCRIPTION_LOCALE(WerehogHubTransformVideo) +{ + { ELanguage::English, "Determines whether to play the Werehog transformation cutscene when changing time of day in the hub areas." } }; CONFIG_DEFINE_LOCALE(LogoSkip) @@ -85,41 +121,81 @@ CONFIG_DEFINE_LOCALE(LogoSkip) { ELanguage::English, "Skip Intro Logos" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(LogoSkip) +{ + { ELanguage::English, "Determines whether to skip the logos during the game's boot sequence." } +}; + CONFIG_DEFINE_LOCALE(CameraXInvert) { { ELanguage::English, "Invert Camera X" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(CameraXInvert) +{ + { ELanguage::English, "Determines whether to invert the camera's left and right movement." } +}; + CONFIG_DEFINE_LOCALE(CameraYInvert) { { ELanguage::English, "Invert Camera Y" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(CameraYInvert) +{ + { ELanguage::English, "Determines whether to invert the camera's up and down movement." } +}; + CONFIG_DEFINE_LOCALE(XButtonHoming) { { ELanguage::English, "Homing Attack on Boost" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(XButtonHoming) +{ + { ELanguage::English, "Determines whether to bind the homing attack to the boost button." } +}; + CONFIG_DEFINE_LOCALE(UnleashCancel) { { ELanguage::English, "Allow Cancelling Unleash" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(UnleashCancel) +{ + { ELanguage::English, "Determines whether to allow cancelling Unleash by pressing the input again." } +}; + CONFIG_DEFINE_LOCALE(MusicVolume) { { ELanguage::English, "Music Volume" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(MusicVolume) +{ + { ELanguage::English, "The volume used for the music." } +}; + CONFIG_DEFINE_LOCALE(SEVolume) { { ELanguage::English, "SE Volume" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(SEVolume) +{ + { ELanguage::English, "The volume used for sound effects." } +}; + CONFIG_DEFINE_LOCALE(VoiceLanguage) { { ELanguage::English, "Voice Language" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(VoiceLanguage) +{ + { ELanguage::English, "The language used for character voices." } +}; + CONFIG_DEFINE_ENUM_LOCALE(EVoiceLanguage) { { @@ -136,46 +212,91 @@ CONFIG_DEFINE_LOCALE(Subtitles) { ELanguage::English, "Subtitles" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(Subtitles) +{ + { ELanguage::English, "Determines whether to display subtitles during events." } +}; + CONFIG_DEFINE_LOCALE(WerehogBattleMusic) { { ELanguage::English, "Werehog Battle Theme" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(WerehogBattleMusic) +{ + { ELanguage::English, "Determines whether to play the battle theme whilst in combat as the Werehog." } +}; + CONFIG_DEFINE_LOCALE(WindowSize) { { ELanguage::English, "Window Size" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(WindowSize) +{ + { ELanguage::English, "The size of the game window in windowed mode." } +}; + CONFIG_DEFINE_LOCALE(ResolutionScale) { { ELanguage::English, "Resolution Scale" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(ResolutionScale) +{ + { ELanguage::English, "The internal resolution the game will render at.\n\n%dx%d" } +}; + CONFIG_DEFINE_LOCALE(Fullscreen) { { ELanguage::English, "Fullscreen" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(Fullscreen) +{ + { ELanguage::English, "Determines whether to use borderless fullscreen.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_LOCALE(VSync) { { ELanguage::English, "V-Sync" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(VSync) +{ + { ELanguage::English, "Determines whether to use V-Sync.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_LOCALE(TripleBuffering) { { ELanguage::English, "Triple Buffering" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(TripleBuffering) +{ + { ELanguage::English, "Determines whether to use triple buffering.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_LOCALE(Brightness) { { ELanguage::English, "Brightness" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(Brightness) +{ + { ELanguage::English, "The brightness level of the game.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_LOCALE(AntiAliasing) { { ELanguage::English, "Anti-Aliasing" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(AntiAliasing) +{ + { ELanguage::English, "The amount of smoothing applied to jagged edges.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_ENUM_LOCALE(EAntiAliasing) { { @@ -191,11 +312,21 @@ CONFIG_DEFINE_LOCALE(AnisotropicFiltering) { ELanguage::English, "Anisotropic Filtering" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(AnisotropicFiltering) +{ + { ELanguage::English, "The amount of detail retained by distant textures.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_LOCALE(ShadowResolution) { { ELanguage::English, "Shadow Resolution" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(ShadowResolution) +{ + { ELanguage::English, "The resolution of real-time shadows.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_ENUM_LOCALE(EShadowResolution) { { @@ -211,6 +342,11 @@ CONFIG_DEFINE_LOCALE(GITextureFiltering) { ELanguage::English, "GI Texture Filtering" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(GITextureFiltering) +{ + { ELanguage::English, "The method used for filtering baked lighting.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_ENUM_LOCALE(EGITextureFiltering) { { @@ -227,21 +363,41 @@ CONFIG_DEFINE_LOCALE(AlphaToCoverage) { ELanguage::English, "Transparency Anti-Aliasing" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(AlphaToCoverage) +{ + { ELanguage::English, "Determines whether to smooth out jagged edges on alpha transparent textures." } +}; + CONFIG_DEFINE_LOCALE(MotionBlur) { { ELanguage::English, "Motion Blur" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(MotionBlur) +{ + { ELanguage::English, "Determines whether to draw per-object motion blur and radial blur." } +}; + CONFIG_DEFINE_LOCALE(Xbox360ColourCorrection) { { ELanguage::English, "Xbox 360 Colour Correction" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(Xbox360ColourCorrection) +{ + { ELanguage::English, "Determines whether to tint the overall appearance of the game with a more warm hue like the original Xbox 360 version." } +}; + CONFIG_DEFINE_LOCALE(MovieScaleMode) { { ELanguage::English, "Movie Scale Mode" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(MovieScaleMode) +{ + { ELanguage::English, "Determines how to scale the movie player.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_ENUM_LOCALE(EMovieScaleMode) { { @@ -259,6 +415,11 @@ CONFIG_DEFINE_LOCALE(UIScaleMode) { ELanguage::English, "UI Scale Mode" } }; +CONFIG_DEFINE_DESCRIPTION_LOCALE(UIScaleMode) +{ + { ELanguage::English, "Determines how to scale the UI.\n\n[PLACEHOLDER]" } +}; + CONFIG_DEFINE_ENUM_LOCALE(EUIScaleMode) { { diff --git a/UnleashedRecomp/ui/options_menu.cpp b/UnleashedRecomp/ui/options_menu.cpp index 82e7659b..49e43df8 100644 --- a/UnleashedRecomp/ui/options_menu.cpp +++ b/UnleashedRecomp/ui/options_menu.cpp @@ -3,10 +3,16 @@ #include #include +constexpr float COMMON_PADDING_POS_Y = 118.0f; +constexpr float COMMON_PADDING_POS_X = 30.0f; +constexpr float INFO_CONTAINER_POS_X = 870.0f; + static ImFont* g_seuratFont; static ImFont* g_dfsogeistdFont; static ImFont* g_newRodinFont; +static const IConfigDef* g_selectedItem; + void OptionsMenu::Init() { auto& io = ImGui::GetIO(); @@ -54,6 +60,26 @@ static void SetShaderModifier(uint32_t shaderModifier) callbackData->setShaderModifier.shaderModifier = shaderModifier; } +// TODO: add delay argument to delay when to start the marquee. Unleashed menus have ~0.9 seconds of delay before the text beings to marquee. +// TODO: reset the marquee position when a different item is selected. This might have to be handled once we use events for controller input. +static void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2& pos, const ImVec2& min, const ImVec2& max, ImU32 color, const char* text, float speed) +{ + auto drawList = ImGui::GetForegroundDrawList(); + auto rectWidth = max.x - min.x; + auto textSize = g_seuratFont->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, text); + auto textX = pos.x - fmodf(speed * ImGui::GetTime(), textSize.x + rectWidth); + + drawList->PushClipRect(min, max, true); + + if (textX < pos.x) + drawList->AddText(font, fontSize, { textX, pos.y }, color, text); + + if (textX + textSize.x < pos.x) + drawList->AddText(font, fontSize, { textX + textSize.x + rectWidth, pos.y }, color, text); + + drawList->PopClipRect(); +} + static void DrawTextWithOutline(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 color, const char* text, int32_t outlineSize, ImU32 outlineColor) { auto drawList = ImGui::GetForegroundDrawList(); @@ -293,7 +319,7 @@ static void DrawCategories() } template -static void DrawConfigOption(int32_t rowIndex, const ConfigDef& config) +static void DrawConfigOption(int32_t rowIndex, const ConfigDef* config) { auto drawList = ImGui::GetForegroundDrawList(); auto clipRectMin = drawList->GetClipRectMin(); @@ -302,26 +328,34 @@ static void DrawConfigOption(int32_t rowIndex, const ConfigDef& config) constexpr ImU32 COLOR0 = IM_COL32(0xE2, 0x71, 0x22, 0x80); constexpr ImU32 COLOR1 = IM_COL32(0x92, 0xFF, 0x31, 0x80); - float gridSize = Scale(GRID_SIZE); - float optionWidth = gridSize * 56.0f; - float optionHeight = gridSize * 5.5f; - float optionPadding = gridSize * 0.5f; - float valueWidth = gridSize * 24.0f; - float valueHeight = gridSize * 3.0f; + auto gridSize = Scale(GRID_SIZE); + auto optionWidth = gridSize * 56.0f; + auto optionHeight = gridSize * 5.5f; + auto optionPadding = gridSize * 0.5f; + auto valueWidth = gridSize * 24.0f; + auto valueHeight = gridSize * 3.0f; // Left side ImVec2 min = { clipRectMin.x, clipRectMin.y + (optionHeight + optionPadding) * rowIndex }; ImVec2 max = { min.x + optionWidth, min.y + optionHeight }; - if (ImGui::IsMouseHoveringRect(min, max, false)) - drawList->AddRectFilledMultiColor(min, max, COLOR0, COLOR0, COLOR1, COLOR1); - - auto configName = config.GetNameLocalised(); - - float size = Scale(26.0f); + auto configName = config->GetNameLocalised(); + auto size = Scale(26.0f); auto textSize = g_seuratFont->CalcTextSizeA(size, FLT_MAX, 0.0f, configName.c_str()); - drawList->AddText(g_seuratFont, size, { min.x + gridSize, min.y + (optionHeight - textSize.y) / 2.0f }, IM_COL32_WHITE, configName.c_str()); + ImVec2 textPos = { min.x + gridSize, min.y + (optionHeight - textSize.y) / 2.0f }; + ImVec4 textClipRect = { min.x, min.y, max.x, max.y }; + + if (ImGui::IsMouseHoveringRect(min, max, false)) + { + g_selectedItem = config; + drawList->AddRectFilledMultiColor(min, max, COLOR0, COLOR0, COLOR1, COLOR1); + DrawTextWithMarquee(g_seuratFont, size, textPos, min, max, IM_COL32_WHITE, configName.c_str(), 250.0f); + } + else + { + drawList->AddText(g_seuratFont, size, textPos, IM_COL32_WHITE, configName.c_str(), 0, 0.0f, &textClipRect); + } // Right side min = { max.x + (clipRectMax.x - max.x - valueWidth) / 2.0f, min.y + (optionHeight - valueHeight) / 2.0f }; @@ -335,7 +369,7 @@ static void DrawConfigOption(int32_t rowIndex, const ConfigDef& config) SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE); - auto valueText = config.GetValueLocalised(); + auto valueText = config->GetValueLocalised(); size = Scale(20.0f); textSize = g_newRodinFont->CalcTextSizeA(size, FLT_MAX, 0.0f, valueText.data()); @@ -370,47 +404,117 @@ static void DrawConfigOptions() switch (g_categoryIndex) { case 0: // SYSTEM - DrawConfigOption(rowIndex++, Config::Language); - DrawConfigOption(rowIndex++, Config::Hints); - DrawConfigOption(rowIndex++, Config::ControlTutorial); - DrawConfigOption(rowIndex++, Config::SaveScoreAtCheckpoints); - DrawConfigOption(rowIndex++, Config::UnleashOutOfControlDrain); - DrawConfigOption(rowIndex++, Config::WerehogHubTransformVideo); - DrawConfigOption(rowIndex++, Config::LogoSkip); + DrawConfigOption(rowIndex++, &Config::Language); + DrawConfigOption(rowIndex++, &Config::Hints); + DrawConfigOption(rowIndex++, &Config::ControlTutorial); + DrawConfigOption(rowIndex++, &Config::SaveScoreAtCheckpoints); + DrawConfigOption(rowIndex++, &Config::UnleashOutOfControlDrain); + DrawConfigOption(rowIndex++, &Config::WerehogHubTransformVideo); + DrawConfigOption(rowIndex++, &Config::LogoSkip); break; case 1: // CONTROLS - DrawConfigOption(rowIndex++, Config::CameraXInvert); - DrawConfigOption(rowIndex++, Config::CameraYInvert); - DrawConfigOption(rowIndex++, Config::XButtonHoming); - DrawConfigOption(rowIndex++, Config::UnleashCancel); + DrawConfigOption(rowIndex++, &Config::CameraXInvert); + DrawConfigOption(rowIndex++, &Config::CameraYInvert); + DrawConfigOption(rowIndex++, &Config::XButtonHoming); + DrawConfigOption(rowIndex++, &Config::UnleashCancel); break; case 2: // AUDIO - DrawConfigOption(rowIndex++, Config::MusicVolume); - DrawConfigOption(rowIndex++, Config::SEVolume); - DrawConfigOption(rowIndex++, Config::VoiceLanguage); - DrawConfigOption(rowIndex++, Config::Subtitles); - DrawConfigOption(rowIndex++, Config::WerehogBattleMusic); + DrawConfigOption(rowIndex++, &Config::MusicVolume); + DrawConfigOption(rowIndex++, &Config::SEVolume); + DrawConfigOption(rowIndex++, &Config::VoiceLanguage); + DrawConfigOption(rowIndex++, &Config::Subtitles); + DrawConfigOption(rowIndex++, &Config::WerehogBattleMusic); break; case 3: // VIDEO // TODO: expose WindowWidth/WindowHeight as WindowSize. - DrawConfigOption(rowIndex++, Config::ResolutionScale); - DrawConfigOption(rowIndex++, Config::Fullscreen); - DrawConfigOption(rowIndex++, Config::VSync); - DrawConfigOption(rowIndex++, Config::TripleBuffering); - DrawConfigOption(rowIndex++, Config::FPS); - DrawConfigOption(rowIndex++, Config::Brightness); - DrawConfigOption(rowIndex++, Config::AntiAliasing); - DrawConfigOption(rowIndex++, Config::ShadowResolution); - DrawConfigOption(rowIndex++, Config::GITextureFiltering); - DrawConfigOption(rowIndex++, Config::AlphaToCoverage); - DrawConfigOption(rowIndex++, Config::MotionBlur); - DrawConfigOption(rowIndex++, Config::Xbox360ColourCorrection); - DrawConfigOption(rowIndex++, Config::MovieScaleMode); - DrawConfigOption(rowIndex++, Config::UIScaleMode); + DrawConfigOption(rowIndex++, &Config::ResolutionScale); + DrawConfigOption(rowIndex++, &Config::Fullscreen); + DrawConfigOption(rowIndex++, &Config::VSync); + DrawConfigOption(rowIndex++, &Config::TripleBuffering); + DrawConfigOption(rowIndex++, &Config::FPS); + DrawConfigOption(rowIndex++, &Config::Brightness); + DrawConfigOption(rowIndex++, &Config::AntiAliasing); + DrawConfigOption(rowIndex++, &Config::ShadowResolution); + DrawConfigOption(rowIndex++, &Config::GITextureFiltering); + DrawConfigOption(rowIndex++, &Config::AlphaToCoverage); + DrawConfigOption(rowIndex++, &Config::MotionBlur); + DrawConfigOption(rowIndex++, &Config::Xbox360ColourCorrection); + DrawConfigOption(rowIndex++, &Config::MovieScaleMode); + DrawConfigOption(rowIndex++, &Config::UIScaleMode); break; } } +void DrawSettingsPanel() +{ + auto drawList = ImGui::GetForegroundDrawList(); + + ImVec2 settingsMin = { Scale(AlignToNextGrid(COMMON_PADDING_POS_X)), Scale(AlignToNextGrid(COMMON_PADDING_POS_Y)) }; + ImVec2 settingsMax = { Scale(AlignToNextGrid(INFO_CONTAINER_POS_X - COMMON_PADDING_POS_X)), Scale(AlignToNextGrid(720.0f - COMMON_PADDING_POS_Y)) }; + + DrawContainer(settingsMin, settingsMax); + DrawCategories(); + DrawConfigOptions(); + + // Pop clip rect from DrawCategories + drawList->PopClipRect(); + + // Pop clip rect from DrawContainer + drawList->PopClipRect(); +} + +void DrawInfoPanel() +{ + auto drawList = ImGui::GetForegroundDrawList(); + + ImVec2 infoMin = { Scale(AlignToNextGrid(INFO_CONTAINER_POS_X)), Scale(AlignToNextGrid(COMMON_PADDING_POS_Y)) }; + ImVec2 infoMax = { Scale(AlignToNextGrid(1280.0f - COMMON_PADDING_POS_X)), Scale(AlignToNextGrid(720.0f - COMMON_PADDING_POS_Y)) }; + + DrawContainer(infoMin, infoMax); + + auto clipRectMin = drawList->GetClipRectMin(); + auto clipRectMax = drawList->GetClipRectMax(); + + ImVec2 thumbnailMax = { clipRectMin.x + ScaleX(343.0f), clipRectMin.y + ScaleY(193.0f) }; + + // Thumbnail box + drawList->AddRectFilled(clipRectMin, thumbnailMax, IM_COL32(0, 0, 0, 255)); + + if (g_selectedItem) + { + auto desc = g_selectedItem->GetDescription(); + + // Specialised description for resolution scale + if (g_selectedItem->GetName() == "ResolutionScale") + { + char buf[100]; + auto resScale = *(float*)g_selectedItem->GetValue(); + + std::snprintf(buf, sizeof(buf), desc.c_str(), + (int)((float)Window::s_width * resScale), + (int)((float)Window::s_height * resScale)); + + desc = buf; + } + + auto size = Scale(26.0f); + auto textSize = g_seuratFont->CalcTextSizeA(size, FLT_MAX, 0.0f, desc.c_str()); + + drawList->AddText( + g_seuratFont, + size, + { clipRectMin.x, thumbnailMax.y + size }, + IM_COL32_WHITE, + desc.c_str(), + 0, + thumbnailMax.x - clipRectMin.x + ); + + // Pop clip rect from DrawContainer + drawList->PopClipRect(); + } +} + void OptionsMenu::Draw() { if (!s_isVisible) @@ -425,24 +529,8 @@ void OptionsMenu::Draw() drawList->AddRectFilled({ 0.0f, 0.0f }, res, IM_COL32(0, 0, 0, 127)); DrawScanlineBars(); - - constexpr float CONTAINER_POS_X = 236.0f; - constexpr float CONTAINER_POS_Y = 118.0f; - - ImVec2 min = { Scale(AlignToNextGrid(CONTAINER_POS_X)), Scale(AlignToNextGrid(CONTAINER_POS_Y)) }; - ImVec2 max = { Scale(AlignToNextGrid(1280.0f - CONTAINER_POS_X)), Scale(AlignToNextGrid(720.0f - CONTAINER_POS_Y)) }; - - DrawContainer(min, max); - - DrawCategories(); - - DrawConfigOptions(); - - // Pop clip rect from DrawCategories - drawList->PopClipRect(); - - // Pop clip rect from DrawContainer - drawList->PopClipRect(); + DrawSettingsPanel(); + DrawInfoPanel(); } void OptionsMenu::Open(bool stage)