options_menu: implemented info panel and text marquee (see TODOs)

This commit is contained in:
Hyper 2024-11-18 00:37:13 +00:00
parent 104da0218b
commit d4d4328874
5 changed files with 360 additions and 85 deletions

View file

@ -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);
});

View file

@ -10,8 +10,8 @@ ConfigDef<T>::ConfigDef(std::string section, std::string name, T defaultValue) :
// CONFIG_DEFINE_LOCALISED
template<typename T>
ConfigDef<T>::ConfigDef(std::string section, std::string name, std::unordered_map<ELanguage, std::string>* nameLocale, T defaultValue)
: Section(section), Name(name), NameLocale(nameLocale), DefaultValue(defaultValue)
ConfigDef<T>::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<T>::ConfigDef(std::string section, std::string name, T defaultValue, s
// CONFIG_DEFINE_ENUM_LOCALISED
template<typename T>
ConfigDef<T>::ConfigDef(std::string section, std::string name, std::unordered_map<ELanguage, std::string>* nameLocale, T defaultValue, std::unordered_map<std::string, T>* enumTemplate, std::unordered_map<ELanguage, std::unordered_map<T, std::string>>* enumLocale)
: Section(section), Name(name), NameLocale(nameLocale), DefaultValue(defaultValue), EnumTemplate(enumTemplate), EnumLocale(enumLocale)
ConfigDef<T>::ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, CONFIG_LOCALE* descLocale, T defaultValue, std::unordered_map<std::string, T>* 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<T>::ConfigDef(std::string section, std::string name, T defaultValue, s
Config::Definitions.emplace_back(this);
}
template<typename T>
std::string ConfigDef<T>::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<typename T>
std::string ConfigDef<T>::GetNameLocalised() const
{
@ -71,7 +92,7 @@ template<typename T>
std::string ConfigDef<T>::GetValueLocalised() const
{
auto language = Config::Language;
std::unordered_map<ELanguage, std::unordered_map<T, std::string>>* locale = nullptr;
CONFIG_ENUM_LOCALE(T)* locale = nullptr;
if constexpr (std::is_enum_v<T>)
{

View file

@ -8,13 +8,13 @@
inline static ConfigDef<type> name{section, #name, defaultValue};
#define CONFIG_DEFINE_LOCALISED(section, type, name, defaultValue) \
inline static ConfigDef<type> name{section, #name, &g_##name##_locale, defaultValue};
inline static ConfigDef<type> name{section, #name, &g_##name##_locale, &g_##name##_desc_locale, defaultValue};
#define CONFIG_DEFINE_ENUM(section, type, name, defaultValue) \
inline static ConfigDef<type> name{section, #name, defaultValue, &g_##type##_template};
#define CONFIG_DEFINE_ENUM_LOCALISED(section, type, name, defaultValue) \
inline static ConfigDef<type> name{section, #name, &g_##name##_locale, defaultValue, &g_##type##_template, &g_##type##_locale};
inline static ConfigDef<type> 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<type> name{section, #name, defaultValue, [](ConfigDef<type>* def) readCallback};
@ -22,8 +22,8 @@
#define CONFIG_DEFINE_ENUM_TEMPLATE(type) \
inline static std::unordered_map<std::string, type> 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<ELanguage, std::string>
#define CONFIG_ENUM_LOCALE(type) std::unordered_map<ELanguage, std::unordered_map<type, std::string>>
#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<ELanguage, std::string>* NameLocale;
CONFIG_LOCALE* NameLocale;
CONFIG_LOCALE* DescLocale;
T DefaultValue{};
T Value{ DefaultValue };
std::unordered_map<std::string, T>* EnumTemplate;
std::map<T, std::string> EnumTemplateReverse{};
std::unordered_map<ELanguage, std::unordered_map<T, std::string>>* EnumLocale;
CONFIG_ENUM_LOCALE(T)* EnumLocale;
std::function<void(ConfigDef<T>*)> 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<ELanguage, std::string>* 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<std::string, T>* enumTemplate);
// CONFIG_DEFINE_ENUM_LOCALISED
ConfigDef(std::string section, std::string name, std::unordered_map<ELanguage, std::string>* nameLocale, T defaultValue, std::unordered_map<std::string, T>* enumTemplate, std::unordered_map<ELanguage, std::unordered_map<T, std::string>>* enumLocale);
ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, CONFIG_LOCALE* descLocale, T defaultValue, std::unordered_map<std::string, T>* enumTemplate, CONFIG_ENUM_LOCALE(T)* enumLocale);
// CONFIG_DEFINE_CALLBACK
ConfigDef(std::string section, std::string name, T defaultValue, std::function<void(ConfigDef<T>*)> 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;
}

View file

@ -5,9 +5,15 @@
#define CONFIG_DEFINE_LOCALE(name) \
inline static std::unordered_map<ELanguage, std::string> g_##name##_locale =
#define CONFIG_DEFINE_DESCRIPTION_LOCALE(name) \
inline static std::unordered_map<ELanguage, std::string> g_##name##_desc_locale =
#define CONFIG_DEFINE_ENUM_LOCALE(type) \
inline static std::unordered_map<ELanguage, std::unordered_map<type, std::string>> g_##type##_locale =
#define CONFIG_DEFINE_ENUM_DESCRIPTION_LOCALE(type) \
inline static std::unordered_map<ELanguage, std::unordered_map<type, std::string>> 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)
{
{

View file

@ -3,10 +3,16 @@
#include <kernel/memory.h>
#include <gpu/imgui_common.h>
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<typename T>
static void DrawConfigOption(int32_t rowIndex, const ConfigDef<T>& config)
static void DrawConfigOption(int32_t rowIndex, const ConfigDef<T>* config)
{
auto drawList = ImGui::GetForegroundDrawList();
auto clipRectMin = drawList->GetClipRectMin();
@ -302,26 +328,34 @@ static void DrawConfigOption(int32_t rowIndex, const ConfigDef<T>& 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<T>& 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)