diff --git a/UnleashedRecomp/api/SWA.h b/UnleashedRecomp/api/SWA.h index cd70b616..dfda8889 100644 --- a/UnleashedRecomp/api/SWA.h +++ b/UnleashedRecomp/api/SWA.h @@ -36,6 +36,7 @@ #include "SWA/CSD/CsdProject.h" #include "SWA/CSD/CsdTexListMirage.h" #include "SWA/CSD/GameObjectCSD.h" +#include "SWA/HUD/Pause/HudPause.h" #include "SWA/Player/Character/EvilSonic/Hud/EvilHudGuide.h" #include "SWA/Player/Character/EvilSonic/EvilSonic.h" #include "SWA/Player/Character/EvilSonic/EvilSonicContext.h" diff --git a/UnleashedRecomp/api/SWA/HUD/Pause/HudPause.h b/UnleashedRecomp/api/SWA/HUD/Pause/HudPause.h new file mode 100644 index 00000000..72406351 --- /dev/null +++ b/UnleashedRecomp/api/SWA/HUD/Pause/HudPause.h @@ -0,0 +1,55 @@ +#pragma once + +#include + +namespace SWA +{ + enum EActionType : uint32_t + { + eActionType_Undefined, + eActionType_Status, + eActionType_Return, + eActionType_Inventory, + eActionType_Skills, + eActionType_Lab, + eActionType_Wait, + eActionType_Restart = 8, + eActionType_Continue + }; + + enum EMenuType : uint32_t + { + eMenuType_WorldMap, + eMenuType_Village, + eMenuType_Stage, + eMenuType_Hub, + eMenuType_Misc + }; + + enum EStatusType : uint32_t + { + eStatusType_Idle, + eStatusType_Accept, + eStatusType_Decline + }; + + enum ETransitionType : uint32_t + { + eTransitionType_Undefined, + eTransitionType_Quit = 2, + eTransitionType_Dialog = 5, + eTransitionType_Hide, + eTransitionType_Abort, + eTransitionType_SubMenu + }; + + class CHudPause : public CGameObject + { + public: + SWA_INSERT_PADDING(0xC8); + be m_Action; + be m_Menu; + be m_Status; + be m_Transition; + }; +} diff --git a/UnleashedRecomp/app.cpp b/UnleashedRecomp/app.cpp index 868c3199..e94176b1 100644 --- a/UnleashedRecomp/app.cpp +++ b/UnleashedRecomp/app.cpp @@ -15,7 +15,7 @@ PPC_FUNC(sub_822C1130) SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); Window::Update(); - audio_patches::Update(g_deltaTime); + AudioPatches::Update(g_deltaTime); __imp__sub_822C1130(ctx, base); } diff --git a/UnleashedRecomp/cfg/config.h b/UnleashedRecomp/cfg/config.h index 78ced728..7dbc5db5 100644 --- a/UnleashedRecomp/cfg/config.h +++ b/UnleashedRecomp/cfg/config.h @@ -1,8 +1,8 @@ #pragma once -#include "config_detail.h" -#include "config_locale.h" -#include "exports.h" +#include +#include +#include class Config { diff --git a/UnleashedRecomp/cfg/config_locale.h b/UnleashedRecomp/locale/config_locale.h similarity index 99% rename from UnleashedRecomp/cfg/config_locale.h rename to UnleashedRecomp/locale/config_locale.h index 89b79a54..1a23b2ef 100644 --- a/UnleashedRecomp/cfg/config_locale.h +++ b/UnleashedRecomp/locale/config_locale.h @@ -1,6 +1,6 @@ #pragma once -#include "config_detail.h" +#include #define CONFIG_DEFINE_LOCALE(name) \ inline static std::unordered_map> g_##name##_locale = diff --git a/UnleashedRecomp/locale/locale.h b/UnleashedRecomp/locale/locale.h new file mode 100644 index 00000000..220796ea --- /dev/null +++ b/UnleashedRecomp/locale/locale.h @@ -0,0 +1,65 @@ +#pragma once + +#include + +inline static std::string g_localeMissing = ""; + +inline static std::unordered_map> g_locale +{ + { + "Options_Category_System", + { + { ELanguage::English, "SYSTEM" } + } + }, + { + "Options_Category_Input", + { + { ELanguage::English, "INPUT" } + } + }, + { + "Options_Category_Audio", + { + { ELanguage::English, "AUDIO" } + } + }, + { + "Options_Category_Video", + { + { ELanguage::English, "VIDEO" } + } + }, + { + "Options_Value_Max", + { + { ELanguage::English, "MAX" } + } + }, + { + "Options_Desc_NotAvailable", + { + { ELanguage::English, "This option is not available at this location." } + } + } +}; + +static std::string& Localise(const char* key) +{ + if (!g_locale.count(key)) + return g_localeMissing; + + if (!g_locale[key].count(Config::Language)) + { + if (g_locale[key].count(ELanguage::English)) + { + return g_locale[key][ELanguage::English]; + } + else + { + return g_localeMissing; + } + } + + return g_locale[key][Config::Language]; +} diff --git a/UnleashedRecomp/patches/audio_patches.cpp b/UnleashedRecomp/patches/audio_patches.cpp index a4389393..2c99a1bf 100644 --- a/UnleashedRecomp/patches/audio_patches.cpp +++ b/UnleashedRecomp/patches/audio_patches.cpp @@ -14,7 +14,7 @@ be* GetVolume(bool isMusic = true) return (be*)g_memory.Translate(4 * ((int)isMusic + 0x1C) + ((be*)g_memory.Translate(ppUnkClass->get() + 4))->get()); } -void audio_patches::Update(float deltaTime) +void AudioPatches::Update(float deltaTime) { auto pMusicVolume = GetVolume(); auto pSEVolume = GetVolume(false); diff --git a/UnleashedRecomp/patches/audio_patches.h b/UnleashedRecomp/patches/audio_patches.h index b839899e..4397c391 100644 --- a/UnleashedRecomp/patches/audio_patches.h +++ b/UnleashedRecomp/patches/audio_patches.h @@ -1,6 +1,6 @@ #pragma once -class audio_patches +class AudioPatches { public: static void Update(float deltaTime); diff --git a/UnleashedRecomp/patches/ui/CHudPause_patches.cpp b/UnleashedRecomp/patches/ui/CHudPause_patches.cpp index 0369788e..a0557e79 100644 --- a/UnleashedRecomp/patches/ui/CHudPause_patches.cpp +++ b/UnleashedRecomp/patches/ui/CHudPause_patches.cpp @@ -3,8 +3,6 @@ #include #include -bool m_isOptionsFromPause = false; - void CHudPauseAddOptionsItemMidAsmHook(PPCRegister& pThis) { auto pStrMemory = __HH_ALLOC(8); @@ -23,74 +21,43 @@ void CHudPauseAddOptionsItemMidAsmHook(PPCRegister& pThis) bool InjectOptionsBehaviour(uint32_t pThis, uint32_t count) { - auto status = *(be*)g_memory.Translate(pThis + 0x190); - auto pauseType = *(be*)g_memory.Translate(pThis + 0x18C); + auto pHudPause = (SWA::CHudPause*)g_memory.Translate(pThis); auto cursorIndex = *(be*)g_memory.Translate(4 * (*(be*)g_memory.Translate(pThis + 0x19C) + 0x68) + pThis); - /* - 0 ---- Undefined - 1 ---- Status - 2 ---- Return to Previous Area - 3 ---- Inventory - 4 ---- Skills - 5 ---- Go to the Lab - 6 ---- Wait until Day/Night - 7 ---- Undefined - 8 ---- Restart Stage - 9 ---- Continue Stage - <=10 - Undefined - */ - auto pExitType = (be*)g_memory.Translate(pThis + 0x188); + auto exitType = SWA::eActionType_Undefined; + auto transitionType = SWA::eTransitionType_Undefined; - /* - 0 --- Undefined - 1 --- Unknown menu - 2 --- Quit menu - 3 --- Pause menu? - 4 --- Undefined - 5 --- Make cursor small? - 6 --- Hide UI and ignore face buttons - 7 --- Stop updating pause menu - 8 --- Hide UI (apart from pause header) and ignore face buttons - <=9 - Stop updating pause menu - */ - auto pTransitionType = (be*)g_memory.Translate(pThis + 0x194); - - auto exitType = 0; - auto transitionType = 0; - - switch (pauseType) + switch (pHudPause->m_Menu) { - case 0: // World Map - case 2: // Stage - case 4: // Misc - exitType = 2; - transitionType = 2; + case SWA::eMenuType_WorldMap: + case SWA::eMenuType_Stage: + case SWA::eMenuType_Misc: + exitType = SWA::eActionType_Return; + transitionType = SWA::eTransitionType_Quit; break; - case 1: // Village - case 3: // Hub - exitType = 2; - transitionType = 6; + case SWA::eMenuType_Village: + case SWA::eMenuType_Hub: + exitType = SWA::eActionType_Return; + transitionType = SWA::eTransitionType_Hide; break; } - if (status == 1) + if (pHudPause->m_Status == SWA::eStatusType_Accept) { if (cursorIndex == count - 2) { - OptionsMenu::Open(pauseType); - m_isOptionsFromPause = true; + OptionsMenu::Open(true, pHudPause->m_Menu); - *pExitType = 0; - *pTransitionType = 6; + pHudPause->m_Action = SWA::eActionType_Undefined; + pHudPause->m_Transition = SWA::eTransitionType_Hide; return true; } else if (cursorIndex == count - 1) { - *pExitType = exitType; - *pTransitionType = transitionType; + pHudPause->m_Action = exitType; + pHudPause->m_Transition = transitionType; return true; } @@ -130,21 +97,18 @@ bool CHudPauseMiscInjectOptionsMidAsmHook(PPCRegister& pThis) PPC_FUNC_IMPL(__imp__sub_824B0930); PPC_FUNC(sub_824B0930) { - if (!OptionsMenu::s_isVisible || !m_isOptionsFromPause) + if (!OptionsMenu::s_isVisible || !OptionsMenu::s_isPause) { __imp__sub_824B0930(ctx, base); return; } - auto pauseType = *(be*)g_memory.Translate(ctx.r3.u32 + 0x18C); - if (auto pInputState = SWA::CInputState::GetInstance()) { // TODO: disable Start button closing menu. if (OptionsMenu::CanClose() && pInputState->GetPadState().IsTapped(SWA::eKeyState_B)) { - OptionsMenu::Close(pauseType); - m_isOptionsFromPause = false; + OptionsMenu::Close(); // Re-open pause menu. GuestToHostFunction(0x824AFD28, ctx.r3.u32, 0, 0, 0, 1); diff --git a/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp b/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp index bbf232c2..71225b30 100644 --- a/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp +++ b/UnleashedRecomp/patches/ui/CTitleStateMenu_patches.cpp @@ -17,6 +17,7 @@ PPC_FUNC(sub_825882B8) { Game_PlaySound("sys_worldmap_window"); Game_PlaySound("sys_worldmap_decide"); + OptionsMenu::Open(); } } @@ -29,6 +30,7 @@ PPC_FUNC(sub_825882B8) if (OptionsMenu::CanClose() && pInputState->GetPadState().IsTapped(SWA::eKeyState_B)) { Game_PlaySound("sys_worldmap_cansel"); + OptionsMenu::Close(); } } diff --git a/UnleashedRecomp/ui/options_menu.cpp b/UnleashedRecomp/ui/options_menu.cpp index 381ae58b..26a61ea8 100644 --- a/UnleashedRecomp/ui/options_menu.cpp +++ b/UnleashedRecomp/ui/options_menu.cpp @@ -6,6 +6,7 @@ #include #include #include +#include constexpr float COMMON_PADDING_POS_Y = 118.0f; constexpr float COMMON_PADDING_POS_X = 30.0f; @@ -16,6 +17,7 @@ static ImFont* g_dfsogeistdFont; static ImFont* g_newRodinFont; static const IConfigDef* g_selectedItem; +static bool g_isSelectedItemAccessible; static bool g_isEnterKeyBuffered = false; @@ -151,7 +153,7 @@ static void DrawScanlineBars() auto& res = ImGui::GetIO().DisplaySize; auto drawList = ImGui::GetForegroundDrawList(); - if (OptionsMenu::s_isStage) + if (OptionsMenu::s_pauseMenuType != SWA::eMenuType_WorldMap) { // Top bar fade drawList->AddRectFilledMultiColor( @@ -291,19 +293,23 @@ static void DrawContainer(ImVec2 min, ImVec2 max) drawList->PushClipRect({ min.x + gridSize * 2.0f, min.y + gridSize * 2.0f }, { max.x - gridSize * 2.0f + 1.0f, max.y - gridSize * 2.0f + 1.0f }); } -// TODO: localise this. -static constexpr const char* CATEGORIES[] = -{ - "SYSTEM", - "INPUT", - "AUDIO", - "VIDEO" -}; - +static int32_t g_categoryCount = 4; static int32_t g_categoryIndex; static ImVec2 g_categoryAnimMin; static ImVec2 g_categoryAnimMax; +static std::string& GetCategory(int index) +{ + // TODO: Don't use raw numbers here! + switch (index) + { + case 0: return Localise("Options_Category_System"); + case 1: return Localise("Options_Category_Input"); + case 2: return Localise("Options_Category_Audio"); + case 3: return Localise("Options_Category_Video"); + } +} + static int32_t g_firstVisibleRowIndex; static int32_t g_prevSelectedRowIndex; static int32_t g_selectedRowIndex; @@ -352,12 +358,12 @@ static bool DrawCategories() { --g_categoryIndex; if (g_categoryIndex < 0) - g_categoryIndex = std::size(CATEGORIES) - 1; + g_categoryIndex = g_categoryCount - 1; } else if (moveRight) { ++g_categoryIndex; - if (g_categoryIndex >= std::size(CATEGORIES)) + if (g_categoryIndex >= g_categoryCount) g_categoryIndex = 0; } @@ -376,22 +382,22 @@ static bool DrawCategories() float tabPadding = gridSize; float size = Scale(32.0f); - ImVec2 textSizes[std::size(CATEGORIES)]; + ImVec2 textSizes[g_categoryCount]; float tabWidthSum = 0.0f; - for (size_t i = 0; i < std::size(CATEGORIES); i++) + for (size_t i = 0; i < g_categoryCount; i++) { - textSizes[i] = g_dfsogeistdFont->CalcTextSizeA(size, FLT_MAX, 0.0f, CATEGORIES[i]); + textSizes[i] = g_dfsogeistdFont->CalcTextSizeA(size, FLT_MAX, 0.0f, GetCategory(i).c_str()); tabWidthSum += textSizes[i].x + textPadding * 2.0f; } - tabWidthSum += (std::size(CATEGORIES) - 1) * tabPadding; + tabWidthSum += (g_categoryCount - 1) * tabPadding; float tabHeight = gridSize * 4.0f; float xOffset = ((clipRectMax.x - clipRectMin.x) - tabWidthSum) / 2.0f; xOffset -= (1.0 - motion) * gridSize * 4.0; - ImVec2 minVec[std::size(CATEGORIES)]; + ImVec2 minVec[g_categoryCount]; - for (size_t i = 0; i < std::size(CATEGORIES); i++) + for (size_t i = 0; i < g_categoryCount; i++) { ImVec2 min = { clipRectMin.x + xOffset, clipRectMin.y }; @@ -454,7 +460,7 @@ static bool DrawCategories() minVec[i] = min; } - for (size_t i = 0; i < std::size(CATEGORIES); i++) + for (size_t i = 0; i < g_categoryCount; i++) { auto& min = minVec[i]; uint8_t alpha = (i == g_categoryIndex ? 235 : 128) * motion; @@ -470,7 +476,7 @@ static bool DrawCategories() size, min, IM_COL32_WHITE, - CATEGORIES[i], + GetCategory(i).c_str(), Scale(3), IM_COL32_BLACK); @@ -490,16 +496,13 @@ static bool DrawCategories() extern void VideoConfigValueChangedCallback(IConfigDef* config); template -static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* config, T valueMin = T(0), T valueCenter = T(0.5), T valueMax = T(1)) +static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* config, bool isAccessible, T valueMin = T(0), T valueCenter = T(0.5), T valueMax = T(1)) { auto drawList = ImGui::GetForegroundDrawList(); auto clipRectMin = drawList->GetClipRectMin(); auto clipRectMax = drawList->GetClipRectMax(); auto& padState = SWA::CInputState::GetInstance()->GetPadState(); - constexpr ImU32 COLOR0 = IM_COL32(0xE2, 0x71, 0x22, 0x80); - constexpr ImU32 COLOR1 = IM_COL32(0x92, 0xFF, 0x31, 0x80); - auto gridSize = Scale(GRID_SIZE); auto optionWidth = gridSize * 54.0f; auto optionHeight = gridSize * 5.5f; @@ -524,64 +527,75 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf if (g_selectedRowIndex == rowIndex) { g_selectedItem = config; + g_isSelectedItemAccessible = isAccessible; if (!g_isEnterKeyBuffered) { - if constexpr (std::is_same_v) + if (isAccessible) { - if (padState.IsTapped(SWA::eKeyState_A)) + if constexpr (std::is_same_v) { - config->Value = !config->Value; - - if (config->Callback) - config->Callback(config); - - VideoConfigValueChangedCallback(config); - - Game_PlaySound("sys_worldmap_finaldecide"); - } - } - else - { - static T s_oldValue; - - if (padState.IsTapped(SWA::eKeyState_A)) - { - g_lockedOnOption ^= true; - if (g_lockedOnOption) + if (padState.IsTapped(SWA::eKeyState_A)) { - g_leftWasHeld = false; - g_rightWasHeld = false; - // remember value - s_oldValue = config->Value; + config->Value = !config->Value; - Game_PlaySound("sys_worldmap_decide"); - } - else - { - // released lock, call video callbacks if value is different - if (config->Value != s_oldValue) - VideoConfigValueChangedCallback(config); + if (config->Callback) + config->Callback(config); + + VideoConfigValueChangedCallback(config); Game_PlaySound("sys_worldmap_finaldecide"); } } - else if (padState.IsTapped(SWA::eKeyState_B)) + else { - // released lock, restore old value - config->Value = s_oldValue; - g_lockedOnOption = false; + static T s_oldValue; - Game_PlaySound("sys_worldmap_cansel"); + if (padState.IsTapped(SWA::eKeyState_A)) + { + g_lockedOnOption ^= true; + + if (g_lockedOnOption) + { + g_leftWasHeld = false; + g_rightWasHeld = false; + // remember value + s_oldValue = config->Value; + + Game_PlaySound("sys_worldmap_decide"); + } + else + { + // released lock, call video callbacks if value is different + if (config->Value != s_oldValue) + VideoConfigValueChangedCallback(config); + + Game_PlaySound("sys_worldmap_finaldecide"); + } + } + else if (padState.IsTapped(SWA::eKeyState_B)) + { + // released lock, restore old value + config->Value = s_oldValue; + g_lockedOnOption = false; + + Game_PlaySound("sys_worldmap_cansel"); + } + + lockedOnOption = g_lockedOnOption; } - - lockedOnOption = g_lockedOnOption; + } + else + { + if (padState.IsTapped(SWA::eKeyState_A)) + Game_PlaySound("sys_actstg_stateserror"); } } } - bool fadedOut = g_lockedOnOption && g_selectedItem != config; - float alpha = fadedOut ? 0.5f : 1.0f; + auto fadedOut = (g_lockedOnOption && g_selectedItem != config) || !isAccessible; + auto alpha = fadedOut ? 0.5f : 1.0f; + auto textColour = IM_COL32(255, 255, 255, 255 * alpha); if (g_selectedItem == config) { @@ -589,13 +603,16 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf double animRatio = std::clamp((ImGui::GetTime() - g_rowSelectionTime) * 60.0 / 8.0, 0.0, 1.0); prevItemOffset *= pow(1.0 - animRatio, 3.0); - drawList->AddRectFilledMultiColor({ min.x, min.y + prevItemOffset }, { max.x, max.y + prevItemOffset }, COLOR0, COLOR0, COLOR1, COLOR1); + auto c0 = IM_COL32(0xE2, 0x71, 0x22, isAccessible ? 0x80 : 0x30); + auto c1 = IM_COL32(0x92, 0xFF, 0x31, isAccessible ? 0x80 : 0x30); - DrawTextWithMarquee(g_seuratFont, size, textPos, min, max, IM_COL32_WHITE, configName.c_str(), g_rowSelectionTime, 0.9, 250.0); + drawList->AddRectFilledMultiColor({ min.x, min.y + prevItemOffset }, { max.x, max.y + prevItemOffset }, c0, c0, c1, c1); + + DrawTextWithMarquee(g_seuratFont, size, textPos, min, max, textColour, configName.c_str(), g_rowSelectionTime, 0.9, 250.0); } else { - drawList->AddText(g_seuratFont, size, textPos, IM_COL32(255, 255, 255, 255 * alpha), configName.c_str(), 0, 0.0f, &textClipRect); + drawList->AddText(g_seuratFont, size, textPos, textColour, configName.c_str(), 0, 0.0f, &textClipRect); } // Right side @@ -773,7 +790,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf if constexpr (std::is_same_v) valueText = std::format("{}%", int32_t(round(config->Value * 100.0f))); else if constexpr (std::is_same_v) - valueText = config->Value >= valueMax ? "MAX" : std::format("{}", config->Value); + valueText = config->Value >= valueMax ? Localise("Options_Value_Max") : std::format("{}", config->Value); else valueText = config->GetValueLocalised(); @@ -816,48 +833,50 @@ static void DrawConfigOptions() int32_t rowCount = 0; + bool isStage = OptionsMenu::s_pauseMenuType == SWA::eMenuType_Stage || OptionsMenu::s_pauseMenuType == SWA::eMenuType_Hub; + // TODO: Don't use raw numbers here! switch (g_categoryIndex) { case 0: // SYSTEM - DrawConfigOption(rowCount++, yOffset, &Config::Language); - DrawConfigOption(rowCount++, yOffset, &Config::Hints); - DrawConfigOption(rowCount++, yOffset, &Config::ControlTutorial); - DrawConfigOption(rowCount++, yOffset, &Config::SaveScoreAtCheckpoints); - DrawConfigOption(rowCount++, yOffset, &Config::UnleashGaugeBehaviour); - DrawConfigOption(rowCount++, yOffset, &Config::WerehogHubTransformVideo); - DrawConfigOption(rowCount++, yOffset, &Config::LogoSkip); + DrawConfigOption(rowCount++, yOffset, &Config::Language, !OptionsMenu::s_isPause); + DrawConfigOption(rowCount++, yOffset, &Config::Hints, !isStage); + DrawConfigOption(rowCount++, yOffset, &Config::ControlTutorial, !isStage); + DrawConfigOption(rowCount++, yOffset, &Config::SaveScoreAtCheckpoints, true); + DrawConfigOption(rowCount++, yOffset, &Config::UnleashGaugeBehaviour, true); + DrawConfigOption(rowCount++, yOffset, &Config::WerehogHubTransformVideo, true); + DrawConfigOption(rowCount++, yOffset, &Config::LogoSkip, true); break; case 1: // INPUT - DrawConfigOption(rowCount++, yOffset, &Config::CameraXInvert); - DrawConfigOption(rowCount++, yOffset, &Config::CameraYInvert); - DrawConfigOption(rowCount++, yOffset, &Config::XButtonHoming); - DrawConfigOption(rowCount++, yOffset, &Config::UnleashCancel); - DrawConfigOption(rowCount++, yOffset, &Config::BackgroundInput); + DrawConfigOption(rowCount++, yOffset, &Config::CameraXInvert, true); + DrawConfigOption(rowCount++, yOffset, &Config::CameraYInvert, true); + DrawConfigOption(rowCount++, yOffset, &Config::XButtonHoming, !OptionsMenu::s_isPause); // TODO: make this editable in stages. + DrawConfigOption(rowCount++, yOffset, &Config::UnleashCancel, true); + DrawConfigOption(rowCount++, yOffset, &Config::BackgroundInput, true); break; case 2: // AUDIO - DrawConfigOption(rowCount++, yOffset, &Config::MusicVolume); - DrawConfigOption(rowCount++, yOffset, &Config::SEVolume); - DrawConfigOption(rowCount++, yOffset, &Config::VoiceLanguage); - DrawConfigOption(rowCount++, yOffset, &Config::Subtitles); - DrawConfigOption(rowCount++, yOffset, &Config::WerehogBattleMusic); + DrawConfigOption(rowCount++, yOffset, &Config::MusicVolume, true); + DrawConfigOption(rowCount++, yOffset, &Config::SEVolume, true); + DrawConfigOption(rowCount++, yOffset, &Config::VoiceLanguage, true); + DrawConfigOption(rowCount++, yOffset, &Config::Subtitles, true); + DrawConfigOption(rowCount++, yOffset, &Config::WerehogBattleMusic, true); break; case 3: // VIDEO // TODO: expose WindowWidth/WindowHeight as WindowSize. - DrawConfigOption(rowCount++, yOffset, &Config::ResolutionScale, 0.25f, 1.0f, 2.0f); - DrawConfigOption(rowCount++, yOffset, &Config::Fullscreen); - DrawConfigOption(rowCount++, yOffset, &Config::VSync); - DrawConfigOption(rowCount++, yOffset, &Config::TripleBuffering); - DrawConfigOption(rowCount++, yOffset, &Config::FPS, 15, 120, 240); - DrawConfigOption(rowCount++, yOffset, &Config::Brightness); - DrawConfigOption(rowCount++, yOffset, &Config::AntiAliasing); - DrawConfigOption(rowCount++, yOffset, &Config::AlphaToCoverage); - DrawConfigOption(rowCount++, yOffset, &Config::ShadowResolution); - DrawConfigOption(rowCount++, yOffset, &Config::GITextureFiltering); - DrawConfigOption(rowCount++, yOffset, &Config::MotionBlur); - DrawConfigOption(rowCount++, yOffset, &Config::Xbox360ColourCorrection); - DrawConfigOption(rowCount++, yOffset, &Config::MovieScaleMode); - DrawConfigOption(rowCount++, yOffset, &Config::UIScaleMode); + DrawConfigOption(rowCount++, yOffset, &Config::ResolutionScale, true, 0.25f, 1.0f, 2.0f); + DrawConfigOption(rowCount++, yOffset, &Config::Fullscreen, true); + DrawConfigOption(rowCount++, yOffset, &Config::VSync, true); + DrawConfigOption(rowCount++, yOffset, &Config::TripleBuffering, true); + DrawConfigOption(rowCount++, yOffset, &Config::FPS, true, 15, 120, 240); + DrawConfigOption(rowCount++, yOffset, &Config::Brightness, true); + DrawConfigOption(rowCount++, yOffset, &Config::AntiAliasing, true); + DrawConfigOption(rowCount++, yOffset, &Config::AlphaToCoverage, true); + DrawConfigOption(rowCount++, yOffset, &Config::ShadowResolution, true); + DrawConfigOption(rowCount++, yOffset, &Config::GITextureFiltering, true); + DrawConfigOption(rowCount++, yOffset, &Config::MotionBlur, true); + DrawConfigOption(rowCount++, yOffset, &Config::Xbox360ColourCorrection, true); + DrawConfigOption(rowCount++, yOffset, &Config::MovieScaleMode, true); + DrawConfigOption(rowCount++, yOffset, &Config::UIScaleMode, true); break; } @@ -974,20 +993,27 @@ static void DrawInfoPanel() { auto desc = g_selectedItem->GetDescription(); - // Specialised description for resolution scale - if (g_selectedItem->GetName() == "ResolutionScale") + if (g_isSelectedItemAccessible) { - char buf[100]; - auto resScale = round(*(float*)g_selectedItem->GetValue() * 1000) / 1000; + // Specialised description for resolution scale + if (g_selectedItem->GetName() == "ResolutionScale") + { + char buf[100]; + auto resScale = round(*(float*)g_selectedItem->GetValue() * 1000) / 1000; - std::snprintf(buf, sizeof(buf), desc.c_str(), - (int)((float)Window::s_width * resScale), - (int)((float)Window::s_height * resScale)); + std::snprintf(buf, sizeof(buf), desc.c_str(), + (int)((float)Window::s_width * resScale), + (int)((float)Window::s_height * resScale)); - desc = buf; + desc = buf; + } + + desc += "\n\n" + g_selectedItem->GetValueDescription(); + } + else + { + desc = Localise("Options_Desc_NotAvailable"); } - - desc += "\n\n" + g_selectedItem->GetValueDescription(); auto size = Scale(26.0f); @@ -1022,7 +1048,7 @@ void OptionsMenu::Draw() auto& res = ImGui::GetIO().DisplaySize; auto drawList = ImGui::GetForegroundDrawList(); - if (s_isStage) + if (s_isPause && s_pauseMenuType != SWA::eMenuType_WorldMap) drawList->AddRectFilled({ 0.0f, 0.0f }, res, IM_COL32(0, 0, 0, 223)); DrawScanlineBars(); @@ -1030,10 +1056,13 @@ void OptionsMenu::Draw() DrawInfoPanel(); } -void OptionsMenu::Open(bool stage) +void OptionsMenu::Open(bool isPause, SWA::EMenuType pauseMenuType) { s_isVisible = true; - s_isStage = stage; + s_isPause = isPause; + + s_pauseMenuType = pauseMenuType; + g_appearTime = ImGui::GetTime(); g_categoryIndex = 0; g_categoryAnimMin = { 0.0f, 0.0f }; @@ -1051,10 +1080,9 @@ void OptionsMenu::Open(bool stage) // TODO: animate Miles Electric in if we're in a stage. } -void OptionsMenu::Close(bool stage) +void OptionsMenu::Close() { s_isVisible = false; - s_isStage = stage; *(bool*)g_memory.Translate(0x8328BB26) = true; diff --git a/UnleashedRecomp/ui/options_menu.h b/UnleashedRecomp/ui/options_menu.h index 7561f2d3..6ea404b5 100644 --- a/UnleashedRecomp/ui/options_menu.h +++ b/UnleashedRecomp/ui/options_menu.h @@ -1,15 +1,19 @@ #pragma once +#include + struct OptionsMenu { public: inline static bool s_isVisible = false; - inline static bool s_isStage = false; + inline static bool s_isPause = false; + + inline static SWA::EMenuType s_pauseMenuType; static void Init(); static void Draw(); - static void Open(bool stage = false); - static void Close(bool stage = false); + static void Open(bool isPause = false, SWA::EMenuType pauseMenuType = SWA::eMenuType_WorldMap); + static void Close(); static bool CanClose(); };