From 64aca784507fdcebd81e216ea3489739550d6a1a Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Fri, 2 Sep 2022 13:19:12 -0400 Subject: [PATCH 1/8] Fixes Switch/Wii U crashes with Wonder Rupees and Bottleable Entities (#1360) * Reorders switch statement to prevent some code that shouldn't execute. * Potentially fixes bottleable entities crash * Solves lack of ItemEntry for GI_MAX * Adds comment clarifying new GetItemEntry --- soh/soh/OTRGlobals.cpp | 3 ++- soh/soh/OTRGlobals.h | 1 - soh/soh/z_play_otr.cpp | 1 - soh/src/code/z_en_item00.c | 10 +++++----- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index cdab324d4..66aa22868 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -289,6 +289,7 @@ extern "C" void VanillaItemTable_Init() { GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, MOD_NONE, GI_BULLET_BAG_50), GET_ITEM_NONE, GET_ITEM_NONE, + GET_ITEM_NONE // GI_MAX - if you need to add to this table insert it before this entry. }; ItemTableManager::Instance->AddItemTable(MOD_NONE); for (uint8_t i = 0; i < ARRAY_COUNT(getItemTable); i++) { @@ -1613,7 +1614,7 @@ extern "C" CustomMessageEntry Randomizer_GetHintFromCheck(RandomizerCheck check) } extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) { - GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(OTRGlobals::Instance->getItemModIndex, getItemID); + GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, getItemID); return giEntry; } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 089394e33..4858c41b2 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -21,7 +21,6 @@ public: std::shared_ptr context; std::shared_ptr gSaveStateMgr; std::shared_ptr gRandomizer; - uint16_t getItemModIndex; OTRGlobals(); ~OTRGlobals(); diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index d0137644c..1a07ceb7e 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -60,7 +60,6 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn) { globalCtx->cUpElfMsgs = nullptr; globalCtx->setupPathList = nullptr; globalCtx->numSetupActors = 0; - OTRGlobals::Instance->getItemModIndex = MOD_NONE; Object_InitBank(globalCtx, &globalCtx->objectCtx); LightContext_Init(globalCtx, &globalCtx->lightCtx); TransitionActor_InitContext(&globalCtx->state, &globalCtx->transiActorCtx); diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 54beafdab..899984b89 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -515,13 +515,13 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) { } if (!Actor_HasParent(&this->actor, globalCtx)) { - if (!gSaveContext.n64ddFlag) { - if (getItemId != GI_NONE) { + if (getItemId != GI_NONE) { + if (!gSaveContext.n64ddFlag) { func_8002F554(&this->actor, globalCtx, getItemId); + } else { + getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } - } else { - getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); - GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } } From 0ce0ab1260dd24ac6168d1cdd28d60f21554cd86 Mon Sep 17 00:00:00 2001 From: David Chavez Date: Sat, 3 Sep 2022 06:00:04 +0200 Subject: [PATCH 2/8] Phase 1: Separate ImGui Drawing From LUS (#1310) * Update LUS imported paths * Introduce GameMenuBar * Fix imports after LUS import paths change * Move Randomizer * Replace needs_save * Migrate Developer Tools * Migrate Cheats * Migrate Enhancements * Separate UIWidgets * Add missing Hooks.cpp file * Migrate Settings * Remove UI methods from LUS * Cleanup imports and exposed properties * Cleanup more methods * Fix project generation * Fix CI compilation * Remove resolved TODO --- libultraship/libultraship/CMakeLists.txt | 1 + libultraship/libultraship/GameOverlay.cpp | 18 +- libultraship/libultraship/ImGuiImpl.cpp | 2119 ++--------------- libultraship/libultraship/ImGuiImpl.h | 87 +- .../include/spdlog/sinks/sohconsole_sink.h | 6 +- libultraship/libultraship/Window.cpp | 2 +- soh/CMakeLists.txt | 14 +- soh/include/global.h | 2 +- soh/include/macros.h | 2 +- soh/include/z64.h | 2 +- soh/include/z64audio.h | 6 +- soh/include/z64effect.h | 2 +- soh/include/z64light.h | 2 +- soh/include/z64transition.h | 2 +- .../controls/GameControlEditor.cpp | 50 +- .../cosmetics/CosmeticsEditor.cpp | 201 +- .../Enhancements/cosmetics/CosmeticsEditor.h | 4 +- soh/soh/Enhancements/debugconsole.cpp | 108 +- .../Enhancements/debugger/ImGuiHelpers.cpp | 22 - soh/soh/Enhancements/debugger/ImGuiHelpers.h | 8 - soh/soh/Enhancements/debugger/actorViewer.cpp | 16 +- soh/soh/Enhancements/debugger/colViewer.cpp | 50 +- .../Enhancements/debugger/debugSaveEditor.cpp | 158 +- soh/soh/Enhancements/gameconsole.h | 4 +- .../randomizer/3drando/entrance.cpp | 2 +- .../Enhancements/randomizer/3drando/fill.cpp | 2 +- .../Enhancements/randomizer/3drando/hints.cpp | 2 +- .../randomizer/3drando/item_location.cpp | 4 +- .../randomizer/3drando/item_pool.cpp | 2 +- .../Enhancements/randomizer/3drando/menu.cpp | 6 +- .../randomizer/3drando/rando_main.cpp | 8 +- .../randomizer/3drando/spoiler_log.cpp | 6 +- .../Enhancements/randomizer/randomizer.cpp | 222 +- .../randomizer/randomizer_item_tracker.cpp | 33 +- soh/soh/Enhancements/savestates.cpp | 14 +- soh/soh/GameMenuBar.cpp | 1367 +++++++++++ soh/soh/GameMenuBar.hpp | 27 + soh/soh/OTRGlobals.cpp | 52 +- soh/soh/OTRGlobals.h | 2 +- soh/soh/SaveManager.cpp | 4 +- soh/soh/SaveManager.h | 2 +- soh/soh/UIWidgets.cpp | 523 ++++ soh/soh/UIWidgets.hpp | 49 + soh/soh/frame_interpolation.cpp | 2 +- soh/soh/z_message_OTR.cpp | 12 +- soh/soh/z_play_otr.cpp | 12 +- soh/soh/z_scene_otr.cpp | 20 +- soh/src/code/audio_playback.c | 2 +- soh/src/code/audio_synthesis.c | 2 +- soh/src/code/code_800F9280.c | 4 +- soh/src/code/z_play.c | 2 +- .../overlays/gamestates/ovl_title/z_title.c | 2 +- 52 files changed, 2719 insertions(+), 2552 deletions(-) delete mode 100644 soh/soh/Enhancements/debugger/ImGuiHelpers.cpp delete mode 100644 soh/soh/Enhancements/debugger/ImGuiHelpers.h create mode 100644 soh/soh/GameMenuBar.cpp create mode 100644 soh/soh/GameMenuBar.hpp create mode 100644 soh/soh/UIWidgets.cpp create mode 100644 soh/soh/UIWidgets.hpp diff --git a/libultraship/libultraship/CMakeLists.txt b/libultraship/libultraship/CMakeLists.txt index aec229bfb..d2b35a1f8 100644 --- a/libultraship/libultraship/CMakeLists.txt +++ b/libultraship/libultraship/CMakeLists.txt @@ -121,6 +121,7 @@ set(Source_Files__CustomImpl source_group("Source Files\\CustomImpl" FILES ${Source_Files__CustomImpl}) set(Source_Files__CustomImpl__Hooks + "Hooks.cpp" "Hooks.h" ) source_group("Source Files\\CustomImpl\\Hooks" FILES ${Source_Files__CustomImpl__Hooks}) diff --git a/libultraship/libultraship/GameOverlay.cpp b/libultraship/libultraship/GameOverlay.cpp index b5225e22e..a331c5cf6 100644 --- a/libultraship/libultraship/GameOverlay.cpp +++ b/libultraship/libultraship/GameOverlay.cpp @@ -16,28 +16,28 @@ namespace Ship { if (CVar_Get(args[2].c_str()) != nullptr) { const char* key = args[2].c_str(); - GameOverlay* overlay = SohImGui::overlay; + GameOverlay* overlay = SohImGui::GetGameOverlay(); if (args[1] == "add") { if (!overlay->RegisteredOverlays.contains(key)) { overlay->RegisteredOverlays[key] = new Overlay({ OverlayType::TEXT, ImStrdup(key), -1.0f }); - SohImGui::console->SendInfoMessage("Added overlay: %s", key); + SohImGui::GetConsole()->SendInfoMessage("Added overlay: %s", key); } else { - SohImGui::console->SendErrorMessage("Overlay already exists: %s", key); + SohImGui::GetConsole()->SendErrorMessage("Overlay already exists: %s", key); } } else if (args[1] == "remove") { if (overlay->RegisteredOverlays.contains(key)) { overlay->RegisteredOverlays.erase(key); - SohImGui::console->SendInfoMessage("Removed overlay: %s", key); + SohImGui::GetConsole()->SendInfoMessage("Removed overlay: %s", key); } else { - SohImGui::console->SendErrorMessage("Overlay not found: %s", key); + SohImGui::GetConsole()->SendErrorMessage("Overlay not found: %s", key); } } } else { - SohImGui::console->SendErrorMessage("CVar {} does not exist", args[2].c_str()); + SohImGui::GetConsole()->SendErrorMessage("CVar {} does not exist", args[2].c_str()); } return CMD_SUCCESS; @@ -124,7 +124,7 @@ namespace Ship { else text_display_end = text_end; - GameOverlay* overlay = SohImGui::overlay; + GameOverlay* overlay = SohImGui::GetGameOverlay(); ImFont* font = overlay->CurrentFont == "Default" ? g.Font : overlay->Fonts[overlay->CurrentFont]; const float font_size = font->FontSize; @@ -157,7 +157,7 @@ namespace Ship { } } - SohImGui::console->AddCommand("overlay", { OverlayCommand, "Draw an overlay using a cvar value" }); + SohImGui::GetConsole()->AddCommand("overlay", { OverlayCommand, "Draw an overlay using a cvar value" }); } void GameOverlay::DrawSettings() { @@ -167,7 +167,7 @@ namespace Ship { if (ImGui::Selectable(name.c_str(), name == this->CurrentFont)) { this->CurrentFont = name; CVar_SetString("gOverlayFont", ImStrdup(name.c_str())); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); } } diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index ed3287a5c..a8901b5a6 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -7,13 +7,6 @@ #include #include -#include -#include -#include -#include -#include -#include "../../soh/include/z64audio.h" -#include "Archive.h" #include "Console.h" #include "Hooks.h" #define IMGUI_DEFINE_MATH_OPERATORS @@ -27,7 +20,6 @@ #include "Lib/stb/stb_image.h" #include "Lib/Fast3D/gfx_rendering_api.h" #include "Lib/spdlog/include/spdlog/common.h" -#include "UltraController.h" #ifdef __WIIU__ #include // GX2SetViewport / GX2SetScissor @@ -69,12 +61,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPAR using namespace Ship; bool oldCursorState = true; -#define EXPERIMENTAL() \ - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ - InsertPadding(3.0f); \ - ImGui::Text("Experimental"); \ - ImGui::PopStyleColor(); \ - PaddedSeparator(false, true); +#define BindButton(btn, status) ImGui::Image(GetTextureByID(DefaultAssets[btn]->textureId), ImVec2(16.0f * scale, 16.0f * scale), ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, (status) ? 255 : 0)); + #define TOGGLE_BTN ImGuiKey_F1 #define TOGGLE_PAD_BTN ImGuiKey_GamepadBack #define HOOK(b) if(b) needs_save = true; @@ -83,21 +71,6 @@ OSContPad* pads; std::map DefaultAssets; std::vector emptyArgs; -bool isBetaQuestEnabled = false; - -enum SeqPlayers { - /* 0 */ SEQ_BGM_MAIN, - /* 1 */ SEQ_FANFARE, - /* 2 */ SEQ_SFX, - /* 3 */ SEQ_BGM_SUB, - /* 4 */ SEQ_MAX -}; - -extern "C" { - void enableBetaQuest() { isBetaQuestEnabled = true; } - void disableBetaQuest() { isBetaQuestEnabled = false; } -} - namespace SohImGui { WindowImpl impl; @@ -106,7 +79,10 @@ namespace SohImGui { GameOverlay* overlay = new GameOverlay; InputEditor* controller = new InputEditor; static ImVector s_GroupPanelLabelStack; - bool p_open = false; + + std::function clientDrawMenu; + std::function clientSetupHooks; + bool needs_save = false; int lastBackendID = 0; bool statsWindowOpen; @@ -132,32 +108,12 @@ namespace SohImGui { #endif }; - - const char* powers[9] = { - "Vanilla (1x)", - "Double (2x)", - "Quadruple (4x)", - "Octuple (8x)", - "Hexadecuple (16x)", - "Duotrigintuple (32x)", - "Quattuorsexagintuple (64x)", - "Octoviginticentuple (128x)", - "Hexaquinquagintiducentuple (256x)" - }; - std::map> hiddenwindowCategories; std::map> windowCategories; std::map customWindows; - void UpdateAudio() { - Audio_SetGameVolume(SEQ_BGM_MAIN, CVar_GetFloat("gMainMusicVolume", 1)); - Audio_SetGameVolume(SEQ_BGM_SUB, CVar_GetFloat("gSubMusicVolume", 1)); - Audio_SetGameVolume(SEQ_FANFARE, CVar_GetFloat("gSFXMusicVolume", 1)); - Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1)); - } - void InitSettings() { - Ship::RegisterHook(UpdateAudio); + clientSetupHooks(); Ship::RegisterHook([] { gfx_get_current_rendering_api()->set_texture_filter((FilteringMode)CVar_GetS32("gTextureFilter", FILTER_THREE_POINT)); if (CVar_GetS32("gConsoleEnabled", 0)) { @@ -171,8 +127,6 @@ namespace SohImGui { } else { controller->Close(); } - - UpdateAudio(); }); } @@ -191,16 +145,6 @@ namespace SohImGui { return 0; } - int ClampFloatToInt(float value, int min, int max) { - return fmin(fmax(value, min), max); - } - - void Tooltip(const char* text) { - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("%s", BreakTooltip(text, 60).c_str()); - } - } - void ImGuiWMInit() { switch (impl.backend) { #ifdef __WIIU__ @@ -352,26 +296,6 @@ namespace SohImGui { } } - void ShowCursor(bool hide, Dialogues d) { - if (d == Dialogues::dLoadSettings) { - Window::GetInstance()->ShowCursor(hide); - return; - } - - if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) { - return; - } - if (!Window::GetInstance()->IsFullscreen()) { - oldCursorState = false; - return; - } - - if (oldCursorState != hide) { - oldCursorState = hide; - Window::GetInstance()->ShowCursor(hide); - } - } - void LoadTexture(const std::string& name, const std::string& path) { GfxRenderingAPI* api = gfx_get_current_rendering_api(); const auto res = Window::GetInstance()->GetResourceManager()->LoadFile(path); @@ -392,65 +316,7 @@ namespace SohImGui { stbi_image_free(img_data); } - void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha) - { - Color_RGBA8 defaultColors; - defaultColors.r = default_colors.x; - defaultColors.g = default_colors.y; - defaultColors.b = default_colors.z; - defaultColors.a = default_colors.w; - - Color_RGBA8 cvarColor = CVar_GetRGBA(cvarname, defaultColors); - - ColorArray.x = cvarColor.r / 255.0; - ColorArray.y = cvarColor.g / 255.0; - ColorArray.z = cvarColor.b / 255.0; - ColorArray.w = cvarColor.a / 255.0; - } - - void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) { - GfxRenderingAPI* api = gfx_get_current_rendering_api(); - const auto res = static_cast(Window::GetInstance()->GetResourceManager()->LoadResource(path).get()); - - std::vector texBuffer; - texBuffer.reserve(res->width * res->height * 4); - - switch (res->texType) { - case Ship::TextureType::RGBA32bpp: - texBuffer.assign(res->imageData, res->imageData + (res->width * res->height * 4)); - break; - case Ship::TextureType::GrayscaleAlpha8bpp: - for (int32_t i = 0; i < res->width * res->height; i++) { - uint8_t ia = res->imageData[i]; - uint8_t color = ((ia >> 4) & 0xF) * 255 / 15; - uint8_t alpha = (ia & 0xF) * 255 / 15; - texBuffer.push_back(color); - texBuffer.push_back(color); - texBuffer.push_back(color); - texBuffer.push_back(alpha); - } - break; - default: - // TODO convert other image types - SPDLOG_WARN("SohImGui::LoadResource: Attempting to load unsupporting image type %s", path.c_str()); - return; - } - - for (size_t pixel = 0; pixel < texBuffer.size() / 4; pixel++) { - texBuffer[pixel * 4 + 0] *= tint.x; - texBuffer[pixel * 4 + 1] *= tint.y; - texBuffer[pixel * 4 + 2] *= tint.z; - texBuffer[pixel * 4 + 3] *= tint.w; - } - - const auto asset = new GameAsset{ api->new_texture() }; - - api->select_texture(0, asset->textureId); - api->set_sampler_parameters(0, false, 0, 0); - api->upload_texture(texBuffer.data(), res->width, res->height); - - DefaultAssets[name] = asset; - } + // MARK: - Public API void Init(WindowImpl window_impl) { CVar_Load(); @@ -549,427 +415,6 @@ namespace SohImGui { ImGuiProcessEvent(event); } -#define BindButton(btn, status) ImGui::Image(GetTextureByID(DefaultAssets[btn]->textureId), ImVec2(16.0f * scale, 16.0f * scale), ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, (status) ? 255 : 0)); - - void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) - { - float value = CVar_GetFloat(key, defaultValue); - - ImGui::Text(name, static_cast(100 * value)); - if (ImGui::SliderFloat((std::string("##") + key).c_str(), &value, 0.0f, 1.0f, "")) { - const float volume = floorf(value * 100) / 100; - CVar_SetFloat(key, volume); - needs_save = true; - Audio_SetGameVolume(playerId, volume); - } - } - - void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue = 0) { - if (FirstTimeValue <= 0) { - FirstTimeValue = 0; - } - uint8_t selected = CVar_GetS32(name, FirstTimeValue); - uint8_t DefaultValue = selected; - std::string comboName = std::string("##") + std::string(name); - if (ImGui::BeginCombo(comboName.c_str(), ComboArray[DefaultValue])) { - for (uint8_t i = 0; i < arraySize; i++) { - if (strlen(ComboArray[i]) > 1) { - if (ImGui::Selectable(ComboArray[i], i == selected)) { - CVar_SetS32(name, i); - selected = i; - needs_save = true; - } - } - } - ImGui::EndCombo(); - } - } - - void EnhancementRadioButton(const char* text, const char* cvarName, int id) { - /*Usage : - EnhancementRadioButton("My Visible Name","gMyCVarName", MyID); - First arg is the visible name of the Radio button - Second is the cvar name where MyID will be saved. - Note: the CVar name should be the same to each Buddies. - Example : - EnhancementRadioButton("English", "gLanguages", 0); - EnhancementRadioButton("German", "gLanguages", 1); - EnhancementRadioButton("French", "gLanguages", 2); - */ - std::string make_invisible = "##"; - make_invisible += text; - make_invisible += cvarName; - - int val = CVar_GetS32(cvarName, 0); - if (ImGui::RadioButton(make_invisible.c_str(), id == val)) { - CVar_SetS32(cvarName, id); - needs_save = true; - } - ImGui::SameLine(); - ImGui::Text("%s", text); - } - - void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) - { - float thickness = ImMax(sz / 5.0f, 1.0f); - sz -= thickness * 0.5f; - pos += ImVec2(thickness * 0.25f, thickness * 0.25f); - - draw_list->PathLineTo(ImVec2(pos.x, pos.y)); - draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y + sz)); - draw_list->PathStroke(col, 0, thickness); - - draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y)); - draw_list->PathLineTo(ImVec2(pos.x, pos.y + sz)); - draw_list->PathStroke(col, 0, thickness); - } - - bool CustomCheckbox(const char* label, bool* v, bool disabled, ImGuiCheckboxGraphics disabledGraphic) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); - - const float square_sz = ImGui::GetFrameHeight(); - const ImVec2 pos = window->DC.CursorPos; - const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); - ImGui::ItemSize(total_bb, style.FramePadding.y); - if (!ImGui::ItemAdd(total_bb, id)) - { - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); - return false; - } - - bool hovered, held; - bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held); - if (pressed) - { - *v = !(*v); - ImGui::MarkItemEdited(id); - } - - const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); - ImGui::RenderNavHighlight(total_bb, id); - ImGui::RenderFrame(check_bb.Min, check_bb.Max, ImGui::GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); - ImU32 check_col = ImGui::GetColorU32(ImGuiCol_CheckMark); - ImU32 cross_col = ImGui::GetColorU32(ImVec4(0.50f, 0.50f, 0.50f, 1.00f)); - bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0; - if (mixed_value) - { - // Undocumented tristate/mixed/indeterminate checkbox (#2644) - // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox) - ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f))); - window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); - } - else if ((!disabled && *v) || (disabled && disabledGraphic == ImGuiCheckboxGraphics::Checkmark)) - { - const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); - } - else if (disabled && disabledGraphic == ImGuiCheckboxGraphics::Cross) { - const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f); - } - - ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); - if (g.LogEnabled) - ImGui::LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); - if (label_size.x > 0.0f) - ImGui::RenderText(label_pos, label); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); - return pressed; - } - - void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, ImGuiCheckboxGraphics disabledGraphic) - { - if (disabled) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); - } - bool val = (bool)CVar_GetS32(cvarName, 0); - if (CustomCheckbox(text, &val, disabled, disabledGraphic)) { - CVar_SetS32(cvarName, val); - needs_save = true; - } - - if (disabled) { - ImGui::PopStyleVar(1); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && disabledTooltipText != "") { - ImGui::SetTooltip("%s", disabledTooltipText); - } - ImGui::PopItemFlag(); - } - } - - void EnhancementButton(const char* text, const char* cvarName) - { - bool val = (bool)CVar_GetS32(cvarName, 0); - if (ImGui::Button(text)) { - CVar_SetS32(cvarName, !val); - CVar_SetS32(cvarName, !val); - needs_save = true; - } - } - - void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton) - { - int val = CVar_GetS32(cvarName, defaultValue); - ImGui::Text(text, val); - if(PlusMinusButton) { - std::string MinusBTNName = " - ##"; - MinusBTNName += cvarName; - if (ImGui::Button(MinusBTNName.c_str())) { - val--; - CVar_SetS32(cvarName, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - } - - if (ImGui::SliderInt(id, &val, min, max, format)) - { - CVar_SetS32(cvarName, val); - needs_save = true; - } - - if(PlusMinusButton) { - std::string PlusBTNName = " + ##"; - PlusBTNName += cvarName; - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNName.c_str())) { - val++; - CVar_SetS32(cvarName, val); - needs_save = true; - } - } - - if (val < min) - { - val = min; - CVar_SetS32(cvarName, val); - needs_save = true; - } - - if (val > max) - { - val = max; - CVar_SetS32(cvarName, val); - needs_save = true; - } - } - - void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton) - { - float val = CVar_GetFloat(cvarName, defaultValue); - - if (!isPercentage) - ImGui::Text(text, val); - else - ImGui::Text(text, static_cast(100 * val)); - - InsertPadding(); - - if(PlusMinusButton) { - std::string MinusBTNName = " - ##"; - MinusBTNName += cvarName; - if (ImGui::Button(MinusBTNName.c_str())) { - if (!isPercentage) - val -= 0.1f; - else - val -= 0.01f; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - } - if (PlusMinusButton) { - #ifdef __WIIU__ - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); - #else - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); - #endif - } - if (ImGui::SliderFloat(id, &val, min, max, format)) - { - CVar_SetFloat(cvarName, val); - needs_save = true; - } - if (PlusMinusButton) { - ImGui::PopItemWidth(); - } - if(PlusMinusButton) { - std::string PlusBTNName = " + ##"; - PlusBTNName += cvarName; - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNName.c_str())) { - if (!isPercentage) - val += 0.1f; - else - val += 0.01f; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - } - - if (val < min) - { - val = min; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - - if (val > max) - { - val = max; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - } - - void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue) { - - if (ImGui::BeginCombo(name.c_str(), items[static_cast(CVar_GetS32(cvarName, defaultValue))].c_str())) { - for (int settingIndex = 0; settingIndex < (int) items.size(); settingIndex++) { - if (ImGui::Selectable(items[settingIndex].c_str())) { - CVar_SetS32(cvarName, settingIndex); - needs_save = true; - - } - } - ImGui::EndCombo(); - } - } - - void RandomizeColor(const char* cvarName, ImVec4* colors) { - Color_RGBA8 NewColors = {0,0,0,255}; - std::string Cvar_RBM = cvarName; - Cvar_RBM += "RBM"; - std::string MakeInvisible = "##"; - MakeInvisible += cvarName; - MakeInvisible += "Random"; - std::string FullName = "Random"; - FullName += MakeInvisible; - if (ImGui::Button(FullName.c_str())) { - s16 RND_R = rand() % (255 - 0); - s16 RND_G = rand() % (255 - 0); - s16 RND_B = rand() % (255 - 0); - colors->x = (float)RND_R / 255; - colors->y = (float)RND_G / 255; - colors->z = (float)RND_B / 255; - NewColors.r = ClampFloatToInt(colors->x * 255, 0, 255); - NewColors.g = ClampFloatToInt(colors->y * 255, 0, 255); - NewColors.b = ClampFloatToInt(colors->z * 255, 0, 255); - CVar_SetRGBA(cvarName, NewColors); - CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. - needs_save = true; - } - Tooltip("Chooses a random color\nOverwrites previously chosen color"); - } - - void RainbowColor(const char* cvarName, ImVec4* colors) { - std::string Cvar_RBM = cvarName; - Cvar_RBM += "RBM"; - std::string MakeInvisible = "Rainbow"; - MakeInvisible += "##"; - MakeInvisible += cvarName; - MakeInvisible += "Rainbow"; - - EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str()); - Tooltip("Cycles through colors on a timer\nOverwrites previously chosen color"); - } - - void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) { - std::string Cvar_RBM = cvarName; - Cvar_RBM += "RBM"; - std::string MakeInvisible = "Reset"; - MakeInvisible += "##"; - MakeInvisible += cvarName; - MakeInvisible += "Reset"; - if (ImGui::Button(MakeInvisible.c_str())) { - colors->x = defaultcolors.x; - colors->y = defaultcolors.y; - colors->z = defaultcolors.z; - if (has_alpha) { colors->w = defaultcolors.w; }; - - Color_RGBA8 colorsRGBA; - colorsRGBA.r = defaultcolors.x; - colorsRGBA.g = defaultcolors.y; - colorsRGBA.b = defaultcolors.z; - if (has_alpha) { colorsRGBA.a = defaultcolors.w; }; - - CVar_SetRGBA(cvarName, colorsRGBA); - CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. - needs_save = true; - } - Tooltip("Revert colors to the game's original colors (GameCube version)\nOverwrites previously chosen color"); - } - - void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) { - LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha); - - ImGuiColorEditFlags flags = ImGuiColorEditFlags_None; - - if (!TitleSameLine) { - ImGui::Text("%s", text); - flags = ImGuiColorEditFlags_NoLabel; - } - - ImGui::PushID(cvarName); - - if (!has_alpha) { - if (ImGui::ColorEdit3(text, (float*)&ColorRGBA, flags)) - { - Color_RGBA8 colors; - colors.r = ColorRGBA.x * 255.0; - colors.g = ColorRGBA.y * 255.0; - colors.b = ColorRGBA.z * 255.0; - colors.a = ColorRGBA.w * 255.0; - - CVar_SetRGBA(cvarName, colors); - needs_save = true; - } - } - else - { - if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags)) - { - Color_RGBA8 colors; - colors.r = ColorRGBA.x / 255; - colors.g = ColorRGBA.y / 255; - colors.b = ColorRGBA.z / 255; - colors.a = ColorRGBA.w / 255; - - CVar_SetRGBA(cvarName, colors); - needs_save = true; - } - } - - ImGui::PopID(); - - //ImGui::SameLine(); // Removing that one to gain some width spacing on the HUD editor - ImGui::PushItemWidth(-FLT_MIN); - ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha); - ImGui::SameLine(); - RandomizeColor(cvarName, &ColorRGBA); - if (allow_rainbow) { - if (ImGui::GetContentRegionAvail().x > 185) { - ImGui::SameLine(); - } - RainbowColor(cvarName, &ColorRGBA); - } - ImGui::NewLine(); - ImGui::PopItemWidth(); - } - void DrawMainMenuAndCalculateGameSize(void) { console->Update(); ImGuiBackendNewFrame(); @@ -1028,13 +473,13 @@ namespace SohImGui { if ((ImGui::IsKeyDown(ImGuiKey_LeftSuper) || ImGui::IsKeyDown(ImGuiKey_RightSuper)) && ImGui::IsKeyPressed(ImGuiKey_R, false)) { - console->Dispatch("reset"); + DispatchConsoleCommand("reset"); } #else if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && ImGui::IsKeyPressed(ImGuiKey_R, false)) { - console->Dispatch("reset"); + DispatchConsoleCommand("reset"); } #endif @@ -1074,921 +519,7 @@ namespace SohImGui { ImGui::SetCursorPosY(0.0f); - if (ImGui::BeginMenu("Settings")) - { - if (ImGui::BeginMenu("Audio")) { - EnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true); - InsertPadding(); - BindAudioSlider("Main Music Volume: %d %%", "gMainMusicVolume", 1.0f, SEQ_BGM_MAIN); - InsertPadding(); - BindAudioSlider("Sub Music Volume: %d %%", "gSubMusicVolume", 1.0f, SEQ_BGM_SUB); - InsertPadding(); - BindAudioSlider("Sound Effects Volume: %d %%", "gSFXMusicVolume", 1.0f, SEQ_SFX); - InsertPadding(); - BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", 1.0f, SEQ_FANFARE); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Controller")) { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2 (12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - if (ImGui::Button(GetWindowButtonText("Controller Configuration", CVar_GetS32("gControllerConfigurationEnabled", 0)).c_str())) - { - bool currentValue = CVar_GetS32("gControllerConfigurationEnabled", 0); - CVar_SetS32("gControllerConfigurationEnabled", !currentValue); - needs_save = true; - if (CVar_GetS32("gControllerConfigurationEnabled", 0)) { - controller->Open(); - } else { - controller->Close(); - } - } - ImGui::PopStyleColor(1); - ImGui::PopStyleVar(3); - #ifndef __SWITCH__ - PaddedEnhancementCheckbox("Use Controller Navigation", "gControlNav", true, false); - Tooltip("Allows controller navigation of the menu bar\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); - #endif - PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false); - Tooltip("Shows currently pressed inputs on the bottom right of the screen"); - InsertPadding(); - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 20.0f); - EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false); - Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); - ImGui::PopItemWidth(); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Graphics")) { - #ifndef __APPLE__ - EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true); - Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing"); - gfx_current_dimensions.internal_mul = CVar_GetFloat("gInternalResolution", 1); - #endif - #ifndef __WIIU__ - PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, false, true, false); - Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); - gfx_msaa_level = CVar_GetS32("gMSAAValue", 1); - #endif - - if (impl.backend == Backend::DX11) - { - const char* cvar = "gExtraLatencyThreshold"; - int val = CVar_GetS32(cvar, 80); - val = MAX(MIN(val, 360), 0); - int fps = val; - - InsertPadding(); - - if (fps == 0) - { - ImGui::Text("Jitter fix: Off"); - } - else - { - ImGui::Text("Jitter fix: >= %d FPS", fps); - } - - std::string MinusBTNELT = " - ##ExtraLatencyThreshold"; - std::string PlusBTNELT = " + ##ExtraLatencyThreshold"; - if (ImGui::Button(MinusBTNELT.c_str())) { - val--; - CVar_SetS32(cvar, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); - if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 360, "", ImGuiSliderFlags_AlwaysClamp)) - { - CVar_SetS32(cvar, val); - needs_save = true; - } - ImGui::PopItemWidth(); - Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to work on one frame while GPU works on the previous frame.\nThis setting should be used when your computer is too slow to do CPU + GPU work in time."); - - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNELT.c_str())) { - val++; - CVar_SetS32(cvar, val); - needs_save = true; - } - - InsertPadding(); - } - - ImGui::Text("Renderer API (Needs reload)"); - if (ImGui::BeginCombo("##RApi", backends[lastBackendID].second)) { - for (uint8_t i = 0; i < sizeof(backends) / sizeof(backends[0]); i++) { - if (ImGui::Selectable(backends[i].second, i == lastBackendID)) { - pConf->setString("Window.GfxBackend", backends[i].first); - lastBackendID = i; - } - } - ImGui::EndCombo(); - } - - EXPERIMENTAL(); - - ImGui::Text("Texture Filter (Needs reload)"); - EnhancementCombobox("gTextureFilter", filters, 3, 0); - - InsertPadding(); - - overlay->DrawSettings(); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Languages")) { - EnhancementRadioButton("English", "gLanguages", 0); - EnhancementRadioButton("German", "gLanguages", 1); - EnhancementRadioButton("French", "gLanguages", 2); - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Enhancements")) - { - - const char* enhancementPresets[4] = { "Default", "Vanilla Plus", "Enhanced", "Randomizer"}; - PaddedText("Enhancement Presets", false, true); - SohImGui::EnhancementCombobox("gSelectEnhancementPresets", enhancementPresets, 4, 0); - Tooltip( - "Default - Set all enhancements to their default values. The true vanilla SoH experience.\n" - "\n" - "Vanilla Plus - Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.\n" - "\n" - "Enhanced - The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.\n" - "\n" - "Randomizer - The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer." - ); - - InsertPadding(); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); - if (ImGui::Button("Apply Preset")) { - applyEnhancementPresets(); - needs_save = true; - } - ImGui::PopStyleVar(1); - - PaddedSeparator(); - - if (ImGui::BeginMenu("Controls")) { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - float availableWidth = ImGui::GetContentRegionAvail().x; - if (ImGui::Button( - GetWindowButtonText("Customize Game Controls", CVar_GetS32("gGameControlEditorEnabled", 0)).c_str(), - ImVec2(availableWidth, 0) - )) { - bool currentValue = CVar_GetS32("gGameControlEditorEnabled", 0); - CVar_SetS32("gGameControlEditorEnabled", !currentValue); - needs_save = true; - customWindows["Game Control Editor"].enabled = CVar_GetS32("gGameControlEditorEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - // TODO mutual exclusions -- There should be some system to prevent conclifting enhancements from being selected - PaddedEnhancementCheckbox("D-pad Support on Pause and File Select", "gDpadPauseName"); - Tooltip("Enables Pause and File Select screen navigation with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate"); - PaddedEnhancementCheckbox("D-pad Support in Text Choice", "gDpadText", true, false); - PaddedEnhancementCheckbox("D-pad Support for Browsing Shop Items", "gDpadShop", true, false); - PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips", true, false); - Tooltip("Allows the D-pad to be used as extra C buttons"); - PaddedEnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor", true, false); - Tooltip("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97"); - PaddedEnhancementCheckbox("Prevent Dropped Ocarina Inputs", "gDpadNoDropOcarinaInput", true, false); - Tooltip("Prevent dropping inputs when playing the ocarina quickly"); - PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL", true, false); - Tooltip("Speak to Navi with L but enter first-person camera with C-Up"); - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Gameplay")) - { - if (ImGui::BeginMenu("Time Savers")) - { - PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, false, false, true); - PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, false, false, true); - EnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3); - Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); - PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, false, false, true); - PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, false, false, true); - PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", true, false); - Tooltip("Speeds up lifting silver rocks and obelisks"); - PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); - Tooltip("Prevent forced Navi conversations"); - PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); - Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); - PaddedEnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood", true, false); - Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); - PaddedEnhancementCheckbox("Fast Chests", "gFastChests", true, false); - Tooltip("Kick open every chest"); - PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); - Tooltip("Skip pickup messages for new consumable items and bottle swipes"); - PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); - Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); - PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); - Tooltip("Skip the part where the Ocarina playback is called when you play a song"); - PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false); - Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); - PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); - Tooltip("Allow Link to put items away without having to wait around"); - PaddedEnhancementCheckbox("Instant Boomerang Recall", "gFastBoomerang", true, false); - Tooltip("Instantly return the boomerang to Link by pressing its item button while it's in the air"); - PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false); - Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); - PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); - Tooltip("When loading a save, places Link at the last entrance he went through.\n" - "This doesn't work if the save was made in a grotto."); - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Difficulty Options")) - { - ImGui::Text("Damage Multiplier"); - EnhancementCombobox("gDamageMul", powers, 9, 0); - Tooltip( - "Modifies all sources of damage not affected by other sliders\n\ - 2x: Can survive all common attacks from the start of the game\n\ - 4x: Dies in 1 hit to any substantial attack from the start of the game\n\ - 8x: Can only survive trivial damage from the start of the game\n\ - 16x: Can survive all common attacks with max health without double defense\n\ - 32x: Can survive all common attacks with max health and double defense\n\ - 64x: Can survive trivial damage with max health without double defense\n\ - 128x: Can survive trivial damage with max health and double defense\n\ - 256x: Cannot survive damage" - ); - PaddedText("Fall Damage Multiplier", true, false); - EnhancementCombobox("gFallDamageMul", powers, 8, 0); - Tooltip( - "Modifies all fall damage\n\ - 2x: Can survive all fall damage from the start of the game\n\ - 4x: Can only survive short fall damage from the start of the game\n\ - 8x: Cannot survive any fall damage from the start of the game\n\ - 16x: Can survive all fall damage with max health without double defense\n\ - 32x: Can survive all fall damage with max health and double defense\n\ - 64x: Can survive short fall damage with double defense\n\ - 128x: Cannot survive fall damage" - ); - PaddedText("Void Damage Multiplier", true, false); - EnhancementCombobox("gVoidDamageMul", powers, 7, 0); - Tooltip( - "Modifies damage taken after falling into a void\n\ - 2x: Can survive void damage from the start of the game\n\ - 4x: Cannot survive void damage from the start of the game\n\ - 8x: Can survive void damage twice with max health without double defense\n\ - 16x: Can survive void damage with max health without double defense\n\ - 32x: Can survive void damage with max health and double defense\n\ - 64x: Cannot survive void damage" - ); - PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); - Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); - PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false); - Tooltip("Bombchus will sometimes drop in place of bombs"); - PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); - Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); - PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); - Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); - InsertPadding(); - - if (ImGui::BeginMenu("Potion Values")) - { - EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect"); - Tooltip("Enable the following changes to the amount of health restored by Red Potions"); - EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Red Potions"); - EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore"); - Tooltip("Toggles from Red Potions restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Green Potion Effect", "gGreenPotionEffect"); - Tooltip("Enable the following changes to the amount of mana restored by Green Potions"); - EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true); - Tooltip("Changes the amount of mana restored by Green Potions, base max mana is 48, max upgraded mana is 96"); - EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore"); - Tooltip("Toggles from Green Potions restoring a fixed amount of mana to a percent of the player's current max mana"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Blue Potion Effects", "gBluePotionEffects"); - Tooltip("Enable the following changes to the amount of health and mana restored by Blue Potions"); - EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Blue Potions"); - EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore"); - Tooltip("Toggles from Blue Potions restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true); - Tooltip("Changes the amount of mana restored by Blue Potions, base max mana is 48, max upgraded mana is 96"); - EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore"); - Tooltip("Toggles from Blue Potions restoring a fixed amount of mana to a percent of the player's current max mana"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Milk Effect", "gMilkEffect"); - Tooltip("Enable the following changes to the amount of health restored by Milk"); - EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Milk"); - EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore"); - Tooltip("Toggles from Milk restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect"); - Tooltip("Enable the following changes to the amount of health restored by Half Milk\nIf this is disabled, Half Milk will behave the same as Full Milk."); - EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Half Milk"); - EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore"); - Tooltip("Toggles from Half Milk restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Fairy Effect", "gFairyEffect"); - Tooltip("Enable the following changes to the amount of health restored by Fairies"); - EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Fairies"); - EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore"); - Tooltip("Toggles from Fairies restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Fairy Revive Effect", "gFairyReviveEffect"); - Tooltip("Enable the following changes to the amount of health restored by Fairy Revivals"); - EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Fairy Revivals"); - EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore"); - Tooltip("Toggles from Fairy Revivals restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Fishing")) { - EnhancementCheckbox("Instant Fishing", "gInstantFishing"); - Tooltip("All fish will be caught instantly"); - PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false); - Tooltip("When a line is stable, guarantee bite. Otherwise use default logic"); - PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 6, 10, "", 10, false, true, false); - Tooltip("The minimum weight for the unique fishing reward as a child"); - PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 8, 13, "", 13, false, true, false); - Tooltip("The minimum weight for the unique fishing reward as an adult"); - ImGui::EndMenu(); - } - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Reduced Clutter")) - { - EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); - Tooltip("Disable the low HP beeping sound"); - PaddedEnhancementCheckbox("Minimal UI", "gMinimalUI", true, false); - Tooltip("Hides most of the UI when not needed\nNote: Doesn't activate until after loading a new scene"); - PaddedEnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio", true, false); - Tooltip("Disables the voice audio when Navi calls you"); - - ImGui::EndMenu(); - } - - InsertPadding(); - - EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); - Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); - PaddedEnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots", true, false); - Tooltip("Allows equipping the tunic and boots to c-buttons"); - PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false); - Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); - PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime", true, false); - Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); - PaddedEnhancementCheckbox("Enable visible guard vision", "gGuardVision", true, false); - PaddedEnhancementCheckbox("Enable passage of time on file select", "gTimeFlowFileSelect", true, false); - PaddedEnhancementCheckbox("Count Golden Skulltulas", "gInjectSkulltulaCount", true, false); - Tooltip("Injects Golden Skulltula total count in pickup messages"); - PaddedEnhancementCheckbox("Pull grave during the day", "gDayGravePull", true, false); - Tooltip("Allows graves to be pulled when child during the day"); - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Graphics")) - { - if (ImGui::BeginMenu("Animated Link in Pause Menu")) { - ImGui::Text("Rotation"); - EnhancementRadioButton("Disabled", "gPauseLiveLinkRotation", 0); - EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveLinkRotation", 1); - Tooltip("Allow you to rotate Link on the Equipment menu with the D-pad\nUse D-pad Up or D-pad Down to reset Link's rotation"); - EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveLinkRotation", 2); - Tooltip("Allow you to rotate Link on the Equipment menu with the C-buttons\nUse C-Up or C-Down to reset Link's rotation"); - EnhancementRadioButton("Rotate Link with Right Stick", "gPauseLiveLinkRotation", 3); - Tooltip("Allow you to rotate Link on the Equipment menu with the Right Stick\nYou can zoom in by pointing up and reset Link's rotation by pointing down"); - if (CVar_GetS32("gPauseLiveLinkRotation", 0) != 0) { - EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", "gPauseLiveLinkRotationSpeed", 1, 20, ""); - } - PaddedSeparator(); - ImGui::Text("Static loop"); - EnhancementRadioButton("Disabled", "gPauseLiveLink", 0); - EnhancementRadioButton("Idle (standing)", "gPauseLiveLink", 1); - EnhancementRadioButton("Idle (look around)", "gPauseLiveLink", 2); - EnhancementRadioButton("Idle (belt)", "gPauseLiveLink", 3); - EnhancementRadioButton("Idle (shield)", "gPauseLiveLink", 4); - EnhancementRadioButton("Idle (test sword)", "gPauseLiveLink", 5); - EnhancementRadioButton("Idle (yawn)", "gPauseLiveLink", 6); - EnhancementRadioButton("Battle Stance", "gPauseLiveLink", 7); - EnhancementRadioButton("Walking (no shield)", "gPauseLiveLink", 8); - EnhancementRadioButton("Walking (holding shield)", "gPauseLiveLink", 9); - EnhancementRadioButton("Running (no shield)", "gPauseLiveLink", 10); - EnhancementRadioButton("Running (holding shield)", "gPauseLiveLink", 11); - EnhancementRadioButton("Hand on hip", "gPauseLiveLink", 12); - EnhancementRadioButton("Spin attack charge", "gPauseLiveLink", 13); - EnhancementRadioButton("Look at hand", "gPauseLiveLink", 14); - PaddedSeparator(); - ImGui::Text("Randomize"); - EnhancementRadioButton("Random", "gPauseLiveLink", 15); - Tooltip("Randomize the animation played each time you open the menu"); - EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16); - Tooltip("Randomize the animation played on the menu after a certain time"); - EnhancementRadioButton("Random cycle (Idle)", "gPauseLiveLink", 17); - Tooltip("Randomize the animation played on the menu after a certain time (Idle animations only)"); - if (CVar_GetS32("gPauseLiveLink", 0) >= 16) { - EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, "", 0, true); - } - - ImGui::EndMenu(); - } - PaddedEnhancementCheckbox("N64 Mode", "gN64Mode", true, false); - Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); - PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops", true, false); - Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); - PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars", true, false); - Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); - PaddedEnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon", true, false); - Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); - PaddedEnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon", true, false); - Tooltip("Always shows dungeon entrance icons on the minimap"); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Fixes")) - { - EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); - Tooltip("Makes the L and R buttons in the pause menu the same color"); - PaddedEnhancementCheckbox("Fix L&Z Page switch in Pause menu", "gNGCKaleidoSwitcher", true, false); - Tooltip("Makes L and R switch pages like on the GameCube\nZ opens the Debug Menu instead"); - PaddedEnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon", true, false); - Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); - PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); - Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); - PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); - Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); - PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); - Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); - PaddedEnhancementCheckbox("Fix Navi text HUD position", "gNaviTextFix", true, false); - Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); - PaddedEnhancementCheckbox("Fix Anubis fireballs", "gAnubisFix", true, false); - Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); - PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", "gCrouchStabHammerFix", true, false); - Tooltip("Make the Megaton Hammer's crouch stab able to destroy rocks without first swinging it normally"); - if (CVar_GetS32("gCrouchStabHammerFix", 0) == 0) { - CVar_SetS32("gCrouchStabFix", 0); - } else { - PaddedEnhancementCheckbox("Remove power crouch stab", "gCrouchStabFix", true, false); - Tooltip("Make crouch stabbing always do the same damage as a regular slash"); - } - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Restoration")) - { - EnhancementCheckbox("Red Ganon blood", "gRedGanonBlood"); - Tooltip("Restore the original red blood from NTSC 1.0/1.1. Disable for green blood"); - PaddedEnhancementCheckbox("Fish while hovering", "gHoverFishing", true, false); - Tooltip("Restore a bug from NTSC 1.0 that allows casting the Fishing Rod while using the Hover Boots"); - PaddedEnhancementCheckbox("N64 Weird Frames", "gN64WeirdFrames", true, false); - Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64"); - PaddedEnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB", true, false); - Tooltip("Allows bombchus to explode out of bounds\nSimilar to GameCube and Wii VC"); - PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", "gGsCutscene", true, false); - - ImGui::EndMenu(); - } - - PaddedEnhancementCheckbox("Autosave", "gAutosave", true, false); - Tooltip("Automatically save the game every time a new area is entered or item is obtained\n" - "To disable saving when obtaining an item, manually set gAutosaveAllItems and gAutosaveMajorItems to 0\n" - "gAutosaveAllItems takes priority over gAutosaveMajorItems if both are set to 1\n" - "gAutosaveMajorItems excludes rupees and health/magic/ammo refills (but includes bombchus)"); - - InsertPadding(); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - static ImVec2 buttonSize(200.0f, 0.0f); - if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gCosmeticsEditorEnabled", 0); - CVar_SetS32("gCosmeticsEditorEnabled", !currentValue); - needs_save = true; - customWindows["Cosmetics Editor"].enabled = CVar_GetS32("gCosmeticsEditorEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - EXPERIMENTAL(); - - const char* fps_cvar = "gInterpolationFPS"; - { - #if defined(__SWITCH__) || defined(__WIIU__) - int minFps = 20; - int maxFps = 60; - #else - int minFps = 20; - int maxFps = 360; - #endif - - int val = CVar_GetS32(fps_cvar, minFps); - val = MAX(MIN(val, maxFps), 20); - - #ifdef __WIIU__ - // only support divisors of 60 on the Wii U - val = 60 / (60 / val); - #endif - - int fps = val; - - if (fps == 20) - { - ImGui::Text("Frame interpolation: Off"); - } - else - { - ImGui::Text("Frame interpolation: %d FPS", fps); - } - - std::string MinusBTNFPSI = " - ##FPSInterpolation"; - std::string PlusBTNFPSI = " + ##FPSInterpolation"; - if (ImGui::Button(MinusBTNFPSI.c_str())) { - #ifdef __WIIU__ - if (val >= 60) val = 30; - else val = 20; - #else - val--; - #endif - CVar_SetS32(fps_cvar, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - #ifdef __WIIU__ - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); - #else - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); - #endif - if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp)) - { - #ifdef __WIIU__ - // only support divisors of 60 on the Wii U - val = 60 / (60 / val); - #endif - if (val > 360) - { - val = 360; - } - else if (val < 20) - { - val = 20; - } - - CVar_SetS32(fps_cvar, val); - needs_save = true; - } - ImGui::PopItemWidth(); - Tooltip("Interpolate extra frames to get smoother graphics\n" - "Set to match your monitor's refresh rate, or a divisor of it\n" - "A higher target FPS than your monitor's refresh rate will just waste resources, " - "and might give a worse result.\n" - "For consistent input lag, set this value and your monitor's refresh rate to a multiple of 20\n" - "Ctrl+Click for keyboard input"); - - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNFPSI.c_str())) { - #ifdef __WIIU__ - if (val <= 20) val = 30; - else val = 60; - #else - val++; - #endif - CVar_SetS32(fps_cvar, val); - needs_save = true; - } - } - - if (impl.backend == Backend::DX11) - { - InsertPadding(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); - if (ImGui::Button("Match Refresh Rate")) - { - int hz = roundf(gfx_get_detected_hz()); - if (hz >= 20 && hz <= 360) - { - CVar_SetS32(fps_cvar, hz); - needs_save = true; - } - } - ImGui::PopStyleVar(1); - InsertPadding(); - } - EnhancementCheckbox("Disable LOD", "gDisableLOD"); - Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); - PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false); - Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); - if (CVar_GetS32("gDisableDrawDistance", 0) == 0) { - CVar_SetS32("gDisableKokiriDrawDistance", 0); - } else if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { - PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); - Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); - } - PaddedEnhancementCheckbox("Skip Text", "gSkipText", true, false); - Tooltip("Holding down B skips text\nKnown to cause a cutscene softlock in Water Temple\nSoftlock can be fixed by pressing D-Right in Debug mode"); - PaddedEnhancementCheckbox("Free Camera", "gFreeCamera", true, false); - Tooltip("Enables camera control\nNote: You must remap C buttons off of the right stick in the controller config menu, and map the camera stick to the right stick."); - - #ifdef __SWITCH__ - InsertPadding(); - int slot = CVar_GetS32("gSwitchPerfMode", (int)SwitchProfiles::STOCK); - ImGui::Text("Switch performance mode"); - if (ImGui::BeginCombo("##perf", SWITCH_CPU_PROFILES[slot])) { - for (int sId = 0; sId <= SwitchProfiles::POWERSAVINGM3; sId++) { - if (ImGui::Selectable(SWITCH_CPU_PROFILES[sId], sId == slot)) { - SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]); - CVar_SetS32("gSwitchPerfMode", sId); - Switch::ApplyOverclock(); - needs_save = true; - } - - } - ImGui::EndCombo(); - } - #endif - - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Cheats")) - { - if (ImGui::BeginMenu("Infinite...")) { - EnhancementCheckbox("Money", "gInfiniteMoney"); - PaddedEnhancementCheckbox("Health", "gInfiniteHealth", true, false); - PaddedEnhancementCheckbox("Ammo", "gInfiniteAmmo", true, false); - PaddedEnhancementCheckbox("Magic", "gInfiniteMagic", true, false); - PaddedEnhancementCheckbox("Nayru's Love", "gInfiniteNayru", true, false); - PaddedEnhancementCheckbox("Epona Boost", "gInfiniteEpona", true, false); - - ImGui::EndMenu(); - } - - PaddedEnhancementCheckbox("No Clip", "gNoClip", true, false); - Tooltip("Allows you to walk through walls"); - PaddedEnhancementCheckbox("Climb Everything", "gClimbEverything", true, false); - Tooltip("Makes every surface in the game climbable"); - PaddedEnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL", true, false); - Tooltip("Holding L makes you float into the air"); - PaddedEnhancementCheckbox("Super Tunic", "gSuperTunic", true, false); - Tooltip("Makes every tunic have the effects of every other tunic"); - PaddedEnhancementCheckbox("Easy ISG", "gEzISG", true, false); - Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); - PaddedEnhancementCheckbox("Unrestricted Items", "gNoRestrictItems", true, false); - Tooltip("Allows you to use any item at any location"); - PaddedEnhancementCheckbox("Freeze Time", "gFreezeTime", true, false); - Tooltip("Freezes the time of day"); - PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); - Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); - PaddedEnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield", true, false); - Tooltip("Prevents the Deku Shield from burning on contact with fire"); - PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded", true, false); - Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); - PaddedEnhancementCheckbox("Time Sync", "gTimeSync", true, false); - Tooltip("This syncs the ingame time with the real world time"); - - { - static int32_t betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); - static int32_t lastBetaQuestEnabled = betaQuestEnabled; - static int32_t betaQuestWorld = CVar_GetS32("gBetaQuestWorld", 0xFFEF); - static int32_t lastBetaQuestWorld = betaQuestWorld; - - if (!isBetaQuestEnabled) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); - } - - PaddedEnhancementCheckbox("Enable Beta Quest", "gEnableBetaQuest", true, false); - Tooltip("Turns on OoT Beta Quest. *WARNING* This will reset your game."); - betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); - if (betaQuestEnabled) { - if (betaQuestEnabled != lastBetaQuestEnabled) { - betaQuestWorld = 0; - } - - ImGui::Text("Beta Quest World: %d", betaQuestWorld); - - if (ImGui::Button(" - ##BetaQuest")) { - betaQuestWorld--; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - - ImGui::SliderInt("##BetaQuest", &betaQuestWorld, 0, 8, "", ImGuiSliderFlags_AlwaysClamp); - Tooltip("Set the Beta Quest world to explore. *WARNING* Changing this will reset your game.\nCtrl+Click to type in a value."); - - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(" + ##BetaQuest")) { - betaQuestWorld++; - } - - if (betaQuestWorld > 8) { - betaQuestWorld = 8; - } - else if (betaQuestWorld < 0) { - betaQuestWorld = 0; - } - } - else { - lastBetaQuestWorld = betaQuestWorld = 0xFFEF; - CVar_SetS32("gBetaQuestWorld", betaQuestWorld); - } - if (betaQuestEnabled != lastBetaQuestEnabled || betaQuestWorld != lastBetaQuestWorld) - { - // Reset the game if the beta quest state or world changed because beta quest happens on redirecting the title screen cutscene. - lastBetaQuestEnabled = betaQuestEnabled; - lastBetaQuestWorld = betaQuestWorld; - CVar_SetS32("gEnableBetaQuest", betaQuestEnabled); - CVar_SetS32("gBetaQuestWorld", betaQuestWorld); - - console->Dispatch("reset"); - - needs_save = true; - } - - if (!isBetaQuestEnabled) { - ImGui::PopItemFlag(); - ImGui::PopStyleVar(1); - } - } - - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Developer Tools")) - { - EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); - Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); - PaddedEnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled", true, false); - Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); - PaddedEnhancementCheckbox("Fast File Select", "gSkipLogoTitle", true, false); - Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); - if (CVar_GetS32("gSkipLogoTitle", 0)) { - const char* FastFileSelect[5] = { - "File N.1", - "File N.2", - "File N.3", - "File select", - "Zelda Map Select (require OoT Debug Mode)" - }; - ImGui::Text("Loading :"); - EnhancementCombobox("gSaveFileID", FastFileSelect, 5, 0); - PaddedEnhancementCheckbox("Create a new save if none", "gCreateNewSave", true, false); - Tooltip("Enable the creation of a new save file if none exist in the File number selected\nNo file name will be assigned please do in Save editor once you see the first text else your save file name will be named \"00000000\"\nIf disabled you will fall back in File select menu"); - }; - PaddedSeparator(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0,0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - static ImVec2 buttonSize(160.0f, 0.0f); - if (ImGui::Button(GetWindowButtonText("Stats", CVar_GetS32("gStatsEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gStatsEnabled", 0); - CVar_SetS32("gStatsEnabled", !currentValue); - statsWindowOpen = true; - needs_save = true; - } - Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Console", CVar_GetS32("gConsoleEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gConsoleEnabled", 0); - CVar_SetS32("gConsoleEnabled", !currentValue); - needs_save = true; - if(CVar_GetS32("gConsoleEnabled", 0)){ - console->Open(); - } else { - console->Close(); - } - } - Tooltip("Enables the console window, allowing you to input commands, type help for some examples"); - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Save Editor", CVar_GetS32("gSaveEditorEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gSaveEditorEnabled", 0); - CVar_SetS32("gSaveEditorEnabled", !currentValue); - needs_save = true; - customWindows["Save Editor"].enabled = CVar_GetS32("gSaveEditorEnabled", 0); - } - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVar_GetS32("gCollisionViewerEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gCollisionViewerEnabled", 0); - CVar_SetS32("gCollisionViewerEnabled", !currentValue); - needs_save = true; - customWindows["Collision Viewer"].enabled = CVar_GetS32("gCollisionViewerEnabled", 0); - } - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVar_GetS32("gActorViewerEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gActorViewerEnabled", 0); - CVar_SetS32("gActorViewerEnabled", !currentValue); - needs_save = true; - customWindows["Actor Viewer"].enabled = CVar_GetS32("gActorViewerEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Randomizer")) - { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - static ImVec2 buttonSize(200.0f, 0.0f); - if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gRandomizerSettingsEnabled", 0); - CVar_SetS32("gRandomizerSettingsEnabled", !currentValue); - needs_save = true; - customWindows["Randomizer Settings"].enabled = CVar_GetS32("gRandomizerSettingsEnabled", 0); - } - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gItemTrackerEnabled", 0); - CVar_SetS32("gItemTrackerEnabled", !currentValue); - needs_save = true; - customWindows["Item Tracker"].enabled = CVar_GetS32("gItemTrackerEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - ImGui::EndMenu(); - } + clientDrawMenu(); ImGui::PopStyleVar(1); ImGui::EndMenuBar(); @@ -2015,19 +546,19 @@ namespace SohImGui { ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); ImGui::Begin("Debug Stats", &statsWindowOpen, ImGuiWindowFlags_NoFocusOnAppearing); -#if defined(_WIN32) + #if defined(_WIN32) ImGui::Text("Platform: Windows"); -#elif defined(__APPLE__) + #elif defined(__APPLE__) ImGui::Text("Platform: macOS"); -#elif defined(__SWITCH__) + #elif defined(__SWITCH__) ImGui::Text("Platform: Nintendo Switch"); -#elif defined(__WIIU__) + #elif defined(__WIIU__) ImGui::Text("Platform: Nintendo Wii U"); -#elif defined(__linux__) + #elif defined(__linux__) ImGui::Text("Platform: Linux"); -#else + #else ImGui::Text("Platform: Unknown"); -#endif + #endif ImGui::Text("Status: %.3f ms/frame (%.1f FPS)", 1000.0f / framerate, framerate); ImGui::End(); ImGui::PopStyleColor(); @@ -2078,6 +609,14 @@ namespace SohImGui { overlay->Draw(); } + void RegisterMenuDrawMethod(std::function drawMethod) { + clientDrawMenu = drawMethod; + } + + void AddSetupHooksDelegate(std::function setupHooksMethod) { + clientSetupHooks = setupHooksMethod; + } + void DrawFramebufferAndGameInput(void) { const ImVec2 main_pos = ImGui::GetWindowPos(); ImVec2 size = ImGui::GetContentRegionAvail(); @@ -2146,360 +685,6 @@ namespace SohImGui { } } - void applyEnhancementPresets(void) { - - switch (CVar_GetS32("gSelectEnhancementPresets", 0)) { - // Default - case 0: - applyEnhancementPresetDefault(); - break; - - // Vanilla Plus - case 1: - applyEnhancementPresetDefault(); - applyEnhancementPresetVanillaPlus(); - break; - - // Enhanced - case 2: - applyEnhancementPresetDefault(); - applyEnhancementPresetVanillaPlus(); - applyEnhancementPresetEnhanced(); - break; - - // Randomizer - case 3: - applyEnhancementPresetDefault(); - applyEnhancementPresetVanillaPlus(); - applyEnhancementPresetEnhanced(); - applyEnhancementPresetRandomizer(); - break; - } - } - - void applyEnhancementPresetDefault(void) { - // D-pad Support on Pause and File Select - CVar_SetS32("gDpadPauseName", 0); - // D-pad Support in Ocarina and Text Choice - CVar_SetS32("gDpadOcarinaText", 0); - // D-pad Support for Browsing Shop Items - CVar_SetS32("gDpadShop", 0); - // D-pad as Equip Items - CVar_SetS32("gDpadEquips", 0); - // Allow the cursor to be on any slot - CVar_SetS32("gPauseAnyCursor", 0); - // Prevent Dropped Ocarina Inputs - CVar_SetS32("gDpadNoDropOcarinaInput", 0); - // Answer Navi Prompt with L Button - CVar_SetS32("gNaviOnL", 0); - - // Text Speed (1 to 5) - CVar_SetS32("gTextSpeed", 1); - // King Zora Speed (1 to 5) - CVar_SetS32("gMweepSpeed", 1); - // Biggoron Forge Time (0 to 3) - CVar_SetS32("gForgeTime", 3); - // Vine/Ladder Climb speed (+0 to +12) - CVar_SetS32("gClimbSpeed", 0); - // Faster Block Push (+0 to +5) - CVar_SetS32("gFasterBlockPush", 0); - // Faster Heavy Block Lift - CVar_SetS32("gFasterHeavyBlockLift", 0); - // No Forced Navi - CVar_SetS32("gNoForcedNavi", 0); - // No Skulltula Freeze - CVar_SetS32("gSkulltulaFreeze", 0); - // MM Bunny Hood - CVar_SetS32("gMMBunnyHood", 0); - // Fast Chests - CVar_SetS32("gFastChests", 0); - // Fast Drops - CVar_SetS32("gFastDrops", 0); - // Better Owl - CVar_SetS32("gBetterOwl", 0); - // Fast Ocarina Playback - CVar_SetS32("gFastOcarinaPlayback", 0); - // Instant Putaway - CVar_SetS32("gInstantPutaway", 0); - // Instant Boomerang Recall - CVar_SetS32("gFastBoomerang", 0); - // Mask Select in Inventory - CVar_SetS32("gMaskSelect", 0); - // Remember Save Location - CVar_SetS32("gRememberSaveLocation", 0); - - // Damage Multiplier (0 to 8) - CVar_SetS32("gDamageMul", 0); - // Fall Damage Multiplier (0 to 7) - CVar_SetS32("gFallDamageMul", 0); - // Void Damage Multiplier (0 to 6) - CVar_SetS32("gVoidDamageMul", 0); - // No Random Drops - CVar_SetS32("gNoRandomDrops", 0); - // No Heart Drops - CVar_SetS32("gNoHeartDrops", 0); - // Enable Bombchu Drops - CVar_SetS32("gBombchuDrops", 0); - // Always Win Goron Pot - CVar_SetS32("gGoronPot", 0); - - // Change Red Potion Effect - CVar_SetS32("gRedPotionEffect", 0); - // Red Potion Health (1 to 100) - CVar_SetS32("gRedPotionHealth", 1); - // Red Potion Percent Restore - CVar_SetS32("gRedPercentRestore", 0); - // Change Green Potion Effect - CVar_SetS32("gGreenPotionEffect", 0); - // Green Potion Mana (1 to 100) - CVar_SetS32("gGreenPotionMana", 1); - // Green Potion Percent Restore - CVar_SetS32("gGreenPercentRestore", 0); - // Change Blue Potion Effects - CVar_SetS32("gBluePotionEffects", 0); - // Blue Potion Health (1 to 100) - CVar_SetS32("gBluePotionHealth", 1); - // Blue Potion Health Percent Restore - CVar_SetS32("gBlueHealthPercentRestore", 0); - // Blue Potion Mana (1 to 100) - CVar_SetS32("gBluePotionMana", 1); - // Blue Potion Mana Percent Restore - CVar_SetS32("gBlueManaPercentRestore", 0); - // Change Milk Effect - CVar_SetS32("gMilkEffect", 0); - // Milk Health (1 to 100) - CVar_SetS32("gMilkHealth", 1); - // Milk Percent Restore - CVar_SetS32("gMilkPercentRestore", 0); - // Separate Half Milk Effect - CVar_SetS32("gSeparateHalfMilkEffect", 0); - // Half Milk Health (1 to 100) - CVar_SetS32("gHalfMilkHealth", 0); - // Half Milk Percent Restore - CVar_SetS32("gHalfMilkPercentRestore", 0); - // Change Fairy Effect - CVar_SetS32("gFairyEffect", 0); - // Fairy (1 to 100) - CVar_SetS32("gFairyHealth", 1); - // Fairy Percent Restore - CVar_SetS32("gFairyPercentRestore", 0); - // Change Fairy Revive Effect - CVar_SetS32("gFairyReviveEffect", 0); - // Fairy Revival (1 to 100) - CVar_SetS32("gFairyReviveHealth", 1); - // Fairy Revive Percent Restore - CVar_SetS32("gFairyRevivePercentRestore", 0); - - // Instant Fishing - CVar_SetS32("gInstantFishing", 0); - // Guarantee Bite - CVar_SetS32("gGuaranteeFishingBite", 0); - // Child Minimum Weight (6 to 10) - CVar_SetS32("gChildMinimumWeightFish", 10); - // Adult Minimum Weight (8 to 13) - CVar_SetS32("gAdultMinimumWeightFish", 13); - - // Mute Low HP Alarm - CVar_SetS32("gLowHpAlarm", 0); - // Minimal UI - CVar_SetS32("gMinimalUI", 0); - // Disable Navi Call Audio - CVar_SetS32("gDisableNaviCallAudio", 0); - - // Visual Stone of Agony - CVar_SetS32("gVisualAgony", 0); - // Assignable Tunics and Boots - CVar_SetS32("gAssignableTunicsAndBoots", 0); - // Equipment Toggle - CVar_SetS32("gEquipmentCanBeRemoved", 0); - // Link's Cow in Both Time Periods - CVar_SetS32("gCowOfTime", 0); - // Enable visible guard vision - CVar_SetS32("gGuardVision", 0); - // Enable passage of time on file select - CVar_SetS32("gTimeFlowFileSelect", 0); - // Count Golden Skulltulas - CVar_SetS32("gInjectSkulltulaCount", 0); - // Pull grave during the day - CVar_SetS32("gDayGravePull", 0); - - // Rotate link (0 to 2) - CVar_SetS32("gPauseLiveLinkRotation", 0); - // Pause link animation (0 to 16) - CVar_SetS32("gPauseLiveLink", 0); - // Frames to wait - CVar_SetS32("gMinFrameCount", 1); - - // N64 Mode - CVar_SetS32("gN64Mode", 0); - // Enable 3D Dropped items/projectiles - CVar_SetS32("gNewDrops", 0); - // Disable Black Bar Letterboxes - CVar_SetS32("gDisableBlackBars", 0); - // Dynamic Wallet Icon - CVar_SetS32("gDynamicWalletIcon", 0); - // Always show dungeon entrances - CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 0); - - // Fix L&R Pause menu - CVar_SetS32("gUniformLR", 0); - // Fix L&Z Page switch in Pause menu - CVar_SetS32("gNGCKaleidoSwitcher", 0); - // Fix Dungeon entrances - CVar_SetS32("gFixDungeonMinimapIcon", 0); - // Fix Two Handed idle animations - CVar_SetS32("gTwoHandedIdle", 0); - // Fix the Gravedigging Tour Glitch - CVar_SetS32("gGravediggingTourFix", 0); - // Fix Deku Nut upgrade - CVar_SetS32("gDekuNutUpgradeFix", 0); - // Fix Navi text HUD position - CVar_SetS32("gNaviTextFix", 0); - // Fix Anubis fireballs - CVar_SetS32("gAnubisFix", 0); - // Fix Megaton Hammer crouch stab - CVar_SetS32("gCrouchStabHammerFix", 0); - // Fix all crouch stab - CVar_SetS32("gCrouchStabFix", 0); - - // Red Ganon blood - CVar_SetS32("gRedGanonBlood", 0); - // Fish while hovering - CVar_SetS32("gHoverFishing", 0); - // N64 Weird Frames - CVar_SetS32("gN64WeirdFrames", 0); - // Bombchus out of bounds - CVar_SetS32("gBombchusOOB", 0); - - CVar_SetS32("gGsCutscene", 0); - // Autosave - CVar_SetS32("gAutosave", 0); - } - - void applyEnhancementPresetVanillaPlus(void) { - // D-pad Support in Ocarina and Text Choice - CVar_SetS32("gDpadOcarinaText", 1); - // D-pad Support for Browsing Shop Items - CVar_SetS32("gDpadShop", 1); - // D-pad as Equip Items - CVar_SetS32("gDpadEquips", 1); - // Prevent Dropped Ocarina Inputs - CVar_SetS32("gDpadNoDropOcarinaInput", 1); - - // Text Speed (1 to 5) - CVar_SetS32("gTextSpeed", 5); - // King Zora Speed (1 to 5) - CVar_SetS32("gMweepSpeed", 2); - // Faster Block Push (+0 to +5) - CVar_SetS32("gFasterBlockPush", 5); - // Better Owl - CVar_SetS32("gBetterOwl", 1); - - // Assignable Tunics and Boots - CVar_SetS32("gAssignableTunicsAndBoots", 1); - // Enable passage of time on file select - CVar_SetS32("gTimeFlowFileSelect", 1); - // Count Golden Skulltulas - CVar_SetS32("gInjectSkulltulaCount", 1); - - // Pause link animation (0 to 16) - CVar_SetS32("gPauseLiveLink", 1); - - // Dynamic Wallet Icon - CVar_SetS32("gDynamicWalletIcon", 1); - // Always show dungeon entrances - CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 1); - - // Fix L&R Pause menu - CVar_SetS32("gUniformLR", 1); - // Fix Dungeon entrances - CVar_SetS32("gFixDungeonMinimapIcon", 1); - // Fix Two Handed idle animations - CVar_SetS32("gTwoHandedIdle", 1); - // Fix the Gravedigging Tour Glitch - CVar_SetS32("gGravediggingTourFix", 1); - // Fix Deku Nut upgrade - CVar_SetS32("gDekuNutUpgradeFix", 1); - - // Red Ganon blood - CVar_SetS32("gRedGanonBlood", 1); - // Fish while hovering - CVar_SetS32("gHoverFishing", 1); - // N64 Weird Frames - CVar_SetS32("gN64WeirdFrames", 1); - // Bombchus out of bounds - CVar_SetS32("gBombchusOOB", 1); - } - - void applyEnhancementPresetEnhanced(void) { - // King Zora Speed (1 to 5) - CVar_SetS32("gMweepSpeed", 5); - // Biggoron Forge Time (0 to 3) - CVar_SetS32("gForgeTime", 0); - // Vine/Ladder Climb speed (+0 to +12) - CVar_SetS32("gClimbSpeed", 1); - // Faster Heavy Block Lift - CVar_SetS32("gFasterHeavyBlockLift", 1); - // No Forced Navi - CVar_SetS32("gNoForcedNavi", 1); - // No Skulltula Freeze - CVar_SetS32("gSkulltulaFreeze", 1); - // MM Bunny Hood - CVar_SetS32("gMMBunnyHood", 1); - // Fast Chests - CVar_SetS32("gFastChests", 1); - // Fast Drops - CVar_SetS32("gFastDrops", 1); - // Fast Ocarina Playback - CVar_SetS32("gFastOcarinaPlayback", 1); - // Instant Putaway - CVar_SetS32("gInstantPutaway", 1); - // Instant Boomerang Recall - CVar_SetS32("gFastBoomerang", 1); - // Mask Select in Inventory - CVar_SetS32("gMaskSelect", 1); - - // Disable Navi Call Audio - CVar_SetS32("gDisableNaviCallAudio", 1); - - // Equipment Toggle - CVar_SetS32("gEquipmentCanBeRemoved", 1); - // Count Golden Skulltulas - CVar_SetS32("gInjectSkulltulaCount", 1); - - // Enable 3D Dropped items/projectiles - CVar_SetS32("gNewDrops", 1); - - // Fix Anubis fireballs - CVar_SetS32("gAnubisFix", 1); - } - - void applyEnhancementPresetRandomizer(void) { - // Allow the cursor to be on any slot - CVar_SetS32("gPauseAnyCursor", 1); - - // Instant Fishing - CVar_SetS32("gInstantFishing", 1); - // Guarantee Bite - CVar_SetS32("gGuaranteeFishingBite", 1); - // Child Minimum Weight (6 to 10) - CVar_SetS32("gChildMinimumWeightFish", 6); - // Adult Minimum Weight (8 to 13) - CVar_SetS32("gAdultMinimumWeightFish", 8); - - // Visual Stone of Agony - CVar_SetS32("gVisualAgony", 1); - // Pull grave during the day - CVar_SetS32("gDayGravePull", 1); - // Pull out Ocarina to Summon Scarecrow - CVar_SetS32("gSkipScarecrow", 0); - - // Pause link animation (0 to 16) - CVar_SetS32("gPauseLiveLink", 16); - // Frames to wait - CVar_SetS32("gMinFrameCount", 200); - } - void Render() { ImGui::Render(); ImGuiRenderDrawData(ImGui::GetDrawData()); @@ -2526,8 +711,41 @@ namespace SohImGui { } } - void BindCmd(const std::string& cmd, CommandEntry entry) { - console->AddCommand(cmd, entry); + void DrawSettings() { + overlay->DrawSettings(); + } + + Backend WindowBackend() { + return impl.backend; + } + + float WindowRefreshRate() { + return gfx_get_detected_hz(); + } + + std::pair* GetAvailableRenderingBackends() { + return backends; + } + + std::pair GetCurrentRenderingBackend() { + return backends[lastBackendID]; + } + + void SetCurrentRenderingBackend(uint8_t index, std::pair backend) { + Window::GetInstance()->GetConfig()->setString("Window.GfxBackend", backend.first); + lastBackendID = index; + } + + const char** GetSupportedTextureFilters() { + return filters; + } + + void SetResolutionMultiplier(float multiplier) { + gfx_current_dimensions.internal_mul = multiplier; + } + + void SetMSAALevel(uint32_t value) { + gfx_msaa_level = value; } void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled, bool isHidden) { @@ -2548,30 +766,135 @@ namespace SohImGui { } } + void EnableWindow(const std::string& name, bool isEnabled) { + customWindows[name].enabled = isEnabled; + } + + Ship::GameOverlay* GetGameOverlay() { + return overlay; + } + + Ship::InputEditor* GetInputEditor() { + return controller; + } + + void ToggleInputEditorWindow(bool isOpen) { + if (isOpen) + controller->Open(); + else + controller->Close(); + } + + void ToggleStatisticsWindow(bool isOpen) { + statsWindowOpen = isOpen; + } + + std::shared_ptr GetConsole() { + return console; + } + + void ToggleConsoleWindow(bool isOpen) { + if (isOpen) + console->Open(); + else + console->Close(); + } + + void DispatchConsoleCommand(const std::string& line) { + console->Dispatch(line); + } + + void RequestCvarSaveOnNextTick() { + needs_save = true; + } + ImTextureID GetTextureByName(const std::string& name) { return GetTextureByID(DefaultAssets[name]->textureId); } ImTextureID GetTextureByID(int id) { -#ifdef ENABLE_DX11 + #ifdef ENABLE_DX11 if (impl.backend == Backend::DX11) { ImTextureID gfx_d3d11_get_texture_by_id(int id); return gfx_d3d11_get_texture_by_id(id); } -#endif -#ifdef __WIIU__ + #endif + #ifdef __WIIU__ if (impl.backend == Backend::GX2) { return gfx_gx2_texture_for_imgui(id); } -#endif + #endif return reinterpret_cast(id); } - void BeginGroupPanel(const char* name, const ImVec2& size) - { + void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) { + GfxRenderingAPI* api = gfx_get_current_rendering_api(); + const auto res = static_cast(Window::GetInstance()->GetResourceManager()->LoadResource(path).get()); + + std::vector texBuffer; + texBuffer.reserve(res->width * res->height * 4); + + switch (res->texType) { + case Ship::TextureType::RGBA32bpp: + texBuffer.assign(res->imageData, res->imageData + (res->width * res->height * 4)); + break; + case Ship::TextureType::GrayscaleAlpha8bpp: + for (int32_t i = 0; i < res->width * res->height; i++) { + uint8_t ia = res->imageData[i]; + uint8_t color = ((ia >> 4) & 0xF) * 255 / 15; + uint8_t alpha = (ia & 0xF) * 255 / 15; + texBuffer.push_back(color); + texBuffer.push_back(color); + texBuffer.push_back(color); + texBuffer.push_back(alpha); + } + break; + default: + // TODO convert other image types + SPDLOG_WARN("SohImGui::LoadResource: Attempting to load unsupporting image type %s", path.c_str()); + return; + } + + for (size_t pixel = 0; pixel < texBuffer.size() / 4; pixel++) { + texBuffer[pixel * 4 + 0] *= tint.x; + texBuffer[pixel * 4 + 1] *= tint.y; + texBuffer[pixel * 4 + 2] *= tint.z; + texBuffer[pixel * 4 + 3] *= tint.w; + } + + const auto asset = new GameAsset{ api->new_texture() }; + + api->select_texture(0, asset->textureId); + api->set_sampler_parameters(0, false, 0, 0); + api->upload_texture(texBuffer.data(), res->width, res->height); + + DefaultAssets[name] = asset; + } + + void ShowCursor(bool hide, Dialogues d) { + if (d == Dialogues::dLoadSettings) { + Window::GetInstance()->ShowCursor(hide); + return; + } + + if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) { + return; + } + if (!Window::GetInstance()->IsFullscreen()) { + oldCursorState = false; + return; + } + + if (oldCursorState != hide) { + oldCursorState = hide; + Window::GetInstance()->ShowCursor(hide); + } + } + + void BeginGroupPanel(const char* name, const ImVec2& size) { ImGui::BeginGroup(); // auto cursorPos = ImGui::GetCursorScreenPos(); @@ -2605,13 +928,13 @@ namespace SohImGui { ImGui::PopStyleVar(2); -#if IMGUI_VERSION_NUM >= 17301 + #if IMGUI_VERSION_NUM >= 17301 ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f; ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f; ImGui::GetCurrentWindow()->InnerRect.Max.x -= frameHeight * 0.5f; -#else + #else ImGui::GetCurrentWindow()->ContentsRegionRect.Max.x -= frameHeight * 0.5f; -#endif + #endif ImGui::GetCurrentWindow()->Size.x -= frameHeight; auto itemWidth = ImGui::CalcItemWidth(); @@ -2676,101 +999,17 @@ namespace SohImGui { ImGui::PopStyleVar(2); -#if IMGUI_VERSION_NUM >= 17301 + #if IMGUI_VERSION_NUM >= 17301 ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f; ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f; ImGui::GetCurrentWindow()->InnerRect.Max.x += frameHeight * 0.5f; -#else + #else ImGui::GetCurrentWindow()->ContentsRegionRect.Max.x += frameHeight * 0.5f; -#endif + #endif ImGui::GetCurrentWindow()->Size.x += frameHeight; - InsertPadding(); + ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::EndGroup(); } - - // Automatically add newlines to break up tooltips longer than a specified number of characters - // Manually included newlines will still be respected and reset the line length - // Default line length is 60 characters - std::string BreakTooltip(const char* text, int lineLength) { - std::string newText(text); - const int tipLength = newText.length(); - int lastSpace = -1; - int currentLineLength = 0; - for (int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) { - if (newText[currentCharacter] == '\n') { - currentLineLength = 0; - lastSpace = -1; - continue; - } - else if (newText[currentCharacter] == ' ') { - lastSpace = currentCharacter; - } - - if ((currentLineLength >= lineLength) && (lastSpace >= 0)) { - newText[lastSpace] = '\n'; - currentLineLength = currentCharacter - lastSpace - 1; - lastSpace = -1; - } - currentLineLength++; - } - return newText; - } - - std::string BreakTooltip(const std::string& text, int lineLength) { - return BreakTooltip(text.c_str(), lineLength); - } - - void InsertPadding(float extraVerticalPadding) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalPadding)); - } - - void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalTopPadding, float extraVerticalBottomPadding) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalTopPadding)); - } - ImGui::Separator(); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalBottomPadding)); - } - } - - void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - } - - void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, ImGuiCheckboxGraphics disabledGraphic) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - } - - void PaddedText(const char* text, bool padTop, bool padBottom) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - ImGui::Text("%s", text); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - } - - std::string GetWindowButtonText(const char* text, bool menuOpen) { - char buttonText[100] = ""; - if(menuOpen) { strcat(buttonText,"> "); } - strcat(buttonText, text); - if (!menuOpen) { strcat(buttonText, " "); } - return buttonText; - } } diff --git a/libultraship/libultraship/ImGuiImpl.h b/libultraship/libultraship/ImGuiImpl.h index 733e9d1cf..cd035ae8a 100644 --- a/libultraship/libultraship/ImGuiImpl.h +++ b/libultraship/libultraship/ImGuiImpl.h @@ -1,14 +1,5 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - void enableBetaQuest(); - void disableBetaQuest(); -#ifdef __cplusplus -} -#endif - #ifdef __cplusplus #include "GameOverlay.h" #include "Lib/ImGui/imgui.h" @@ -34,14 +25,6 @@ namespace SohImGui { dLoadSettings, }; - // Enumeration for disabled checkbox graphics - enum class ImGuiCheckboxGraphics - { - Cross, - Checkmark, - None - }; - typedef struct { Backend backend; union { @@ -76,8 +59,6 @@ namespace SohImGui { } gx2; } EventImpl; - extern WindowImpl impl; - using WindowDrawFunc = void(*)(bool& enabled); typedef struct { @@ -85,55 +66,49 @@ namespace SohImGui { WindowDrawFunc drawFunc; } CustomWindow; - extern std::shared_ptr console; - extern Ship::InputEditor* controller; - extern Ship::GameOverlay* overlay; - extern bool needs_save; void Init(WindowImpl window_impl); void Update(EventImpl event); - void Tooltip(const char* text); - - void EnhancementRadioButton(const char* text, const char* cvarName, int id); - void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross); - void EnhancementButton(const char* text, const char* cvarName); - void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false); - void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false); - void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); - void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); - void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue = 0); - - void applyEnhancementPresets(void); - void applyEnhancementPresetDefault(void); - void applyEnhancementPresetVanillaPlus(void); - void applyEnhancementPresetEnhanced(void); - void applyEnhancementPresetRandomizer(void); void DrawMainMenuAndCalculateGameSize(void); + void RegisterMenuDrawMethod(std::function drawMethod); + void AddSetupHooksDelegate(std::function setupHooksMethod); void DrawFramebufferAndGameInput(void); void Render(void); void CancelFrame(void); - void ShowCursor(bool hide, Dialogues w); - void BindCmd(const std::string& cmd, Ship::CommandEntry entry); - void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled=false, bool isHidden=false); - void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1)); - void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha=false); - int ClampFloatToInt(float value, int min, int max); - void RandomizeColor(const char* cvarName, ImVec4* colors); - void RainbowColor(const char* cvarName, ImVec4* colors); - void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha); + void DrawSettings(); + + Backend WindowBackend(); + float WindowRefreshRate(); + std::pair* GetAvailableRenderingBackends(); + std::pair GetCurrentRenderingBackend(); + void SetCurrentRenderingBackend(uint8_t index, std::pair); + const char** GetSupportedTextureFilters(); + void SetResolutionMultiplier(float multiplier); + void SetMSAALevel(uint32_t value); + + void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled = false, bool isHidden = false); + void EnableWindow(const std::string& name, bool isEnabled = true); + + Ship::GameOverlay* GetGameOverlay(); + + Ship::InputEditor* GetInputEditor(); + void ToggleInputEditorWindow(bool isOpen = true); + void ToggleStatisticsWindow(bool isOpen = true); + + std::shared_ptr GetConsole(); + void ToggleConsoleWindow(bool isOpen = true); + void DispatchConsoleCommand(const std::string& line); + + void RequestCvarSaveOnNextTick(); + ImTextureID GetTextureByID(int id); ImTextureID GetTextureByName(const std::string& name); + void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1)); + + void ShowCursor(bool hide, Dialogues w); void BeginGroupPanel(const char* name, const ImVec2 & size = ImVec2(0.0f, 0.0f)); void EndGroupPanel(float minHeight = 0.0f); - std::string BreakTooltip(const char* text, int lineLength = 60); - std::string BreakTooltip(const std::string& text, int lineLength = 60); - void InsertPadding(float extraVerticalPadding = 0.0f); - void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f); - void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true); - void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross); - void PaddedText(const char* text, bool padTop = true, bool padBottom = true); - std::string GetWindowButtonText(const char* text, bool menuOpen); } #endif diff --git a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h index 8a629aa1a..4bb8cf2c6 100644 --- a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h +++ b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h @@ -41,8 +41,8 @@ protected: } formatted.push_back('\0'); const char* msg_output = formatted.data(); - if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->IsOpened()) { - SohImGui::console->Append("Logs", msg.level, "%s", msg_output); + if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::GetConsole()->IsOpened()) { + SohImGui::GetConsole()->Append("Logs", msg.level, "%s", msg_output); } } @@ -57,4 +57,4 @@ private: using soh_sink_mt = sohconsole_sink; using soh_sink_st = sohconsole_sink; } // namespace sinks -} // namespace spdlog \ No newline at end of file +} // namespace spdlog diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index b9e84fd60..36a10b505 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -86,7 +86,7 @@ extern "C" { pad->gyro_x = 0; pad->gyro_y = 0; - if (SohImGui::controller->IsOpened()) return; + if (SohImGui::GetInputEditor()->IsOpened()) return; Ship::Window::GetInstance()->GetControlDeck()->WriteToPad(pad); Ship::ExecuteHooks(pad); diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 50bf5fa69..e903ee541 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -162,6 +162,7 @@ set(Header_Files__soh__Enhancements__controls ) source_group("Header Files\\soh\\Enhancements\\controls" FILES ${Header_Files__soh__Enhancements__controls}) + set(Header_Files__soh__Enhancements__cosmetics "soh/Enhancements/cosmetics/CosmeticsEditor.h" ) @@ -172,7 +173,6 @@ set(Header_Files__soh__Enhancements__debugger "soh/Enhancements/debugger/colViewer.h" "soh/Enhancements/debugger/debugger.h" "soh/Enhancements/debugger/debugSaveEditor.h" - "soh/Enhancements/debugger/ImGuiHelpers.h" ) source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__soh__Enhancements__debugger}) @@ -251,6 +251,10 @@ set(Source_Files__soh "soh/z_message_OTR.cpp" "soh/z_play_otr.cpp" "soh/z_scene_otr.cpp" + "soh/GameMenuBar.hpp" + "soh/GameMenuBar.cpp" + "soh/UIWidgets.hpp" + "soh/UIWidgets.cpp" ) source_group("Source Files\\soh" FILES ${Source_Files__soh}) @@ -277,7 +281,6 @@ set(Source_Files__soh__Enhancements__debugger "soh/Enhancements/debugger/colViewer.cpp" "soh/Enhancements/debugger/debugger.cpp" "soh/Enhancements/debugger/debugSaveEditor.cpp" - "soh/Enhancements/debugger/ImGuiHelpers.cpp" ) source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__soh__Enhancements__debugger}) @@ -1669,14 +1672,13 @@ set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PRIVATE assets ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${CMAKE_CURRENT_SOURCE_DIR}/src/ + ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship + ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/libjpeg/include/ - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/spdlog/include/ + ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64/PR ${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64 - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64/PR ${SDL2-INCLUDE} - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/ ${CMAKE_CURRENT_SOURCE_DIR}/assets/ . ) diff --git a/soh/include/global.h b/soh/include/global.h index 65203c1aa..aa904984f 100644 --- a/soh/include/global.h +++ b/soh/include/global.h @@ -6,7 +6,7 @@ #include "macros.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/gameconsole.h" -#include "Cvar.h" +#include diff --git a/soh/include/macros.h b/soh/include/macros.h index 1822cb1d6..e726d9f00 100644 --- a/soh/include/macros.h +++ b/soh/include/macros.h @@ -1,7 +1,7 @@ #ifndef MACROS_H #define MACROS_H -#include "endianness.h" +#include #define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0])) diff --git a/soh/include/z64.h b/soh/include/z64.h index 1f0bbc25c..7264b663b 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -26,7 +26,7 @@ #include "z64interface.h" #include "sequence.h" #include "sfx.h" -#include "color.h" +#include #include "ichain.h" #include "regs.h" diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index e821d7f17..8f7b8f2b4 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -1,7 +1,7 @@ #ifndef Z64_AUDIO_H #define Z64_AUDIO_H -#include "endianness.h" +#include #define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) @@ -815,7 +815,7 @@ typedef struct { /* 0x0E */ u8 ttl; // duration after which the DMA can be discarded } SampleDma; // size = 0x10 -#include +#include typedef struct { /* 0x0000 */ char unk_0000; @@ -1122,4 +1122,4 @@ float Audio_GetGameVolume(int player_id); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/soh/include/z64effect.h b/soh/include/z64effect.h index 861eb9070..7b364f0ea 100644 --- a/soh/include/z64effect.h +++ b/soh/include/z64effect.h @@ -1,7 +1,7 @@ #ifndef Z64EFFECT_H #define Z64EFFECT_H -#include "color.h" +#include struct GraphicsContext; struct GlobalContext; diff --git a/soh/include/z64light.h b/soh/include/z64light.h index 639490022..d642a7364 100644 --- a/soh/include/z64light.h +++ b/soh/include/z64light.h @@ -4,7 +4,7 @@ #include "ultra64.h" #include "ultra64/gbi.h" #include "z64math.h" -#include "color.h" +#include typedef struct { /* 0x0 */ s16 x; diff --git a/soh/include/z64transition.h b/soh/include/z64transition.h index 2adb6f604..9c93e44b7 100644 --- a/soh/include/z64transition.h +++ b/soh/include/z64transition.h @@ -2,7 +2,7 @@ #define Z64TRANSITION_H #include "ultra64.h" -#include "color.h" +#include typedef struct { f32 unk_0; diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index ee8e33dea..f494711e6 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -6,12 +6,14 @@ #include #include -#include "Lib/ImGui/imgui.h" -#include "Lib/ImGui/imgui_internal.h" -#include "Cvar.h" -#include "UltraController.h" -#include "Utils/StringHelper.h" -#include "../libultraship/ImGuiImpl.h" +#include +#include +#include +#include +#include +#include + +#include "../../UIWidgets.hpp" namespace GameControlEditor { const ImGuiTableFlags PANEL_TABLE_FLAGS = @@ -50,7 +52,11 @@ namespace GameControlEditor { // place the ? button to the most of the right side of the cell it is using. ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15); ImGui::SmallButton("?"); - SohImGui::Tooltip(helptext.c_str()); + + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", helptext.c_str()); + } + if (sameline) { //I do not use ImGui::SameLine(); because it make some element vanish. ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22); @@ -119,7 +125,7 @@ namespace GameControlEditor { preview = "Unknown"; } - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); ImVec2 cursorPos = ImGui::GetCursorPos(); ImVec2 textSize = ImGui::CalcTextSize(mapping.label); ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4); @@ -140,7 +146,7 @@ namespace GameControlEditor { } ImGui::EndCombo(); } - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); } void DrawOcarinaControlPanel() { @@ -157,7 +163,7 @@ namespace GameControlEditor { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - SohImGui::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); + UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); if (CVar_GetS32("gCustomOcarinaControls", 0) == 1) { if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) { @@ -194,10 +200,10 @@ namespace GameControlEditor { ImGui::EndTable(); } } else { - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::TextWrapped("To modify the main ocarina controls, select the \"Customize Ocarina Controls\" checkbox."); - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); } SohImGui::BeginGroupPanel("Alternate controls", ImGui::GetContentRegionAvail()); @@ -206,9 +212,9 @@ namespace GameControlEditor { ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS); TableHelper::InitHeader(false); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); + UIWidgets::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); TableHelper::NextCol(); - SohImGui::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); + UIWidgets::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); ImGui::EndTable(); } SohImGui::EndGroupPanel(); @@ -223,17 +229,17 @@ namespace GameControlEditor { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - SohImGui::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); - SohImGui::Tooltip("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); + UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis"); - SohImGui::Tooltip("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis"); + UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); - SohImGui::Tooltip("Allows for aiming with the rights stick when:\n-Aiming in the C-Up view\n-Aiming with weapons"); + UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); + UIWidgets::Tooltip("Allows for aiming with the rights stick when:\n-Aiming in the C-Up view\n-Aiming with weapons"); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::PaddedEnhancementCheckbox("Auto-Center First Person View", "gAutoCenterView"); - SohImGui::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Auto-Center First Person View", "gAutoCenterView"); + UIWidgets::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); } void DrawUI(bool& open) { diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index b04f30e35..5782119f1 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1,11 +1,13 @@ #include "CosmeticsEditor.h" -#include "../libultraship/ImGuiImpl.h" +#include #include -#include +#include #include #include -#include +#include + +#include "../../UIWidgets.hpp" const char* RainbowColorCvarList[] = { //This is the list of possible CVars that has rainbow effect. @@ -51,9 +53,9 @@ void GetRandomColorRGB(CosmeticsColorSection* ColorSection, int SectionSize){ std::string cvarName = Element->CvarName; std::string Cvar_RBM = cvarName + "RBM"; colors = RANDOMIZE_32(255); - NewColors.r = SohImGui::ClampFloatToInt(colors.x * 255, 0, 255); - NewColors.g = SohImGui::ClampFloatToInt(colors.y * 255, 0, 255); - NewColors.b = SohImGui::ClampFloatToInt(colors.z * 255, 0, 255); + NewColors.r = fmin(fmax(colors.x * 255, 0), 255); + NewColors.g = fmin(fmax(colors.y * 255, 0), 255); + NewColors.b = fmin(fmax(colors.z * 255, 0), 255); Element->ModifiedColor = colors; CVar_SetRGBA(cvarName.c_str(), NewColors); CVar_SetS32(Cvar_RBM.c_str(), 0); @@ -149,9 +151,9 @@ void LoadRainbowColor(bool& open) { case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break; } Color_RGBA8 NewColorRGB = { - SohImGui::ClampFloatToInt(NewColor.x, 0, 255), - SohImGui::ClampFloatToInt(NewColor.y, 0, 255), - SohImGui::ClampFloatToInt(NewColor.z, 0, 255), + fmin(fmax(NewColor.x, 0), 255), + fmin(fmax(NewColor.y, 0), 255), + fmin(fmax(NewColor.z, 0), 255), 255 }; if (CVar_GetS32(Cvar_RBM.c_str(), 0) != 0) { @@ -187,7 +189,7 @@ void Draw_HelpIcon(const std::string& helptext, bool sameline = true, int Pos = ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x-60); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15); ImGui::SmallButton("?"); - SohImGui::Tooltip(helptext.c_str()); + UIWidgets::Tooltip(helptext.c_str()); if (sameline) { //I do not use ImGui::SameLine(); because it make some element vanish. ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22); @@ -197,96 +199,96 @@ void Draw_HelpIcon(const std::string& helptext, bool sameline = true, int Pos = void DrawUseMarginsSlider(const std::string ElementName, const std::string CvarName){ std::string CvarLabel = CvarName + "UseMargins"; std::string Label = ElementName + " use margins"; - SohImGui::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str()); - SohImGui::Tooltip("Using this allow you move the element with General margins sliders"); + UIWidgets::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str()); + UIWidgets::Tooltip("Using this allow you move the element with General margins sliders"); } void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = true){ std::string CvarLabel = CvarName + "PosType"; - SohImGui::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0); - SohImGui::Tooltip("This will use original intended elements position"); - SohImGui::EnhancementRadioButton("Anchor to the left", CvarLabel.c_str(), 1); - SohImGui::Tooltip("This will make your elements follow the left side of your game window"); - SohImGui::EnhancementRadioButton("Anchor to the right", CvarLabel.c_str(), 2); - SohImGui::Tooltip("This will make your elements follow the right side of your game window"); + UIWidgets::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0); + UIWidgets::Tooltip("This will use original intended elements position"); + UIWidgets::EnhancementRadioButton("Anchor to the left", CvarLabel.c_str(), 1); + UIWidgets::Tooltip("This will make your elements follow the left side of your game window"); + UIWidgets::EnhancementRadioButton("Anchor to the right", CvarLabel.c_str(), 2); + UIWidgets::Tooltip("This will make your elements follow the right side of your game window"); if (NoAnchorEnabled) { - SohImGui::EnhancementRadioButton("No anchors", CvarLabel.c_str(), 3); - SohImGui::Tooltip("This will make your elements to not follow any side\nBetter used for center elements"); + UIWidgets::EnhancementRadioButton("No anchors", CvarLabel.c_str(), 3); + UIWidgets::Tooltip("This will make your elements to not follow any side\nBetter used for center elements"); } - SohImGui::EnhancementRadioButton("Hidden", CvarLabel.c_str(), 4); - SohImGui::Tooltip("This will make your elements hidden"); + UIWidgets::EnhancementRadioButton("Hidden", CvarLabel.c_str(), 4); + UIWidgets::Tooltip("This will make your elements hidden"); } void DrawTransitions(const std::string CvarName){ - SohImGui::EnhancementRadioButton("Really slow fade (white)", CvarName.c_str(), 8); + UIWidgets::EnhancementRadioButton("Really slow fade (white)", CvarName.c_str(), 8); Table_NextCol(); - SohImGui::EnhancementRadioButton("Really slow fade (black)", CvarName.c_str(), 7); + UIWidgets::EnhancementRadioButton("Really slow fade (black)", CvarName.c_str(), 7); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow fade (white)", CvarName.c_str(), 10); + UIWidgets::EnhancementRadioButton("Slow fade (white)", CvarName.c_str(), 10); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow fade (black)", CvarName.c_str(), 9); + UIWidgets::EnhancementRadioButton("Slow fade (black)", CvarName.c_str(), 9); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal fade (white)", CvarName.c_str(), 3); + UIWidgets::EnhancementRadioButton("Normal fade (white)", CvarName.c_str(), 3); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal fade (black)", CvarName.c_str(), 2); + UIWidgets::EnhancementRadioButton("Normal fade (black)", CvarName.c_str(), 2); Table_NextLine(); - SohImGui::EnhancementRadioButton("Fast fade (white)", CvarName.c_str(), 5); + UIWidgets::EnhancementRadioButton("Fast fade (white)", CvarName.c_str(), 5); Table_NextCol(); - SohImGui::EnhancementRadioButton("Fast fade (black)", CvarName.c_str(), 4); + UIWidgets::EnhancementRadioButton("Fast fade (black)", CvarName.c_str(), 4); Table_NextLine(); - SohImGui::EnhancementRadioButton("Fast circle (white)", CvarName.c_str(), 40); + UIWidgets::EnhancementRadioButton("Fast circle (white)", CvarName.c_str(), 40); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal circle (black)", CvarName.c_str(), 32); + UIWidgets::EnhancementRadioButton("Normal circle (black)", CvarName.c_str(), 32); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow circle (white)", CvarName.c_str(), 41); + UIWidgets::EnhancementRadioButton("Slow circle (white)", CvarName.c_str(), 41); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow circle (black)", CvarName.c_str(), 33); + UIWidgets::EnhancementRadioButton("Slow circle (black)", CvarName.c_str(), 33); Table_NextLine(); - SohImGui::EnhancementRadioButton("Fast noise circle (white)", CvarName.c_str(), 42); + UIWidgets::EnhancementRadioButton("Fast noise circle (white)", CvarName.c_str(), 42); Table_NextCol(); - SohImGui::EnhancementRadioButton("Fast noise circle (black)", CvarName.c_str(), 34); + UIWidgets::EnhancementRadioButton("Fast noise circle (black)", CvarName.c_str(), 34); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow noise circle (white)", CvarName.c_str(), 43); + UIWidgets::EnhancementRadioButton("Slow noise circle (white)", CvarName.c_str(), 43); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow noise circle (black)", CvarName.c_str(), 35); + UIWidgets::EnhancementRadioButton("Slow noise circle (black)", CvarName.c_str(), 35); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal waves circle (white)", CvarName.c_str(), 44); + UIWidgets::EnhancementRadioButton("Normal waves circle (white)", CvarName.c_str(), 44); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal waves circle (black)", CvarName.c_str(), 36); + UIWidgets::EnhancementRadioButton("Normal waves circle (black)", CvarName.c_str(), 36); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow waves circle (white)", CvarName.c_str(), 45); + UIWidgets::EnhancementRadioButton("Slow waves circle (white)", CvarName.c_str(), 45); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow waves circle (black)", CvarName.c_str(), 37); + UIWidgets::EnhancementRadioButton("Slow waves circle (black)", CvarName.c_str(), 37); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal close circle (white)", CvarName.c_str(), 46); + UIWidgets::EnhancementRadioButton("Normal close circle (white)", CvarName.c_str(), 46); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal close circle (black)", CvarName.c_str(), 38); + UIWidgets::EnhancementRadioButton("Normal close circle (black)", CvarName.c_str(), 38); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow close circle (white)", CvarName.c_str(), 47); + UIWidgets::EnhancementRadioButton("Slow close circle (white)", CvarName.c_str(), 47); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow close circle (black)", CvarName.c_str(), 39); + UIWidgets::EnhancementRadioButton("Slow close circle (black)", CvarName.c_str(), 39); Table_NextLine(); - SohImGui::EnhancementRadioButton("Super fast circle (white)", CvarName.c_str(), 56); + UIWidgets::EnhancementRadioButton("Super fast circle (white)", CvarName.c_str(), 56); Table_NextCol(); - SohImGui::EnhancementRadioButton("Super fast circle (black)", CvarName.c_str(), 58); + UIWidgets::EnhancementRadioButton("Super fast circle (black)", CvarName.c_str(), 58); Table_NextLine(); - SohImGui::EnhancementRadioButton("Super fast noise circle (white)", CvarName.c_str(), 57); + UIWidgets::EnhancementRadioButton("Super fast noise circle (white)", CvarName.c_str(), 57); Table_NextCol(); - SohImGui::EnhancementRadioButton("Super fast noise circle (black)", CvarName.c_str(), 59); + UIWidgets::EnhancementRadioButton("Super fast noise circle (black)", CvarName.c_str(), 59); } void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX, int MaxX){ std::string PosXCvar = CvarName+"PosX"; std::string PosYCvar = CvarName+"PosY"; std::string InvisibleLabelX = "##"+PosXCvar; std::string InvisibleLabelY = "##"+PosYCvar; - SohImGui::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0, true); - SohImGui::Tooltip("This slider is used to move Up and Down your elements."); - SohImGui::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0, true); - SohImGui::Tooltip("This slider is used to move Left and Right your elements."); + UIWidgets::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0, true); + UIWidgets::Tooltip("This slider is used to move Up and Down your elements."); + UIWidgets::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0, true); + UIWidgets::Tooltip("This slider is used to move Left and Right your elements."); } void DrawScaleSlider(const std::string CvarName,float DefaultValue){ std::string InvisibleLabel = "##"+CvarName; std::string CvarLabel = CvarName+"Scale"; //Disabled for now. feature not done and several fixes needed to be merged. - //SohImGui::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true,true); + //UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true,true); } void DrawColorSection(CosmeticsColorSection* ColorSection, int SectionSize) { for (s16 i = 0; i < SectionSize; i++) { @@ -308,7 +310,7 @@ void DrawColorSection(CosmeticsColorSection* ColorSection, int SectionSize) { Table_NextLine(); } Draw_HelpIcon(Tooltip.c_str()); - SohImGui::EnhancementColor(Name.c_str(), Cvar.c_str(), ModifiedColor, DefaultColor, canRainbow, hasAlpha, sameLine); + UIWidgets::EnhancementColor(Name.c_str(), Cvar.c_str(), ModifiedColor, DefaultColor, canRainbow, hasAlpha, sameLine); } } void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSection* ColorSection, int SectionSize, bool isAllCosmetics = false){ @@ -335,21 +337,21 @@ void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSectio CVar_SetS32("gCCparated", 1); GetRandomColorRGB(ColorSection, SectionSize); } - SohImGui::Tooltip(Tooltip_RNG.c_str()); + UIWidgets::Tooltip(Tooltip_RNG.c_str()); Table_NextCol(); if(ImGui::Button(Reset_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f))){ GetDefaultColorRGB(ColorSection, SectionSize); } - SohImGui::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); - SohImGui::Tooltip(Tooltip_RNG.c_str()); + UIWidgets::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); + UIWidgets::Tooltip(Tooltip_RNG.c_str()); ImGui::EndTable(); } } void Draw_Npcs(){ DrawRandomizeResetButton("all NPCs", NPCs_section, SECTION_SIZE(NPCs_section)); - SohImGui::EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol"); - SohImGui::Tooltip("Enable/Disable custom Navi colors\nIf disabled, default colors will be used\nColors go into effect when Navi goes back into your pockets"); + UIWidgets::EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol"); + UIWidgets::Tooltip("Enable/Disable custom Navi colors\nIf disabled, default colors will be used\nColors go into effect when Navi goes back into your pockets"); if (CVar_GetS32("gUseNaviCol",0)) { DrawRandomizeResetButton("Navi's", Navi_Section, SECTION_SIZE(Navi_Section)); }; @@ -360,8 +362,8 @@ void Draw_Npcs(){ DrawColorSection(Navi_Section, SECTION_SIZE(Navi_Section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol"); - SohImGui::Tooltip("Enable/Disable custom Keese element colors\nIf disabled, default element colors will be used\nColors go into effect when Keese respawn (or when the room is reloaded)"); + UIWidgets::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol"); + UIWidgets::Tooltip("Enable/Disable custom Keese element colors\nIf disabled, default element colors will be used\nColors go into effect when Keese respawn (or when the room is reloaded)"); if (CVar_GetS32("gUseKeeseCol",0) && ImGui::BeginTable("tableKeese", 2, FlagsTable)) { ImGui::TableSetupColumn("Fire colors##Keese", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("Ice colors##Keese", FlagsCell, TablesCellsWidth/2); @@ -369,8 +371,8 @@ void Draw_Npcs(){ DrawColorSection(Keese_Section, SECTION_SIZE(Keese_Section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom colors for Dogs", "gUseDogsCol"); - SohImGui::Tooltip("Enable/Disable custom colors for the two Dog variants\nIf disabled, default colors will be used"); + UIWidgets::EnhancementCheckbox("Custom colors for Dogs", "gUseDogsCol"); + UIWidgets::Tooltip("Enable/Disable custom colors for the two Dog variants\nIf disabled, default colors will be used"); if (CVar_GetS32("gUseDogsCol",0) && ImGui::BeginTable("tableDogs", 2, FlagsTable)) { ImGui::TableSetupColumn("White Dog color", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("Brown Dog color", FlagsCell, TablesCellsWidth/2); @@ -381,8 +383,8 @@ void Draw_Npcs(){ } void Draw_ItemsSkills(){ DrawRandomizeResetButton("all skills and items", AllItemsSkills_section, SECTION_SIZE(AllItemsSkills_section)); - SohImGui::EnhancementCheckbox("Custom tunics color", "gUseTunicsCol"); - SohImGui::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); + UIWidgets::EnhancementCheckbox("Custom tunics color", "gUseTunicsCol"); + UIWidgets::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); if (CVar_GetS32("gUseTunicsCol",0)) { DrawRandomizeResetButton("Link's tunics", Tunics_Section, SECTION_SIZE(Tunics_Section)); }; @@ -394,7 +396,7 @@ void Draw_ItemsSkills(){ DrawColorSection(Tunics_Section, SECTION_SIZE(Tunics_Section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom arrows colors", "gUseArrowsCol"); + UIWidgets::EnhancementCheckbox("Custom arrows colors", "gUseArrowsCol"); if (CVar_GetS32("gUseArrowsCol",0)) { DrawRandomizeResetButton("elemental arrows", Arrows_section, SECTION_SIZE(Arrows_section)); } @@ -405,7 +407,7 @@ void Draw_ItemsSkills(){ DrawColorSection(Arrows_section, SECTION_SIZE(Arrows_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom spells colors", "gUseSpellsCol"); + UIWidgets::EnhancementCheckbox("Custom spells colors", "gUseSpellsCol"); if (CVar_GetS32("gUseSpellsCol",0)) { DrawRandomizeResetButton("spells", Spells_section, SECTION_SIZE(Spells_section)); } @@ -416,7 +418,7 @@ void Draw_ItemsSkills(){ DrawColorSection(Spells_section, SECTION_SIZE(Spells_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom spin attack colors", "gUseChargedCol"); + UIWidgets::EnhancementCheckbox("Custom spin attack colors", "gUseChargedCol"); if (CVar_GetS32("gUseChargedCol",0)) { DrawRandomizeResetButton("spins attack", SpinAtk_section, SECTION_SIZE(SpinAtk_section)); } @@ -427,13 +429,13 @@ void Draw_ItemsSkills(){ DrawColorSection(SpinAtk_section, SECTION_SIZE(SpinAtk_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom trails color", "gUseTrailsCol"); + UIWidgets::EnhancementCheckbox("Custom trails color", "gUseTrailsCol"); if (CVar_GetS32("gUseTrailsCol",0) && ImGui::BeginTable("tabletrails", 1, FlagsTable)) { ImGui::TableSetupColumn("Custom Trails", FlagsCell, TablesCellsWidth); Table_InitHeader(); DrawColorSection(Trails_section, SECTION_SIZE(Trails_section)); - SohImGui::EnhancementSliderInt("Trails duration: %dx", "##TrailsMul", "gTrailDurantion", 1, 5, ""); - SohImGui::Tooltip("The longer the trails the weirder it become"); + UIWidgets::EnhancementSliderInt("Trails duration: %dx", "##TrailsMul", "gTrailDurantion", 1, 5, ""); + UIWidgets::Tooltip("The longer the trails the weirder it become"); ImGui::NewLine(); ImGui::EndTable(); } @@ -455,18 +457,18 @@ void Draw_Placements(){ if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) { ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth); Table_InitHeader(); - SohImGui::EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); - SohImGui::EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, ImGui::GetWindowViewport()->Size.x, "", 0, true); - SohImGui::EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0, true); - SohImGui::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); + UIWidgets::EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); + UIWidgets::EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, ImGui::GetWindowViewport()->Size.x, "", 0, true); + UIWidgets::EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0, true); + UIWidgets::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); SetMarginAll("All margins on",true); - SohImGui::Tooltip("Set most of the element to use margin\nSome elements with default position will not be affected\nElements without Archor or Hidden will not be turned on"); + UIWidgets::Tooltip("Set most of the element to use margin\nSome elements with default position will not be affected\nElements without Archor or Hidden will not be turned on"); ImGui::SameLine(); SetMarginAll("All margins off",false); - SohImGui::Tooltip("Set all of the element to not use margin"); + UIWidgets::Tooltip("Set all of the element to not use margin"); ImGui::SameLine(); ResetPositionAll(); - SohImGui::Tooltip("Revert every element to use their original position and no margins"); + UIWidgets::Tooltip("Revert every element to use their original position and no margins"); ImGui::NewLine(); ImGui::EndTable(); } @@ -775,7 +777,7 @@ void Draw_HUDButtons(){ DrawColorSection(C_Btn_Unified_section, SECTION_SIZE(C_Btn_Unified_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("C-Buttons use separate colors", "gCCparated"); + UIWidgets::EnhancementCheckbox("C-Buttons use separate colors", "gCCparated"); if (CVar_GetS32("gCCparated",0) && ImGui::CollapsingHeader("C Button individual colors")) { if (ImGui::BeginTable("tableBTN_CSep", 1, FlagsTable)) { ImGui::TableSetupColumn("C-Buttons individual colors", FlagsCell, TablesCellsWidth); @@ -813,19 +815,19 @@ void Draw_General(){ ImGui::TableSetupColumn("Custom Schemes", FlagsCell, TablesCellsWidth); Table_InitHeader(); Draw_HelpIcon("Change interface color to N64 style"); - SohImGui::EnhancementRadioButton("N64 Colors", "gHudColors", 0); + UIWidgets::EnhancementRadioButton("N64 Colors", "gHudColors", 0); Table_NextCol(); Draw_HelpIcon("Change interface color to GameCube style"); - SohImGui::EnhancementRadioButton("GCN Colors", "gHudColors", 1); + UIWidgets::EnhancementRadioButton("GCN Colors", "gHudColors", 1); Table_NextCol(); Draw_HelpIcon("Lets you change every interface color to your liking"); - SohImGui::EnhancementRadioButton("Custom Colors", "gHudColors", 2); + UIWidgets::EnhancementRadioButton("Custom Colors", "gHudColors", 2); ImGui::EndTable(); } if (CVar_GetS32("gHudColors",0) ==2 ){ DrawRandomizeResetButton("interface (excluding buttons)", Misc_Interface_section, SECTION_SIZE(Misc_Interface_section)); if (ImGui::CollapsingHeader("Hearts colors")) { - SohImGui::Tooltip("Hearts colors in general\nDD stand for Double Defense"); + UIWidgets::Tooltip("Hearts colors in general\nDD stand for Double Defense"); if (ImGui::BeginTable("tableHearts", 3, FlagsTable | ImGuiTableFlags_Hideable)) { ImGui::TableSetupColumn("Hearts (normal)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3); ImGui::TableSetupColumn("Hearts (DD)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3); @@ -874,25 +876,25 @@ void Draw_General(){ ImGui::TableSetupColumn("transitionother1", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("transitionother2", FlagsCell, TablesCellsWidth/2); Table_InitHeader(false); - SohImGui::EnhancementRadioButton("Originals", "gSceneTransitions", 255); - SohImGui::Tooltip("This will make the game use original scenes transitions"); + UIWidgets::EnhancementRadioButton("Originals", "gSceneTransitions", 255); + UIWidgets::Tooltip("This will make the game use original scenes transitions"); Table_NextCol(); - SohImGui::EnhancementRadioButton("None", "gSceneTransitions", 11); - SohImGui::Tooltip("This will make the game use no any scenes transitions"); + UIWidgets::EnhancementRadioButton("None", "gSceneTransitions", 11); + UIWidgets::Tooltip("This will make the game use no any scenes transitions"); Table_NextLine(); - SohImGui::EnhancementRadioButton("Desert mode (persistant)", "gSceneTransitions", 14); - SohImGui::Tooltip("This will make the game use the sand storm scenes transitions that will persist in map"); + UIWidgets::EnhancementRadioButton("Desert mode (persistant)", "gSceneTransitions", 14); + UIWidgets::Tooltip("This will make the game use the sand storm scenes transitions that will persist in map"); Table_NextCol(); - SohImGui::EnhancementRadioButton("Desert mode (non persistant)", "gSceneTransitions", 15); - SohImGui::Tooltip("This will make the game use the sand storm scenes transitions"); + UIWidgets::EnhancementRadioButton("Desert mode (non persistant)", "gSceneTransitions", 15); + UIWidgets::Tooltip("This will make the game use the sand storm scenes transitions"); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal fade (green)", "gSceneTransitions", 18); - SohImGui::Tooltip("This will make the game use a greenish fade in/out scenes transitions"); + UIWidgets::EnhancementRadioButton("Normal fade (green)", "gSceneTransitions", 18); + UIWidgets::Tooltip("This will make the game use a greenish fade in/out scenes transitions"); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal fade (blue)", "gSceneTransitions", 19); - SohImGui::Tooltip("This will make the game use a blue fade in/out scenes transitions"); + UIWidgets::EnhancementRadioButton("Normal fade (blue)", "gSceneTransitions", 19); + UIWidgets::Tooltip("This will make the game use a blue fade in/out scenes transitions"); Table_NextLine(); - SohImGui::EnhancementRadioButton("Triforce", "gSceneTransitions", 1); + UIWidgets::EnhancementRadioButton("Triforce", "gSceneTransitions", 1); ImGui::EndTable(); } if (ImGui::BeginTable("tabletransitionCol", 2, FlagsTable | ImGuiTableFlags_Hideable)) { @@ -948,6 +950,7 @@ void DrawCosmeticsEditor(bool& open) { } ImGui::End(); } + void InitCosmeticsEditor() { //This allow to hide a window without disturbing the player nor adding things in menu //LoadRainbowColor() will this way run in background once it's window is activated @@ -955,4 +958,4 @@ void InitCosmeticsEditor() { SohImGui::AddWindow("Enhancements", "Rainbowfunction", LoadRainbowColor, true, true); //Draw the bar in the menu. SohImGui::AddWindow("Enhancements", "Cosmetics Editor", DrawCosmeticsEditor); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h index 4b6ea249b..cd104633d 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h @@ -1,5 +1,5 @@ #pragma once -#include "../libultraship/ImGuiImpl.h" +#include #define SECTION_SIZE(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define RANDOMIZE_32(Max) GetRandomValue(Max); #define CATEGORY_NPC 0 @@ -405,4 +405,4 @@ static CosmeticsColorSection AllItemsSkills_section[]{ void InitCosmeticsEditor();//Init the menu itself void LoadRainbowColor(); -void NewSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0); \ No newline at end of file +void NewSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0); diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 409f2e4b5..36c9f9ea0 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1,7 +1,7 @@ #include "debugconsole.h" -#include "../libultraship/ImGuiImpl.h" +#include #include "savestates.h" -#include "Console.h" +#include #include #include @@ -12,8 +12,8 @@ #define PATH_HACK #include -#include "Window.h" -#include "Lib/ImGui/imgui_internal.h" +#include +#include #undef PATH_HACK #undef Path @@ -25,18 +25,18 @@ extern "C" { extern GlobalContext* gGlobalCtx; } -#include "Cvar.h" +#include -#define CMD_REGISTER SohImGui::BindCmd +#define CMD_REGISTER SohImGui::GetConsole()->AddCommand static bool ActorSpawnHandler(std::shared_ptr Console, const std::vector& args) { if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) { - SohImGui::console->SendErrorMessage("Not enough arguments passed to actorspawn"); + SohImGui::GetConsole()->SendErrorMessage("Not enough arguments passed to actorspawn"); return CMD_FAILED; } if (gGlobalCtx == nullptr) { - SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } @@ -72,7 +72,7 @@ static bool ActorSpawnHandler(std::shared_ptr Console, const std: if (Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, actorId, spawnPoint.pos.x, spawnPoint.pos.y, spawnPoint.pos.z, spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) { - SohImGui::console->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL"); + SohImGui::GetConsole()->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL"); return CMD_FAILED; } return CMD_SUCCESS; @@ -81,13 +81,13 @@ static bool ActorSpawnHandler(std::shared_ptr Console, const std: static bool KillPlayerHandler(std::shared_ptr Console, const std::vector&) { gSaveContext.health = 0; - SohImGui::console->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?"); + SohImGui::GetConsole()->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?"); return CMD_SUCCESS; } static bool SetPlayerHealthHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -96,18 +96,18 @@ static bool SetPlayerHealthHandler(std::shared_ptr Console, const try { health = std::stoi(args[1]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Health value must be an integer."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Health value must be an integer."); return CMD_FAILED; } if (health < 0) { - SohImGui::console->SendErrorMessage("[SOH] Health value must be a positive integer"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Health value must be a positive integer"); return CMD_SUCCESS; } gSaveContext.health = health * 0x10; - SohImGui::console->SendInfoMessage("[SOH] Player health updated to %d", health); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Player health updated to %d", health); return CMD_SUCCESS; } @@ -129,31 +129,31 @@ static bool RuppeHandler(std::shared_ptr Console, const std::vect rupeeAmount = std::stoi(args[1]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Rupee count must be an integer."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Rupee count must be an integer."); return CMD_FAILED; } if (rupeeAmount < 0) { - SohImGui::console->SendErrorMessage("[SOH] Rupee count must be positive"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Rupee count must be positive"); return CMD_FAILED; } gSaveContext.rupees = rupeeAmount; - SohImGui::console->SendInfoMessage("Set rupee count to %u", rupeeAmount); + SohImGui::GetConsole()->SendInfoMessage("Set rupee count to %u", rupeeAmount); return CMD_SUCCESS; } static bool SetPosHandler(std::shared_ptr Console, const std::vector args) { if (gGlobalCtx == nullptr) { - SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } Player* player = GET_PLAYER(gGlobalCtx); if (args.size() == 1) { - SohImGui::console->SendInfoMessage("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, + SohImGui::GetConsole()->SendInfoMessage("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y, player->actor.world.pos.z); return CMD_SUCCESS; @@ -165,7 +165,7 @@ static bool SetPosHandler(std::shared_ptr Console, const std::vec player->actor.world.pos.y = std::stof(args[2]); player->actor.world.pos.z = std::stof(args[3]); - SohImGui::console->SendInfoMessage("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, + SohImGui::GetConsole()->SendInfoMessage("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y, player->actor.world.pos.z); return CMD_SUCCESS; @@ -173,7 +173,7 @@ static bool SetPosHandler(std::shared_ptr Console, const std::vec static bool ResetHandler(std::shared_ptr Console, std::vector args) { if (gGlobalCtx == nullptr) { - SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } @@ -194,7 +194,7 @@ const static std::map ammoItems{ static bool AmmoHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 3) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -203,19 +203,19 @@ static bool AmmoHandler(std::shared_ptr Console, const std::vecto try { count = std::stoi(args[2]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("Ammo count must be an integer"); + SohImGui::GetConsole()->SendErrorMessage("Ammo count must be an integer"); return CMD_FAILED; } if (count < 0) { - SohImGui::console->SendErrorMessage("Ammo count must be positive"); + SohImGui::GetConsole()->SendErrorMessage("Ammo count must be positive"); return CMD_FAILED; } const auto& it = ammoItems.find(args[1]); if (it == ammoItems.end()) { - SohImGui::console->SendErrorMessage("Invalid item passed"); + SohImGui::GetConsole()->SendErrorMessage("Invalid item passed"); return CMD_FAILED; } @@ -237,7 +237,7 @@ const static std::map bottleItems{ static bool BottleHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 3) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -245,19 +245,19 @@ static bool BottleHandler(std::shared_ptr Console, const std::vec try { slot = std::stoi(args[2]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Bottle slot must be an integer."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Bottle slot must be an integer."); return CMD_FAILED; } if ((slot < 1) || (slot > 4)) { - SohImGui::console->SendErrorMessage("Invalid slot passed"); + SohImGui::GetConsole()->SendErrorMessage("Invalid slot passed"); return CMD_FAILED; } const auto& it = bottleItems.find(args[1]); if (it == bottleItems.end()) { - SohImGui::console->SendErrorMessage("Invalid item passed"); + SohImGui::GetConsole()->SendErrorMessage("Invalid item passed"); return CMD_FAILED; } @@ -269,7 +269,7 @@ static bool BottleHandler(std::shared_ptr Console, const std::vec static bool BHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -279,7 +279,7 @@ static bool BHandler(std::shared_ptr Console, const std::vector Console, const std::vector& args) { if (args.size() != 3) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -290,7 +290,7 @@ static bool ItemHandler(std::shared_ptr Console, const std::vecto static bool EntranceHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -299,7 +299,7 @@ static bool EntranceHandler(std::shared_ptr Console, const std::v try { entrance = std::stoi(args[1], nullptr, 16); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Entrance value must be a Hex number."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Entrance value must be a Hex number."); return CMD_FAILED; } @@ -319,7 +319,7 @@ static bool VoidHandler(std::shared_ptr Console, const std::vecto gGlobalCtx->fadeTransition = 2; gSaveContext.nextTransition = 2; } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } return CMD_SUCCESS; @@ -332,7 +332,7 @@ static bool ReloadHandler(std::shared_ptr Console, const std::vec gGlobalCtx->fadeTransition = 11; gSaveContext.nextTransition = 11; } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } return CMD_SUCCESS; @@ -345,11 +345,11 @@ static bool FWHandler(std::shared_ptr Console, const std::vector< gGlobalCtx->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex; gGlobalCtx->fadeTransition = 5; } else { - SohImGui::console->SendErrorMessage("Farore's wind not set!"); + SohImGui::GetConsole()->SendErrorMessage("Farore's wind not set!"); } } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } @@ -361,7 +361,7 @@ static bool FileSelectHandler(std::shared_ptr Console, const std: SET_NEXT_GAMESTATE(&gGlobalCtx->state, FileChoose_Init, FileChooseContext); gGlobalCtx->state.running = 0; } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } return CMD_SUCCESS; @@ -378,10 +378,10 @@ static bool SaveStateHandler(std::shared_ptr Console, const std:: switch (rtn) { case SaveStateReturn::SUCCESS: - SohImGui::console->SendInfoMessage("[SOH] Saved state to slot %u", slot); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Saved state to slot %u", slot); return CMD_SUCCESS; case SaveStateReturn::FAIL_WRONG_GAMESTATE: - SohImGui::console->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\""); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\""); return CMD_FAILED; } } @@ -392,16 +392,16 @@ static bool LoadStateHandler(std::shared_ptr Console, const std:: switch (rtn) { case SaveStateReturn::SUCCESS: - SohImGui::console->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot); return CMD_SUCCESS; case SaveStateReturn::FAIL_INVALID_SLOT: - SohImGui::console->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot); return CMD_FAILED; case SaveStateReturn::FAIL_STATE_EMPTY: - SohImGui::console->SendErrorMessage("[SOH] State Slot (%u) is empty", slot); + SohImGui::GetConsole()->SendErrorMessage("[SOH] State Slot (%u) is empty", slot); return CMD_FAILED; case SaveStateReturn::FAIL_WRONG_GAMESTATE: - SohImGui::console->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\""); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\""); return CMD_FAILED; } @@ -409,7 +409,7 @@ static bool LoadStateHandler(std::shared_ptr Console, const std:: static bool StateSlotSelectHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } int slot; @@ -417,17 +417,17 @@ static bool StateSlotSelectHandler(std::shared_ptr Console, const try { slot = std::stoi(args[1], nullptr, 10); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] SaveState slot value must be a number."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] SaveState slot value must be a number."); return CMD_FAILED; } if (slot < 0) { - SohImGui::console->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2"); return CMD_FAILED; } OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot); - SohImGui::console->SendInfoMessage("[SOH] Slot %u selected", + SohImGui::GetConsole()->SendInfoMessage("[SOH] Slot %u selected", OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot()); return CMD_SUCCESS; } @@ -488,7 +488,7 @@ static bool SetCVarHandler(std::shared_ptr Console, const std::ve CVar_Save(); - //SohImGui::console->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z); + //SohImGui::GetConsole()->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z); return CMD_SUCCESS; } @@ -502,17 +502,17 @@ static bool GetCVarHandler(std::shared_ptr Console, const std::ve if (cvar != nullptr) { if (cvar->type == CVarType::S32) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); else if (cvar->type == CVarType::Float) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); else if (cvar->type == CVarType::String) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); else if (cvar->type == CVarType::RGBA) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); } else { - SohImGui::console->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str()); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str()); } diff --git a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp b/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp deleted file mode 100644 index 7fec0de14..000000000 --- a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "ImGuiHelpers.h" -#include "../../../../libultraship/libultraship/ImGuiImpl.h" - -// Adds a text tooltip for the previous ImGui item -void SetLastItemHoverText(const std::string& text) { - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); - ImGui::EndTooltip(); - } -} - -// Adds a "?" next to the previous ImGui item with a custom tooltip -void InsertHelpHoverText(const std::string& text) { - ImGui::SameLine(); - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); - ImGui::EndTooltip(); - } -} diff --git a/soh/soh/Enhancements/debugger/ImGuiHelpers.h b/soh/soh/Enhancements/debugger/ImGuiHelpers.h deleted file mode 100644 index 7f01e4580..000000000 --- a/soh/soh/Enhancements/debugger/ImGuiHelpers.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "../libultraship/Lib/ImGui/imgui.h" - -#include - -void SetLastItemHoverText(const std::string& text); - -void InsertHelpHoverText(const std::string& text); diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp index 33bc532a0..8c6a4d543 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.cpp +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -1,13 +1,13 @@ #include "actorViewer.h" #include "../../util.h" -#include "../libultraship/ImGuiImpl.h" -#include "ImGuiHelpers.h" +#include "../../UIWidgets.hpp" +#include #include #include #include #include -#include +#include extern "C" { #include @@ -632,7 +632,7 @@ void DrawActorViewer(bool& open) { if (display.category == ACTORCAT_BOSS || display.category == ACTORCAT_ENEMY) { ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display.colChkInfo.health); - InsertHelpHoverText("Some actors might not use this!"); + UIWidgets::InsertHelpHoverText("Some actors might not use this!"); } if (ImGui::Button("Refresh")) { @@ -667,7 +667,7 @@ void DrawActorViewer(bool& open) { rm = TARGET; } } - InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies"); + UIWidgets::InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies"); if (ImGui::Button("Fetch from Held")) { Player* player = GET_PLAYER(gGlobalCtx); fetch = player->heldActor; @@ -678,7 +678,7 @@ void DrawActorViewer(bool& open) { rm = HELD; } } - InsertHelpHoverText("Grabs actor that Link is holding"); + UIWidgets::InsertHelpHoverText("Grabs actor that Link is holding"); if (ImGui::Button("Fetch from Interaction")) { Player* player = GET_PLAYER(gGlobalCtx); fetch = player->interactRangeActor; @@ -689,7 +689,7 @@ void DrawActorViewer(bool& open) { rm = INTERACT; } } - InsertHelpHoverText("Grabs actor from \"interaction range\""); + UIWidgets::InsertHelpHoverText("Grabs actor from \"interaction range\""); ImGui::TreePop(); } @@ -776,4 +776,4 @@ void DrawActorViewer(bool& open) { void InitActorViewer() { SohImGui::AddWindow("Developer Tools", "Actor Viewer", DrawActorViewer); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index e98ff0399..0146e626f 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -1,12 +1,12 @@ #include "colViewer.h" -#include "../libultraship/ImGuiImpl.h" -#include "ImGuiHelpers.h" +#include #include "../../frame_interpolation.h" +#include "../../UIWidgets.hpp" #include #include #include -#include +#include extern "C" { #include @@ -62,42 +62,42 @@ void DrawColViewerWindow(bool& open) { ImGui::End(); return; } - SohImGui::EnhancementCheckbox("Enabled", "gColViewerEnabled"); + UIWidgets::EnhancementCheckbox("Enabled", "gColViewerEnabled"); - SohImGui::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames); - SohImGui::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames); - SohImGui::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames); - SohImGui::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames); - SohImGui::EnhancementCheckbox("Apply as decal", "gColViewerDecal"); - InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " + UIWidgets::EnhancementCheckbox("Apply as decal", "gColViewerDecal"); + UIWidgets::InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " "with the scene geometry, but can cause other artifacts."); - SohImGui::EnhancementCheckbox("Shaded", "gColViewerShaded"); - InsertHelpHoverText("Applies the scene's shading to the collision display."); + UIWidgets::EnhancementCheckbox("Shaded", "gColViewerShaded"); + UIWidgets::InsertHelpHoverText("Applies the scene's shading to the collision display."); // This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered() const std::string colorHelpText = "View and change the colors used for collision display."; if (ImGui::TreeNode("Colors")) { - InsertHelpHoverText(colorHelpText); + UIWidgets::InsertHelpHoverText(colorHelpText); - SohImGui::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false); - SohImGui::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255), + UIWidgets::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false); + UIWidgets::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255), false); - SohImGui::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false); - SohImGui::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface", + UIWidgets::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false); + UIWidgets::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface", specialSurface_col, ImVec4(192, 255, 192, 255), false); - SohImGui::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable", + UIWidgets::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable", interactable_col, ImVec4(192, 0, 192, 255), false); - SohImGui::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false); - SohImGui::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false); - SohImGui::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false); - SohImGui::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false); - SohImGui::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false); - SohImGui::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false); + UIWidgets::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false); + UIWidgets::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false); + UIWidgets::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false); + UIWidgets::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false); + UIWidgets::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false); + UIWidgets::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false); ImGui::TreePop(); } else { - InsertHelpHoverText(colorHelpText); + UIWidgets::InsertHelpHoverText(colorHelpText); } ImGui::End(); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 5e21cec08..dfe947be8 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1,13 +1,13 @@ #include "debugSaveEditor.h" #include "../../util.h" -#include "../libultraship/ImGuiImpl.h" -#include "ImGuiHelpers.h" +#include +#include "../../UIWidgets.hpp" #include #include #include #include -#include +#include extern "C" { #include @@ -309,7 +309,7 @@ void DrawInfoTab() { ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::Text("Name: %s", name.c_str()); - InsertHelpHoverText("Player Name"); + UIWidgets::InsertHelpHoverText("Player Name"); std::string nameID; for (int i = 0; i < 8; i++) { nameID = z2ASCII(i); @@ -326,7 +326,7 @@ void DrawInfoTab() { if (ImGui::IsItemDeactivated()) { gSaveContext.healthCapacity = healthIntermediary; } - InsertHelpHoverText("Maximum health. 16 units per full heart"); + UIWidgets::InsertHelpHoverText("Maximum health. 16 units per full heart"); if (gSaveContext.health > gSaveContext.healthCapacity) { gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max } @@ -335,7 +335,7 @@ void DrawInfoTab() { const uint16_t healthMax = gSaveContext.healthCapacity; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SliderScalar("Health", ImGuiDataType_S16, &gSaveContext.health, &healthMin, &healthMax); - InsertHelpHoverText("Current health. 16 units per full heart"); + UIWidgets::InsertHelpHoverText("Current health. 16 units per full heart"); bool doubleDefense = gSaveContext.doubleDefense != 0; if (ImGui::Checkbox("Double Defense", &doubleDefense)) { @@ -343,7 +343,7 @@ void DrawInfoTab() { gSaveContext.inventory.defenseHearts = gSaveContext.doubleDefense ? 20 : 0; // Set to get the border drawn in the UI } - InsertHelpHoverText("Is double defense unlocked?"); + UIWidgets::InsertHelpHoverText("Is double defense unlocked?"); std::string magicName; if (gSaveContext.magicLevel == 2) { @@ -373,7 +373,7 @@ void DrawInfoTab() { ImGui::EndCombo(); } - InsertHelpHoverText("Current magic level"); + UIWidgets::InsertHelpHoverText("Current magic level"); gSaveContext.unk_13F4 = gSaveContext.magicLevel * 0x30; // Set to get the bar drawn in the UI if (gSaveContext.magic > gSaveContext.unk_13F4) { gSaveContext.magic = gSaveContext.unk_13F4; // Clamp magic to new max @@ -383,16 +383,16 @@ void DrawInfoTab() { const uint8_t magicMax = gSaveContext.unk_13F4; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SliderScalar("Magic", ImGuiDataType_S8, &gSaveContext.magic, &magicMin, &magicMax); - InsertHelpHoverText("Current magic. 48 units per magic level"); + UIWidgets::InsertHelpHoverText("Current magic. 48 units per magic level"); ImGui::InputScalar("Rupees", ImGuiDataType_S16, &gSaveContext.rupees); - InsertHelpHoverText("Current rupees"); + UIWidgets::InsertHelpHoverText("Current rupees"); const uint16_t dayTimeMin = 0; const uint16_t dayTimeMax = 0xFFFF; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SliderScalar("Time", ImGuiDataType_U16, &gSaveContext.dayTime, &dayTimeMin, &dayTimeMax); - InsertHelpHoverText("Time of day"); + UIWidgets::InsertHelpHoverText("Time of day"); if (ImGui::Button("Dawn")) { gSaveContext.dayTime = 0x4000; } @@ -410,43 +410,43 @@ void DrawInfoTab() { } ImGui::InputScalar("Total Days", ImGuiDataType_S32, &gSaveContext.totalDays); - InsertHelpHoverText("Total number of days elapsed since the start of the game"); + UIWidgets::InsertHelpHoverText("Total number of days elapsed since the start of the game"); ImGui::InputScalar("Deaths", ImGuiDataType_U16, &gSaveContext.deaths); - InsertHelpHoverText("Total number of deaths"); + UIWidgets::InsertHelpHoverText("Total number of deaths"); bool bgsFlag = gSaveContext.bgsFlag != 0; if (ImGui::Checkbox("Has BGS", &bgsFlag)) { gSaveContext.bgsFlag = bgsFlag; } - InsertHelpHoverText("Is Biggoron sword unlocked? Replaces Giant's knife"); + UIWidgets::InsertHelpHoverText("Is Biggoron sword unlocked? Replaces Giant's knife"); ImGui::InputScalar("Sword Health", ImGuiDataType_U16, &gSaveContext.swordHealth); - InsertHelpHoverText("Giant's knife health. Default is 8. Must be >0 for Biggoron sword to work"); + UIWidgets::InsertHelpHoverText("Giant's knife health. Default is 8. Must be >0 for Biggoron sword to work"); ImGui::InputScalar("Bgs Day Count", ImGuiDataType_S32, &gSaveContext.bgsDayCount); - InsertHelpHoverText("Total number of days elapsed since giving Biggoron the claim check"); + UIWidgets::InsertHelpHoverText("Total number of days elapsed since giving Biggoron the claim check"); ImGui::InputScalar("Entrance Index", ImGuiDataType_S32, &gSaveContext.entranceIndex); - InsertHelpHoverText("From which entrance did Link arrive?"); + UIWidgets::InsertHelpHoverText("From which entrance did Link arrive?"); ImGui::InputScalar("Cutscene Index", ImGuiDataType_S32, &gSaveContext.cutsceneIndex); - InsertHelpHoverText("Which cutscene is this?"); + UIWidgets::InsertHelpHoverText("Which cutscene is this?"); ImGui::InputScalar("Navi Timer", ImGuiDataType_U16, &gSaveContext.naviTimer); - InsertHelpHoverText("Navi wants to talk at 600 units, decides not to at 3000."); + UIWidgets::InsertHelpHoverText("Navi wants to talk at 600 units, decides not to at 3000."); ImGui::InputScalar("Timer 1 State", ImGuiDataType_S16, &gSaveContext.timer1State); - InsertHelpHoverText("Heat timer, race timer, etc. Has white font"); + UIWidgets::InsertHelpHoverText("Heat timer, race timer, etc. Has white font"); ImGui::InputScalar("Timer 1 Value", ImGuiDataType_S16, &gSaveContext.timer1Value, &one, NULL); - InsertHelpHoverText("Time, in seconds"); + UIWidgets::InsertHelpHoverText("Time, in seconds"); ImGui::InputScalar("Timer 2 State", ImGuiDataType_S16, &gSaveContext.timer2State); - InsertHelpHoverText("Trade timer, Ganon collapse timer, etc. Has yellow font"); + UIWidgets::InsertHelpHoverText("Trade timer, Ganon collapse timer, etc. Has yellow font"); ImGui::InputScalar("Timer 2 Value", ImGuiDataType_S16, &gSaveContext.timer2Value, &one, NULL); - InsertHelpHoverText("Time, in seconds"); + UIWidgets::InsertHelpHoverText("Time, in seconds"); const char* audioName; switch (gSaveContext.audioSetting) { @@ -481,13 +481,13 @@ void DrawInfoTab() { ImGui::EndCombo(); } - InsertHelpHoverText("Sound setting"); + UIWidgets::InsertHelpHoverText("Sound setting"); bool n64DDFlag = gSaveContext.n64ddFlag != 0; if (ImGui::Checkbox("64 DD file?", &n64DDFlag)) { gSaveContext.n64ddFlag = n64DDFlag; } - InsertHelpHoverText("WARNING! If you save, your file may be locked! Use caution!"); + UIWidgets::InsertHelpHoverText("WARNING! If you save, your file may be locked! Use caution!"); if (ImGui::BeginCombo("Z Target Mode", gSaveContext.zTargetSetting ? "Hold" : "Switch")) { if (ImGui::Selectable("Switch")) { @@ -498,7 +498,7 @@ void DrawInfoTab() { } ImGui::EndCombo(); } - InsertHelpHoverText("Z-Targeting behavior"); + UIWidgets::InsertHelpHoverText("Z-Targeting behavior"); ImGui::PushItemWidth(ImGui::GetFontSize() * 10); @@ -529,7 +529,7 @@ void DrawInventoryTab() { static bool restrictToValid = true; ImGui::Checkbox("Restrict to valid items", &restrictToValid); - InsertHelpHoverText("Restricts items and ammo to only what is possible to legally acquire in-game"); + UIWidgets::InsertHelpHoverText("Restricts items and ammo to only what is possible to legally acquire in-game"); for (int32_t y = 0; y < 4; y++) { for (int32_t x = 0; x < 6; x++) { @@ -568,7 +568,7 @@ void DrawInventoryTab() { gSaveContext.inventory.items[selectedIndex] = ITEM_NONE; ImGui::CloseCurrentPopup(); } - SetLastItemHoverText("None"); + UIWidgets::SetLastItemHoverText("None"); std::vector possibleItems; if (restrictToValid) { @@ -598,7 +598,7 @@ void DrawInventoryTab() { gSaveContext.inventory.items[selectedIndex] = slotEntry.id; ImGui::CloseCurrentPopup(); } - SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); } ImGui::EndPopup(); @@ -682,7 +682,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Switch"); - InsertHelpHoverText("Permanently-saved switch flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved switch flags"); DrawFlagArray32("Switch", act->flags.swch); }); @@ -690,13 +690,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Switch"); - InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); + UIWidgets::InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); DrawFlagArray32("Temp Switch", act->flags.tempSwch); }); DrawGroupWithBorder([&]() { ImGui::Text("Clear"); - InsertHelpHoverText("Permanently-saved room-clear flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved room-clear flags"); DrawFlagArray32("Clear", act->flags.clear); }); @@ -704,13 +704,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Clear"); - InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); + UIWidgets::InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); DrawFlagArray32("Temp Clear", act->flags.tempClear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); - InsertHelpHoverText("Permanently-saved collect flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved collect flags"); DrawFlagArray32("Collect", act->flags.collect); }); @@ -718,13 +718,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Collect"); - InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); + UIWidgets::InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); DrawFlagArray32("Temp Collect", act->flags.tempCollect); }); DrawGroupWithBorder([&]() { ImGui::Text("Chest"); - InsertHelpHoverText("Permanently-saved chest flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved chest flags"); DrawFlagArray32("Chest", act->flags.chest); }); @@ -738,7 +738,7 @@ void DrawFlagsTab() { act->flags.collect = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect; act->flags.chest = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest; } - SetLastItemHoverText("Load flags from saved scene flags. Normally happens on scene load"); + UIWidgets::SetLastItemHoverText("Load flags from saved scene flags. Normally happens on scene load"); if (ImGui::Button("Save Flags")) { gSaveContext.sceneFlags[gGlobalCtx->sceneNum].swch = act->flags.swch; @@ -746,7 +746,7 @@ void DrawFlagsTab() { gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect = act->flags.collect; gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest = act->flags.chest; } - SetLastItemHoverText("Save current scene flags. Normally happens on scene exit"); + UIWidgets::SetLastItemHoverText("Save current scene flags. Normally happens on scene exit"); ImGui::EndGroup(); } else { @@ -776,12 +776,12 @@ void DrawFlagsTab() { if (ImGui::Button("Current")) { selectedSceneFlagMap = gGlobalCtx->sceneNum; } - SetLastItemHoverText("Open flags for current scene"); + UIWidgets::SetLastItemHoverText("Open flags for current scene"); } DrawGroupWithBorder([&]() { ImGui::Text("Switch"); - InsertHelpHoverText("Switch flags"); + UIWidgets::InsertHelpHoverText("Switch flags"); DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch); }); @@ -789,13 +789,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Clear"); - InsertHelpHoverText("Room-clear flags"); + UIWidgets::InsertHelpHoverText("Room-clear flags"); DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); - InsertHelpHoverText("Collect flags"); + UIWidgets::InsertHelpHoverText("Collect flags"); DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect); }); @@ -803,13 +803,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Chest"); - InsertHelpHoverText("Chest flags"); + UIWidgets::InsertHelpHoverText("Chest flags"); DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest); }); DrawGroupWithBorder([&]() { ImGui::Text("Rooms"); - InsertHelpHoverText("Flags for visted rooms"); + UIWidgets::InsertHelpHoverText("Flags for visted rooms"); DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms); }); @@ -817,7 +817,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Floors"); - InsertHelpHoverText("Flags for visted floors"); + UIWidgets::InsertHelpHoverText("Flags for visted floors"); DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors); }); @@ -870,7 +870,7 @@ void DrawFlagsTab() { static bool keepGsCountUpdated = true; ImGui::Checkbox("Keep GS Count Updated", &keepGsCountUpdated); - InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags"); + UIWidgets::InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags"); int32_t gsCount = 0; if (keepGsCountUpdated) { for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) { @@ -883,85 +883,85 @@ void DrawFlagsTab() { if (ImGui::TreeNode("Event Check Inf Flags")) { DrawGroupWithBorder([&]() { ImGui::Text("0"); - InsertHelpHoverText("Mostly Kokiri Forest related"); + UIWidgets::InsertHelpHoverText("Mostly Kokiri Forest related"); DrawFlagArray16("eci0", gSaveContext.eventChkInf[0]); }); DrawGroupWithBorder([&]() { ImGui::Text("1"); - InsertHelpHoverText("Mostly Lon Lon Ranch related"); + UIWidgets::InsertHelpHoverText("Mostly Lon Lon Ranch related"); DrawFlagArray16("eci1", gSaveContext.eventChkInf[1]); }); DrawGroupWithBorder([&]() { ImGui::Text("2"); - InsertHelpHoverText("Dodongo Related?"); + UIWidgets::InsertHelpHoverText("Dodongo Related?"); DrawFlagArray16("eci2", gSaveContext.eventChkInf[2]); }); DrawGroupWithBorder([&]() { ImGui::Text("3"); - InsertHelpHoverText("Mostly Zora related"); + UIWidgets::InsertHelpHoverText("Mostly Zora related"); DrawFlagArray16("eci3", gSaveContext.eventChkInf[3]); }); DrawGroupWithBorder([&]() { ImGui::Text("4"); - InsertHelpHoverText("Random"); + UIWidgets::InsertHelpHoverText("Random"); DrawFlagArray16("eci4", gSaveContext.eventChkInf[4]); }); DrawGroupWithBorder([&]() { ImGui::Text("5"); - InsertHelpHoverText("Mostly song learning related"); + UIWidgets::InsertHelpHoverText("Mostly song learning related"); DrawFlagArray16("eci5", gSaveContext.eventChkInf[5]); }); DrawGroupWithBorder([&]() { ImGui::Text("6"); - InsertHelpHoverText("Random"); + UIWidgets::InsertHelpHoverText("Random"); DrawFlagArray16("eci6", gSaveContext.eventChkInf[6]); }); DrawGroupWithBorder([&]() { ImGui::Text("7"); - InsertHelpHoverText("Boss Battle related"); + UIWidgets::InsertHelpHoverText("Boss Battle related"); DrawFlagArray16("eci7", gSaveContext.eventChkInf[7]); }); DrawGroupWithBorder([&]() { ImGui::Text("8"); - InsertHelpHoverText("Mask related?"); + UIWidgets::InsertHelpHoverText("Mask related?"); DrawFlagArray16("eci8", gSaveContext.eventChkInf[8]); }); DrawGroupWithBorder([&]() { ImGui::Text("9"); - InsertHelpHoverText("Mostly carpenter related"); + UIWidgets::InsertHelpHoverText("Mostly carpenter related"); DrawFlagArray16("eci9", gSaveContext.eventChkInf[9]); }); DrawGroupWithBorder([&]() { ImGui::Text("A"); - InsertHelpHoverText("First-time overworld entrance cs related"); + UIWidgets::InsertHelpHoverText("First-time overworld entrance cs related"); DrawFlagArray16("eci10", gSaveContext.eventChkInf[10]); }); DrawGroupWithBorder([&]() { ImGui::Text("B"); - InsertHelpHoverText("First-time dungeon entrance cs/trial cs related"); + UIWidgets::InsertHelpHoverText("First-time dungeon entrance cs/trial cs related"); DrawFlagArray16("eci11", gSaveContext.eventChkInf[11]); }); DrawGroupWithBorder([&]() { ImGui::Text("C"); - InsertHelpHoverText("Random"); + UIWidgets::InsertHelpHoverText("Random"); DrawFlagArray16("eci12", gSaveContext.eventChkInf[12]); }); DrawGroupWithBorder([&]() { ImGui::Text("D"); - InsertHelpHoverText("Frog songs/GS rewards"); + UIWidgets::InsertHelpHoverText("Frog songs/GS rewards"); DrawFlagArray16("eci13", gSaveContext.eventChkInf[13]); }); @@ -1014,7 +1014,7 @@ void DrawUpgrade(const std::string& categoryName, int32_t categoryId, const std: ImGui::EndCombo(); } ImGui::PopID(); - SetLastItemHoverText(categoryName.c_str()); + UIWidgets::SetLastItemHoverText(categoryName.c_str()); } // Draws a combo that lets you choose and upgrade value from a popup grid of icons @@ -1039,7 +1039,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const } ImGui::PopStyleVar(); ImGui::PopStyleColor(); - SetLastItemHoverText(categoryName.c_str()); + UIWidgets::SetLastItemHoverText(categoryName.c_str()); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); if (ImGui::BeginPopup(upgradePopupPicker)) { @@ -1053,7 +1053,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const Inventory_ChangeUpgrade(categoryId, pickerIndex); ImGui::CloseCurrentPopup(); } - SetLastItemHoverText("None"); + UIWidgets::SetLastItemHoverText("None"); } else { const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]]; if (ImGui::ImageButton(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), @@ -1061,7 +1061,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const Inventory_ChangeUpgrade(categoryId, pickerIndex); ImGui::CloseCurrentPopup(); } - SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); } } @@ -1103,7 +1103,7 @@ void DrawEquipmentTab() { } ImGui::PopStyleColor(); ImGui::PopID(); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } const std::vector bulletBagValues = { @@ -1193,7 +1193,7 @@ void DrawQuestItemButton(uint32_t item) { } } ImGui::PopStyleColor(); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); } // Draws a toggleable icon for a dungeon item that is faded when disabled @@ -1211,7 +1211,7 @@ void DrawDungeonItemButton(uint32_t item, uint32_t scene) { } } ImGui::PopStyleColor(); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } void DrawQuestStatusTab() { @@ -1258,11 +1258,11 @@ void DrawQuestStatusTab() { } } ImGui::PopStyleColor(); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); } ImGui::InputScalar("GS Count", ImGuiDataType_S16, &gSaveContext.inventory.gsTokens); - InsertHelpHoverText("Number of gold skulltula tokens aquired"); + UIWidgets::InsertHelpHoverText("Number of gold skulltula tokens aquired"); uint32_t bitMask = 1 << QUEST_SKULL_TOKEN; bool gsUnlocked = (bitMask & gSaveContext.inventory.questItems) != 0; @@ -1273,7 +1273,7 @@ void DrawQuestStatusTab() { gSaveContext.inventory.questItems &= ~bitMask; } } - InsertHelpHoverText("If unlocked, enables showing the gold skulltula count in the quest status menu"); + UIWidgets::InsertHelpHoverText("If unlocked, enables showing the gold skulltula count in the quest status menu"); int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28; if (ImGui::BeginCombo("PoH count", std::to_string(pohCount).c_str())) { @@ -1285,7 +1285,7 @@ void DrawQuestStatusTab() { } ImGui::EndCombo(); } - InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container"); + UIWidgets::InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container"); DrawGroupWithBorder([&]() { ImGui::Text("Dungeon Items"); @@ -1410,7 +1410,7 @@ void DrawPlayerTab() { DrawGroupWithBorder([&]() { ImGui::Text("Link's Rotation"); - InsertHelpHoverText("For Link's rotation in relation to the world"); + UIWidgets::InsertHelpHoverText("For Link's rotation in relation to the world"); ImGui::InputScalar("X Rot", ImGuiDataType_S16, &player->actor.world.rot.x); ImGui::SameLine(); ImGui::InputScalar("Y Rot", ImGuiDataType_S16, &player->actor.world.rot.y); @@ -1420,7 +1420,7 @@ void DrawPlayerTab() { DrawGroupWithBorder([&]() { ImGui::Text("Link's Model Rotation"); - InsertHelpHoverText("For Link's actual model"); + UIWidgets::InsertHelpHoverText("For Link's actual model"); ImGui::InputScalar("X ModRot", ImGuiDataType_S16, &player->actor.shape.rot.x); ImGui::SameLine(); ImGui::InputScalar("Y ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y); @@ -1429,19 +1429,19 @@ void DrawPlayerTab() { }); ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity); - InsertHelpHoverText("Link's speed along the XZ plane"); + UIWidgets::InsertHelpHoverText("Link's speed along the XZ plane"); ImGui::InputScalar("Y Velocity", ImGuiDataType_Float, &player->actor.velocity.y); - InsertHelpHoverText("Link's speed along the Y plane. Caps at -20"); + UIWidgets::InsertHelpHoverText("Link's speed along the Y plane. Caps at -20"); ImGui::InputScalar("Wall Height", ImGuiDataType_Float, &player->wallHeight); - InsertHelpHoverText("Height used to determine whether Link can climb or grab a ledge at the top"); + UIWidgets::InsertHelpHoverText("Height used to determine whether Link can climb or grab a ledge at the top"); ImGui::InputScalar("Invincibility Timer", ImGuiDataType_S8, &player->invincibilityTimer); - InsertHelpHoverText("Can't take damage while this is nonzero"); + UIWidgets::InsertHelpHoverText("Can't take damage while this is nonzero"); ImGui::InputScalar("Gravity", ImGuiDataType_Float, &player->actor.gravity); - InsertHelpHoverText("Rate at which Link falls. Default -4.0f"); + UIWidgets::InsertHelpHoverText("Rate at which Link falls. Default -4.0f"); if (ImGui::BeginCombo("Link Age on Load", gGlobalCtx->linkAgeOnLoad == 0 ? "Adult" : "Child")) { if (ImGui::Selectable("Adult")) { @@ -1453,7 +1453,7 @@ void DrawPlayerTab() { ImGui::EndCombo(); } - InsertHelpHoverText("This will change Link's age when you load a map"); + UIWidgets::InsertHelpHoverText("This will change Link's age when you load a map"); ImGui::Separator(); diff --git a/soh/soh/Enhancements/gameconsole.h b/soh/soh/Enhancements/gameconsole.h index 33301afe6..27838ff63 100644 --- a/soh/soh/Enhancements/gameconsole.h +++ b/soh/soh/Enhancements/gameconsole.h @@ -3,7 +3,7 @@ #include #include -#include "Cvar.h" +#include #define MAX_CVARS 2048 @@ -39,4 +39,4 @@ s32 GameConsole_Split(char* str, char** argv); } #endif -#endif \ No newline at end of file +#endif diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp index 144759e29..549624760 100644 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include std::list entranceOverrides = {}; bool noRandomEntrances = false; diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 14bf594c2..34037f3a1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include using namespace CustomMessages; using namespace Logic; diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 4c18524fc..b5f0743fb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -12,7 +12,7 @@ #include "trial.hpp" #include "entrance.hpp" #include "z64item.h" -#include +#include using namespace CustomMessages; using namespace Logic; diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp index 27101864b..83cf12b30 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp @@ -6,7 +6,7 @@ #include "shops.hpp" #include "debug.hpp" #include "keys.hpp" -#include +#include //Location definitions static std::array locationTable; @@ -1577,4 +1577,4 @@ void CreateItemOverrides() { } SPDLOG_DEBUG("Overrides Created: "); SPDLOG_DEBUG(std::to_string(overrides.size())); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index b7ed68ea6..ad85bd401 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -9,7 +9,7 @@ #include "settings.hpp" #include "spoiler_log.hpp" #include "z64item.h" -#include +#include using namespace Settings; diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index f7699b754..468758fe3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -13,8 +13,8 @@ #include "spoiler_log.hpp" #include "location_access.hpp" #include "debug.hpp" -#include -#include "soh/Enhancements/randomizer/randomizerTypes.h" +#include +#include "../../randomizer/randomizerTypes.h" namespace { bool seedChanged; @@ -547,4 +547,4 @@ std::string GenerateRandomizer(std::unordered_map std::string GetInput(const char* hintText) { return std::string(); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index 7d0fc8b14..ac68e579b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -5,9 +5,9 @@ #include "location_access.hpp" #include "rando_main.hpp" // #include -#include -#include -#include +#include +#include +#include #define TICKS_PER_SEC 268123480.0 @@ -25,4 +25,4 @@ void RandoMain::GenerateRando(std::unordered_map cvarS CVar_Save(); CVar_Load(); CVar_SetS32("gNewSeedGenerated", 1); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index c9af08082..9ea43f2b2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -11,7 +11,7 @@ #include "utils.hpp" #include "shops.hpp" #include "hints.hpp" -#include "Lib/nlohmann/json.hpp" +#include #include #include @@ -26,7 +26,7 @@ #include #include -#include "Window.h" +#include using json = nlohmann::json; @@ -771,4 +771,4 @@ bool PlacementLog_Write() { contentNode->SetCData(true); return true; -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 495850361..0d0f4300b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1,21 +1,21 @@ #include "randomizer.h" -#include "Lib/nlohmann/json.hpp" +#include #include #include #include #include #include -#include +#include #include #include -#include "../libultraship/ImGuiImpl.h" +#include #include #include "3drando/rando_main.hpp" -#include -#include "Lib/ImGui/imgui_internal.h" -#include -#include -#include +#include "../../UIWidgets.hpp" +#include +#include "../custom-message/CustomMessageManager.h" +#include "../custom-message/CustomMessageTypes.h" +#include "../item-tables/ItemTableManager.h" #include using json = nlohmann::json; @@ -3364,7 +3364,7 @@ void DrawRandoEditor(bool& open) { ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * disableEditingRandoSettings ? 0.5f : 1.0f); - SohImGui::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); + UIWidgets::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); if (CVar_GetS32("gRandomizer", 0) == 1) { if (ImGui::Button("Generate Seed")) { @@ -3404,17 +3404,17 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Forest"); switch (CVar_GetS32("gRandomizeForest", 1)) { case 1: - InsertHelpHoverText("Mido no longer blocks the path to the Deku Tree\n" + UIWidgets::InsertHelpHoverText("Mido no longer blocks the path to the Deku Tree\n" "The Kokiri boy no longer blocks the path out of the forest."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The Kokiri boy no longer blocks the path out of the forest\nMido " "still blocks the path to the Deku Tree, requiring the Kokiri Sword " "and a Deku Shield to access the Deku Tree."); break; case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Beating Deku Tree is logically required to leave the forest area " "(Kokiri Forest / Lost Woods / Sacred Forest Meadow / Deku Tree) " "while the Kokiri Sword and a Deku Shield are required to access the " @@ -3422,125 +3422,125 @@ void DrawRandoEditor(bool& open) { "forest area.\nThis setting is incompatible with starting as adult."); break; } - SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 1); + UIWidgets::EnhancementCombobox("gRandomizeForest", randoForest, 3, 1); ImGui::Separator(); // Kakariko Gate ImGui::Text("Kakariko Gate"); switch (CVar_GetS32("gRandomizeKakarikoGate", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The gate and the Happy Mask Shop both remain closed until showing " "Zelda's Letter to the guard in Kakariko."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The gate is always open instead of needing Zelda's Letter.\nThe Happy Mask Shop " "opens upon obtaining Zelda's Letter without needing to show it to the guard."); break; } - SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 1); + UIWidgets::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 1); ImGui::Separator(); // Door of Time ImGui::Text("Door of Time"); switch (CVar_GetS32("gRandomizeDoorOfTime", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The Door of Time starts opened instead of needing to play the Song of Time."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Only an Ocarina and the Song of Time need to be found to open the Door of Time."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The Ocarina of Time, the Song of Time and all Spiritual Stones need to " "be found to open the Door of Time."); break; } - SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); ImGui::Separator(); // Zora's Fountain ImGui::Text("Zora's Fountain"); switch (CVar_GetS32("gRandomizeZorasFountain", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "King Zora obstructs the way to Zora's Fountain.\nRuto's Letter must be " "shown as child in order to move him from both eras."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "King Zora is always moved in the adult era.\nThis means Ruto's Letter is " "only required to access Zora's fountain as child."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "King Zora starts as moved in both the child and adult eras.\nThis also " "removes Ruto's Letter from the pool since it can't be used."); break; } - SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); ImGui::Separator(); // Gerudo Fortress ImGui::Text("Gerudo Fortress"); switch (CVar_GetS32("gRandomizeGerudoFortress", 0)) { case 0: - InsertHelpHoverText("All 4 carpenters can be rescued."); + UIWidgets::InsertHelpHoverText("All 4 carpenters can be rescued."); break; case 1: - InsertHelpHoverText("Only the bottom left carpenter must be rescued."); + UIWidgets::InsertHelpHoverText("Only the bottom left carpenter must be rescued."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The carpenters are rescued from the start of the game and if \"Shuffle " "Gerudo Card\" is disabled, the player starts with the Gerudo Card in " "the inventory allowing access to Gerudo Training Grounds."); break; } - SohImGui::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 1); + UIWidgets::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 1); ImGui::Separator(); // Rainbow Bridge ImGui::Text("Rainbow Bridge"); - SohImGui::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 3); + UIWidgets::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 3); switch (CVar_GetS32("gRandomizeRainbowBridge", 3)) { case 1: - InsertHelpHoverText("The Rainbow Bridge requires Shadow and Spirit Medallions as well " + UIWidgets::InsertHelpHoverText("The Rainbow Bridge requires Shadow and Spirit Medallions as well " "as Light Arrows."); break; case 2: - InsertHelpHoverText("The Rainbow Bridge requires collecting a configurable number of " + UIWidgets::InsertHelpHoverText("The Rainbow Bridge requires collecting a configurable number of " "Spiritual Stones."); - SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", + UIWidgets::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", "gRandomizeStoneCount", 0, 3, ""); - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "Sets the number of Spiritual Stones required to spawn the Rainbow Bridge."); break; case 3: - SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", + UIWidgets::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", "gRandomizeMedallionCount", 0, 6, "", 6); - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "The Rainbow Bridge requires collecting a configurable number of Medallions."); break; case 4: - SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", + UIWidgets::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", "gRandomizeRewardCount", 0, 9, ""); - SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " + UIWidgets::SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " "Dungeon Rewards."); break; case 5: - SohImGui::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", + UIWidgets::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", "gRandomizeDungeonCount", 0, 8, ""); - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "The Rainbow Bridge requires completing a configurable number of Dungeons.\nDungeons " "are considered complete when Link steps into the blue warp at the end of them."); break; case 6: - SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", + UIWidgets::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", "gRandomizeTokenCount", 0, 100, ""); - SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " + UIWidgets::SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " "Gold Skulltula Tokens."); break; } @@ -3557,8 +3557,8 @@ void DrawRandoEditor(bool& open) { // "gRandomizeGanonTrialCount", 0, 6, ""); //InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); // RANDTODO: Switch back to slider when pre-completing some of Ganon's Trials is properly implemnted. - SohImGui::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount"); + UIWidgets::InsertHelpHoverText( "Sets whether or not Ganon's Castle Trials are required to enter Ganon's Tower."); // } @@ -3698,23 +3698,23 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Shuffle Dungeon Rewards"); switch (CVar_GetS32("gRandomizeShuffleDungeonReward", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Medallions and Spiritual Stones will be given as rewards for beating dungeons.\n" "This setting will force Link's Pocket to be a Medallion or a Spiritual Stone."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Medallions and Spiritual Stones can only appear inside of dungeons."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Medallions and Spiritual Stones can only appear outside dungeons."); break; case 3: - InsertHelpHoverText("Medallions and Spiritual Stones can appear anywhere."); + UIWidgets::InsertHelpHoverText("Medallions and Spiritual Stones can appear anywhere."); break; } - SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, + UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); // todo: support non dungeon rewards for link's pocket @@ -3748,10 +3748,10 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Shuffle Songs"); switch (CVar_GetS32("gRandomizeShuffleSongs", 0)) { case 0: - InsertHelpHoverText("Songs will only appear at locations that normally teach songs."); + UIWidgets::InsertHelpHoverText("Songs will only appear at locations that normally teach songs."); break; case 1: - InsertHelpHoverText("Songs appear at the end of dungeons.\nFor major dungeons, they " + UIWidgets::InsertHelpHoverText("Songs appear at the end of dungeons.\nFor major dungeons, they " "will be at the boss heart container location.\nThe remaining 4 " "songs are placed at:\n- Zelda's Lullaby location\n" "- Ice Cavern's Serenade of Water Location\n" @@ -3759,10 +3759,10 @@ void DrawRandoEditor(bool& open) { "- Gerudo Training Ground's Ice Arrow Location."); break; case 2: - InsertHelpHoverText("Songs can appear in any location"); + UIWidgets::InsertHelpHoverText("Songs can appear in any location"); break; } - SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); ImGui::Separator(); // todo implement shops @@ -3863,19 +3863,19 @@ void DrawRandoEditor(bool& open) { if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { // Shuffle Kokiri Sword ImGui::Text("Shuffle Kokiri Sword"); - InsertHelpHoverText("Enabling this shuffles the Kokiri Sword into the item pool.\nThis will " + UIWidgets::InsertHelpHoverText("Enabling this shuffles the Kokiri Sword into the item pool.\nThis will " "require extensive use of sticks until the sword is found."); - SohImGui::EnhancementCombobox("gRandomizeShuffleKokiriSword", randoShuffleKokiriSword, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleKokiriSword", randoShuffleKokiriSword, 2, 0); ImGui::Separator(); } if(CVar_GetS32("gRandomizeStartingOcarina", 0) == 0) { // Shuffle Ocarinas ImGui::Text("Shuffle Ocarinas"); - InsertHelpHoverText("Enabling this shuffles the Fairy Ocarina and the Ocarina of time into " + UIWidgets::InsertHelpHoverText("Enabling this shuffles the Fairy Ocarina and the Ocarina of time into " "the item pool.\n" "This will require finding an Ocarina before being able to play songs."); - SohImGui::EnhancementCombobox("gRandomizeShuffleOcarinas", randoShuffleOcarinas, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleOcarinas", randoShuffleOcarinas, 2, 0); ImGui::Separator(); } @@ -3883,22 +3883,22 @@ void DrawRandoEditor(bool& open) { if(CVar_GetS32("gRandomizeSkipChildZelda", 0) == 0) { // Shuffle Weird Egg ImGui::Text("Shuffle Weird Egg"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Enabling this shuffles the Weird Egg from Malon into the item pool.\nThis " "will require finding the Weird Egg to talk to Zelda in Hyrule Castle which " "in turn unlocks rewards from Impa, Saria, Malon and Talon as well as the " "Happy Mask Sidequest.\nThe Weird egg is also required for Zelda's Letter to " "unlock the Kakariko Gate as child which can lock some progression."); - SohImGui::EnhancementCombobox("gRandomizeShuffleWeirdEgg", randoShuffleWeirdEgg, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleWeirdEgg", randoShuffleWeirdEgg, 2, 0); ImGui::Separator(); } // Shuffle Gerudo Membership Card ImGui::Text("Shuffle Gerudo Membership Card"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Enabling this shuffles the Gerudo Membership Card into the item pool.\nThe Gerudo " "Token is required to enter the Gerudo Training Ground."); - SohImGui::EnhancementCombobox("gRandomizeShuffleGerudoToken", randoShuffleGerudoToken, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleGerudoToken", randoShuffleGerudoToken, 2, 0); ImGui::Separator(); // todo implement magic bean 10 pack @@ -3939,14 +3939,14 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemWidth(); ImGui::TableNextColumn(); - SohImGui::EnhancementCheckbox("Start with Fairy Ocarina", "gRandomizeStartingOcarina"); - SohImGui::EnhancementCheckbox("Start with Kokiri Sword", "gRandomizeStartingKokiriSword"); - SohImGui::EnhancementCheckbox("Start with Deku Shield", "gRandomizeStartingDekuShield"); - SohImGui::EnhancementCheckbox("Start with Maps/Compasses", "gRandomizeStartingMapsCompasses"); - SohImGui::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); - SohImGui::EnhancementCheckbox("Start with Consumables", "gRandomizeStartingConsumables"); - SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); - InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); + UIWidgets::EnhancementCheckbox("Start with Fairy Ocarina", "gRandomizeStartingOcarina"); + UIWidgets::EnhancementCheckbox("Start with Kokiri Sword", "gRandomizeStartingKokiriSword"); + UIWidgets::EnhancementCheckbox("Start with Deku Shield", "gRandomizeStartingDekuShield"); + UIWidgets::EnhancementCheckbox("Start with Maps/Compasses", "gRandomizeStartingMapsCompasses"); + UIWidgets::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); + UIWidgets::EnhancementCheckbox("Start with Consumables", "gRandomizeStartingConsumables"); + UIWidgets::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); + UIWidgets::InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); // todo dungeon items stuff (more details in commented out block) // ImGui::TableNextColumn(); @@ -4088,19 +4088,19 @@ void DrawRandoEditor(bool& open) { // Ganon's Boss Key ImGui::PushItemWidth(-FLT_MIN); ImGui::Text("Ganon's Boss Key"); - SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 3, + UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 3, 0); switch (CVar_GetS32("gRandomizeShuffleGanonBossKey", 0)) { case 0: - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "Ganon's Boss Key is given to you from the start and you don't " "have to worry about finding it."); break; case 1: - SetLastItemHoverText("Ganon's Boss Key will appear in the vanilla location."); + UIWidgets::SetLastItemHoverText("Ganon's Boss Key will appear in the vanilla location."); break; case 2: - SetLastItemHoverText("Ganon's Boss Key will appear somewhere inside Ganon's Castle."); + UIWidgets::SetLastItemHoverText("Ganon's Boss Key will appear somewhere inside Ganon's Castle."); break; // case 0: // SetLastItemHoverText( @@ -4219,30 +4219,30 @@ void DrawRandoEditor(bool& open) { // ImGui::Separator(); // Cuccos to return - SohImGui::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", + UIWidgets::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", "gRandomizeCuccosToReturn", 0, 7, "", 7); - InsertHelpHoverText("The cucco Lady will give a reward for returning this many of her cuccos to the pen."); + UIWidgets::InsertHelpHoverText("The cucco Lady will give a reward for returning this many of her cuccos to the pen."); ImGui::Separator(); // // Big Poe Target Count - SohImGui::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", + UIWidgets::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", "gRandomizeBigPoeTargetCount", 1, 10, "", 10); - InsertHelpHoverText("The Poe buyer will give a reward for turning in the chosen number of Big Poes."); + UIWidgets::InsertHelpHoverText("The Poe buyer will give a reward for turning in the chosen number of Big Poes."); ImGui::Separator(); // // Skip child stealth - SohImGui::EnhancementCheckbox("Skip Child Stealth", "gRandomizeSkipChildStealth"); - InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); + UIWidgets::EnhancementCheckbox("Skip Child Stealth", "gRandomizeSkipChildStealth"); + UIWidgets::InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); ImGui::Separator(); // Skip Epona race - SohImGui::EnhancementCheckbox("Skip Epona Race", "gRandomizeSkipEponaRace"); - InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); + UIWidgets::EnhancementCheckbox("Skip Epona Race", "gRandomizeSkipEponaRace"); + UIWidgets::InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); ImGui::Separator(); // Skip tower escape - SohImGui::EnhancementCheckbox("Skip Tower Escape", "gRandomizeSkipTowerEscape"); - InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); + UIWidgets::EnhancementCheckbox("Skip Tower Escape", "gRandomizeSkipTowerEscape"); + UIWidgets::InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); ImGui::Separator(); // todo implement complete mask quest @@ -4275,53 +4275,53 @@ void DrawRandoEditor(bool& open) { ImGui::PushItemWidth(-FLT_MIN); // Gossip Stone Hints ImGui::Text("Gossip Stone Hints"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Gossip Stones can be made to give hints about where items can be found.\nDifferent settings can " "be chosen to decide which item is needed to speak to Gossip Stones. \nChoosing to stick with the " "Mask of Truth will make the hints very difficult to obtain.\nHints for \"on the way of the " "hero\" are locations that contain items that are required to beat the game."); - SohImGui::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) { // Hint Clarity ImGui::Indent(); ImGui::Text("Hint Clarity"); switch (CVar_GetS32("gRandomizeHintClarity", 2)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the difficulty of hints.\nObscure: Hints are unique for each thing, but the " "writing may be confusing.\nEx: Kokiri Sword > a butter knife"); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the difficulty of hints.\nAmbiguous: Hints are clearly written, " "but may refer to more than one thing.\nEx: Kokiri Sword > a sword"); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the difficulty of hints.\nClear: Hints are clearly written and " "are unique for each thing.\nEx: Kokiri Sword > the Kokiri Sword"); break; } - SohImGui::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); + UIWidgets::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); // Hint Distribution ImGui::Text("Hint Distribution"); switch (CVar_GetS32("gRandomizeHintDistribution", 1)) { case 0: - InsertHelpHoverText("Only junk hints."); + UIWidgets::InsertHelpHoverText("Only junk hints."); break; case 1: - InsertHelpHoverText("Recommended hint spread."); + UIWidgets::InsertHelpHoverText("Recommended hint spread."); break; case 2: - InsertHelpHoverText("More useful hints."); + UIWidgets::InsertHelpHoverText("More useful hints."); break; case 3: - InsertHelpHoverText("Many powerful hints."); + UIWidgets::InsertHelpHoverText("Many powerful hints."); break; } - SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); ImGui::Unindent(); } ImGui::Separator(); @@ -4375,43 +4375,43 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Item Pool"); switch (CVar_GetS32("gRandomizeItemPool", 1)) { case 0: - InsertHelpHoverText("Extra major items are added to the pool."); + UIWidgets::InsertHelpHoverText("Extra major items are added to the pool."); break; case 1: - InsertHelpHoverText("Original item pool."); + UIWidgets::InsertHelpHoverText("Original item pool."); break; case 2: - InsertHelpHoverText("Some excess items are removed, including health upgrades."); + UIWidgets::InsertHelpHoverText("Some excess items are removed, including health upgrades."); break; case 3: - InsertHelpHoverText("Most excess items are removed."); + UIWidgets::InsertHelpHoverText("Most excess items are removed."); break; } - SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); ImGui::Separator(); // // Ice Traps ImGui::Text("Ice Traps"); switch (CVar_GetS32("gRandomizeIceTraps", 1)) { case 0: - InsertHelpHoverText("All Ice Traps are removed."); + UIWidgets::InsertHelpHoverText("All Ice Traps are removed."); break; case 1: - InsertHelpHoverText("Only Ice Traps from the base item pool are placed."); + UIWidgets::InsertHelpHoverText("Only Ice Traps from the base item pool are placed."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Chance to add extra Ice Traps when junk items are added to the item pool."); break; case 3: - InsertHelpHoverText("All added junk items will be Ice Traps."); + UIWidgets::InsertHelpHoverText("All added junk items will be Ice Traps."); break; case 4: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "All junk items will be replaced by Ice Traps, even those in the base pool."); break; } - SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); + UIWidgets::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); ImGui::Separator(); // todo implement double defense getitem @@ -4450,17 +4450,17 @@ void DrawRandoEditor(bool& open) { ImGui::TableNextColumn(); // COLUMN 2 - OPEN EXCLUDE LOCATIONS ImGui::NewLine(); - SohImGui::EnhancementCheckbox("Deku Theater Mask of Truth", "gRandomizeExcludeDekuTheaterMaskOfTruth"); + UIWidgets::EnhancementCheckbox("Deku Theater Mask of Truth", "gRandomizeExcludeDekuTheaterMaskOfTruth"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("10 Skulltula Reward", "gRandomizeExcludeKak10SkullReward"); + UIWidgets::EnhancementCheckbox("10 Skulltula Reward", "gRandomizeExcludeKak10SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("20 Skulltula Reward", "gRandomizeExcludeKak20SkullReward"); + UIWidgets::EnhancementCheckbox("20 Skulltula Reward", "gRandomizeExcludeKak20SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("30 Skulltula Reward", "gRandomizeExcludeKak30SkullReward"); + UIWidgets::EnhancementCheckbox("30 Skulltula Reward", "gRandomizeExcludeKak30SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("40 Skulltula Reward", "gRandomizeExcludeKak40SkullReward"); + UIWidgets::EnhancementCheckbox("40 Skulltula Reward", "gRandomizeExcludeKak40SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("50 Skulltula Reward", "gRandomizeExcludeKak50SkullReward"); + UIWidgets::EnhancementCheckbox("50 Skulltula Reward", "gRandomizeExcludeKak50SkullReward"); // ImGui::TableNextColumn(); // // COLUMN 3 - LOGICAL TRICKS // ImGui::NewLine(); @@ -4742,4 +4742,4 @@ void Rando_Init(void) { InitRando(); } -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 2dcef684c..e9b321434 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -1,13 +1,13 @@ #include "randomizer_item_tracker.h" #include "../../util.h" -#include "../libultraship/ImGuiImpl.h" -#include +#include +#include "../../UIWidgets.hpp" #include #include #include #include -#include +#include extern "C" { #include @@ -20,6 +20,7 @@ extern GlobalContext* gGlobalCtx; #include "textures/icon_item_24_static/icon_item_24_static.h" } + typedef struct { uint32_t id; std::string name; @@ -252,7 +253,7 @@ void DrawEquip(uint32_t itemId) { ImGui::Image(SohImGui::GetTextureByName(hasEquip ? entry.name : entry.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } std::unordered_map questTrackerMap = { @@ -300,7 +301,7 @@ void DrawQuest(uint32_t itemId) { ImGui::EndGroup(); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); }; std::unordered_map itemTrackerMap = { @@ -677,7 +678,7 @@ void DrawItem(uint32_t itemId) { } ImGui::EndGroup(); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } void DrawBottle(uint32_t itemId, uint32_t bottleSlot) { @@ -688,7 +689,7 @@ void DrawBottle(uint32_t itemId, uint32_t bottleSlot) { ImGui::Image(SohImGui::GetTextureByName(hasItem ? entry.name : entry.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); }; typedef struct { @@ -733,12 +734,12 @@ void DrawUpgrade(int32_t categoryId) { const ItemTrackerUpgradeEntry& entry = upgradeTrackerMap[categoryId][0]; ImGui::Image(SohImGui::GetTextureByName(entry.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } else { const ItemTrackerUpgradeEntry& entry = upgradeTrackerMap[categoryId][CUR_UPG_VALUE(categoryId) - 1]; ImGui::Image(SohImGui::GetTextureByName(entry.name), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } } @@ -804,7 +805,7 @@ void DrawSong(int32_t songId) { bool hasSong = (bitMask & gSaveContext.inventory.questItems) != 0; ImGui::Image(SohImGui::GetTextureByName(hasSong ? entry.name : entry.nameFaded), ImVec2(iconSize/1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); } void DrawItemTracker(bool& open) { @@ -983,12 +984,12 @@ void DrawItemTracker(bool& open) { } else { minimalSpacingX = 32; } - SohImGui::EnhancementCheckbox("Display \"Ammo/MaxAmo\"", "gItemTrackerAmmoDisplay"); - SohImGui::EnhancementCheckbox("Randomizer colors for Songs", "gItemTrackeSongColor"); - SohImGui::Tooltip("Will display non-warp songs with randomizer colors instead of pure white"); - SohImGui::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gRandoTrackIconSize", 32, 128, ""); + UIWidgets::EnhancementCheckbox("Display \"Ammo/MaxAmo\"", "gItemTrackerAmmoDisplay"); + UIWidgets::EnhancementCheckbox("Randomizer colors for Songs", "gItemTrackeSongColor"); + UIWidgets::Tooltip("Will display non-warp songs with randomizer colors instead of pure white"); + UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gRandoTrackIconSize", 32, 128, ""); - SohImGui::EnhancementSliderInt("X spacing : %dpx", "##ITEMTRACKERSPACINGX", "gRandoTrackIconSpacingX", minimalSpacingX, 256, + UIWidgets::EnhancementSliderInt("X spacing : %dpx", "##ITEMTRACKERSPACINGX", "gRandoTrackIconSpacingX", minimalSpacingX, 256, ""); // SohImGui::EnhancementSliderInt("Y Spacing : %dpx", "##ITEMTRACKERSPACINGY", "gRandoTrackIconSpacingY", 0, // 16, ""); @@ -1016,4 +1017,4 @@ void DrawItemTracker(bool& open) { void InitItemTracker() { SohImGui::AddWindow("Randomizer", "Item Tracker", DrawItemTracker); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/savestates.cpp b/soh/soh/Enhancements/savestates.cpp index 37856aa81..4296ce869 100644 --- a/soh/soh/Enhancements/savestates.cpp +++ b/soh/soh/Enhancements/savestates.cpp @@ -1,6 +1,6 @@ #include "savestates.h" -#include "GameVersions.h" +#include #include // std::sprintf @@ -9,7 +9,7 @@ #include #include -#include +#include #include "z64.h" #include "z64save.h" @@ -823,7 +823,7 @@ extern "C" void ProcessSaveStateRequests(void) { } void SaveStateMgr::SetCurrentSlot(unsigned int slot) { - SohImGui::overlay->TextDrawNotification(1.0f, true, "slot %u set", slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "slot %u set", slot); this->currentSlot = slot; } @@ -841,12 +841,12 @@ void SaveStateMgr::ProcessSaveStateRequests(void) { this->states[request.slot] = std::make_shared(OTRGlobals::Instance->gSaveStateMgr, request.slot); } this->states[request.slot]->Save(); - SohImGui::overlay->TextDrawNotification(1.0f, true, "saved state %u", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "saved state %u", request.slot); break; case RequestType::LOAD: if (this->states.contains(request.slot)) { this->states[request.slot]->Load(); - SohImGui::overlay->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); } else { SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); } @@ -862,7 +862,7 @@ void SaveStateMgr::ProcessSaveStateRequests(void) { SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { if (gGlobalCtx == nullptr) { SPDLOG_ERROR("[SOH] Can not save or load a state outside of \"GamePlay\""); - SohImGui::overlay->TextDrawNotification(1.0f, true, "states not available here", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "states not available here", request.slot); return SaveStateReturn::FAIL_WRONG_GAMESTATE; } @@ -876,7 +876,7 @@ SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { return SaveStateReturn::SUCCESS; } else { SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); - SohImGui::overlay->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); return SaveStateReturn::FAIL_INVALID_SLOT; } [[unlikely]] default: diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp new file mode 100644 index 000000000..cf843cc8b --- /dev/null +++ b/soh/soh/GameMenuBar.cpp @@ -0,0 +1,1367 @@ +// +// GameMenuBar.cpp +// soh +// +// Created by David Chavez on 24.08.22. +// + +#include "GameMenuBar.hpp" + +#include +#include +#define IMGUI_DEFINE_MATH_OPERATORS +#include +#include +#include +#include +#include +#include +#include + +#ifdef __SWITCH__ +#include +#endif + +#include "UIWidgets.hpp" +#include "include/z64audio.h" + +#define EXPERIMENTAL() \ + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ + UIWidgets::Spacer(3.0f); \ + ImGui::Text("Experimental"); \ + ImGui::PopStyleColor(); \ + UIWidgets::PaddedSeparator(false, true); + +bool isBetaQuestEnabled = false; + +extern "C" { + void enableBetaQuest() { isBetaQuestEnabled = true; } + void disableBetaQuest() { isBetaQuestEnabled = false; } +} + +enum SeqPlayers { + /* 0 */ SEQ_BGM_MAIN, + /* 1 */ SEQ_FANFARE, + /* 2 */ SEQ_SFX, + /* 3 */ SEQ_BGM_SUB, + /* 4 */ SEQ_MAX +}; + +namespace GameMenuBar { + + // MARK: - Properties + + const char* powers[9] = { + "Vanilla (1x)", + "Double (2x)", + "Quadruple (4x)", + "Octuple (8x)", + "Hexadecuple (16x)", + "Duotrigintuple (32x)", + "Quattuorsexagintuple (64x)", + "Octoviginticentuple (128x)", + "Hexaquinquagintiducentuple (256x)" + }; + + // MARK: - Helpers + + std::string GetWindowButtonText(const char* text, bool menuOpen) { + char buttonText[100] = ""; + if(menuOpen) { strcat(buttonText,"> "); } + strcat(buttonText, text); + if (!menuOpen) { strcat(buttonText, " "); } + return buttonText; + } + + void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) { + float value = CVar_GetFloat(key, defaultValue); + + ImGui::Text(name, static_cast(100 * value)); + if (ImGui::SliderFloat((std::string("##") + key).c_str(), &value, 0.0f, 1.0f, "")) { + const float volume = floorf(value * 100) / 100; + CVar_SetFloat(key, volume); + SohImGui::RequestCvarSaveOnNextTick(); + Audio_SetGameVolume(playerId, volume); + } + } + + void UpdateAudio() { + Audio_SetGameVolume(SEQ_BGM_MAIN, CVar_GetFloat("gMainMusicVolume", 1)); + Audio_SetGameVolume(SEQ_BGM_SUB, CVar_GetFloat("gSubMusicVolume", 1)); + Audio_SetGameVolume(SEQ_FANFARE, CVar_GetFloat("gSFXMusicVolume", 1)); + Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1)); + } + + void applyEnhancementPresetDefault(void) { + // D-pad Support on Pause and File Select + CVar_SetS32("gDpadPauseName", 0); + // D-pad Support in Ocarina and Text Choice + CVar_SetS32("gDpadOcarinaText", 0); + // D-pad Support for Browsing Shop Items + CVar_SetS32("gDpadShop", 0); + // D-pad as Equip Items + CVar_SetS32("gDpadEquips", 0); + // Allow the cursor to be on any slot + CVar_SetS32("gPauseAnyCursor", 0); + // Prevent Dropped Ocarina Inputs + CVar_SetS32("gDpadNoDropOcarinaInput", 0); + // Answer Navi Prompt with L Button + CVar_SetS32("gNaviOnL", 0); + + // Text Speed (1 to 5) + CVar_SetS32("gTextSpeed", 1); + // King Zora Speed (1 to 5) + CVar_SetS32("gMweepSpeed", 1); + // Biggoron Forge Time (0 to 3) + CVar_SetS32("gForgeTime", 3); + // Vine/Ladder Climb speed (+0 to +12) + CVar_SetS32("gClimbSpeed", 0); + // Faster Block Push (+0 to +5) + CVar_SetS32("gFasterBlockPush", 0); + // Faster Heavy Block Lift + CVar_SetS32("gFasterHeavyBlockLift", 0); + // No Forced Navi + CVar_SetS32("gNoForcedNavi", 0); + // No Skulltula Freeze + CVar_SetS32("gSkulltulaFreeze", 0); + // MM Bunny Hood + CVar_SetS32("gMMBunnyHood", 0); + // Fast Chests + CVar_SetS32("gFastChests", 0); + // Fast Drops + CVar_SetS32("gFastDrops", 0); + // Better Owl + CVar_SetS32("gBetterOwl", 0); + // Fast Ocarina Playback + CVar_SetS32("gFastOcarinaPlayback", 0); + // Instant Putaway + CVar_SetS32("gInstantPutaway", 0); + // Instant Boomerang Recall + CVar_SetS32("gFastBoomerang", 0); + // Mask Select in Inventory + CVar_SetS32("gMaskSelect", 0); + // Remember Save Location + CVar_SetS32("gRememberSaveLocation", 0); + + // Damage Multiplier (0 to 8) + CVar_SetS32("gDamageMul", 0); + // Fall Damage Multiplier (0 to 7) + CVar_SetS32("gFallDamageMul", 0); + // Void Damage Multiplier (0 to 6) + CVar_SetS32("gVoidDamageMul", 0); + // No Random Drops + CVar_SetS32("gNoRandomDrops", 0); + // No Heart Drops + CVar_SetS32("gNoHeartDrops", 0); + // Enable Bombchu Drops + CVar_SetS32("gBombchuDrops", 0); + // Always Win Goron Pot + CVar_SetS32("gGoronPot", 0); + + // Change Red Potion Effect + CVar_SetS32("gRedPotionEffect", 0); + // Red Potion Health (1 to 100) + CVar_SetS32("gRedPotionHealth", 1); + // Red Potion Percent Restore + CVar_SetS32("gRedPercentRestore", 0); + // Change Green Potion Effect + CVar_SetS32("gGreenPotionEffect", 0); + // Green Potion Mana (1 to 100) + CVar_SetS32("gGreenPotionMana", 1); + // Green Potion Percent Restore + CVar_SetS32("gGreenPercentRestore", 0); + // Change Blue Potion Effects + CVar_SetS32("gBluePotionEffects", 0); + // Blue Potion Health (1 to 100) + CVar_SetS32("gBluePotionHealth", 1); + // Blue Potion Health Percent Restore + CVar_SetS32("gBlueHealthPercentRestore", 0); + // Blue Potion Mana (1 to 100) + CVar_SetS32("gBluePotionMana", 1); + // Blue Potion Mana Percent Restore + CVar_SetS32("gBlueManaPercentRestore", 0); + // Change Milk Effect + CVar_SetS32("gMilkEffect", 0); + // Milk Health (1 to 100) + CVar_SetS32("gMilkHealth", 1); + // Milk Percent Restore + CVar_SetS32("gMilkPercentRestore", 0); + // Separate Half Milk Effect + CVar_SetS32("gSeparateHalfMilkEffect", 0); + // Half Milk Health (1 to 100) + CVar_SetS32("gHalfMilkHealth", 0); + // Half Milk Percent Restore + CVar_SetS32("gHalfMilkPercentRestore", 0); + // Change Fairy Effect + CVar_SetS32("gFairyEffect", 0); + // Fairy (1 to 100) + CVar_SetS32("gFairyHealth", 1); + // Fairy Percent Restore + CVar_SetS32("gFairyPercentRestore", 0); + // Change Fairy Revive Effect + CVar_SetS32("gFairyReviveEffect", 0); + // Fairy Revival (1 to 100) + CVar_SetS32("gFairyReviveHealth", 1); + // Fairy Revive Percent Restore + CVar_SetS32("gFairyRevivePercentRestore", 0); + + // Instant Fishing + CVar_SetS32("gInstantFishing", 0); + // Guarantee Bite + CVar_SetS32("gGuaranteeFishingBite", 0); + // Child Minimum Weight (6 to 10) + CVar_SetS32("gChildMinimumWeightFish", 10); + // Adult Minimum Weight (8 to 13) + CVar_SetS32("gAdultMinimumWeightFish", 13); + + // Mute Low HP Alarm + CVar_SetS32("gLowHpAlarm", 0); + // Minimal UI + CVar_SetS32("gMinimalUI", 0); + // Disable Navi Call Audio + CVar_SetS32("gDisableNaviCallAudio", 0); + + // Visual Stone of Agony + CVar_SetS32("gVisualAgony", 0); + // Assignable Tunics and Boots + CVar_SetS32("gAssignableTunicsAndBoots", 0); + // Equipment Toggle + CVar_SetS32("gEquipmentCanBeRemoved", 0); + // Link's Cow in Both Time Periods + CVar_SetS32("gCowOfTime", 0); + // Enable visible guard vision + CVar_SetS32("gGuardVision", 0); + // Enable passage of time on file select + CVar_SetS32("gTimeFlowFileSelect", 0); + // Count Golden Skulltulas + CVar_SetS32("gInjectSkulltulaCount", 0); + // Pull grave during the day + CVar_SetS32("gDayGravePull", 0); + + // Rotate link (0 to 2) + CVar_SetS32("gPauseLiveLinkRotation", 0); + // Pause link animation (0 to 16) + CVar_SetS32("gPauseLiveLink", 0); + // Frames to wait + CVar_SetS32("gMinFrameCount", 1); + + // N64 Mode + CVar_SetS32("gN64Mode", 0); + // Enable 3D Dropped items/projectiles + CVar_SetS32("gNewDrops", 0); + // Disable Black Bar Letterboxes + CVar_SetS32("gDisableBlackBars", 0); + // Dynamic Wallet Icon + CVar_SetS32("gDynamicWalletIcon", 0); + // Always show dungeon entrances + CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 0); + + // Fix L&R Pause menu + CVar_SetS32("gUniformLR", 0); + // Fix L&Z Page switch in Pause menu + CVar_SetS32("gNGCKaleidoSwitcher", 0); + // Fix Dungeon entrances + CVar_SetS32("gFixDungeonMinimapIcon", 0); + // Fix Two Handed idle animations + CVar_SetS32("gTwoHandedIdle", 0); + // Fix the Gravedigging Tour Glitch + CVar_SetS32("gGravediggingTourFix", 0); + // Fix Deku Nut upgrade + CVar_SetS32("gDekuNutUpgradeFix", 0); + // Fix Navi text HUD position + CVar_SetS32("gNaviTextFix", 0); + // Fix Anubis fireballs + CVar_SetS32("gAnubisFix", 0); + // Fix Megaton Hammer crouch stab + CVar_SetS32("gCrouchStabHammerFix", 0); + // Fix all crouch stab + CVar_SetS32("gCrouchStabFix", 0); + + // Red Ganon blood + CVar_SetS32("gRedGanonBlood", 0); + // Fish while hovering + CVar_SetS32("gHoverFishing", 0); + // N64 Weird Frames + CVar_SetS32("gN64WeirdFrames", 0); + // Bombchus out of bounds + CVar_SetS32("gBombchusOOB", 0); + + CVar_SetS32("gGsCutscene", 0); + // Autosave + CVar_SetS32("gAutosave", 0); + } + + void applyEnhancementPresetVanillaPlus(void) { + // D-pad Support in Ocarina and Text Choice + CVar_SetS32("gDpadOcarinaText", 1); + // D-pad Support for Browsing Shop Items + CVar_SetS32("gDpadShop", 1); + // D-pad as Equip Items + CVar_SetS32("gDpadEquips", 1); + // Prevent Dropped Ocarina Inputs + CVar_SetS32("gDpadNoDropOcarinaInput", 1); + + // Text Speed (1 to 5) + CVar_SetS32("gTextSpeed", 5); + // King Zora Speed (1 to 5) + CVar_SetS32("gMweepSpeed", 2); + // Faster Block Push (+0 to +5) + CVar_SetS32("gFasterBlockPush", 5); + // Better Owl + CVar_SetS32("gBetterOwl", 1); + + // Assignable Tunics and Boots + CVar_SetS32("gAssignableTunicsAndBoots", 1); + // Enable passage of time on file select + CVar_SetS32("gTimeFlowFileSelect", 1); + // Count Golden Skulltulas + CVar_SetS32("gInjectSkulltulaCount", 1); + + // Pause link animation (0 to 16) + CVar_SetS32("gPauseLiveLink", 1); + + // Dynamic Wallet Icon + CVar_SetS32("gDynamicWalletIcon", 1); + // Always show dungeon entrances + CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 1); + + // Fix L&R Pause menu + CVar_SetS32("gUniformLR", 1); + // Fix Dungeon entrances + CVar_SetS32("gFixDungeonMinimapIcon", 1); + // Fix Two Handed idle animations + CVar_SetS32("gTwoHandedIdle", 1); + // Fix the Gravedigging Tour Glitch + CVar_SetS32("gGravediggingTourFix", 1); + // Fix Deku Nut upgrade + CVar_SetS32("gDekuNutUpgradeFix", 1); + + // Red Ganon blood + CVar_SetS32("gRedGanonBlood", 1); + // Fish while hovering + CVar_SetS32("gHoverFishing", 1); + // N64 Weird Frames + CVar_SetS32("gN64WeirdFrames", 1); + // Bombchus out of bounds + CVar_SetS32("gBombchusOOB", 1); + } + + void applyEnhancementPresetEnhanced(void) { + // King Zora Speed (1 to 5) + CVar_SetS32("gMweepSpeed", 5); + // Biggoron Forge Time (0 to 3) + CVar_SetS32("gForgeTime", 0); + // Vine/Ladder Climb speed (+0 to +12) + CVar_SetS32("gClimbSpeed", 1); + // Faster Heavy Block Lift + CVar_SetS32("gFasterHeavyBlockLift", 1); + // No Forced Navi + CVar_SetS32("gNoForcedNavi", 1); + // No Skulltula Freeze + CVar_SetS32("gSkulltulaFreeze", 1); + // MM Bunny Hood + CVar_SetS32("gMMBunnyHood", 1); + // Fast Chests + CVar_SetS32("gFastChests", 1); + // Fast Drops + CVar_SetS32("gFastDrops", 1); + // Fast Ocarina Playback + CVar_SetS32("gFastOcarinaPlayback", 1); + // Instant Putaway + CVar_SetS32("gInstantPutaway", 1); + // Instant Boomerang Recall + CVar_SetS32("gFastBoomerang", 1); + // Mask Select in Inventory + CVar_SetS32("gMaskSelect", 1); + + // Disable Navi Call Audio + CVar_SetS32("gDisableNaviCallAudio", 1); + + // Equipment Toggle + CVar_SetS32("gEquipmentCanBeRemoved", 1); + // Count Golden Skulltulas + CVar_SetS32("gInjectSkulltulaCount", 1); + + // Enable 3D Dropped items/projectiles + CVar_SetS32("gNewDrops", 1); + + // Fix Anubis fireballs + CVar_SetS32("gAnubisFix", 1); + } + + void applyEnhancementPresetRandomizer(void) { + // Allow the cursor to be on any slot + CVar_SetS32("gPauseAnyCursor", 1); + + // Instant Fishing + CVar_SetS32("gInstantFishing", 1); + // Guarantee Bite + CVar_SetS32("gGuaranteeFishingBite", 1); + // Child Minimum Weight (6 to 10) + CVar_SetS32("gChildMinimumWeightFish", 6); + // Adult Minimum Weight (8 to 13) + CVar_SetS32("gAdultMinimumWeightFish", 8); + + // Visual Stone of Agony + CVar_SetS32("gVisualAgony", 1); + // Pull grave during the day + CVar_SetS32("gDayGravePull", 1); + // Pull out Ocarina to Summon Scarecrow + CVar_SetS32("gSkipScarecrow", 0); + + // Pause link animation (0 to 16) + CVar_SetS32("gPauseLiveLink", 16); + // Frames to wait + CVar_SetS32("gMinFrameCount", 200); + } + + void applyEnhancementPresets(void) { + switch (CVar_GetS32("gSelectEnhancementPresets", 0)) { + // Default + case 0: + applyEnhancementPresetDefault(); + break; + + // Vanilla Plus + case 1: + applyEnhancementPresetDefault(); + applyEnhancementPresetVanillaPlus(); + break; + + // Enhanced + case 2: + applyEnhancementPresetDefault(); + applyEnhancementPresetVanillaPlus(); + applyEnhancementPresetEnhanced(); + break; + + // Randomizer + case 3: + applyEnhancementPresetDefault(); + applyEnhancementPresetVanillaPlus(); + applyEnhancementPresetEnhanced(); + applyEnhancementPresetRandomizer(); + break; + } + } + + // MARK: - Delegates + + void SetupHooks() { + Ship::RegisterHook(UpdateAudio); + Ship::RegisterHook(UpdateAudio); + } + + void Draw() { + if (ImGui::BeginMenu("Settings")) + { + if (ImGui::BeginMenu("Audio")) { + UIWidgets::EnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true); + UIWidgets::Spacer(0); + BindAudioSlider("Main Music Volume: %d %%", "gMainMusicVolume", 1.0f, SEQ_BGM_MAIN); + UIWidgets::Spacer(0); + BindAudioSlider("Sub Music Volume: %d %%", "gSubMusicVolume", 1.0f, SEQ_BGM_SUB); + UIWidgets::Spacer(0); + BindAudioSlider("Sound Effects Volume: %d %%", "gSFXMusicVolume", 1.0f, SEQ_SFX); + UIWidgets::Spacer(0); + BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", 1.0f, SEQ_FANFARE); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Controller")) { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2 (12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + if (ImGui::Button(GetWindowButtonText("Controller Configuration", CVar_GetS32("gControllerConfigurationEnabled", 0)).c_str())) + { + bool currentValue = CVar_GetS32("gControllerConfigurationEnabled", 0); + CVar_SetS32("gControllerConfigurationEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::ToggleInputEditorWindow(CVar_GetS32("gControllerConfigurationEnabled", 0)); + } + ImGui::PopStyleColor(1); + ImGui::PopStyleVar(3); + #ifndef __SWITCH__ + UIWidgets::PaddedEnhancementCheckbox("Use Controller Navigation", "gControlNav", true, false); + UIWidgets::Tooltip("Allows controller navigation of the menu bar\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); + #endif + UIWidgets::PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false); + UIWidgets::Tooltip("Shows currently pressed inputs on the bottom right of the screen"); + UIWidgets::Spacer(0); + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 20.0f); + UIWidgets::EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false); + UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); + ImGui::PopItemWidth(); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Graphics")) { + #ifndef __APPLE__ + UIWidgets::EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true); + UIWidgets::Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing"); + SohImGui::SetResolutionMultiplier(CVar_GetFloat("gInternalResolution", 1)); + #endif + #ifndef __WIIU__ + UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, false, true, false); + UIWidgets::Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); + SohImGui::SetMSAALevel(CVar_GetS32("gMSAAValue", 1)); + #endif + + if (SohImGui::WindowBackend() == SohImGui::Backend::DX11) + { + const char* cvar = "gExtraLatencyThreshold"; + int val = CVar_GetS32(cvar, 80); + val = fmax(fmin(val, 360), 0); + int fps = val; + + UIWidgets::Spacer(0); + + if (fps == 0) + { + ImGui::Text("Jitter fix: Off"); + } + else + { + ImGui::Text("Jitter fix: >= %d FPS", fps); + } + + std::string MinusBTNELT = " - ##ExtraLatencyThreshold"; + std::string PlusBTNELT = " + ##ExtraLatencyThreshold"; + if (ImGui::Button(MinusBTNELT.c_str())) { + val--; + CVar_SetS32(cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); + if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 360, "", ImGuiSliderFlags_AlwaysClamp)) + { + CVar_SetS32(cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::PopItemWidth(); + UIWidgets::Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to work on one frame while GPU works on the previous frame.\nThis setting should be used when your computer is too slow to do CPU + GPU work in time."); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNELT.c_str())) { + val++; + CVar_SetS32(cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + UIWidgets::Spacer(0); + } + + ImGui::Text("Renderer API (Needs reload)"); + auto backends = SohImGui::GetAvailableRenderingBackends(); + auto currentBackend = SohImGui::GetCurrentRenderingBackend(); + + if (ImGui::BeginCombo("##RApi", currentBackend.second)) { + for (uint8_t i = 0; i < sizeof(backends) / sizeof(backends[0]); i++) { + if (ImGui::Selectable(backends[i].second, backends[i] == currentBackend)) { + SohImGui::SetCurrentRenderingBackend(i, backends[i]); + } + } + + ImGui::EndCombo(); + } + + EXPERIMENTAL(); + + ImGui::Text("Texture Filter (Needs reload)"); + UIWidgets::EnhancementCombobox("gTextureFilter", SohImGui::GetSupportedTextureFilters(), 3, 0); + + UIWidgets::Spacer(0); + + SohImGui::DrawSettings(); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Languages")) { + UIWidgets::EnhancementRadioButton("English", "gLanguages", 0); + UIWidgets::EnhancementRadioButton("German", "gLanguages", 1); + UIWidgets::EnhancementRadioButton("French", "gLanguages", 2); + ImGui::EndMenu(); + } + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Enhancements")) + { + + const char* enhancementPresets[4] = { "Default", "Vanilla Plus", "Enhanced", "Randomizer"}; + UIWidgets::PaddedText("Enhancement Presets", false, true); + UIWidgets::EnhancementCombobox("gSelectEnhancementPresets", enhancementPresets, 4, 0); + UIWidgets::Tooltip( + "Default - Set all enhancements to their default values. The true vanilla SoH experience.\n" + "\n" + "Vanilla Plus - Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.\n" + "\n" + "Enhanced - The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.\n" + "\n" + "Randomizer - The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer." + ); + + UIWidgets::Spacer(0); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); + if (ImGui::Button("Apply Preset")) { + applyEnhancementPresets(); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::PopStyleVar(1); + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Controls")) { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + float availableWidth = ImGui::GetContentRegionAvail().x; + if (ImGui::Button( + GetWindowButtonText("Customize Game Controls", CVar_GetS32("gGameControlEditorEnabled", 0)).c_str(), + ImVec2(availableWidth, 0) + )) { + bool currentValue = CVar_GetS32("gGameControlEditorEnabled", 0); + CVar_SetS32("gGameControlEditorEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Game Control Editor", CVar_GetS32("gGameControlEditorEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + // TODO mutual exclusions -- There should be some system to prevent conclifting enhancements from being selected + UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause and File Select", "gDpadPauseName"); + UIWidgets::Tooltip("Enables Pause and File Select screen navigation with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate"); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Choice", "gDpadText", true, false); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support for Browsing Shop Items", "gDpadShop", true, false); + UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips", true, false); + UIWidgets::Tooltip("Allows the D-pad to be used as extra C buttons"); + UIWidgets::PaddedEnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor", true, false); + UIWidgets::Tooltip("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97"); + UIWidgets::PaddedEnhancementCheckbox("Prevent Dropped Ocarina Inputs", "gDpadNoDropOcarinaInput", true, false); + UIWidgets::Tooltip("Prevent dropping inputs when playing the ocarina quickly"); + UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL", true, false); + UIWidgets::Tooltip("Speak to Navi with L but enter first-person camera with C-Up"); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Gameplay")) + { + if (ImGui::BeginMenu("Time Savers")) + { + UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, false, false, true); + UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, false, false, true); + UIWidgets::EnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3); + UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); + UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, false, false, true); + UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, false, false, true); + UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", true, false); + UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); + UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); + UIWidgets::Tooltip("Prevent forced Navi conversations"); + UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); + UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); + UIWidgets::PaddedEnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood", true, false); + UIWidgets::Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); + UIWidgets::PaddedEnhancementCheckbox("Fast Chests", "gFastChests", true, false); + UIWidgets::Tooltip("Kick open every chest"); + UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); + UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); + UIWidgets::PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); + UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); + UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); + UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false); + UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); + UIWidgets::PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); + UIWidgets::Tooltip("Allow Link to put items away without having to wait around"); + UIWidgets::PaddedEnhancementCheckbox("Instant Boomerang Recall", "gFastBoomerang", true, false); + UIWidgets::Tooltip("Instantly return the boomerang to Link by pressing its item button while it's in the air"); + UIWidgets::PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false); + UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); + UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); + UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" + "This doesn't work if the save was made in a grotto."); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Difficulty Options")) + { + ImGui::Text("Damage Multiplier"); + UIWidgets::EnhancementCombobox("gDamageMul", powers, 9, 0); + UIWidgets::Tooltip( + "Modifies all sources of damage not affected by other sliders\n\ + 2x: Can survive all common attacks from the start of the game\n\ + 4x: Dies in 1 hit to any substantial attack from the start of the game\n\ + 8x: Can only survive trivial damage from the start of the game\n\ + 16x: Can survive all common attacks with max health without double defense\n\ + 32x: Can survive all common attacks with max health and double defense\n\ + 64x: Can survive trivial damage with max health without double defense\n\ + 128x: Can survive trivial damage with max health and double defense\n\ + 256x: Cannot survive damage" + ); + UIWidgets::PaddedText("Fall Damage Multiplier", true, false); + UIWidgets::EnhancementCombobox("gFallDamageMul", powers, 8, 0); + UIWidgets::Tooltip( + "Modifies all fall damage\n\ + 2x: Can survive all fall damage from the start of the game\n\ + 4x: Can only survive short fall damage from the start of the game\n\ + 8x: Cannot survive any fall damage from the start of the game\n\ + 16x: Can survive all fall damage with max health without double defense\n\ + 32x: Can survive all fall damage with max health and double defense\n\ + 64x: Can survive short fall damage with double defense\n\ + 128x: Cannot survive fall damage" + ); + UIWidgets::PaddedText("Void Damage Multiplier", true, false); + UIWidgets::EnhancementCombobox("gVoidDamageMul", powers, 7, 0); + UIWidgets::Tooltip( + "Modifies damage taken after falling into a void\n\ + 2x: Can survive void damage from the start of the game\n\ + 4x: Cannot survive void damage from the start of the game\n\ + 8x: Can survive void damage twice with max health without double defense\n\ + 16x: Can survive void damage with max health without double defense\n\ + 32x: Can survive void damage with max health and double defense\n\ + 64x: Cannot survive void damage" + ); + UIWidgets::PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); + UIWidgets::Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); + UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false); + UIWidgets::Tooltip("Bombchus will sometimes drop in place of bombs"); + UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); + UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); + UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); + UIWidgets::Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Potion Values")) + { + UIWidgets::EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Red Potions"); + UIWidgets::EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Red Potions"); + UIWidgets::EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore"); + UIWidgets::Tooltip("Toggles from Red Potions restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Green Potion Effect", "gGreenPotionEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of mana restored by Green Potions"); + UIWidgets::EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of mana restored by Green Potions, base max mana is 48, max upgraded mana is 96"); + UIWidgets::EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore"); + UIWidgets::Tooltip("Toggles from Green Potions restoring a fixed amount of mana to a percent of the player's current max mana"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Blue Potion Effects", "gBluePotionEffects"); + UIWidgets::Tooltip("Enable the following changes to the amount of health and mana restored by Blue Potions"); + UIWidgets::EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Blue Potions"); + UIWidgets::EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore"); + UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of mana restored by Blue Potions, base max mana is 48, max upgraded mana is 96"); + UIWidgets::EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore"); + UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of mana to a percent of the player's current max mana"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Milk Effect", "gMilkEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Milk"); + UIWidgets::EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Milk"); + UIWidgets::EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore"); + UIWidgets::Tooltip("Toggles from Milk restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Half Milk\nIf this is disabled, Half Milk will behave the same as Full Milk."); + UIWidgets::EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Half Milk"); + UIWidgets::EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore"); + UIWidgets::Tooltip("Toggles from Half Milk restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Fairy Effect", "gFairyEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairies"); + UIWidgets::EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Fairies"); + UIWidgets::EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore"); + UIWidgets::Tooltip("Toggles from Fairies restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Fairy Revive Effect", "gFairyReviveEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairy Revivals"); + UIWidgets::EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Fairy Revivals"); + UIWidgets::EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore"); + UIWidgets::Tooltip("Toggles from Fairy Revivals restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Fishing")) { + UIWidgets::EnhancementCheckbox("Instant Fishing", "gInstantFishing"); + UIWidgets::Tooltip("All fish will be caught instantly"); + UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false); + UIWidgets::Tooltip("When a line is stable, guarantee bite. Otherwise use default logic"); + UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 6, 10, "", 10, false, true, false); + UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child"); + UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 8, 13, "", 13, false, true, false); + UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult"); + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Reduced Clutter")) + { + UIWidgets::EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); + UIWidgets::Tooltip("Disable the low HP beeping sound"); + UIWidgets::PaddedEnhancementCheckbox("Minimal UI", "gMinimalUI", true, false); + UIWidgets::Tooltip("Hides most of the UI when not needed\nNote: Doesn't activate until after loading a new scene"); + UIWidgets::PaddedEnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio", true, false); + UIWidgets::Tooltip("Disables the voice audio when Navi calls you"); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + UIWidgets::EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); + UIWidgets::Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); + UIWidgets::PaddedEnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots", true, false); + UIWidgets::Tooltip("Allows equipping the tunic and boots to c-buttons"); + UIWidgets::PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false); + UIWidgets::Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); + UIWidgets::PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime", true, false); + UIWidgets::Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); + UIWidgets::PaddedEnhancementCheckbox("Enable visible guard vision", "gGuardVision", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable passage of time on file select", "gTimeFlowFileSelect", true, false); + UIWidgets::PaddedEnhancementCheckbox("Count Golden Skulltulas", "gInjectSkulltulaCount", true, false); + UIWidgets::Tooltip("Injects Golden Skulltula total count in pickup messages"); + UIWidgets::PaddedEnhancementCheckbox("Pull grave during the day", "gDayGravePull", true, false); + UIWidgets::Tooltip("Allows graves to be pulled when child during the day"); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Graphics")) + { + if (ImGui::BeginMenu("Animated Link in Pause Menu")) { + ImGui::Text("Rotation"); + UIWidgets::EnhancementRadioButton("Disabled", "gPauseLiveLinkRotation", 0); + UIWidgets::EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveLinkRotation", 1); + UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the D-pad\nUse D-pad Up or D-pad Down to reset Link's rotation"); + UIWidgets::EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveLinkRotation", 2); + UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the C-buttons\nUse C-Up or C-Down to reset Link's rotation"); + UIWidgets::EnhancementRadioButton("Rotate Link with Right Stick", "gPauseLiveLinkRotation", 3); + UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the Right Stick\nYou can zoom in by pointing up and reset Link's rotation by pointing down"); + if (CVar_GetS32("gPauseLiveLinkRotation", 0) != 0) { + UIWidgets::EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", "gPauseLiveLinkRotationSpeed", 1, 20, ""); + } + UIWidgets::PaddedSeparator(); + ImGui::Text("Static loop"); + UIWidgets::EnhancementRadioButton("Disabled", "gPauseLiveLink", 0); + UIWidgets::EnhancementRadioButton("Idle (standing)", "gPauseLiveLink", 1); + UIWidgets::EnhancementRadioButton("Idle (look around)", "gPauseLiveLink", 2); + UIWidgets::EnhancementRadioButton("Idle (belt)", "gPauseLiveLink", 3); + UIWidgets::EnhancementRadioButton("Idle (shield)", "gPauseLiveLink", 4); + UIWidgets::EnhancementRadioButton("Idle (test sword)", "gPauseLiveLink", 5); + UIWidgets::EnhancementRadioButton("Idle (yawn)", "gPauseLiveLink", 6); + UIWidgets::EnhancementRadioButton("Battle Stance", "gPauseLiveLink", 7); + UIWidgets::EnhancementRadioButton("Walking (no shield)", "gPauseLiveLink", 8); + UIWidgets::EnhancementRadioButton("Walking (holding shield)", "gPauseLiveLink", 9); + UIWidgets::EnhancementRadioButton("Running (no shield)", "gPauseLiveLink", 10); + UIWidgets::EnhancementRadioButton("Running (holding shield)", "gPauseLiveLink", 11); + UIWidgets::EnhancementRadioButton("Hand on hip", "gPauseLiveLink", 12); + UIWidgets::EnhancementRadioButton("Spin attack charge", "gPauseLiveLink", 13); + UIWidgets::EnhancementRadioButton("Look at hand", "gPauseLiveLink", 14); + UIWidgets::PaddedSeparator(); + ImGui::Text("Randomize"); + UIWidgets::EnhancementRadioButton("Random", "gPauseLiveLink", 15); + UIWidgets::Tooltip("Randomize the animation played each time you open the menu"); + UIWidgets::EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16); + UIWidgets::Tooltip("Randomize the animation played on the menu after a certain time"); + UIWidgets::EnhancementRadioButton("Random cycle (Idle)", "gPauseLiveLink", 17); + UIWidgets::Tooltip("Randomize the animation played on the menu after a certain time (Idle animations only)"); + if (CVar_GetS32("gPauseLiveLink", 0) >= 16) { + UIWidgets::EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, "", 0, true); + } + + ImGui::EndMenu(); + } + UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gN64Mode", true, false); + UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); + UIWidgets::PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops", true, false); + UIWidgets::Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); + UIWidgets::PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars", true, false); + UIWidgets::Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); + UIWidgets::PaddedEnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon", true, false); + UIWidgets::Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); + UIWidgets::PaddedEnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon", true, false); + UIWidgets::Tooltip("Always shows dungeon entrance icons on the minimap"); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Fixes")) + { + UIWidgets::EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); + UIWidgets::Tooltip("Makes the L and R buttons in the pause menu the same color"); + UIWidgets::PaddedEnhancementCheckbox("Fix L&Z Page switch in Pause menu", "gNGCKaleidoSwitcher", true, false); + UIWidgets::Tooltip("Makes L and R switch pages like on the GameCube\nZ opens the Debug Menu instead"); + UIWidgets::PaddedEnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon", true, false); + UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); + UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); + UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); + UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); + UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); + UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); + UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); + UIWidgets::PaddedEnhancementCheckbox("Fix Navi text HUD position", "gNaviTextFix", true, false); + UIWidgets::Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); + UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", "gAnubisFix", true, false); + UIWidgets::Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); + UIWidgets::PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", "gCrouchStabHammerFix", true, false); + UIWidgets::Tooltip("Make the Megaton Hammer's crouch stab able to destroy rocks without first swinging it normally"); + if (CVar_GetS32("gCrouchStabHammerFix", 0) == 0) { + CVar_SetS32("gCrouchStabFix", 0); + } else { + UIWidgets::PaddedEnhancementCheckbox("Remove power crouch stab", "gCrouchStabFix", true, false); + UIWidgets::Tooltip("Make crouch stabbing always do the same damage as a regular slash"); + } + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Restoration")) + { + UIWidgets::EnhancementCheckbox("Red Ganon blood", "gRedGanonBlood"); + UIWidgets::Tooltip("Restore the original red blood from NTSC 1.0/1.1. Disable for green blood"); + UIWidgets::PaddedEnhancementCheckbox("Fish while hovering", "gHoverFishing", true, false); + UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows casting the Fishing Rod while using the Hover Boots"); + UIWidgets::PaddedEnhancementCheckbox("N64 Weird Frames", "gN64WeirdFrames", true, false); + UIWidgets::Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64"); + UIWidgets::PaddedEnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB", true, false); + UIWidgets::Tooltip("Allows bombchus to explode out of bounds\nSimilar to GameCube and Wii VC"); + UIWidgets::PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", "gGsCutscene", true, false); + + ImGui::EndMenu(); + } + + UIWidgets::PaddedEnhancementCheckbox("Autosave", "gAutosave", true, false); + UIWidgets::Tooltip("Automatically save the game every time a new area is entered or item is obtained\n" + "To disable saving when obtaining an item, manually set gAutosaveAllItems and gAutosaveMajorItems to 0\n" + "gAutosaveAllItems takes priority over gAutosaveMajorItems if both are set to 1\n" + "gAutosaveMajorItems excludes rupees and health/magic/ammo refills (but includes bombchus)"); + + UIWidgets::Spacer(0); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + static ImVec2 buttonSize(200.0f, 0.0f); + if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gCosmeticsEditorEnabled", 0); + CVar_SetS32("gCosmeticsEditorEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + EXPERIMENTAL(); + + const char* fps_cvar = "gInterpolationFPS"; + { + #if defined(__SWITCH__) || defined(__WIIU__) + int minFps = 20; + int maxFps = 60; + #else + int minFps = 20; + int maxFps = 360; + #endif + + int val = CVar_GetS32(fps_cvar, minFps); + val = fmax(fmin(val, maxFps), 20); + + #ifdef __WIIU__ + // only support divisors of 60 on the Wii U + val = 60 / (60 / val); + #endif + + int fps = val; + + if (fps == 20) + { + ImGui::Text("Frame interpolation: Off"); + } + else + { + ImGui::Text("Frame interpolation: %d FPS", fps); + } + + std::string MinusBTNFPSI = " - ##FPSInterpolation"; + std::string PlusBTNFPSI = " + ##FPSInterpolation"; + if (ImGui::Button(MinusBTNFPSI.c_str())) { + #ifdef __WIIU__ + if (val >= 60) val = 30; + else val = 20; + #else + val--; + #endif + CVar_SetS32(fps_cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + #ifdef __WIIU__ + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); + #else + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); + #endif + if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp)) + { + #ifdef __WIIU__ + // only support divisors of 60 on the Wii U + val = 60 / (60 / val); + #endif + if (val > 360) + { + val = 360; + } + else if (val < 20) + { + val = 20; + } + + CVar_SetS32(fps_cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::PopItemWidth(); + UIWidgets::Tooltip("Interpolate extra frames to get smoother graphics\n" + "Set to match your monitor's refresh rate, or a divisor of it\n" + "A higher target FPS than your monitor's refresh rate will just waste resources, " + "and might give a worse result.\n" + "For consistent input lag, set this value and your monitor's refresh rate to a multiple of 20\n" + "Ctrl+Click for keyboard input"); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNFPSI.c_str())) { + #ifdef __WIIU__ + if (val <= 20) val = 30; + else val = 60; + #else + val++; + #endif + CVar_SetS32(fps_cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + if (SohImGui::WindowBackend() == SohImGui::Backend::DX11) + { + UIWidgets::Spacer(0); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); + if (ImGui::Button("Match Refresh Rate")) + { + int hz = roundf(SohImGui::WindowRefreshRate()); + if (hz >= 20 && hz <= 360) + { + CVar_SetS32(fps_cvar, hz); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + ImGui::PopStyleVar(1); + UIWidgets::Spacer(0); + } + UIWidgets::EnhancementCheckbox("Disable LOD", "gDisableLOD"); + UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); + UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false); + UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); + if (CVar_GetS32("gDisableDrawDistance", 0) == 0) { + CVar_SetS32("gDisableKokiriDrawDistance", 0); + } else if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); + UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); + } + UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", true, false); + UIWidgets::Tooltip("Holding down B skips text\nKnown to cause a cutscene softlock in Water Temple\nSoftlock can be fixed by pressing D-Right in Debug mode"); + UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera", true, false); + UIWidgets::Tooltip("Enables camera control\nNote: You must remap C buttons off of the right stick in the controller config menu, and map the camera stick to the right stick."); + + #ifdef __SWITCH__ + UIWidgets::Spacer(0); + int slot = CVar_GetS32("gSwitchPerfMode", (int)Ship::SwitchProfiles::STOCK); + ImGui::Text("Switch performance mode"); + if (ImGui::BeginCombo("##perf", SWITCH_CPU_PROFILES[slot])) { + for (int sId = 0; sId <= Ship::SwitchProfiles::POWERSAVINGM3; sId++) { + if (ImGui::Selectable(SWITCH_CPU_PROFILES[sId], sId == slot)) { + SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]); + CVar_SetS32("gSwitchPerfMode", sId); + Ship::Switch::ApplyOverclock(); + SohImGui::RequestCvarSaveOnNextTick(); + } + + } + ImGui::EndCombo(); + } + #endif + + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Cheats")) + { + if (ImGui::BeginMenu("Infinite...")) { + UIWidgets::EnhancementCheckbox("Money", "gInfiniteMoney"); + UIWidgets::PaddedEnhancementCheckbox("Health", "gInfiniteHealth", true, false); + UIWidgets::PaddedEnhancementCheckbox("Ammo", "gInfiniteAmmo", true, false); + UIWidgets::PaddedEnhancementCheckbox("Magic", "gInfiniteMagic", true, false); + UIWidgets::PaddedEnhancementCheckbox("Nayru's Love", "gInfiniteNayru", true, false); + UIWidgets::PaddedEnhancementCheckbox("Epona Boost", "gInfiniteEpona", true, false); + + ImGui::EndMenu(); + } + + UIWidgets::PaddedEnhancementCheckbox("No Clip", "gNoClip", true, false); + UIWidgets::Tooltip("Allows you to walk through walls"); + UIWidgets::PaddedEnhancementCheckbox("Climb Everything", "gClimbEverything", true, false); + UIWidgets::Tooltip("Makes every surface in the game climbable"); + UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL", true, false); + UIWidgets::Tooltip("Holding L makes you float into the air"); + UIWidgets::PaddedEnhancementCheckbox("Super Tunic", "gSuperTunic", true, false); + UIWidgets::Tooltip("Makes every tunic have the effects of every other tunic"); + UIWidgets::PaddedEnhancementCheckbox("Easy ISG", "gEzISG", true, false); + UIWidgets::Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); + UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", "gNoRestrictItems", true, false); + UIWidgets::Tooltip("Allows you to use any item at any location"); + UIWidgets::PaddedEnhancementCheckbox("Freeze Time", "gFreezeTime", true, false); + UIWidgets::Tooltip("Freezes the time of day"); + UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); + UIWidgets::Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); + UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield", true, false); + UIWidgets::Tooltip("Prevents the Deku Shield from burning on contact with fire"); + UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded", true, false); + UIWidgets::Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); + UIWidgets::PaddedEnhancementCheckbox("Time Sync", "gTimeSync", true, false); + UIWidgets::Tooltip("This syncs the ingame time with the real world time"); + + { + static int32_t betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); + static int32_t lastBetaQuestEnabled = betaQuestEnabled; + static int32_t betaQuestWorld = CVar_GetS32("gBetaQuestWorld", 0xFFEF); + static int32_t lastBetaQuestWorld = betaQuestWorld; + + if (!isBetaQuestEnabled) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + } + + UIWidgets::PaddedEnhancementCheckbox("Enable Beta Quest", "gEnableBetaQuest", true, false); + UIWidgets::Tooltip("Turns on OoT Beta Quest. *WARNING* This will reset your game."); + betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); + if (betaQuestEnabled) { + if (betaQuestEnabled != lastBetaQuestEnabled) { + betaQuestWorld = 0; + } + + ImGui::Text("Beta Quest World: %d", betaQuestWorld); + + if (ImGui::Button(" - ##BetaQuest")) { + betaQuestWorld--; + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + + ImGui::SliderInt("##BetaQuest", &betaQuestWorld, 0, 8, "", ImGuiSliderFlags_AlwaysClamp); + UIWidgets::Tooltip("Set the Beta Quest world to explore. *WARNING* Changing this will reset your game.\nCtrl+Click to type in a value."); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(" + ##BetaQuest")) { + betaQuestWorld++; + } + + if (betaQuestWorld > 8) { + betaQuestWorld = 8; + } + else if (betaQuestWorld < 0) { + betaQuestWorld = 0; + } + } + else { + lastBetaQuestWorld = betaQuestWorld = 0xFFEF; + CVar_SetS32("gBetaQuestWorld", betaQuestWorld); + } + if (betaQuestEnabled != lastBetaQuestEnabled || betaQuestWorld != lastBetaQuestWorld) + { + // Reset the game if the beta quest state or world changed because beta quest happens on redirecting the title screen cutscene. + lastBetaQuestEnabled = betaQuestEnabled; + lastBetaQuestWorld = betaQuestWorld; + CVar_SetS32("gEnableBetaQuest", betaQuestEnabled); + CVar_SetS32("gBetaQuestWorld", betaQuestWorld); + + SohImGui::DispatchConsoleCommand("reset"); + + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (!isBetaQuestEnabled) { + ImGui::PopItemFlag(); + ImGui::PopStyleVar(1); + } + } + + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Developer Tools")) + { + UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); + UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); + UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled", true, false); + UIWidgets::Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); + UIWidgets::PaddedEnhancementCheckbox("Fast File Select", "gSkipLogoTitle", true, false); + UIWidgets::Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); + if (CVar_GetS32("gSkipLogoTitle", 0)) { + const char* FastFileSelect[5] = { + "File N.1", + "File N.2", + "File N.3", + "File select", + "Zelda Map Select (require OoT Debug Mode)" + }; + ImGui::Text("Loading :"); + UIWidgets::EnhancementCombobox("gSaveFileID", FastFileSelect, 5, 0); + UIWidgets::PaddedEnhancementCheckbox("Create a new save if none", "gCreateNewSave", true, false); + UIWidgets::Tooltip("Enable the creation of a new save file if none exist in the File number selected\nNo file name will be assigned please do in Save editor once you see the first text else your save file name will be named \"00000000\"\nIf disabled you will fall back in File select menu"); + }; + UIWidgets::PaddedSeparator(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0,0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + static ImVec2 buttonSize(160.0f, 0.0f); + if (ImGui::Button(GetWindowButtonText("Stats", CVar_GetS32("gStatsEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gStatsEnabled", 0); + CVar_SetS32("gStatsEnabled", !currentValue); + SohImGui::ToggleStatisticsWindow(true); + SohImGui::RequestCvarSaveOnNextTick(); + } + UIWidgets::Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Console", CVar_GetS32("gConsoleEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gConsoleEnabled", 0); + CVar_SetS32("gConsoleEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::ToggleConsoleWindow(!currentValue); + } + UIWidgets::Tooltip("Enables the console window, allowing you to input commands, type help for some examples"); + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Save Editor", CVar_GetS32("gSaveEditorEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gSaveEditorEnabled", 0); + CVar_SetS32("gSaveEditorEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Save Editor", CVar_GetS32("gSaveEditorEnabled", 0)); + } + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVar_GetS32("gCollisionViewerEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gCollisionViewerEnabled", 0); + CVar_SetS32("gCollisionViewerEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Collision Viewer", CVar_GetS32("gCollisionViewerEnabled", 0)); + } + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVar_GetS32("gActorViewerEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gActorViewerEnabled", 0); + CVar_SetS32("gActorViewerEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Actor Viewer", CVar_GetS32("gActorViewerEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Randomizer")) + { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + static ImVec2 buttonSize(200.0f, 0.0f); + if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gRandomizerSettingsEnabled", 0); + CVar_SetS32("gRandomizerSettingsEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)); + } + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gItemTrackerEnabled", 0); + CVar_SetS32("gItemTrackerEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + ImGui::EndMenu(); + } + } +} diff --git a/soh/soh/GameMenuBar.hpp b/soh/soh/GameMenuBar.hpp new file mode 100644 index 000000000..07280707b --- /dev/null +++ b/soh/soh/GameMenuBar.hpp @@ -0,0 +1,27 @@ +// +// GameMenuBar.hpp +// soh +// +// Created by David Chavez on 24.08.22. +// + +#ifndef GameMenuBar_hpp +#define GameMenuBar_hpp + +#include + +#ifdef __cplusplus +extern "C" { +#endif + void enableBetaQuest(); + void disableBetaQuest(); +#ifdef __cplusplus +} +#endif + +namespace GameMenuBar { + void SetupHooks(); + void Draw(); +} + +#endif /* GameMenuBar_hpp */ diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 66aa22868..d7ae15bcc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -5,45 +5,45 @@ #include #include -#include "ResourceMgr.h" -#include "DisplayList.h" -#include "PlayerAnimation.h" -#include "Skeleton.h" -#include "Window.h" +#include +#include +#include +#include +#include #include "z64animation.h" #include "z64bgcheck.h" #include "Enhancements/gameconsole.h" #include -#include +#include #ifdef _WIN32 #include #else #include #endif -#include -#include -#include -#include "Lib/stb/stb_image.h" +#include +#include +#include +#include #define DRMP3_IMPLEMENTATION -#include "Lib/dr_libs/mp3.h" +#include #define DRWAV_IMPLEMENTATION -#include "Lib/dr_libs/wav.h" -#include "AudioPlayer.h" +#include +#include #include "Enhancements/controls/GameControlEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugconsole.h" #include "Enhancements/debugger/debugger.h" -#include +#include "Enhancements/randomizer/randomizer_item_tracker.h" #include "Enhancements/n64_weird_frame_data.inc" -#include "soh/frame_interpolation.h" +#include "frame_interpolation.h" #include "variables.h" #include "macros.h" #include -#include "Hooks.h" -#include +#include +#include "Enhancements/custom-message/CustomMessageManager.h" -#include "Lib/Fast3D/gfx_pc.h" -#include "Lib/Fast3D/gfx_rendering_api.h" +#include +#include #ifdef __APPLE__ #include @@ -52,15 +52,16 @@ #endif #ifdef __SWITCH__ -#include "SwitchImpl.h" +#include #elif defined(__WIIU__) -#include "WiiUImpl.h" +#include #endif -#include -#include +#include +#include "Enhancements/custom-message/CustomMessageTypes.h" #include -#include +#include "Enhancements/item-tables/ItemTableManager.h" +#include "GameMenuBar.hpp" OTRGlobals* OTRGlobals::Instance; SaveManager* SaveManager::Instance; @@ -321,6 +322,9 @@ extern "C" void InitOTR() { #elif defined(__WIIU__) Ship::WiiU::Init(); #endif + SohImGui::AddSetupHooksDelegate(GameMenuBar::SetupHooks); + SohImGui::RegisterMenuDrawMethod(GameMenuBar::Draw); + OTRGlobals::Instance = new OTRGlobals(); SaveManager::Instance = new SaveManager(); CustomMessageManager::Instance = new CustomMessageManager(); diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 4858c41b2..658044ed8 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -7,7 +7,7 @@ #include #ifdef __cplusplus -#include "Window.h" +#include #include "Enhancements/savestates.h" #include "Enhancements/randomizer/randomizer.h" diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 9bf99ac12..d02584413 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -4,7 +4,7 @@ #include "z64.h" #include "functions.h" #include "macros.h" -#include "Cvar.h" +#include #define NOGDI // avoid various windows defines that conflict with things in z64.h #include "spdlog/spdlog.h" @@ -1599,4 +1599,4 @@ extern "C" void Save_DeleteFile(int fileNum) { extern "C" bool Save_Exist(int fileNum) { return SaveManager::Instance->SaveFile_Exist(fileNum); -} \ No newline at end of file +} diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 06a382baa..1acbcbfc9 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -23,7 +23,7 @@ typedef struct { #include #include -#include "Lib/nlohmann/json.hpp" +#include class SaveManager { public: diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp new file mode 100644 index 000000000..d61ddc0f9 --- /dev/null +++ b/soh/soh/UIWidgets.cpp @@ -0,0 +1,523 @@ +// +// UIWidgets.cpp +// soh +// +// Created by David Chavez on 25.08.22. +// + +#include "UIWidgets.hpp" + +#define IMGUI_DEFINE_MATH_OPERATORS +#include +#include +#include + +#include + +namespace UIWidgets { + + // MARK: - Layout Helper + + // Automatically adds newlines to break up text longer than a specified number of characters + // Manually included newlines will still be respected and reset the line length + // If line is midword when it hits the limit, text should break at the last encountered space + char* WrappedText(const char* text, unsigned int charactersPerLine) { + std::string newText(text); + const size_t tipLength = newText.length(); + int lastSpace = -1; + size_t currentLineLength = 0; + for (unsigned int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) { + if (newText[currentCharacter] == '\n') { + currentLineLength = 0; + lastSpace = -1; + continue; + } else if (newText[currentCharacter] == ' ') { + lastSpace = currentCharacter; + } + + if ((currentLineLength >= charactersPerLine) && (lastSpace >= 0)) { + newText[lastSpace] = '\n'; + currentLineLength = currentCharacter - lastSpace - 1; + lastSpace = -1; + } + currentLineLength++; + } + + return strdup(newText.c_str()); + } + + char* WrappedText(const std::string& text, unsigned int charactersPerLine) { + return WrappedText(text.c_str(), charactersPerLine); + } + + void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha) + { + Color_RGBA8 defaultColors; + defaultColors.r = default_colors.x; + defaultColors.g = default_colors.y; + defaultColors.b = default_colors.z; + defaultColors.a = default_colors.w; + + Color_RGBA8 cvarColor = CVar_GetRGBA(cvarname, defaultColors); + + ColorArray.x = cvarColor.r / 255.0; + ColorArray.y = cvarColor.g / 255.0; + ColorArray.z = cvarColor.b / 255.0; + ColorArray.w = cvarColor.a / 255.0; + } + + void SetLastItemHoverText(const std::string& text) { + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("%s", WrappedText(text, 60)); + ImGui::EndTooltip(); + } + } + + // Adds a "?" next to the previous ImGui item with a custom tooltip + void InsertHelpHoverText(const std::string& text) { + ImGui::SameLine(); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("%s", WrappedText(text, 60)); + ImGui::EndTooltip(); + } + } + + + // MARK: - UI Elements + + void Tooltip(const char* text) { + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", WrappedText(text)); + } + } + + void Spacer(float height) { + ImGui::Dummy(ImVec2(0.0f, height)); + } + + void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalTopPadding, float extraVerticalBottomPadding) { + if (padTop) + Spacer(0); + + ImGui::Separator(); + + if (padBottom) + Spacer(0); + } + + void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) { + float thickness = ImMax(sz / 5.0f, 1.0f); + sz -= thickness * 0.5f; + pos += ImVec2(thickness * 0.25f, thickness * 0.25f); + + draw_list->PathLineTo(ImVec2(pos.x, pos.y)); + draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y + sz)); + draw_list->PathStroke(col, 0, thickness); + + draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y)); + draw_list->PathLineTo(ImVec2(pos.x, pos.y + sz)); + draw_list->PathStroke(col, 0, thickness); + } + + bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic) { + ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); + + const float square_sz = ImGui::GetFrameHeight(); + const ImVec2 pos = window->DC.CursorPos; + const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); + ImGui::ItemSize(total_bb, style.FramePadding.y); + if (!ImGui::ItemAdd(total_bb, id)) { + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); + return false; + } + + bool hovered, held; + bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held); + if (pressed) { + *v = !(*v); + ImGui::MarkItemEdited(id); + } + + const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); + ImGui::RenderNavHighlight(total_bb, id); + ImGui::RenderFrame(check_bb.Min, check_bb.Max, ImGui::GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); + ImU32 check_col = ImGui::GetColorU32(ImGuiCol_CheckMark); + ImU32 cross_col = ImGui::GetColorU32(ImVec4(0.50f, 0.50f, 0.50f, 1.00f)); + bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0; + if (mixed_value) { + // Undocumented tristate/mixed/indeterminate checkbox (#2644) + // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox) + ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f))); + window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); + } else if ((!disabled && *v) || (disabled && disabledGraphic == CheckboxGraphics::Checkmark)) { + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); + ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); + } else if (disabled && disabledGraphic == CheckboxGraphics::Cross) { + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); + RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f); + } + + ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); + if (g.LogEnabled) + ImGui::LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); + if (label_size.x > 0.0f) + ImGui::RenderText(label_pos, label); + + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); + return pressed; + } + + void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) { + if (disabled) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + } + bool val = (bool)CVar_GetS32(cvarName, 0); + if (CustomCheckbox(text, &val, disabled, disabledGraphic)) { + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (disabled) { + ImGui::PopStyleVar(1); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(disabledTooltipText, "") != 0) { + ImGui::SetTooltip("%s", disabledTooltipText); + } + ImGui::PopItemFlag(); + } + } + + void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) { + if (padTop) Spacer(0); + + EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic); + + if (padBottom) Spacer(0); + } + + void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue) { + if (ImGui::BeginCombo(name.c_str(), items[static_cast(CVar_GetS32(cvarName, defaultValue))].c_str())) { + for (int settingIndex = 0; settingIndex < (int) items.size(); settingIndex++) { + if (ImGui::Selectable(items[settingIndex].c_str())) { + CVar_SetS32(cvarName, settingIndex); + SohImGui::RequestCvarSaveOnNextTick(); + + } + } + ImGui::EndCombo(); + } + } + + void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue) { + if (FirstTimeValue <= 0) { + FirstTimeValue = 0; + } + uint8_t selected = CVar_GetS32(name, FirstTimeValue); + uint8_t DefaultValue = selected; + std::string comboName = std::string("##") + std::string(name); + if (ImGui::BeginCombo(comboName.c_str(), ComboArray[DefaultValue])) { + for (uint8_t i = 0; i < arraySize; i++) { + if (strlen(ComboArray[i]) > 1) { + if (ImGui::Selectable(ComboArray[i], i == selected)) { + CVar_SetS32(name, i); + selected = i; + SohImGui::RequestCvarSaveOnNextTick(); + } + } + } + ImGui::EndCombo(); + } + } + + void PaddedText(const char* text, bool padTop, bool padBottom) { + if (padTop) + Spacer(0); + + ImGui::Text("%s", text); + + if (padBottom) + Spacer(0); + } + + void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton) { + int val = CVar_GetS32(cvarName, defaultValue); + ImGui::Text(text, val); + if(PlusMinusButton) { + std::string MinusBTNName = " - ##"; + MinusBTNName += cvarName; + if (ImGui::Button(MinusBTNName.c_str())) { + val--; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + } + + if (ImGui::SliderInt(id, &val, min, max, format)) + { + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if(PlusMinusButton) { + std::string PlusBTNName = " + ##"; + PlusBTNName += cvarName; + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNName.c_str())) { + val++; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + if (val < min) + { + val = min; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (val > max) + { + val = max; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton) { + float val = CVar_GetFloat(cvarName, defaultValue); + + if (!isPercentage) + ImGui::Text(text, val); + else + ImGui::Text(text, static_cast(100 * val)); + + Spacer(0); + + if(PlusMinusButton) { + std::string MinusBTNName = " - ##"; + MinusBTNName += cvarName; + if (ImGui::Button(MinusBTNName.c_str())) { + if (!isPercentage) + val -= 0.1f; + else + val -= 0.01f; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + } + if (PlusMinusButton) { + #ifdef __WIIU__ + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); + #else + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); + #endif + } + if (ImGui::SliderFloat(id, &val, min, max, format)) + { + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + if (PlusMinusButton) { + ImGui::PopItemWidth(); + } + if(PlusMinusButton) { + std::string PlusBTNName = " + ##"; + PlusBTNName += cvarName; + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNName.c_str())) { + if (!isPercentage) + val += 0.1f; + else + val += 0.01f; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + if (val < min) + { + val = min; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (val > max) + { + val = max; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom) { + if (padTop) + Spacer(0); + + EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton); + + if (padBottom) + Spacer(0); + } + + void EnhancementRadioButton(const char* text, const char* cvarName, int id) { + /*Usage : + EnhancementRadioButton("My Visible Name","gMyCVarName", MyID); + First arg is the visible name of the Radio button + Second is the cvar name where MyID will be saved. + Note: the CVar name should be the same to each Buddies. + Example : + EnhancementRadioButton("English", "gLanguages", 0); + EnhancementRadioButton("German", "gLanguages", 1); + EnhancementRadioButton("French", "gLanguages", 2); + */ + std::string make_invisible = "##"; + make_invisible += text; + make_invisible += cvarName; + + int val = CVar_GetS32(cvarName, 0); + if (ImGui::RadioButton(make_invisible.c_str(), id == val)) { + CVar_SetS32(cvarName, id); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::Text("%s", text); + } + + void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) { + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "Reset"; + MakeInvisible += "##"; + MakeInvisible += cvarName; + MakeInvisible += "Reset"; + if (ImGui::Button(MakeInvisible.c_str())) { + colors->x = defaultcolors.x; + colors->y = defaultcolors.y; + colors->z = defaultcolors.z; + if (has_alpha) { colors->w = defaultcolors.w; }; + + Color_RGBA8 colorsRGBA; + colorsRGBA.r = defaultcolors.x; + colorsRGBA.g = defaultcolors.y; + colorsRGBA.b = defaultcolors.z; + if (has_alpha) { colorsRGBA.a = defaultcolors.w; }; + + CVar_SetRGBA(cvarName, colorsRGBA); + CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. + SohImGui::RequestCvarSaveOnNextTick(); + } + Tooltip("Revert colors to the game's original colors (GameCube version)\nOverwrites previously chosen color"); + } + + void RandomizeColor(const char* cvarName, ImVec4* colors) { + Color_RGBA8 NewColors = {0,0,0,255}; + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "##"; + MakeInvisible += cvarName; + MakeInvisible += "Random"; + std::string FullName = "Random"; + FullName += MakeInvisible; + if (ImGui::Button(FullName.c_str())) { + s16 RND_R = rand() % (255 - 0); + s16 RND_G = rand() % (255 - 0); + s16 RND_B = rand() % (255 - 0); + colors->x = (float)RND_R / 255; + colors->y = (float)RND_G / 255; + colors->z = (float)RND_B / 255; + NewColors.r = fmin(fmax(colors->x, 0), 255); + NewColors.g = fmin(fmax(colors->y, 0), 255); + NewColors.b = fmin(fmax(colors->z, 0), 255); + CVar_SetRGBA(cvarName, NewColors); + CVar_SetS32(Cvar_RBM.c_str(), 0); // On click disable rainbow mode. + SohImGui::RequestCvarSaveOnNextTick(); + } + Tooltip("Chooses a random color\nOverwrites previously chosen color"); + } + + void RainbowColor(const char* cvarName, ImVec4* colors) { + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "Rainbow"; + MakeInvisible += "##"; + MakeInvisible += cvarName; + MakeInvisible += "Rainbow"; + + EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str()); + Tooltip("Cycles through colors on a timer\nOverwrites previously chosen color"); + } + + void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) { + LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha); + + ImGuiColorEditFlags flags = ImGuiColorEditFlags_None; + + if (!TitleSameLine) { + ImGui::Text("%s", text); + flags = ImGuiColorEditFlags_NoLabel; + } + + ImGui::PushID(cvarName); + + if (!has_alpha) { + if (ImGui::ColorEdit3(text, (float*)&ColorRGBA, flags)) + { + Color_RGBA8 colors; + colors.r = ColorRGBA.x * 255.0; + colors.g = ColorRGBA.y * 255.0; + colors.b = ColorRGBA.z * 255.0; + colors.a = ColorRGBA.w * 255.0; + + CVar_SetRGBA(cvarName, colors); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + else + { + if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags)) + { + Color_RGBA8 colors; + colors.r = ColorRGBA.x / 255; + colors.g = ColorRGBA.y / 255; + colors.b = ColorRGBA.z / 255; + colors.a = ColorRGBA.w / 255; + + CVar_SetRGBA(cvarName, colors); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + ImGui::PopID(); + + //ImGui::SameLine(); // Removing that one to gain some width spacing on the HUD editor + ImGui::PushItemWidth(-FLT_MIN); + ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha); + ImGui::SameLine(); + RandomizeColor(cvarName, &ColorRGBA); + if (allow_rainbow) { + if (ImGui::GetContentRegionAvail().x > 185) { + ImGui::SameLine(); + } + RainbowColor(cvarName, &ColorRGBA); + } + ImGui::NewLine(); + ImGui::PopItemWidth(); + } +} diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp new file mode 100644 index 000000000..6ea62a9fa --- /dev/null +++ b/soh/soh/UIWidgets.hpp @@ -0,0 +1,49 @@ +// +// UIWidgets.hpp +// soh +// +// Created by David Chavez on 25.08.22. +// + +#ifndef UIWidgets_hpp +#define UIWidgets_hpp + +#include +#include +#include +#include + +namespace UIWidgets { + + // MARK: - Enums + + enum class CheckboxGraphics { + Cross, + Checkmark, + None + }; + + char* WrappedText(const char* text, unsigned int charactersPerLine = 60); + char* WrappedText(const std::string& text, unsigned int charactersPerLine); + + void SetLastItemHoverText(const std::string& text); + void InsertHelpHoverText(const std::string& text); + + void Tooltip(const char* text); + void Spacer(float height); + + void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f); + void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross); + void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross); + void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue = 0); + void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); + void PaddedText(const char* text, bool padTop = true, bool padBottom = true); + void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false); + void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true); + void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false); + void EnhancementRadioButton(const char* text, const char* cvarName, int id); + + void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); +} + +#endif /* UIWidgets_hpp */ diff --git a/soh/soh/frame_interpolation.cpp b/soh/soh/frame_interpolation.cpp index 44c255db1..79ac23d43 100644 --- a/soh/soh/frame_interpolation.cpp +++ b/soh/soh/frame_interpolation.cpp @@ -1,4 +1,4 @@ -#include "Cvar.h" +#include #include #include diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index c6be43964..1c5e82b43 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -1,13 +1,13 @@ #include "OTRGlobals.h" -#include "ResourceMgr.h" -#include "Scene.h" -#include "Utils/StringHelper.h" +#include +#include +#include #include "global.h" #include "vt.h" -#include +#include #include -#include -#include +#include "Enhancements/custom-message/CustomMessageManager.h" +#include "Enhancements/custom-message/CustomMessageTypes.h" extern "C" MessageTableEntry* sNesMessageEntryTablePtr; extern "C" MessageTableEntry* sGerMessageEntryTablePtr; diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index 1a07ceb7e..52b71c905 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -1,10 +1,10 @@ -#include "OTRGlobals.h" -#include "ResourceMgr.h" -#include "Scene.h" -#include "Utils/StringHelper.h" +#include "OTRGlobals.h" +#include +#include +#include #include "global.h" #include "vt.h" -#include "Vertex.h" +#include extern "C" void Gameplay_InitScene(GlobalContext * globalCtx, s32 spawn); extern "C" void Gameplay_InitEnvironment(GlobalContext * globalCtx, s16 skyboxId); @@ -76,4 +76,4 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn) { auto data2 = ResourceMgr_LoadVtxByCRC(0x68d4ea06044e228f);*/ volatile int a = 0; -} \ No newline at end of file +} diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 73953c681..97c0b8040 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -1,15 +1,15 @@ -#include "OTRGlobals.h" -#include "ResourceMgr.h" -#include "Scene.h" -#include "Utils/StringHelper.h" +#include "OTRGlobals.h" +#include +#include +#include #include "global.h" #include "vt.h" -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include extern Ship::Resource* OTRGameplay_LoadFile(GlobalContext* globalCtx, const char* fileName); extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId); diff --git a/soh/src/code/audio_playback.c b/soh/src/code/audio_playback.c index b2017b514..2c7ff425d 100644 --- a/soh/src/code/audio_playback.c +++ b/soh/src/code/audio_playback.c @@ -1,5 +1,5 @@ #include "global.h" -#include "Cvar.h" +#include extern bool gUseLegacySD; diff --git a/soh/src/code/audio_synthesis.c b/soh/src/code/audio_synthesis.c index 67f7033ea..72dbb25ec 100644 --- a/soh/src/code/audio_synthesis.c +++ b/soh/src/code/audio_synthesis.c @@ -1,6 +1,6 @@ #include "ultra64.h" #include "global.h" -#include "mixer.h" +#include #define DEFAULT_LEN_1CH 0x1A0 #define DEFAULT_LEN_2CH 0x340 diff --git a/soh/src/code/code_800F9280.c b/soh/src/code/code_800F9280.c index 6ca2ad75d..5fa3d50fa 100644 --- a/soh/src/code/code_800F9280.c +++ b/soh/src/code/code_800F9280.c @@ -1,7 +1,7 @@ #include "ultra64.h" #include "global.h" -#include "ultra64/abi.h" -#include "mixer.h" +#include +#include typedef struct { u8 unk_0; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 6b311fd4c..f831bc830 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -4,7 +4,7 @@ #include #include "soh/Enhancements/gameconsole.h" -#include "../libultraship/ImGuiImpl.h" +#include #include "soh/frame_interpolation.h" #include diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index 73da17185..de83f8c2a 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -10,7 +10,7 @@ #include "alloca.h" #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" #include -#include "GameVersions.h" +#include #include const char* GetGameVersionString(); From 8118947ab059b4ffec91ed87620f777e1b0ef09e Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Sat, 3 Sep 2022 01:15:43 -0400 Subject: [PATCH 3/8] Windows crash handler. (#1383) * Windows crash handler. * Fix naming convention. --- libultraship/libultraship/CrashHandler.cpp | 437 +++++++++++++++------ libultraship/libultraship/CrashHandler.h | 23 +- soh/src/code/main.c | 2 + 3 files changed, 333 insertions(+), 129 deletions(-) diff --git a/libultraship/libultraship/CrashHandler.cpp b/libultraship/libultraship/CrashHandler.cpp index f8d66beab..f454ddfdc 100644 --- a/libultraship/libultraship/CrashHandler.cpp +++ b/libultraship/libultraship/CrashHandler.cpp @@ -1,6 +1,9 @@ #include "spdlog/spdlog.h" #include "Utils/StringHelper.h" #include "CrashHandler.h" +#include "Window.h" + +extern "C" void DeinitOTR(void); #if defined(__linux__) #include @@ -10,163 +13,343 @@ #include #include -extern "C" void DeinitOTR(void); static void PrintRegisters(ucontext_t* ctx) { - char regbuffer[1024]; - SPDLOG_CRITICAL("Registers:"); + char regbuffer[1024]; + SPDLOG_CRITICAL("Registers:"); #if defined(__x86_64__) - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); - SPDLOG_CRITICAL("RAX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); - SPDLOG_CRITICAL("RDI: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); - SPDLOG_CRITICAL("RSI: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); - SPDLOG_CRITICAL("RDX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); - SPDLOG_CRITICAL("RCX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); - SPDLOG_CRITICAL("R8 : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); - SPDLOG_CRITICAL("R9 : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); - SPDLOG_CRITICAL("R10: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); - SPDLOG_CRITICAL("R11: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); - SPDLOG_CRITICAL("RSP: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); - SPDLOG_CRITICAL("RBX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); - SPDLOG_CRITICAL("RBP: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); - SPDLOG_CRITICAL("R12: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); - SPDLOG_CRITICAL("R13: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); - SPDLOG_CRITICAL("R14: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); - SPDLOG_CRITICAL("R15: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); - SPDLOG_CRITICAL("RIP: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); - SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); + SPDLOG_CRITICAL("RAX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); + SPDLOG_CRITICAL("RDI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); + SPDLOG_CRITICAL("RSI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); + SPDLOG_CRITICAL("RDX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); + SPDLOG_CRITICAL("RCX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); + SPDLOG_CRITICAL("R8 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); + SPDLOG_CRITICAL("R9 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); + SPDLOG_CRITICAL("R10: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); + SPDLOG_CRITICAL("R11: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); + SPDLOG_CRITICAL("RSP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); + SPDLOG_CRITICAL("RBX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); + SPDLOG_CRITICAL("RBP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); + SPDLOG_CRITICAL("R12: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); + SPDLOG_CRITICAL("R13: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); + SPDLOG_CRITICAL("R14: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); + SPDLOG_CRITICAL("R15: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); + SPDLOG_CRITICAL("RIP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); #else - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); - SPDLOG_CRITICAL("EDI : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); - SPDLOG_CRITICAL("ESI : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); - SPDLOG_CRITICAL("EBP : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); - SPDLOG_CRITICAL("ESP : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); - SPDLOG_CRITICAL("EBX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); - SPDLOG_CRITICAL("EDX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); - SPDLOG_CRITICAL("ECX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); - SPDLOG_CRITICAL("EAX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); - SPDLOG_CRITICAL("EIP : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); - SPDLOG_CRITICAL("EFL : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); + SPDLOG_CRITICAL("EDI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); + SPDLOG_CRITICAL("ESI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); + SPDLOG_CRITICAL("EBP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); + SPDLOG_CRITICAL("ESP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); + SPDLOG_CRITICAL("EBX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); + SPDLOG_CRITICAL("EDX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); + SPDLOG_CRITICAL("ECX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); + SPDLOG_CRITICAL("EAX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); + SPDLOG_CRITICAL("EIP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFL : {} ", regbuffer); #endif } -static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) -{ - std::array arr; - ucontext_t* ctx = static_cast(data); - constexpr size_t nMaxFrames = arr.size(); - size_t size = backtrace(arr.data(), nMaxFrames); - char** symbols = backtrace_symbols(arr.data(), nMaxFrames); +static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) { + std::array arr; + ucontext_t* ctx = static_cast(data); + constexpr size_t nMaxFrames = arr.size(); + size_t size = backtrace(arr.data(), nMaxFrames); + char** symbols = backtrace_symbols(arr.data(), nMaxFrames); - SPDLOG_CRITICAL("(Signal: {})\n", sig); + SPDLOG_CRITICAL("(Signal: {})", sig); - switch (sig) { - case SIGILL: - SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); - break; - case SIGABRT: - SPDLOG_CRITICAL("ABORT"); - break; - case SIGFPE: - SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); - break; - case SIGSEGV: - SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); - break; - } + switch (sig) { + case SIGILL: + SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); + break; + case SIGABRT: + SPDLOG_CRITICAL("ABORT"); + break; + case SIGFPE: + SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); + break; + case SIGSEGV: + SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); + break; + } - PrintRegisters(ctx); + PrintRegisters(ctx); - SPDLOG_CRITICAL("Traceback:\n"); - for (size_t i = 1; i < size; i++) - { - Dl_info info; - int gotAddress = dladdr(arr[i], &info); - std::string functionName(symbols[i]); + SPDLOG_CRITICAL("Traceback:"); + for (size_t i = 1; i < size; i++) { + Dl_info info; + int gotAddress = dladdr(arr[i], &info); + std::string functionName(symbols[i]); - if (gotAddress != 0 && info.dli_sname != nullptr) - { + if (gotAddress != 0 && info.dli_sname != nullptr) { FILE* pipe; - int32_t status; - char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); - const char* nameFound = info.dli_sname; + int32_t status; + char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); + const char* nameFound = info.dli_sname; - if (status == 0) - { - nameFound = demangled; - } + if (status == 0) { + nameFound = demangled; + } #if 0 - char command[256]; + char command[256]; char addrLine[128]; snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr); - pipe = popen(command, "r"); + pipe = popen(command, "r"); fgets(addrLine, 128, pipe); - #endif - + #endif + functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound, - (char*)arr[i] - (char*)info.dli_saddr); - free(demangled); - } + (char*)arr[i] - (char*)info.dli_saddr); + free(demangled); + } - SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); - } + SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); + } - free(symbols); - DeinitOTR(); - exit(1); + free(symbols); + DeinitOTR(); + exit(1); } static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) { - DeinitOTR(); - exit(1); + DeinitOTR(); + exit(1); } extern "C" void SetupHandlerLinux() { - struct sigaction action; - struct sigaction shutdownAction; + struct sigaction action; + struct sigaction shutdownAction; - action.sa_flags = SA_SIGINFO; - action.sa_sigaction = ErrorHandler; - - sigaction(SIGILL, &action, nullptr); - sigaction(SIGABRT, &action, nullptr); - sigaction(SIGFPE, &action, nullptr); - sigaction(SIGSEGV, &action, nullptr); - - shutdownAction.sa_flags = SA_SIGINFO; - shutdownAction.sa_sigaction = ShutdownHandler; - sigaction(SIGINT, &shutdownAction, nullptr); - sigaction(SIGTERM, &shutdownAction, nullptr); - sigaction(SIGQUIT, &shutdownAction, nullptr); - sigaction(SIGKILL, &shutdownAction, nullptr); + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = ErrorHandler; + sigaction(SIGILL, &action, nullptr); + sigaction(SIGABRT, &action, nullptr); + sigaction(SIGFPE, &action, nullptr); + sigaction(SIGSEGV, &action, nullptr); + shutdownAction.sa_flags = SA_SIGINFO; + shutdownAction.sa_sigaction = ShutdownHandler; + sigaction(SIGINT, &shutdownAction, nullptr); + sigaction(SIGTERM, &shutdownAction, nullptr); + sigaction(SIGQUIT, &shutdownAction, nullptr); + sigaction(SIGKILL, &shutdownAction, nullptr); } +#elif _WIN32 + +#if defined(_WIN32) && !defined(_WIN64) +#define WINDOWS_32_BIT +#endif + +static void PrintRegisters(CONTEXT* ctx) { + SPDLOG_CRITICAL("Register dump"); + char regBuff[50]; +#if defined(_M_AMD64) + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rax); + SPDLOG_CRITICAL("RAX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rcx); + SPDLOG_CRITICAL("RCX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rdx); + SPDLOG_CRITICAL("RDX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rbx); + SPDLOG_CRITICAL("RBX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rsp); + SPDLOG_CRITICAL("RSP: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rbp); + SPDLOG_CRITICAL("RBP: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rsi); + SPDLOG_CRITICAL("RSI: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rdi); + SPDLOG_CRITICAL("RDI: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R9); + SPDLOG_CRITICAL("R9: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R10); + SPDLOG_CRITICAL("R10: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R11); + SPDLOG_CRITICAL("R11: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R12); + SPDLOG_CRITICAL("R12: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R13); + SPDLOG_CRITICAL("R13: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R14); + SPDLOG_CRITICAL("R14: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R15); + SPDLOG_CRITICAL("R15: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rip); + SPDLOG_CRITICAL("RIP: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->EFlags); + SPDLOG_CRITICAL("EFLAGS: {}", regBuff); +#elif WINDOWS_32_BIT + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Edi); + SPDLOG_CRITICAL("EDI: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Esi); + SPDLOG_CRITICAL("ESI: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ebx); + SPDLOG_CRITICAL("EBX: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ecx); + SPDLOG_CRITICAL("ECX: 0x{}", ctx->Ecx); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Eax); + SPDLOG_CRITICAL("EAX: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ebp); + SPDLOG_CRITICAL("EBP: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Esp); + SPDLOG_CRITICAL("ESP: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->EFlags); + SPDLOG_CRITICAL("EFLAGS: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Eip); + SPDLOG_CRITICAL("EIP: 0x{}", regBuff); +#endif +} + +static void printStack(CONTEXT* ctx) { + BOOL result; + HANDLE process; + HANDLE thread; + HMODULE hModule; + ULONG frame; + DWORD64 displacement; + DWORD disp; + +#if defined(_M_AMD64) + STACKFRAME64 stack; + memset(&stack, 0, sizeof(STACKFRAME64)); +#elif WINDOWS_32_BIT + STACKFRAME stack; + memset(&stack, 0, sizeof(STACKFRAME)); + stack.AddrPC.Offset = (*ctx).Eip; + stack.AddrPC.Mode = AddrModeFlat; + stack.AddrStack.Offset = (*ctx).Esp; + stack.AddrStack.Mode = AddrModeFlat; + stack.AddrFrame.Offset = (*ctx).Ebp; + stack.AddrFrame.Mode = AddrModeFlat; +#endif + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME + sizeof(TCHAR)]; + char module[512]; + + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + + CONTEXT ctx2; + memcpy(&ctx2, ctx, sizeof(CONTEXT)); + + PrintRegisters(&ctx2); + + process = GetCurrentProcess(); + thread = GetCurrentThread(); + SymInitialize(process, nullptr, true); + + + constexpr DWORD machineType = +#if defined(_M_AMD64) + IMAGE_FILE_MACHINE_AMD64; +#elif WINDOWS_32_BIT + IMAGE_FILE_MACHINE_I386; +#endif + + displacement = 0; + for (frame = 0;; frame++) { + result = StackWalk(machineType, process, thread, &stack, &ctx2, nullptr, SymFunctionTableAccess, + SymGetModuleBase, nullptr); + if (!result) { + break; + } + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol); +#if defined(_M_AMD64) + IMAGEHLP_LINE64 line; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); +#elif WINDOWS_32_BIT + IMAGEHLP_LINE line; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE); +#endif + if (SymGetLineFromAddr(process, stack.AddrPC.Offset, &disp, &line)) { + SPDLOG_CRITICAL("{} in {}: line: {}: ", symbol->Name, line.FileName, line.LineNumber); + } + else { + char addrString[25]; + snprintf(addrString, std::size(addrString), "0x%016llX", symbol->Address); + SPDLOG_CRITICAL("at {}, addr 0x{}", symbol->Name, addrString); + hModule = nullptr; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCTSTR)(stack.AddrPC.Offset), &hModule); + + if (hModule != nullptr) { + GetModuleFileNameA(hModule, module, sizeof(module)); + } + SPDLOG_CRITICAL("In {}", module); + } + } + Ship::Window::GetInstance()->GetLogger()->flush(); + spdlog::shutdown(); + DeinitOTR(); +} + +extern "C" LONG seh_filter(struct _EXCEPTION_POINTERS* ex) { + char exceptionString[20]; + + snprintf(exceptionString, std::size(exceptionString), "0x%x", ex->ExceptionRecord->ExceptionCode); + + SPDLOG_CRITICAL("EXCEPTION {} occurred", exceptionString); + printStack(ex->ContextRecord); + MessageBox(nullptr, L"SoH Has crashed. Please upload the logs to the support channel in discord.", L"Crash", MB_OK | MB_ICONERROR); + + return EXCEPTION_EXECUTE_HANDLER; +} + + #endif diff --git a/libultraship/libultraship/CrashHandler.h b/libultraship/libultraship/CrashHandler.h index e068a4e38..103034ea4 100644 --- a/libultraship/libultraship/CrashHandler.h +++ b/libultraship/libultraship/CrashHandler.h @@ -13,6 +13,25 @@ void SetupHandlerLinux(void); } #endif -#endif // __linux__ +#elif _WIN32 // __linux__ ^^^^ _WIN32 vvvvv +#include +#include -#endif // CRASH_HANDLER_H \ No newline at end of file +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +LONG seh_filter(struct _EXCEPTION_POINTERS* ex); + +#ifdef __cplusplus +} +#endif + +#pragma comment(lib, "Dbghelp.lib") +#endif + +#endif // CRASH_HANDLER_H diff --git a/soh/src/code/main.c b/soh/src/code/main.c index 8e9fe1776..07e54b5be 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -42,6 +42,8 @@ int main(int argc, char** argv) { #ifdef __linux__ SetupHandlerLinux(); +#elif _WIN32 + SetUnhandledExceptionFilter(seh_filter); #endif GameConsole_Init(); From edb5261b07c3b22af2591ced7fbc1783f4312d3a Mon Sep 17 00:00:00 2001 From: Ada <60364512+GreatArgorath@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:20:15 +0100 Subject: [PATCH 4/8] Fixes ToT Fog --- libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index cca872f99..23b72a944 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -2134,6 +2134,10 @@ static void gfx_run_dl(Gfx* cmd) { switch (opcode) { // RSP commands: + case G_LOAD_UCODE: + rsp.fog_mul = 0; + rsp.fog_offset = 0; + break; case G_MARKER: { cmd++; From b14fb37b814f06fa8b75d8ce9312abf1f501ebfe Mon Sep 17 00:00:00 2001 From: Ada <60364512+GreatArgorath@users.noreply.github.com> Date: Wed, 17 Aug 2022 14:47:43 +0100 Subject: [PATCH 5/8] Update libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp Co-authored-by: David Chavez --- libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 23b72a944..9fde7e276 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -2134,7 +2134,7 @@ static void gfx_run_dl(Gfx* cmd) { switch (opcode) { // RSP commands: - case G_LOAD_UCODE: + case G_LOAD_UCODE: rsp.fog_mul = 0; rsp.fog_offset = 0; break; From d2fa0d648544a2149cf7d6053cafd50c20437724 Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Mon, 22 Aug 2022 04:19:02 +0200 Subject: [PATCH 6/8] Rando: Fix Fast File Select seed loading (#1252) * FixRandoLoading * better methode --- soh/src/overlays/gamestates/ovl_title/z_title.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index de83f8c2a..7c63ef35c 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -301,6 +301,9 @@ void Title_Init(GameState* thisx) { saveloading = true; gSaveContext.fileNum = selectedfile; Sram_OpenSave(); + Randomizer_LoadSettings(""); + Randomizer_LoadHintLocations(""); + Randomizer_LoadItemLocations("", true); gSaveContext.gameMode = 0; gSaveContext.magic = gSaveContext.magic; SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext); From 6daf357fd95d4a500b0b47273306d1a29e9b3701 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sat, 3 Sep 2022 02:13:20 -0400 Subject: [PATCH 7/8] fix include fix build (#1385) Co-authored-by: briaguya --- soh/src/code/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/code/main.c b/soh/src/code/main.c index 07e54b5be..7a6d6c6d9 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -3,7 +3,7 @@ #include #include "soh/OTRGlobals.h" -#include "../libultraship/CrashHandler.h" +#include s32 gScreenWidth = SCREEN_WIDTH; From f1dc980de84766053a8fe28420ca1701d4367432 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 11:16:43 +0200 Subject: [PATCH 8/8] Fixed autobreak after ImGui cleanup --- soh/soh/UIWidgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index d61ddc0f9..148a820c2 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -25,7 +25,7 @@ namespace UIWidgets { std::string newText(text); const size_t tipLength = newText.length(); int lastSpace = -1; - size_t currentLineLength = 0; + int currentLineLength = 0; for (unsigned int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) { if (newText[currentCharacter] == '\n') { currentLineLength = 0;