Merge branch 'options-menu' into music-attenuation

This commit is contained in:
Hyper 2024-11-21 01:51:13 +00:00
commit a2a086c52c
14 changed files with 314 additions and 195 deletions

View file

@ -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"

View file

@ -0,0 +1,55 @@
#pragma once
#include <SWA.inl>
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<EActionType> m_Action;
be<EMenuType> m_Menu;
be<EStatusType> m_Status;
be<ETransitionType> m_Transition;
};
}

View file

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

View file

@ -1,8 +1,8 @@
#pragma once
#include "config_detail.h"
#include "config_locale.h"
#include "exports.h"
#include <cfg/config_detail.h>
#include <locale/config_locale.h>
#include <exports.h>
class Config
{

View file

@ -1,6 +1,6 @@
#pragma once
#include "config_detail.h"
#include <cfg/config_detail.h>
#define CONFIG_DEFINE_LOCALE(name) \
inline static std::unordered_map<ELanguage, std::tuple<std::string, std::string>> g_##name##_locale =

View file

@ -0,0 +1,65 @@
#pragma once
#include <cfg/config.h>
inline static std::string g_localeMissing = "<missing string>";
inline static std::unordered_map<std::string, std::unordered_map<ELanguage, std::string>> 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];
}

View file

@ -50,7 +50,7 @@ be<float>* GetVolume(bool isMusic = true)
return (be<float>*)g_memory.Translate(4 * ((int)isMusic + 0x1C) + ((be<uint32_t>*)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);

View file

@ -1,6 +1,6 @@
#pragma once
class audio_patches
class AudioPatches
{
public:
static void Update(float deltaTime);

View file

@ -23,20 +23,20 @@ bool CameraAspectRatioMidAsmHook(PPCRegister& r31)
return newAspectRatio < m_baseAspectRatio;
}
void CameraBoostAspectRatioMidAsmHook(PPCRegister& r31, PPCRegister& f0)
bool CameraBoostAspectRatioMidAsmHook(PPCRegister& r31, PPCRegister& f0, PPCRegister& f10, PPCRegister& f12)
{
auto pCamera = (SWA::CCamera*)g_memory.Translate(r31.u32);
if (Window::s_width < Window::s_height)
{
// Use horizontal FOV for narrow aspect ratios.
f0.f32 = pCamera->m_HorzFieldOfView;
pCamera->m_VertFieldOfView = pCamera->m_HorzFieldOfView + f10.f64;
}
else
{
// Use vertical FOV for wide aspect ratios.
f0.f32 = pCamera->m_VertFieldOfView;
pCamera->m_VertFieldOfView = (f12.f64 / f0.f64) + f10.f64;
}
return true;
}
PPC_FUNC_IMPL(__imp__sub_824697B0);

View file

@ -3,8 +3,6 @@
#include <api/SWA.h>
#include <ui/options_menu.h>
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<uint32_t>*)g_memory.Translate(pThis + 0x190);
auto pauseType = *(be<uint32_t>*)g_memory.Translate(pThis + 0x18C);
auto pHudPause = (SWA::CHudPause*)g_memory.Translate(pThis);
auto cursorIndex = *(be<uint32_t>*)g_memory.Translate(4 * (*(be<uint32_t>*)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<uint32_t>*)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<uint32_t>*)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<uint32_t>*)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<int>(0x824AFD28, ctx.r3.u32, 0, 0, 0, 1);

View file

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

View file

@ -6,6 +6,7 @@
#include <gpu/imgui_common.h>
#include <kernel/heap.h>
#include <kernel/memory.h>
#include <locale/locale.h>
constexpr float COMMON_PADDING_POS_Y = 118.0f;
constexpr float COMMON_PADDING_POS_X = 30.0f;
@ -16,8 +17,10 @@ static ImFont* g_dfsogeistdFont;
static ImFont* g_newRodinFont;
static const IConfigDef* g_selectedItem;
static bool g_isSelectedItemAccessible;
static bool g_isEnterKeyBuffered = false;
static double g_appearTime = 0.0;
void OptionsMenu::Init()
@ -150,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(
@ -290,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;
@ -351,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;
}
@ -375,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 };
@ -453,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;
@ -469,7 +476,7 @@ static bool DrawCategories()
size,
min,
IM_COL32_WHITE,
CATEGORIES[i],
GetCategory(i).c_str(),
Scale(3),
IM_COL32_BLACK);
@ -489,16 +496,13 @@ static bool DrawCategories()
extern void VideoConfigValueChangedCallback(IConfigDef* config);
template<typename T>
static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* config, T valueMin = T(0), T valueCenter = T(0.5), T valueMax = T(1))
static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* 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;
@ -523,64 +527,75 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
if (g_selectedRowIndex == rowIndex)
{
g_selectedItem = config;
g_isSelectedItemAccessible = isAccessible;
if (!g_isEnterKeyBuffered)
{
if constexpr (std::is_same_v<T, bool>)
if (isAccessible)
{
if (padState.IsTapped(SWA::eKeyState_A))
if constexpr (std::is_same_v<T, bool>)
{
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)
{
@ -588,13 +603,16 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* 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
@ -772,7 +790,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
if constexpr (std::is_same_v<T, float>)
valueText = std::format("{}%", int32_t(round(config->Value * 100.0f)));
else if constexpr (std::is_same_v<T, int32_t>)
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();
@ -815,49 +833,51 @@ 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::MusicAttenuation); // TODO: grey this out for non-Windows platforms.
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::MusicAttenuation, true); // TODO: grey this out for non-Windows platforms.
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;
}
@ -965,7 +985,7 @@ static void DrawInfoPanel()
auto clipRectMin = drawList->GetClipRectMin();
auto clipRectMax = drawList->GetClipRectMax();
ImVec2 thumbnailMax = { clipRectMin.x + ScaleX(343.0f), clipRectMin.y + ScaleY(193.0f) };
ImVec2 thumbnailMax = { clipRectMin.x + ScaleX(343.0f), clipRectMin.y + ScaleY(198.0f) };
// Thumbnail box
drawList->AddRectFilled(clipRectMin, thumbnailMax, IM_COL32(0, 0, 0, 255));
@ -974,33 +994,38 @@ 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);
auto textSize = g_seuratFont->CalcTextSizeA(size, FLT_MAX, 0.0f, desc.c_str());
// TODO: fix word wrap width not scaling to resolution.
drawList->AddText(
g_seuratFont,
size,
{ clipRectMin.x, thumbnailMax.y + size },
{ clipRectMin.x, thumbnailMax.y + size - 5.0f },
IM_COL32_WHITE,
desc.c_str(),
0,
thumbnailMax.x - clipRectMin.x
clipRectMax.x - clipRectMin.x
);
// Pop clip rect from DrawContainer
@ -1012,7 +1037,7 @@ void OptionsMenu::Draw()
{
auto pInputState = SWA::CInputState::GetInstance();
if (!s_isVisible || pInputState->GetPadState().IsDown(SWA::eKeyState_Y))
if (!s_isVisible)
return;
// We've entered the menu now, no need to check this.
@ -1024,7 +1049,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();
@ -1032,10 +1057,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 };
@ -1053,10 +1081,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;

View file

@ -1,15 +1,19 @@
#pragma once
#include <api/SWA.h>
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();
};

View file

@ -98,8 +98,9 @@ jump_address_on_false = 0x82468EE0
[[midasm_hook]]
name = "CameraBoostAspectRatioMidAsmHook"
address = 0x8246BDA8
registers = ["r31", "f0"]
address = 0x8246BDA0
registers = ["r31", "f0", "f10", "f12"]
jump_address_on_true = 0x8246BDAC
[[midasm_hook]]
name = "CSDAspectRatioMidAsmHook"