diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index 9f90cd04..c44c4b35 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -501,8 +501,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/op BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bilinear.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bilinear.dds" ARRAY_NAME "g_gi_texture_filtering_bilinear" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bicubic.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bicubic.dds" ARRAY_NAME "g_gi_texture_filtering_bicubic" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/hints.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/hints.dds" ARRAY_NAME "g_hints" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/invert_camera_x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/invert_camera_x.dds" ARRAY_NAME "g_invert_camera_x" COMPRESSION_TYPE "zstd") -BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/invert_camera_y.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/invert_camera_y.dds" ARRAY_NAME "g_invert_camera_y" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/horizontal_camera.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/horizontal_camera.dds" ARRAY_NAME "g_horizontal_camera" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/language.dds" ARRAY_NAME "g_language" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/master_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/master_volume.dds" ARRAY_NAME "g_master_volume" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/monitor.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/monitor.dds" ARRAY_NAME "g_monitor" COMPRESSION_TYPE "zstd") @@ -525,6 +524,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/op BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" ARRAY_NAME "g_transparency_antialiasing_false" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" ARRAY_NAME "g_transparency_antialiasing_true" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_scale_mode.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_scale_mode.dds" ARRAY_NAME "g_ui_scale_mode" COMPRESSION_TYPE "zstd") +BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vertical_camera.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vertical_camera.dds" ARRAY_NAME "g_vertical_camera" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/voice_language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/voice_language.dds" ARRAY_NAME "g_voice_language" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration.dds" ARRAY_NAME "g_vibration" COMPRESSION_TYPE "zstd") BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync.dds" ARRAY_NAME "g_vsync" COMPRESSION_TYPE "zstd") diff --git a/UnleashedRecomp/api/SWA.h b/UnleashedRecomp/api/SWA.h index 88828888..6a30e755 100644 --- a/UnleashedRecomp/api/SWA.h +++ b/UnleashedRecomp/api/SWA.h @@ -62,6 +62,7 @@ #include "SWA/Camera/Camera.h" #include "SWA/Camera/CameraController.h" #include "SWA/CharacterUtility/CharacterProxy.h" +#include "SWA/Globals.h" #include "SWA/HUD/GeneralWindow/GeneralWindow.h" #include "SWA/HUD/Loading/Loading.h" #include "SWA/HUD/Pause/HudPause.h" diff --git a/UnleashedRecomp/api/SWA/Globals.h b/UnleashedRecomp/api/SWA/Globals.h new file mode 100644 index 00000000..34dc697e --- /dev/null +++ b/UnleashedRecomp/api/SWA/Globals.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +namespace SWA +{ + struct SGlobals + { + // ms_DrawLightFieldSamplingPoint: サンプリング点をデバッグ表示 + static inline bool* ms_DrawLightFieldSamplingPoint; + + // ms_IgnoreLightFieldData: データを無視する + static inline bool* ms_IgnoreLightFieldData; + + // IsCollisionRender + static inline bool* ms_IsCollisionRender; + + // N/A + static inline bool* ms_IsLoading; + + // IsObjectCollisionRender + static inline bool* ms_IsObjectCollisionRender; + + // ms_IsRenderDebugDraw: デバッグ描画 + static inline bool* ms_IsRenderDebugDraw; + + // ms_IsRenderDebugDrawText: デバッグ文字描画 + static inline bool* ms_IsRenderDebugDrawText; + + // ms_IsRenderDebugPositionDraw: デバッグ位置描画 + static inline bool* ms_IsRenderDebugPositionDraw; + + // ms_IsRenderGameMainHud: ゲームメインHUD 描画 + static inline bool* ms_IsRenderGameMainHud; + + // ms_IsRenderHud: 全 HUD 描画 + static inline bool* ms_IsRenderHud; + + // ms_IsRenderHudPause: ポーズメニュー 描画 + static inline bool* ms_IsRenderHudPause; + + // IsTriggerRender + static inline bool* ms_IsTriggerRender; + + // ms_LightFieldDebug: 値をデバッグ表示 + static inline bool* ms_LightFieldDebug; + + // VisualizeLoadedLevel: ミップレベルを視覚化 赤=0, 緑=1, 青=2, 黄=未ロード + static inline bool* ms_VisualizeLoadedLevel; + + static void Init() + { + ms_DrawLightFieldSamplingPoint = (bool*)MmGetHostAddress(0x83367BCE); + ms_IgnoreLightFieldData = (bool*)MmGetHostAddress(0x83367BCF); + ms_IsCollisionRender = (bool*)MmGetHostAddress(0x833678A6); + ms_IsLoading = (bool*)MmGetHostAddress(0x83367A4C); + ms_IsObjectCollisionRender = (bool*)MmGetHostAddress(0x83367905); + ms_IsRenderDebugDraw = (bool*)MmGetHostAddress(0x8328BB23); + ms_IsRenderDebugDrawText = (bool*)MmGetHostAddress(0x8328BB25); + ms_IsRenderDebugPositionDraw = (bool*)MmGetHostAddress(0x8328BB24); + ms_IsRenderGameMainHud = (bool*)MmGetHostAddress(0x8328BB27); + ms_IsRenderHud = (bool*)MmGetHostAddress(0x8328BB26); + ms_IsRenderHudPause = (bool*)MmGetHostAddress(0x8328BB28); + ms_IsTriggerRender = (bool*)MmGetHostAddress(0x83367904); + ms_LightFieldDebug = (bool*)MmGetHostAddress(0x83367BCD); + ms_VisualizeLoadedLevel = (bool*)MmGetHostAddress(0x833678C1); + } + }; +} diff --git a/UnleashedRecomp/app.cpp b/UnleashedRecomp/app.cpp index 710aeea7..5b6c1632 100644 --- a/UnleashedRecomp/app.cpp +++ b/UnleashedRecomp/app.cpp @@ -1,4 +1,5 @@ -#include +#include "app.h" +#include #include #include #include @@ -34,6 +35,8 @@ PPC_FUNC(sub_824EB490) App::s_isInit = true; App::s_isMissingDLC = !Installer::checkAllDLC(GetGamePath()); App::s_language = Config::Language; + + SWA::SGlobals::Init(); Registry::Save(); __imp__sub_824EB490(ctx, base); diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 3be1d37e..c3d7f014 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -3435,7 +3435,7 @@ static RenderPipeline* CreateGraphicsPipelineInRenderThread(PipelineState pipeli pipeline = CreateGraphicsPipeline(pipelineState); #ifdef ASYNC_PSO_DEBUG - bool loading = *reinterpret_cast(g_memory.Translate(0x83367A4C)); + bool loading = *SWA::SGlobals::ms_IsLoading; if (loading) ++g_pipelinesCreatedAsynchronously; @@ -5407,7 +5407,7 @@ static void PipelineCompilerThread() #ifdef _WIN32 int newThreadPriority = threadPriority; - bool loading = *reinterpret_cast(g_memory.Translate(0x83367A4C)); + bool loading = *SWA::SGlobals::ms_IsLoading; if (loading) newThreadPriority = THREAD_PRIORITY_HIGHEST; else @@ -5468,7 +5468,7 @@ static void EnqueueGraphicsPipelineCompilation( if (shouldCompile) { - bool loading = *reinterpret_cast(g_memory.Translate(0x83367A4C)); + bool loading = *SWA::SGlobals::ms_IsLoading; if (!loading && isPrecompiledPipeline) { // We can just compile here during the logos. @@ -5805,7 +5805,7 @@ static void CompileMeshPipeline(const Mesh& mesh, CompilationArgs& args) // We cannot rely on this being accurate during loading as SceneEffect.prm.xml gets loaded a bit later. bool planarReflectionEnabled = *reinterpret_cast(g_memory.Translate(0x832FA0D8)); - bool loading = *reinterpret_cast(g_memory.Translate(0x83367A4C)); + bool loading = *SWA::SGlobals::ms_IsLoading; bool compileNoMsaaPipeline = pipelineState.sampleCount != 1 && (loading || planarReflectionEnabled); auto noMsaaPipeline = pipelineState; diff --git a/UnleashedRecomp/locale/config_locale.cpp b/UnleashedRecomp/locale/config_locale.cpp index 63038fd9..30d7beef 100644 --- a/UnleashedRecomp/locale/config_locale.cpp +++ b/UnleashedRecomp/locale/config_locale.cpp @@ -49,6 +49,52 @@ CONFIG_DEFINE_ENUM_LOCALE(ELanguage) } }; +CONFIG_DEFINE_ENUM_LOCALE(EVoiceLanguage) +{ + { + ELanguage::English, + { + { EVoiceLanguage::English, { "ENGLISH", "" } }, + { EVoiceLanguage::Japanese, { "JAPANESE", "" } } + } + }, + { + ELanguage::Japanese, + { + { EVoiceLanguage::English, { "英語", "" } }, + { EVoiceLanguage::Japanese, { "日本語", "" } } + } + }, + { + ELanguage::German, + { + { EVoiceLanguage::English, { "ENGLISCH", "" } }, + { EVoiceLanguage::Japanese, { "JAPANISCH", "" } } + } + }, + { + ELanguage::French, + { + { EVoiceLanguage::English, { "ANGLAIS", "" } }, + { EVoiceLanguage::Japanese, { "JAPONAIS", "" } } + } + }, + { + ELanguage::Spanish, + { + { EVoiceLanguage::English, { "INGLÉS", "" } }, + { EVoiceLanguage::Japanese, { "JAPONÉS", "" } } + } + }, + { + ELanguage::Italian, + { + { EVoiceLanguage::English, { "INGLESE", "" } }, + { EVoiceLanguage::Japanese, { "GIAPPONESE", "" } } + } + }, +}; + CONFIG_DEFINE_LOCALE(Hints) { { ELanguage::English, { "Hints", "Show hint rings in stages." } } @@ -97,14 +143,25 @@ CONFIG_DEFINE_ENUM_LOCALE(EControllerIcons) } }; -CONFIG_DEFINE_LOCALE(InvertCameraX) +CONFIG_DEFINE_LOCALE(HorizontalCamera) { - { ELanguage::English, { "Invert Camera X", "Toggle between inverted left and right camera movement." } } + { ELanguage::English, { "Horizontal Camera", "Change how the camera moves left and right." } } }; -CONFIG_DEFINE_LOCALE(InvertCameraY) +CONFIG_DEFINE_LOCALE(VerticalCamera) { - { ELanguage::English, { "Invert Camera Y", "Toggle between inverted up and down camera movement." } } + { ELanguage::English, { "Vertical Camera", "Change how the camera moves up and down." } } +}; + +CONFIG_DEFINE_ENUM_LOCALE(ECameraRotationMode) +{ + { + ELanguage::English, + { + { ECameraRotationMode::Normal, { "NORMAL", "" } }, + { ECameraRotationMode::Reverse, { "REVERSE", "" } } + } + } }; CONFIG_DEFINE_LOCALE(Vibration) @@ -158,17 +215,6 @@ CONFIG_DEFINE_LOCALE(VoiceLanguage) { ELanguage::English, { "Voice Language", "Change the language used for character voices." } } }; -CONFIG_DEFINE_ENUM_LOCALE(EVoiceLanguage) -{ - { - ELanguage::English, - { - { EVoiceLanguage::English, { "ENGLISH", "" } }, - { EVoiceLanguage::Japanese, { "日本語", "" } } - } - } -}; - CONFIG_DEFINE_LOCALE(Subtitles) { { ELanguage::English, { "Subtitles", "Show subtitles during dialogue." } } diff --git a/UnleashedRecomp/locale/locale.cpp b/UnleashedRecomp/locale/locale.cpp index c511ae73..26a7819c 100644 --- a/UnleashedRecomp/locale/locale.cpp +++ b/UnleashedRecomp/locale/locale.cpp @@ -177,7 +177,7 @@ std::unordered_map> g_lo { "Installer_Page_SelectGameAndUpdate", { - { ELanguage::English, "Add the sources for your copy of the game and its title update." } + { ELanguage::English, "Add the sources for the game and its title update." } } }, { diff --git a/UnleashedRecomp/patches/CHudPause_patches.cpp b/UnleashedRecomp/patches/CHudPause_patches.cpp index a6481400..45a47f7c 100644 --- a/UnleashedRecomp/patches/CHudPause_patches.cpp +++ b/UnleashedRecomp/patches/CHudPause_patches.cpp @@ -161,9 +161,7 @@ PPC_FUNC(sub_824B0930) { g_achievementMenuIntroTime = 0; - const auto ms_IsRenderHud = (bool*)g_memory.Translate(0x8328BB26); - - if (*ms_IsRenderHud && pHudPause->m_IsShown && !pHudPause->m_Submenu && pHudPause->m_Transition == SWA::eTransitionType_Undefined) + if (*SWA::SGlobals::ms_IsRenderHud && pHudPause->m_IsShown && !pHudPause->m_Submenu && pHudPause->m_Transition == SWA::eTransitionType_Undefined) { ButtonGuide::Open(Button(Localise("Achievements_Name"), EButtonIcon::Back, EButtonAlignment::Left, EFontQuality::Low)); g_isClosed = false; diff --git a/UnleashedRecomp/patches/camera_patches.cpp b/UnleashedRecomp/patches/camera_patches.cpp index 558c6be0..059f5c65 100644 --- a/UnleashedRecomp/patches/camera_patches.cpp +++ b/UnleashedRecomp/patches/camera_patches.cpp @@ -43,8 +43,8 @@ PPC_FUNC(sub_824697B0) { auto pCamera = (SWA::CCamera*)g_memory.Translate(ctx.r3.u32); - pCamera->m_InvertX = Config::InvertCameraX; - pCamera->m_InvertY = Config::InvertCameraY; + pCamera->m_InvertX = Config::HorizontalCamera == ECameraRotationMode::Reverse; + pCamera->m_InvertY = Config::VerticalCamera == ECameraRotationMode::Reverse; __imp__sub_824697B0(ctx, base); } diff --git a/UnleashedRecomp/patches/fps_patches.cpp b/UnleashedRecomp/patches/fps_patches.cpp index aac1be6a..41cc7e00 100644 --- a/UnleashedRecomp/patches/fps_patches.cpp +++ b/UnleashedRecomp/patches/fps_patches.cpp @@ -94,7 +94,7 @@ bool LoadingUpdateMidAsmHook(PPCRegister& r31) g_ppcContext->f1.f64 = deltaTime; g_memory.FindFunction(update)(*g_ppcContext, base); - bool loading = PPC_LOAD_U8(0x83367A4C); + bool loading = *SWA::SGlobals::ms_IsLoading; if (loading) { now = std::chrono::steady_clock::now(); diff --git a/UnleashedRecomp/patches/frontend_listener.cpp b/UnleashedRecomp/patches/frontend_listener.cpp index 9061948a..c66224ac 100644 --- a/UnleashedRecomp/patches/frontend_listener.cpp +++ b/UnleashedRecomp/patches/frontend_listener.cpp @@ -21,12 +21,9 @@ public: if (event->key.keysym.sym != SDLK_F8 || m_isF8KeyDown) break; - // アプリケーション設定 / 開発用 / デバッグ / HUD / 全 HUD 描画 - const auto ms_IsRenderHud = (bool*)g_memory.Translate(0x8328BB26); + *SWA::SGlobals::ms_IsRenderHud = !*SWA::SGlobals::ms_IsRenderHud; - *ms_IsRenderHud = !*ms_IsRenderHud; - - LOGFN("HUD {}", *ms_IsRenderHud ? "ON" : "OFF"); + LOGFN("HUD {}", *SWA::SGlobals::ms_IsRenderHud ? "ON" : "OFF"); m_isF8KeyDown = true; @@ -38,4 +35,5 @@ public: break; } } -} g_frontendlistener; +} +g_frontendListener; diff --git a/UnleashedRecomp/ui/options_menu.cpp b/UnleashedRecomp/ui/options_menu.cpp index 1f701e31..8e6a79b3 100644 --- a/UnleashedRecomp/ui/options_menu.cpp +++ b/UnleashedRecomp/ui/options_menu.cpp @@ -27,6 +27,8 @@ static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_DURATION = 6.0; static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_IN_TIME = MILES_ELECTRIC_SCALE_DURATION - 2.0; static constexpr double MILES_ELECTRIC_FOREGROUND_FADE_OUT_TIME = MILES_ELECTRIC_FOREGROUND_FADE_IN_TIME + MILES_ELECTRIC_FOREGROUND_FADE_DURATION; +static constexpr double VALUE_SLIDER_INTRO_DURATION = 20.0; + static constexpr double CONTAINER_LINE_ANIMATION_DURATION = 8.0; static constexpr double CONTAINER_OUTER_TIME = CONTAINER_LINE_ANIMATION_DURATION + 8.0; // 8 frame delay @@ -70,6 +72,7 @@ static bool g_rightWasHeld; static bool g_downWasHeld; static bool g_lockedOnOption; +static double g_lockedOnTime; static double g_lastTappedTime; static double g_lastIncrementTime; static double g_lastIncrementSoundTime; @@ -589,6 +592,132 @@ static bool DrawCategories() return false; } +static void DrawSelectionArrows(ImVec2 min, ImVec2 max, bool isLeftTapped, bool isRightTapped, bool isSlider) +{ + static constexpr double sizeMotionDuration = 16.0; + + static bool isLeftArrowMotion = false; + static bool isRightArrowMotion = false; + + auto drawList = ImGui::GetForegroundDrawList(); + auto gridSize = Scale(GRID_SIZE); + auto width = gridSize * 2.5f; + auto padding = gridSize; + + auto bgMotion = (isLeftArrowMotion || isRightArrowMotion) + ? ComputeMotion(g_lastTappedTime, 8.0, sizeMotionDuration) + : 0; + + if (isLeftTapped) + { + isLeftArrowMotion = true; + isRightArrowMotion = false; + } + + if (isRightTapped) + { + isLeftArrowMotion = false; + isRightArrowMotion = true; + } + + if (bgMotion >= 1.0 || isSlider) + { + isLeftArrowMotion = false; + isRightArrowMotion = false; + } + + auto getBgColour = [&](bool isAnim) -> ImU32 + { + return IM_COL32(0, 97, 0, Lerp(96, 255, isAnim ? bgMotion : 1)); + }; + + auto bgLeftColour = getBgColour(isLeftArrowMotion); + auto bgRightColour = getBgColour(isRightArrowMotion); + + auto invertMotion = isSlider ? ComputeMotion(g_lockedOnTime, 0, VALUE_SLIDER_INTRO_DURATION) : 0; + auto invertMotionX = invertMotion > 0.5 ? 1.0 : 0.0; // Arrow side point invert animation + + auto xAdd = Hermite(0, Scale(10), sin(invertMotion * M_PI)); // Arrow jump animation + auto y = (min.y + max.y) / 2.0f; + + // Left triangle vertices + auto leftX = Lerp(min.x - padding, min.x - padding - width, invertMotionX) - xAdd; + auto leftV1Y = Hermite(min.y, max.y, invertMotion); + auto leftV2Y = Hermite(max.y, min.y, invertMotion); + auto leftV3X = Hermite(min.x - padding - width, min.x - padding, invertMotionX) - xAdd; + + // Right triangle vertices + auto rightX = Lerp(max.x + padding, max.x + padding + width, invertMotionX) + xAdd; + auto rightV1Y = Hermite(max.y, min.y, invertMotion); + auto rightV2Y = Hermite(min.y, max.y, invertMotion); + auto rightV3X = Hermite(max.x + padding + width, max.x + padding, invertMotionX) + xAdd; + + auto drawLeftArrow = [&](ImU32 col) + { + drawList->AddTriangleFilled({ leftX, leftV1Y }, { leftX, leftV2Y }, { leftV3X, y }, col); + }; + + auto drawRightArrow = [&](ImU32 col) + { + drawList->AddTriangleFilled({ rightX, rightV1Y }, { rightX, rightV2Y }, { rightV3X, y }, col); + }; + + drawLeftArrow(bgLeftColour); + drawRightArrow(bgRightColour); + + // Additive gradient colours + auto c0 = IM_COL32(255, 0, 255, 255); + auto c1 = IM_COL32(255, 128, 255, 255); + + SetAdditive(true); + + // Apply additive gradients + SetGradient({ leftX, leftV1Y }, { leftV3X, y }, c0, c1, c1, c0); + drawLeftArrow(bgLeftColour); + SetGradient({ rightX, rightV1Y }, { rightV3X, y }, c0, c1, c1, c0); + drawRightArrow(bgRightColour); + ResetGradient(); + + if (isSlider) + { + auto col = IM_COL32(0, 97, 0, 255 * invertMotion); + + drawLeftArrow(col); + drawRightArrow(col); + } + else + { + auto fgMotion = ComputeMotion(g_lastTappedTime, 0, sizeMotionDuration); + auto fgMotionSine = sin(fgMotion * M_PI); + auto fgScale = Lerp(0, Scale(4), fgMotionSine); + auto fgColour = IM_COL32(0, 97, 0, 255 * fgMotionSine); + + if (isLeftArrowMotion) + { + drawList->AddTriangleFilled + ( + { min.x - padding, min.y - fgScale }, + { min.x - padding, max.y + fgScale }, + { min.x - padding - width - (fgScale + Scale(2)), (min.y + max.y) / 2.0f }, + fgColour + ); + } + + if (isRightArrowMotion) + { + drawList->AddTriangleFilled + ( + { max.x + padding, max.y + fgScale }, + { max.x + padding, min.y - fgScale }, + { max.x + padding + width + (fgScale + Scale(2)), (min.y + max.y) / 2.0f }, + fgColour + ); + } + } + + SetAdditive(false); +} + template static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* config, bool isAccessible, std::string* inaccessibleReason = nullptr, @@ -601,15 +730,15 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf constexpr float OPTION_NARROW_GRID_COUNT = 36.0f; constexpr float OPTION_WIDE_GRID_COUNT = 54.0f; + constexpr bool IS_SLIDER_TYPE = std::is_same_v || std::is_same_v; + auto isValueSlider = IS_SLIDER_TYPE && isSlider; auto gridSize = Scale(GRID_SIZE); auto optionWidth = gridSize * floor(Lerp(OPTION_NARROW_GRID_COUNT, OPTION_WIDE_GRID_COUNT, g_aspectRatioNarrowScale)); auto optionHeight = gridSize * 5.5f; auto optionPadding = gridSize * 0.5f; auto valueWidth = Scale(192.0f); auto valueHeight = gridSize * 3.0f; - auto triangleWidth = gridSize * 2.5f; - auto trianglePadding = gridSize; // Left side ImVec2 min = { clipRectMin.x, clipRectMin.y + (optionHeight + optionPadding) * rowIndex + yOffset }; @@ -623,6 +752,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf ImVec4 textClipRect = { min.x, min.y, max.x, max.y }; bool lockedOnOption = false; + if (g_selectedRowIndex == rowIndex) { g_selectedItem = config; @@ -657,6 +787,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf if (g_lockedOnOption) { + g_lockedOnTime = ImGui::GetTime(); g_leftWasHeld = false; g_rightWasHeld = false; @@ -725,9 +856,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf auto textColour = IM_COL32(255, 255, 255, 255 * alpha); if (Config::Language == ELanguage::Japanese) - { textPos.y += Scale(10.0f); - } if (g_selectedItem == config) { @@ -788,12 +917,19 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf { if constexpr (std::is_same_v || std::is_same_v) { + if (lockedOnOption) + { + SetAdditive(true); + drawList->AddRectFilled(min, max, IM_COL32(192, 192, 0, 96 * ComputeMotion(g_lockedOnTime, 0, VALUE_SLIDER_INTRO_DURATION))); + SetAdditive(false); + } + // Inner container of slider const uint32_t innerColor0 = IM_COL32(0, 65, 0, 255 * alpha); const uint32_t innerColor1 = IM_COL32(0, 32, 0, 255 * alpha); - float xPadding = Scale(6.0f); - float yPadding = Scale(3.0f); + float xPadding = Scale(6); + float yPadding = Scale(3); drawList->AddRectFilledMultiColor ( @@ -809,8 +945,8 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf const uint32_t sliderColor0 = IM_COL32(57, 241, 0, 255 * alpha); const uint32_t sliderColor1 = IM_COL32(2, 106, 0, 255 * alpha); - xPadding += Scale(1.0f); - yPadding += Scale(1.0f); + xPadding += Scale(2); + yPadding += Scale(2); ImVec2 sliderMin = { min.x + xPadding, min.y + yPadding }; ImVec2 sliderMax = { max.x - xPadding, max.y - yPadding }; @@ -835,26 +971,6 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf // Selection triangles if (lockedOnOption) { - constexpr uint32_t COLOR = IM_COL32(0, 97, 0, 255); - - // Left - drawList->AddTriangleFilled - ( - { min.x - trianglePadding, min.y }, - { min.x - trianglePadding, max.y }, - { min.x - trianglePadding - triangleWidth, (min.y + max.y) / 2.0f }, - COLOR - ); - - // Right - drawList->AddTriangleFilled - ( - { max.x + trianglePadding, max.y }, - { max.x + trianglePadding, min.y }, - { max.x + trianglePadding + triangleWidth, (min.y + max.y) / 2.0f }, - COLOR - ); - bool leftIsHeld = padState.IsDown(SWA::eKeyState_DpadLeft) || padState.LeftStickHorizontal < -0.5f; bool rightIsHeld = padState.IsDown(SWA::eKeyState_DpadRight) || padState.LeftStickHorizontal > 0.5f; @@ -872,6 +988,8 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef* conf g_leftWasHeld = leftIsHeld; g_rightWasHeld = rightIsHeld; + DrawSelectionArrows(min, max, leftTapped, rightTapped, isValueSlider); + if constexpr (std::is_enum_v) { auto it = config->EnumTemplateReverse.find(config->Value); @@ -1058,8 +1176,8 @@ static void DrawConfigOptions() break; case 1: // INPUT - DrawConfigOption(rowCount++, yOffset, &Config::InvertCameraX, true); - DrawConfigOption(rowCount++, yOffset, &Config::InvertCameraY, true); + DrawConfigOption(rowCount++, yOffset, &Config::HorizontalCamera, true); + DrawConfigOption(rowCount++, yOffset, &Config::VerticalCamera, true); DrawConfigOption(rowCount++, yOffset, &Config::Vibration, true); DrawConfigOption(rowCount++, yOffset, &Config::AllowBackgroundInput, true); DrawConfigOption(rowCount++, yOffset, &Config::ControllerIcons, true); @@ -1312,7 +1430,7 @@ static void DrawInfoPanel(ImVec2 infoMin, ImVec2 infoMax) static void SetOptionsMenuVisible(bool isVisible) { OptionsMenu::s_isVisible = isVisible; - *(bool*)g_memory.Translate(0x8328BB26) = !isVisible; + *SWA::SGlobals::ms_IsRenderHud = !isVisible; } static bool DrawMilesElectric() diff --git a/UnleashedRecomp/ui/options_menu_thumbnails.cpp b/UnleashedRecomp/ui/options_menu_thumbnails.cpp index f963dd98..7bae7ce4 100644 --- a/UnleashedRecomp/ui/options_menu_thumbnails.cpp +++ b/UnleashedRecomp/ui/options_menu_thumbnails.cpp @@ -17,8 +17,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -41,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -74,8 +74,8 @@ void LoadThumbnails() g_timeOfDayTransitionThumbnails[ETimeOfDayTransition::Xbox] = LOAD_ZSTD_TEXTURE(g_time_of_day_transition_xbox); g_timeOfDayTransitionThumbnails[ETimeOfDayTransition::PlayStation] = LOAD_ZSTD_TEXTURE(g_time_of_day_transition_playstation); - g_configThumbnails[&Config::InvertCameraX] = LOAD_ZSTD_TEXTURE(g_invert_camera_x); - g_configThumbnails[&Config::InvertCameraY] = LOAD_ZSTD_TEXTURE(g_invert_camera_y); + g_configThumbnails[&Config::HorizontalCamera] = LOAD_ZSTD_TEXTURE(g_horizontal_camera); + g_configThumbnails[&Config::VerticalCamera] = LOAD_ZSTD_TEXTURE(g_vertical_camera); g_configThumbnails[&Config::Vibration] = LOAD_ZSTD_TEXTURE(g_vibration); g_configThumbnails[&Config::AllowBackgroundInput] = LOAD_ZSTD_TEXTURE(g_allow_background_input); g_configThumbnails[&Config::ControllerIcons] = LOAD_ZSTD_TEXTURE(g_controller_icons); diff --git a/UnleashedRecomp/user/config.cpp b/UnleashedRecomp/user/config.cpp index 726f7cc8..4c52b521 100644 --- a/UnleashedRecomp/user/config.cpp +++ b/UnleashedRecomp/user/config.cpp @@ -18,18 +18,18 @@ CONFIG_DEFINE_ENUM_TEMPLATE(ELanguage) { "Italian", ELanguage::Italian } }; -CONFIG_DEFINE_ENUM_TEMPLATE(EUnleashGaugeBehaviour) -{ - { "Original", EUnleashGaugeBehaviour::Original }, - { "Revised", EUnleashGaugeBehaviour::Revised } -}; - CONFIG_DEFINE_ENUM_TEMPLATE(ETimeOfDayTransition) { { "Xbox", ETimeOfDayTransition::Xbox }, { "PlayStation", ETimeOfDayTransition::PlayStation } }; +CONFIG_DEFINE_ENUM_TEMPLATE(ECameraRotationMode) +{ + { "Normal", ECameraRotationMode::Normal }, + { "Reverse", ECameraRotationMode::Reverse }, +}; + CONFIG_DEFINE_ENUM_TEMPLATE(EControllerIcons) { { "Auto", EControllerIcons::Auto }, diff --git a/UnleashedRecomp/user/config.h b/UnleashedRecomp/user/config.h index 1ff6d532..000e17c9 100644 --- a/UnleashedRecomp/user/config.h +++ b/UnleashedRecomp/user/config.h @@ -29,10 +29,10 @@ public: extern std::vector g_configDefinitions; -enum class EUnleashGaugeBehaviour : uint32_t +enum class EVoiceLanguage : uint32_t { - Original, - Revised + English, + Japanese }; enum class ETimeOfDayTransition : uint32_t @@ -41,6 +41,12 @@ enum class ETimeOfDayTransition : uint32_t PlayStation }; +enum class ECameraRotationMode : uint32_t +{ + Normal, + Reverse +}; + enum class EControllerIcons : uint32_t { Auto, @@ -54,12 +60,6 @@ enum class EChannelConfiguration : uint32_t Surround }; -enum class EVoiceLanguage : uint32_t -{ - English, - Japanese -}; - enum class EGraphicsAPI : uint32_t { #ifdef UNLEASHED_RECOMP_D3D12 diff --git a/UnleashedRecomp/user/config_def.h b/UnleashedRecomp/user/config_def.h index 22ebd6ba..dab2e4b5 100644 --- a/UnleashedRecomp/user/config_def.h +++ b/UnleashedRecomp/user/config_def.h @@ -10,8 +10,8 @@ CONFIG_DEFINE_LOCALISED("System", bool, AchievementNotifications, true); CONFIG_DEFINE_ENUM_LOCALISED("System", ETimeOfDayTransition, TimeOfDayTransition, ETimeOfDayTransition::Xbox); CONFIG_DEFINE("System", bool, ShowConsole, false); -CONFIG_DEFINE_LOCALISED("Input", bool, InvertCameraX, false); -CONFIG_DEFINE_LOCALISED("Input", bool, InvertCameraY, false); +CONFIG_DEFINE_ENUM_LOCALISED("Input", ECameraRotationMode, HorizontalCamera, ECameraRotationMode::Normal); +CONFIG_DEFINE_ENUM_LOCALISED("Input", ECameraRotationMode, VerticalCamera, ECameraRotationMode::Normal); CONFIG_DEFINE_LOCALISED("Input", bool, Vibration, true); CONFIG_DEFINE_LOCALISED("Input", bool, AllowBackgroundInput, false); CONFIG_DEFINE_ENUM_LOCALISED("Input", EControllerIcons, ControllerIcons, EControllerIcons::Auto); @@ -81,9 +81,9 @@ CONFIG_DEFINE_HIDDEN("Exports", bool, DisableDLCIcon, false); CONFIG_DEFINE_HIDDEN("Exports", bool, DisableDWMRoundedCorners, false); CONFIG_DEFINE_HIDDEN("Exports", bool, FixUnleashOutOfControlDrain, false); CONFIG_DEFINE_HIDDEN("Exports", bool, HomingAttackOnBoost, true); +CONFIG_DEFINE_HIDDEN("Exports", bool, HUDToggleHotkey, false); CONFIG_DEFINE_HIDDEN("Exports", bool, SaveScoreAtCheckpoints, false); CONFIG_DEFINE_HIDDEN("Exports", bool, SkipIntroLogos, false); CONFIG_DEFINE_HIDDEN("Exports", bool, UseOfficialTitleOnTitleBar, false); -CONFIG_DEFINE_HIDDEN("Exports", bool, HUDToggleHotkey, false); CONFIG_DEFINE("Update", time_t, LastChecked, 0); diff --git a/UnleashedRecompResources b/UnleashedRecompResources index 66a238a2..2d135d17 160000 --- a/UnleashedRecompResources +++ b/UnleashedRecompResources @@ -1 +1 @@ -Subproject commit 66a238a20da25725ea3252949fdab3a94c509e36 +Subproject commit 2d135d175dfbedd84d78fb846bcc7de4a859f8ef