From ba693ecac4c8895c5bcfa154d5190d67f51cabbe Mon Sep 17 00:00:00 2001 From: Malkierian Date: Tue, 16 Sep 2025 18:57:33 -0700 Subject: [PATCH] Search Exclusion and Search Widgets (#5656) * Implement widget search exclusion. Exclude all external windows from the search. * Add second column to search results for non-widget results. * Implement extra search index. Add various controls, audio editor, and tracker options to the extra search index. Fix capitalization on a few options. Add click-to-view functionality to extra search column. * Add extraSearchWidgets for searching through non-menu widgets. Convert Controls extraSearches to widgets. Used to display in-window, as well as provide reference to extraSearchWidgets. * Swap Audio search to menu widget search system. * Fix missing static on a ShipInit instance. * Implement SearchWidgets in popout windows. Remove remaining vestiges of custom search. * Add SearchWidget for randomizing audio on seed gen. * Remove comments on color picker entries in WidgetType. * Put all search results in middle column for width management. Change combobox alignment and label position in search results to unify them all to left and above for better organization. Add "Search Results" text to header of results page for clarification. * clang --- soh/soh/Enhancements/Presets/Presets.cpp | 4 +- soh/soh/Enhancements/audio/AudioEditor.cpp | 175 +++++---- .../controls/SohInputEditorWindow.cpp | 95 +++-- .../randomizer/randomizer_check_tracker.cpp | 176 +++++---- .../randomizer/randomizer_item_tracker.cpp | 353 +++++++++++------- .../ObjectExtension/ActorMaximumHealth.cpp | 2 +- soh/soh/SohGui/Menu.cpp | 115 +++++- soh/soh/SohGui/Menu.h | 1 + soh/soh/SohGui/MenuTypes.h | 129 ++++--- soh/soh/SohGui/SohMenu.cpp | 5 +- soh/soh/SohGui/SohMenuDevTools.cpp | 10 + soh/soh/SohGui/SohMenuEnhancements.cpp | 4 + soh/soh/SohGui/SohMenuRandomizer.cpp | 8 + soh/soh/SohGui/SohMenuSettings.cpp | 3 + soh/soh/SohGui/UIWidgets.hpp | 58 +++ 15 files changed, 774 insertions(+), 364 deletions(-) diff --git a/soh/soh/Enhancements/Presets/Presets.cpp b/soh/soh/Enhancements/Presets/Presets.cpp index 0132efd6c..b8503cbc6 100644 --- a/soh/soh/Enhancements/Presets/Presets.cpp +++ b/soh/soh/Enhancements/Presets/Presets.cpp @@ -437,7 +437,9 @@ void PresetsCustomWidget(WidgetInfo& info) { void RegisterPresetsWidgets() { SohGui::mSohMenu->AddSidebarEntry("Settings", "Presets", 1); WidgetPath path = { "Settings", "Presets", SECTION_COLUMN_1 }; - SohGui::mSohMenu->AddWidget(path, "PresetsWidget", WIDGET_CUSTOM).CustomFunction(PresetsCustomWidget); + SohGui::mSohMenu->AddWidget(path, "PresetsWidget", WIDGET_CUSTOM) + .CustomFunction(PresetsCustomWidget) + .HideInSearch(true); presetFolder = Ship::Context::GetInstance()->GetPathRelativeToAppDirectory("presets"); std::fill_n(saveSection, PRESET_SECTION_MAX, true); LoadPresets(); diff --git a/soh/soh/Enhancements/audio/AudioEditor.cpp b/soh/soh/Enhancements/audio/AudioEditor.cpp index f031048f2..18b5cec1a 100644 --- a/soh/soh/Enhancements/audio/AudioEditor.cpp +++ b/soh/soh/Enhancements/audio/AudioEditor.cpp @@ -11,7 +11,7 @@ #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" #include -#include "soh/SohGui/UIWidgets.hpp" +#include "soh/SohGui/SohMenu.h" #include "soh/SohGui/SohGui.hpp" #include "AudioCollection.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" @@ -25,6 +25,23 @@ Vec3f pos = { 0.0f, 0.0f, 0.0f }; f32 freqScale = 1.0f; s8 reverbAdd = 0; +using namespace UIWidgets; + +static WidgetInfo lowHpAlarm; +static WidgetInfo naviCall; +static WidgetInfo enemyProx; +static WidgetInfo leadingMusic; +static WidgetInfo displaySeqName; +static WidgetInfo ovlDuration; +static WidgetInfo voicePitch; +static WidgetInfo randoMusicOnSceneChange; +static WidgetInfo randomAudioOnSeedGen; +static WidgetInfo lowerOctaves; + +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + // Authentic sequence counts // used to ensure we have enough to shuffle #define SEQ_COUNT_BGM_WORLD 30 @@ -527,75 +544,22 @@ void AudioEditor::DrawElement() { ImGui::TableNextRow(); ImGui::TableNextColumn(); if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) { - UIWidgets::CVarCheckbox( - "Mute Low HP Alarm", CVAR_AUDIO("LowHpAlarm"), - UIWidgets::CheckboxOptions().Color(THEME_COLOR).Tooltip("Disable the low HP beeping sound.")); - UIWidgets::CVarCheckbox("Disable Navi Call Audio", CVAR_AUDIO("DisableNaviCallAudio"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Disables the voice audio when Navi calls you.")); - UIWidgets::CVarCheckbox( - "Disable Enemy Proximity Music", CVAR_AUDIO("EnemyBGMDisable"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Disables the music change when getting close to enemies. Useful for hearing " - "your custom music for each scene more often.")); - UIWidgets::CVarCheckbox( - "Disable Leading Music in Lost Woods", CVAR_AUDIO("LostWoodsConsistentVolume"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Disables the volume shifting in the Lost Woods. Useful for hearing " - "your custom music in the Lost Woods if you don't need the navigation assitance " - "the volume changing provides. If toggling this while in the Lost Woods, reload " - "the area for the effect to kick in.")); - UIWidgets::CVarCheckbox( - "Display Sequence Name on Overlay", CVAR_AUDIO("SeqNameOverlay"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Displays the name of the current sequence in the corner of the screen whenever a new " - "sequence " - "is loaded to the main sequence player (does not apply to fanfares or enemy BGM).")); - UIWidgets::CVarSliderInt("Overlay Duration: %d seconds", CVAR_AUDIO("SeqNameOverlayDuration"), - UIWidgets::IntSliderOptions() - .Min(1) - .Max(10) - .DefaultValue(5) - .Size(ImVec2(300.0f, 0.0f)) - .Color(THEME_COLOR)); - UIWidgets::CVarSliderFloat("Link's voice pitch multiplier", CVAR_AUDIO("LinkVoiceFreqMultiplier"), - UIWidgets::FloatSliderOptions() - .IsPercentage() - .Min(0.4f) - .Max(2.5f) - .DefaultValue(1.0f) - .Size(ImVec2(300.0f, 0.0f)) - .Color(THEME_COLOR)); + SohGui::mSohMenu->MenuDrawItem(lowHpAlarm, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(naviCall, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(enemyProx, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(leadingMusic, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(displaySeqName, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(ovlDuration, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(voicePitch, ImGui::GetContentRegionAvail().x, THEME_COLOR); ImGui::SameLine(); ImGui::SetCursorPosY(ImGui::GetCursorPos().y + 40.f); if (UIWidgets::Button("Reset##linkVoiceFreqMultiplier", UIWidgets::ButtonOptions().Size(ImVec2(80, 36)).Padding(ImVec2(5.0f, 0.0f)))) { CVarSetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0f); } - UIWidgets::CVarCheckbox( - "Randomize All Music and Sound Effects on New Scene", CVAR_AUDIO("RandomizeAllOnNewScene"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip( - "Enables randomizing all unlocked music and sound effects when you enter a new scene.")); - UIWidgets::CVarCheckbox("Randomize All Music and Sound Effects on Randomizer Generation", - CVAR_AUDIO("RandomizeAllOnRandoGen"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Enables randomizing all unlocked music and sound effects when " - "you generate a new randomizer.")); - UIWidgets::CVarCheckbox( - "Lower Octaves of Unplayable High Notes", CVAR_AUDIO("ExperimentalOctaveDrop"), - UIWidgets::CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Some custom sequences may have notes that are too high for the game's audio " - "engine to play. Enabling this checkbox will cause these notes to drop a " - "couple of octaves so they can still harmonize with the other notes of the " - "sequence.")); + SohGui::mSohMenu->MenuDrawItem(randoMusicOnSceneChange, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(randomAudioOnSeedGen, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(lowerOctaves, ImGui::GetContentRegionAvail().x, THEME_COLOR); } ImGui::EndChild(); ImGui::EndTable(); @@ -849,3 +813,86 @@ void AudioEditor_UnlockAll() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); } + +void RegisterAudioWidgets() { + lowHpAlarm = { .name = "Mute Low HP Alarm", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + lowHpAlarm.CVar(CVAR_AUDIO("LowHpAlarm")) + .Options(CheckboxOptions().Color(THEME_COLOR).Tooltip("Disable the low HP beeping sound.")); + SohGui::mSohMenu->AddSearchWidget({ lowHpAlarm, "Enhancements", "Audio Editor", "Audio Options" }); + + naviCall = { .name = "Disable Navi Call Audio", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + naviCall.CVar(CVAR_AUDIO("DisableNaviCallAudio")) + .Options(CheckboxOptions().Color(THEME_COLOR).Tooltip("Disables the voice audio when Navi calls you.")); + SohGui::mSohMenu->AddSearchWidget({ naviCall, "Enhancements", "Audio Editor", "Audio Options" }); + + enemyProx = { .name = "Disable Enemy Proximity Music", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + enemyProx.CVar(CVAR_AUDIO("EnemyBGMDisable")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Disables the music change when getting close to enemies. Useful for hearing " + "your custom music for each scene more often.")); + + leadingMusic = { .name = "Disable Leading Music in Lost Woods", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + leadingMusic.CVar(CVAR_AUDIO("LostWoodsConsistentVolume")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Disables the volume shifting in the Lost Woods. Useful for hearing " + "your custom music in the Lost Woods if you don't need the navigation assitance " + "the volume changing provides. If toggling this while in the Lost Woods, reload " + "the area for the effect to kick in.")); + SohGui::mSohMenu->AddSearchWidget({ leadingMusic, "Enhancements", "Audio Editor", "Audio Options" }); + + displaySeqName = { .name = "Display Sequence Name on Overlay", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + displaySeqName.CVar(CVAR_AUDIO("SeqNameOverlay")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Displays the name of the current sequence in the corner of the screen whenever a new " + "sequence " + "is loaded to the main sequence player (does not apply to fanfares or enemy BGM).")); + SohGui::mSohMenu->AddSearchWidget({ displaySeqName, "Enhancements", "Audio Editor", "Audio Options" }); + + ovlDuration = { .name = "Overlay Duration: %d seconds", .type = WidgetType::WIDGET_CVAR_SLIDER_INT }; + ovlDuration.CVar(CVAR_AUDIO("SeqNameOverlayDuration")) + .Options(IntSliderOptions().Color(THEME_COLOR).Min(1).Max(10).DefaultValue(5).Size(ImVec2(300.0f, 0.0f))); + SohGui::mSohMenu->AddSearchWidget({ ovlDuration, "Enhancements", "Audio Editor", "Audio Options" }); + + voicePitch = { .name = "Link's Voice Pitch Multiplier", .type = WidgetType::WIDGET_CVAR_SLIDER_FLOAT }; + voicePitch.CVar(CVAR_AUDIO("LinkVoiceFreqMultiplier")) + .Options(FloatSliderOptions() + .Color(THEME_COLOR) + .IsPercentage() + .Min(0.4f) + .Max(2.5f) + .DefaultValue(1.0f) + .Size(ImVec2(300.0f, 0.0f))); + SohGui::mSohMenu->AddSearchWidget({ voicePitch, "Enhancements", "Audio Editor", "Audio Options" }); + + randoMusicOnSceneChange = { .name = "Randomize All Music and Sound Effects on New Scene", + .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + randoMusicOnSceneChange.CVar(CVAR_AUDIO("RandomizeAllOnNewScene")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene.")); + SohGui::mSohMenu->AddSearchWidget({ randoMusicOnSceneChange, "Enhancements", "Audio Editor", "Audio Options" }); + + randomAudioOnSeedGen = { .name = "Randomize All Music and Sound Effects on Randomizer Generation", + .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + randomAudioOnSeedGen.CVar(CVAR_AUDIO("RandomizeAllOnRandoGen")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Enables randomizing all unlocked music and sound effects when you generate a new " + "randomizer. Respects locks already in place.")); + SohGui::mSohMenu->AddSearchWidget({ randomAudioOnSeedGen, "Enhancements", "Audio Editor", "Audio Options" }); + + lowerOctaves = { .name = "Lower Octaves of Unplayable High Notes", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + lowerOctaves.CVar(CVAR_AUDIO("ExperimentalOctaveDrop")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Some custom sequences may have notes that are too high for the game's audio " + "engine to play. Enabling this checkbox will cause these notes to drop a " + "couple of octaves so they can still harmonize with the other notes of the " + "sequence.")); + SohGui::mSohMenu->AddSearchWidget({ lowerOctaves, "Enhancements", "Audio Editor", "Audio Options" }); +} + +static RegisterMenuInitFunc initAudioWidgets(RegisterAudioWidgets); diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 41a31f8be..6fc7f6624 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1,7 +1,7 @@ #include "SohInputEditorWindow.h" #include #include "soh/OTRGlobals.h" -#include "soh/SohGui/UIWidgets.hpp" +#include "soh/SohGui/SohMenu.h" #include "soh/SohGui/SohGui.hpp" #include "z64.h" #include "soh/cvar_prefixes.h" @@ -13,6 +13,17 @@ using namespace UIWidgets; +static WidgetInfo freeLook; +static WidgetInfo mouseControl; +static WidgetInfo rightStickOcarina; +static WidgetInfo dpadOcarina; +static WidgetInfo dpadPause; +static WidgetInfo dpadText; + +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + SohInputEditorWindow::~SohInputEditorWindow() { } @@ -1321,8 +1332,8 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { ImGui::SetCursorPos(ImVec2(cursor.x, cursor.y + 5)); CheckboxOptions checkOpt = CheckboxOptions().Color(THEME_COLOR); - CVarCheckbox("Dpad Ocarina Playback", CVAR_SETTING("CustomOcarina.Dpad"), checkOpt); - CVarCheckbox("Right Stick Ocarina Playback", CVAR_SETTING("CustomOcarina.RightStick"), checkOpt); + SohGui::mSohMenu->MenuDrawItem(dpadOcarina, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(rightStickOcarina, ImGui::GetContentRegionAvail().x, THEME_COLOR); CVarCheckbox("Customize Ocarina Controls", CVAR_SETTING("CustomOcarina.Enabled"), checkOpt); if (!CVarGetInteger(CVAR_SETTING("CustomOcarina.Enabled"), 0)) { @@ -1354,12 +1365,8 @@ void SohInputEditorWindow::DrawOcarinaControlPanel() { void SohInputEditorWindow::DrawCameraControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - CVarCheckbox( - "Enable Mouse Controls", CVAR_SETTING("EnableMouse"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Allows for using the mouse to control the camera (must enable Free Look), " - "aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)")); + SohGui::mSohMenu->MenuDrawItem(mouseControl, ImGui::GetContentRegionAvail().x, THEME_COLOR); + Ship::GuiWindow::BeginGroupPanel("Aiming/First-Person Camera", ImGui::GetContentRegionAvail()); CVarCheckbox("Right Stick Aiming", CVAR_SETTING("Controls.RightStickAim"), CheckboxOptions() @@ -1427,14 +1434,7 @@ void SohInputEditorWindow::DrawCameraControlPanel() { ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); Ship::GuiWindow::BeginGroupPanel("Third-Person Camera", ImGui::GetContentRegionAvail()); - CVarCheckbox( - "Free Look", CVAR_SETTING("FreeLook.Enabled"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Enables free look 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.\n" - "Doesn't work in areas were the game locks the camera.\n" - "Scene reload may be necessary to enable.")); + SohGui::mSohMenu->MenuDrawItem(freeLook, ImGui::GetContentRegionAvail().x, THEME_COLOR); CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look")); CVarCheckbox( @@ -1467,16 +1467,8 @@ void SohInputEditorWindow::DrawDpadControlPanel() { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); Ship::GuiWindow::BeginGroupPanel("D-Pad Options", ImGui::GetContentRegionAvail()); - CVarCheckbox("D-pad Support on Pause Screen", CVAR_SETTING("DPadOnPause"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold " - "C-Up to equip instead of navigate")); - CVarCheckbox("D-pad Support in Text Boxes", CVAR_SETTING("DpadInText"), - CheckboxOptions() - .Color(THEME_COLOR) - .Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry " - "screens with the D-pad")); + SohGui::mSohMenu->MenuDrawItem(dpadPause, ImGui::GetContentRegionAvail().x, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(dpadText, ImGui::GetContentRegionAvail().x, THEME_COLOR); if (!CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0) && !CVarGetInteger(CVAR_SETTING("DpadInText"), 0)) { ImGui::BeginDisabled(); @@ -1902,3 +1894,52 @@ void SohInputEditorWindow::DrawElement() { ImGui::PopStyleColor(3); ImGui::PopFont(); } + +void RegisterInputEditorWidgets() { + dpadOcarina = { .name = "Dpad Ocarina Playback", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dpadOcarina.CVar(CVAR_SETTING("CustomOcarina.Dpad")).Options(CheckboxOptions().Color(THEME_COLOR)); + SohGui::mSohMenu->AddSearchWidget({ dpadOcarina, "Settings", "Controls", "Ocarina Controls", "" }); + + freeLook = { .name = "Free Look", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + freeLook.CVar(CVAR_SETTING("FreeLook.Enabled")) + .Options( + CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip( + "Enables free look 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.\n" + "Doesn't work in areas were the game locks the camera.\n" + "Scene reload may be necessary to enable.")); + SohGui::mSohMenu->AddSearchWidget({ freeLook, "Settings", "Controls", "Camera Controls" }); + + mouseControl = { .name = "Enable Mouse Controls", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + mouseControl.CVar(CVAR_SETTING("EnableMouse")) + .Options( + CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Allows for using the mouse to control the camera (must enable Free Look), " + "aim with the shield, and perform quickspin attacks (quickly rotate the mouse then press B)")); + SohGui::mSohMenu->AddSearchWidget({ mouseControl, "Settings", "Controls", "Camera Controls" }); + + rightStickOcarina = { .name = "Right Stick Ocarina Playback", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + rightStickOcarina.CVar(CVAR_SETTING("CustomOcarina.RightStick")).Options(CheckboxOptions().Color(THEME_COLOR)); + SohGui::mSohMenu->AddSearchWidget({ rightStickOcarina, "Settings", "Controls", "Ocarina Controls" }); + + dpadPause = { .name = "D-pad Support on Pause Screen", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dpadPause.CVar(CVAR_SETTING("DPadOnPause")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Navigate Pause with the D-pad\nIf used with \"D-pad as Equip Items\", you must hold " + "C-Up to equip instead of navigate")); + SohGui::mSohMenu->AddSearchWidget({ dpadPause, "Settings", "Controls", "Dpad Controls" }); + + dpadText = { .name = "D-pad Support in Text Boxes", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dpadText.CVar(CVAR_SETTING("DpadInText")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Navigate choices in text boxes, shop item selection, and the file select / name entry " + "screens with the D-pad")); + SohGui::mSohMenu->AddSearchWidget({ dpadText, "Settings", "Controls", "Dpad Controls" }); +} + +static RegisterMenuInitFunc initInputWidgets(RegisterInputEditorWidgets); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 52611b89b..1859ed473 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -8,6 +8,7 @@ #include "soh/ResourceManagerHelpers.h" #include "soh/SohGui/UIWidgets.hpp" #include "soh/SohGui/SohGui.hpp" +#include "soh/SohGui/SohMenu.h" #include "dungeon.h" #include "entrance.h" #include "location_access.h" @@ -39,9 +40,21 @@ extern std::vector dungeonRewardMedallions; extern std::vector songItems; extern std::vector equipmentItems; +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + using json = nlohmann::json; +using namespace UIWidgets; namespace CheckTracker { +static WidgetInfo backgroundColorWidget; +static WidgetInfo windowTypeWidget; +static WidgetInfo dungeonSpoilerWidget; +static WidgetInfo hideUnshuffledShopWidget; +static WidgetInfo showGSWidget; +static WidgetInfo showLogicWidget; +static WidgetInfo checkAvailabilityWidget; // settings bool showShops; @@ -936,43 +949,6 @@ void SetAreaSpoiled(RandomizerCheckArea rcArea) { } void CheckTrackerWindow::DrawElement() { - Color_Background = CVarGetColor(CVAR_TRACKER_CHECK("BgColor.Value"), Color_Bg_Default); - Color_Area_Incomplete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.MainColor.Value"), Color_Main_Default); - Color_Area_Incomplete_Extra = - CVarGetColor(CVAR_TRACKER_CHECK("AreaIncomplete.ExtraColor.Value"), Color_Area_Incomplete_Extra_Default); - Color_Area_Complete_Main = CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.MainColor.Value"), Color_Main_Default); - Color_Area_Complete_Extra = - CVarGetColor(CVAR_TRACKER_CHECK("AreaComplete.ExtraColor.Value"), Color_Area_Complete_Extra_Default); - Color_Unchecked_Main = CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.MainColor.Value"), Color_Main_Default); - Color_Unchecked_Extra = - CVarGetColor(CVAR_TRACKER_CHECK("Unchecked.ExtraColor.Value"), Color_Unchecked_Extra_Default); - Color_Skipped_Main = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.MainColor.Value"), Color_Main_Default); - Color_Skipped_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Skipped.ExtraColor.Value"), Color_Skipped_Extra_Default); - Color_Seen_Main = CVarGetColor(CVAR_TRACKER_CHECK("Seen.MainColor.Value"), Color_Main_Default); - Color_Seen_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Seen.ExtraColor.Value"), Color_Seen_Extra_Default); - Color_Hinted_Main = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.MainColor.Value"), Color_Main_Default); - Color_Hinted_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Hinted.ExtraColor.Value"), Color_Hinted_Extra_Default); - Color_Collected_Main = CVarGetColor(CVAR_TRACKER_CHECK("Collected.MainColor.Value"), Color_Main_Default); - Color_Collected_Extra = - CVarGetColor(CVAR_TRACKER_CHECK("Collected.ExtraColor.Value"), Color_Collected_Extra_Default); - Color_Scummed_Main = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.MainColor.Value"), Color_Main_Default); - Color_Scummed_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Scummed.ExtraColor.Value"), Color_Scummed_Extra_Default); - Color_Saved_Main = CVarGetColor(CVAR_TRACKER_CHECK("Saved.MainColor.Value"), Color_Main_Default); - Color_Saved_Extra = CVarGetColor(CVAR_TRACKER_CHECK("Saved.ExtraColor.Value"), Color_Saved_Extra_Default); - hideUnchecked = CVarGetInteger(CVAR_TRACKER_CHECK("Unchecked.Hide"), 0); - hideScummed = CVarGetInteger(CVAR_TRACKER_CHECK("Scummed.Hide"), 0); - hideSeen = CVarGetInteger(CVAR_TRACKER_CHECK("Seen.Hide"), 0); - hideSkipped = CVarGetInteger(CVAR_TRACKER_CHECK("Skipped.Hide"), 0); - hideSaved = CVarGetInteger(CVAR_TRACKER_CHECK("Saved.Hide"), 0); - hideCollected = CVarGetInteger(CVAR_TRACKER_CHECK("Collected.Hide"), 0); - showHidden = CVarGetInteger(CVAR_TRACKER_CHECK("ShowHidden"), 0); - mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); - showLogicTooltip = CVarGetInteger(CVAR_TRACKER_CHECK("ShowLogic"), 0); - enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); - onlyShowAvailable = CVarGetInteger(CVAR_TRACKER_CHECK("OnlyShowAvailable"), 0); - - hideShopUnshuffledChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), 0); - alwaysShowGS = CVarGetInteger(CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), 0); if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { if (CVarGetInteger(CVAR_TRACKER_CHECK("ShowOnlyPaused"), 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { @@ -2089,22 +2065,14 @@ void CheckTrackerSettingsWindow::DrawElement() { ImGui::TableHeadersRow(); ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - UIWidgets::CVarColorPicker("BG Color", CVAR_TRACKER_CHECK("BgColor"), Color_Bg_Default, true, - UIWidgets::ColorPickerResetButton | UIWidgets::ColorPickerRandomButton, THEME_COLOR); - ImGui::PopItemWidth(); + SohGui::mSohMenu->MenuDrawItem(backgroundColorWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); - UIWidgets::CVarCombobox("Window Type", CVAR_TRACKER_CHECK("WindowType"), windowType, - UIWidgets::ComboboxOptions() - .LabelPosition(UIWidgets::LabelPositions::Far) - .ComponentAlignment(UIWidgets::ComponentAlignments::Right) - .Color(THEME_COLOR) - .DefaultIndex(TRACKER_WINDOW_WINDOW)); + SohGui::mSohMenu->MenuDrawItem(windowTypeWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); if (CVarGetInteger(CVAR_TRACKER_CHECK("WindowType"), TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { UIWidgets::CVarCheckbox("Enable Dragging", CVAR_TRACKER_CHECK("Draggable"), UIWidgets::CheckboxOptions().Color(THEME_COLOR)); - UIWidgets::CVarCheckbox("Only enable while paused", CVAR_TRACKER_CHECK("ShowOnlyPaused"), + UIWidgets::CVarCheckbox("Only Enable While Paused", CVAR_TRACKER_CHECK("ShowOnlyPaused"), UIWidgets::CheckboxOptions().Color(THEME_COLOR)); UIWidgets::CVarCombobox("Display Mode", CVAR_TRACKER_CHECK("DisplayType"), displayType, UIWidgets::ComboboxOptions() @@ -2129,41 +2097,17 @@ void CheckTrackerSettingsWindow::DrawElement() { } } ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - UIWidgets::CVarCheckbox("Vanilla/MQ Dungeon Spoilers", CVAR_TRACKER_CHECK("MQSpoilers"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. " - "Otherwise, Vanilla/MQ dungeon locations must be unlocked.") - .Color(THEME_COLOR)); + SohGui::mSohMenu->MenuDrawItem(dungeonSpoilerWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); ImGui::EndDisabled(); - if (UIWidgets::CVarCheckbox( - "Hide unshuffled shop item checks", CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will prevent the tracker from displaying slots with non-shop-item shuffles.") - .Color(THEME_COLOR))) { - hideShopUnshuffledChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), 0); - UpdateFilters(); - } - if (UIWidgets::CVarCheckbox( - "Always show gold skulltulas", CVAR_TRACKER_CHECK("AlwaysShowGSLocs"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings.") - .Color(THEME_COLOR))) { - alwaysShowGS = !alwaysShowGS; - UpdateFilters(); - } - UIWidgets::CVarCheckbox("Show Logic", CVAR_TRACKER_CHECK("ShowLogic"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will show a check's logic when hovering over it.") - .Color(THEME_COLOR)); + + SohGui::mSohMenu->MenuDrawItem(hideUnshuffledShopWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); + + SohGui::mSohMenu->MenuDrawItem(showGSWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); + + SohGui::mSohMenu->MenuDrawItem(showLogicWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); + ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); - if (UIWidgets::CVarCheckbox("Enable Available Checks", CVAR_TRACKER_CHECK("EnableAvailableChecks"), - UIWidgets::CheckboxOptions() - .Tooltip("If enabled, will show the checks that are available to be collected " - "with your current progress.") - .Color(THEME_COLOR))) { - enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); - RecalculateAvailableChecks(); - } + SohGui::mSohMenu->MenuDrawItem(checkAvailabilityWidget, ImGui::GetContentRegionAvail().x, THEME_COLOR); ImGui::EndDisabled(); // Filtering settings @@ -2240,4 +2184,74 @@ void CheckTrackerWindow::InitElement() { void CheckTrackerWindow::UpdateElement() { } + +void RegisterCheckTrackerWidgets() { + backgroundColorWidget = { .name = "Background Color##CheckTrackerBgColor", + .type = WidgetType::WIDGET_CVAR_COLOR_PICKER }; + backgroundColorWidget.CVar(CVAR_TRACKER_ITEM("BgColor")) + .Options( + ColorPickerOptions().Color(THEME_COLOR).DefaultValue(Color_Bg_Default).UseAlpha().ShowReset().ShowRandom()); + SohGui::mSohMenu->AddSearchWidget({ backgroundColorWidget, "Randomizer", "Check Tracker", "General Settings" }); + + windowTypeWidget = { .name = "Window Type", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + windowTypeWidget.CVar(CVAR_TRACKER_ITEM("WindowType")) + .Options(ComboboxOptions() + .DefaultIndex(TRACKER_WINDOW_WINDOW) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(windowType)); + SohGui::mSohMenu->AddSearchWidget({ windowTypeWidget, "Randomizer", "Check Tracker", "General Settings" }); + + dungeonSpoilerWidget = { .name = "Vanilla/MQ Dungeon Spoilers", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + dungeonSpoilerWidget.CVar(CVAR_TRACKER_CHECK("MQSpoilers")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. " + "Otherwise, Vanilla/MQ dungeon locations must be unlocked.")); + SohGui::mSohMenu->AddSearchWidget({ dungeonSpoilerWidget, "Randomizer", "Check Tracker", "General Settings" }); + + hideUnshuffledShopWidget = { .name = "Hide Unshuffled Shop Item Checks", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + hideUnshuffledShopWidget.CVar(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks")) + .Options( + CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will prevent the tracker from displaying slots with non-shop-item shuffles.")) + .Callback([&](WidgetInfo& info) { + hideShopUnshuffledChecks = CVarGetInteger(CVAR_TRACKER_CHECK("HideUnshuffledShopChecks"), 0); + UpdateFilters(); + }); + SohGui::mSohMenu->AddSearchWidget({ hideUnshuffledShopWidget, "Randomizer", "Check Tracker", "General Settings" }); + + showGSWidget = { .name = "Always Show Gold Skulltulas", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + showGSWidget.CVar(CVAR_TRACKER_CHECK("AlwaysShowGSLocs")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings.")) + .Callback([&](WidgetInfo& info) { + alwaysShowGS = !alwaysShowGS; + UpdateFilters(); + }); + SohGui::mSohMenu->AddSearchWidget({ showGSWidget, "Randomizer", "Check Tracker", "General Settings" }); + + showLogicWidget = { .name = "Show Logic", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + showLogicWidget.CVar(CVAR_TRACKER_CHECK("ShowLogic")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will show a check's logic when hovering over it.")); + SohGui::mSohMenu->AddSearchWidget({ showLogicWidget, "Randomizer", "Check Tracker", "General Settings" }); + + checkAvailabilityWidget = { .name = "Enable Available Checks", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + checkAvailabilityWidget.CVar(CVAR_TRACKER_CHECK("EnableAvailableChecks")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("If enabled, will show the checks that are available to be collected " + "with your current progress.")) + .Callback([&](WidgetInfo& info) { + enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); + RecalculateAvailableChecks(); + }); +} + +static RegisterMenuInitFunc initCheckTrackerWidgets(RegisterCheckTrackerWidgets); } // namespace CheckTracker diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 81144c7a7..1e677df1a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -1,20 +1,22 @@ -#include "randomizer_item_tracker.h" -#include "soh/util.h" -#include "soh/OTRGlobals.h" -#include "soh/cvar_prefixes.h" -#include "soh/SaveManager.h" -#include "soh/ResourceManagerHelpers.h" -#include "soh/SohGui/UIWidgets.hpp" -#include "soh/SohGui/SohGui.hpp" -#include "randomizerTypes.h" - +#include #include #include #include + #include -#include "soh/Enhancements/game-interactor/GameInteractor.h" + #include "randomizer_check_tracker.h" -#include +#include "randomizer_item_tracker.h" +#include "randomizerTypes.h" +#include "soh/cvar_prefixes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/OTRGlobals.h" +#include "soh/ResourceManagerHelpers.h" +#include "soh/SaveManager.h" +#include "soh/SohGui/SohGui.hpp" +#include "soh/SohGui/SohMenu.h" +#include "soh/SohGui/UIWidgets.hpp" +#include "soh/util.h" extern "C" { #include @@ -42,6 +44,27 @@ bool shouldUpdateVectors = true; std::vector mainWindowItems = {}; +static WidgetInfo backgroundColor; +static WidgetInfo windowTypeWidget; +static WidgetInfo enableDraggingWidget; +static WidgetInfo onlyPausedWidget; +static WidgetInfo ammoTracking; +static WidgetInfo keyTracking; +static WidgetInfo triforcePieceCount; +static WidgetInfo dungeonItemTracking; +static WidgetInfo gregTracking; +static WidgetInfo triforcePieceTracking; +static WidgetInfo bossSoulsTracking; +static WidgetInfo ocarinaButtonTracking; +static WidgetInfo overworldKeysTracking; +static WidgetInfo fishingPoleTracking; +static WidgetInfo personalNotesWiget; +static WidgetInfo hookshotIdentWidget; + +namespace SohGui { +extern std::shared_ptr mSohMenu; +} + std::vector inventoryItems = { ITEM_TRACKER_ITEM(ITEM_STICK, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_NUT, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_BOMB, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_BOW, 0, DrawItem), @@ -1764,24 +1787,15 @@ void ItemTrackerSettingsWindow::DrawElement() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - CVarColorPicker("Background Color##gItemTrackerBgColor", CVAR_TRACKER_ITEM("BgColor"), { 0, 0, 0, 0 }, true, - ColorPickerRandomButton | ColorPickerResetButton, THEME_COLOR); - + SohGui::mSohMenu->MenuDrawItem(backgroundColor, 250, THEME_COLOR); ImGui::PopItemWidth(); - if (CVarCombobox("Window Type", CVAR_TRACKER_ITEM("WindowType"), windowTypes, - ComboboxOptions() - .DefaultIndex(TRACKER_WINDOW_FLOATING) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } + SohGui::mSohMenu->MenuDrawItem(windowTypeWidget, 250, THEME_COLOR); if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { if (CVarCheckbox("Enable Dragging", CVAR_TRACKER_ITEM("Draggable"), CheckboxOptions().Color(THEME_COLOR))) { shouldUpdateVectors = true; } - if (CVarCheckbox("Only enable while paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"), + if (CVarCheckbox("Only Enable While Paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"), CheckboxOptions().Color(THEME_COLOR))) { shouldUpdateVectors = true; } @@ -1822,14 +1836,7 @@ void ItemTrackerSettingsWindow::DrawElement() { IntSliderOptions().Min(1).Max(30).DefaultValue(13).Color(THEME_COLOR)); ImGui::NewLine(); - CVarCombobox("Ammo/Capacity Tracking", CVAR_TRACKER_ITEM("ItemCountType"), itemTrackerCapacityTrackOptions, - ComboboxOptions() - .DefaultIndex(ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) - .ComponentAlignment(ComponentAlignments::Left) - .LabelPosition(LabelPositions::Above) - .Color(THEME_COLOR) - .Tooltip("Customize what the numbers under each item are tracking." - "\n\nNote: items without capacity upgrades will track ammo even in capacity mode")); + SohGui::mSohMenu->MenuDrawItem(ammoTracking, 250, THEME_COLOR); if (CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) == @@ -1840,22 +1847,8 @@ void ItemTrackerSettingsWindow::DrawElement() { } } - CVarCombobox("Key Count Tracking", CVAR_TRACKER_ITEM("KeyCounts"), itemTrackerKeyTrackOptions, - ComboboxOptions() - .DefaultIndex(KEYS_COLLECTED_MAX) - .ComponentAlignment(ComponentAlignments::Left) - .LabelPosition(LabelPositions::Above) - .Color(THEME_COLOR) - .Tooltip("Customize what numbers are shown for key tracking.")); - - CVarCombobox("Triforce Piece Count Tracking", CVAR_TRACKER_ITEM("TriforcePieceCounts"), - itemTrackerTriforcePieceTrackOptions, - ComboboxOptions() - .DefaultIndex(TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX) - .ComponentAlignment(ComponentAlignments::Left) - .LabelPosition(LabelPositions::Above) - .Color(THEME_COLOR) - .Tooltip("Customize what numbers are shown for triforce piece tracking.")); + SohGui::mSohMenu->MenuDrawItem(keyTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(triforcePieceCount, 250, THEME_COLOR); ImGui::TableNextColumn(); @@ -1906,14 +1899,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .Color(THEME_COLOR))) { shouldUpdateVectors = true; } - if (CVarCombobox("Dungeon Items", CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } + SohGui::mSohMenu->MenuDrawItem(dungeonItemTracking, 250, THEME_COLOR); if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != SECTION_DISPLAY_HIDDEN) { if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) == @@ -1928,61 +1914,14 @@ void ItemTrackerSettingsWindow::DrawElement() { shouldUpdateVectors = true; } } - if (CVarCombobox("Greg", CVAR_TRACKER_ITEM("DisplayType.Greg"), extendedDisplayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } + SohGui::mSohMenu->MenuDrawItem(gregTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(triforcePieceTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(bossSoulsTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(ocarinaButtonTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(overworldKeysTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(fishingPoleTracking, 250, THEME_COLOR); - if (CVarCombobox("Triforce Pieces", CVAR_TRACKER_ITEM("DisplayType.TriforcePieces"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Boss Souls", CVAR_TRACKER_ITEM("DisplayType.BossSouls"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Ocarina Buttons", CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Overworld Keys", CVAR_TRACKER_ITEM("DisplayType.OverworldKeys"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Fishing Pole", CVAR_TRACKER_ITEM("DisplayType.FishingPole"), extendedDisplayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - - if (CVarCombobox("Total Checks", "gTrackers.ItemTracker.TotalChecks.DisplayType", minimalDisplayTypes, + if (CVarCombobox("Total Checks", CVAR_TRACKER_ITEM("TotalChecks.DisplayType"), minimalDisplayTypes, ComboboxOptions() .DefaultIndex(SECTION_DISPLAY_MINIMAL_HIDDEN) .ComponentAlignment(ComponentAlignments::Right) @@ -1991,23 +1930,8 @@ void ItemTrackerSettingsWindow::DrawElement() { shouldUpdateVectors = true; } - if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || - (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING && - CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) != - TRACKER_DISPLAY_COMBO_BUTTON)) { - if (CVarCombobox("Personal notes", CVAR_TRACKER_ITEM("DisplayType.Notes"), displayTypes, - ComboboxOptions() - .DefaultIndex(SECTION_DISPLAY_HIDDEN) - .ComponentAlignment(ComponentAlignments::Right) - .LabelPosition(LabelPositions::Far) - .Color(THEME_COLOR))) { - shouldUpdateVectors = true; - } - } - CVarCheckbox("Show Hookshot Identifiers", CVAR_TRACKER_ITEM("HookshotIdentifier"), - CheckboxOptions() - .Tooltip("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot.") - .Color(THEME_COLOR)); + SohGui::mSohMenu->MenuDrawItem(personalNotesWiget, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(hookshotIdentWidget, 250, THEME_COLOR); ImGui::PopStyleVar(1); ImGui::EndTable(); @@ -2026,3 +1950,178 @@ void ItemTrackerWindow::InitElement() { GameInteractor::Instance->RegisterGameHook(ItemTrackerOnFrame); } + +void RegisterItemTrackerWidgets() { + backgroundColor = { .name = "Background Color##gItemTrackerBgColor", .type = WidgetType::WIDGET_CVAR_COLOR_PICKER }; + backgroundColor.CVar(CVAR_TRACKER_ITEM("BgColor")) + .Options( + ColorPickerOptions().Color(THEME_COLOR).DefaultValue({ 0, 0, 0, 0 }).UseAlpha().ShowReset().ShowRandom()); + SohGui::mSohMenu->AddSearchWidget({ backgroundColor, "Randomizer", "Item Tracker", "General Settings" }); + + windowTypeWidget = { .name = "Window Type", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + windowTypeWidget.CVar(CVAR_TRACKER_ITEM("WindowType")) + .Options(ComboboxOptions() + .DefaultIndex(TRACKER_WINDOW_FLOATING) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(windowTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + SohGui::mSohMenu->AddSearchWidget({ windowTypeWidget, "Randomizer", "Item Tracker", "General Settings" }); + enableDraggingWidget; + onlyPausedWidget; + + ammoTracking = { .name = "Ammo/Capacity Tracking", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + ammoTracking.CVar(CVAR_TRACKER_ITEM("ItemCountType")) + .Options(ComboboxOptions() + .DefaultIndex(ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(itemTrackerCapacityTrackOptions) + .Tooltip("Customize what the numbers under each item are tracking." + "\n\nNote: items without capacity upgrades will track ammo even in capacity mode")); + SohGui::mSohMenu->AddSearchWidget({ ammoTracking, "Randomizer", "Item Tracker", "General Settings" }); + + keyTracking = { .name = "Key Count Tracking", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + keyTracking.CVar(CVAR_TRACKER_ITEM("KeyCounts")) + .Options(ComboboxOptions() + .DefaultIndex(KEYS_COLLECTED_MAX) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(itemTrackerKeyTrackOptions) + .Tooltip("Customize what numbers are shown for key tracking.")); + SohGui::mSohMenu->AddSearchWidget({ keyTracking, "Randomizer", "Item Tracker", "General Settings" }); + + triforcePieceTracking = { .name = "Triforce Pieces", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + triforcePieceTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.TriforcePieces")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + SohGui::mSohMenu->AddSearchWidget({ triforcePieceTracking, "Randomizer", "Item Tracker", "General Settings" }); + + dungeonItemTracking = { .name = "Dungeon Items", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + dungeonItemTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.DungeonItems")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { dungeonItemTracking, "Randomizer", "Item Tracker", "General Settings", "keys maps compasses icon" }); + + gregTracking = { .name = "Greg", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + gregTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.Greg")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(extendedDisplayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget({ gregTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + bossSoulsTracking = { .name = "Boss Souls", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + bossSoulsTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.Greg")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget({ bossSoulsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + triforcePieceCount = { .name = "Triforce Piece Count Tracking", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + triforcePieceCount.CVar(CVAR_TRACKER_ITEM("TriforcePieceCounts")) + .Options(ComboboxOptions() + .DefaultIndex(TRIFORCE_PIECE_COLLECTED_REQUIRED_MAX) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(itemTrackerTriforcePieceTrackOptions) + .Tooltip("Customize what numbers are shown for triforce piece tracking.")); + SohGui::mSohMenu->AddSearchWidget({ triforcePieceCount, "Randomizer", "Item Tracker", "General Settings" }); + + ocarinaButtonTracking = { .name = "Ocarina Buttons", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + ocarinaButtonTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.OcarinaButtons")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { ocarinaButtonTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + overworldKeysTracking = { .name = "Overworld Keys", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + overworldKeysTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.OverworldKeys")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { overworldKeysTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + fishingPoleTracking = { .name = "Fishing Pole", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + fishingPoleTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.FishingPole")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_EXTENDED_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(extendedDisplayTypes)) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget( + { fishingPoleTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + + personalNotesWiget = { .name = "Personal notes", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + static const char* notesDisabledTooltip = + "Disabled because tracker is set to floating and display combo is enabled."; + personalNotesWiget.CVar(CVAR_TRACKER_ITEM("DisplayType.Notes")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .PreFunc([&](WidgetInfo& info) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW || + (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING && + CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) != + TRACKER_DISPLAY_COMBO_BUTTON)) { + info.options.get()->disabled = true; + info.options.get()->disabledTooltip = notesDisabledTooltip; + } + }) + .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + ; + SohGui::mSohMenu->AddSearchWidget({ personalNotesWiget, "Randomizer", "Item Tracker", "General Settings" }); + + hookshotIdentWidget = { .name = "Show Hookshot Identifiers", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + hookshotIdentWidget.CVar(CVAR_SETTING("FreeLook.Enabled")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot.")); + SohGui::mSohMenu->AddSearchWidget( + { hookshotIdentWidget, "Settings", "Controls", "Camera Controls", "longshot icon" }); +} + +static RegisterMenuInitFunc initItemTrackerWidgets(RegisterItemTrackerWidgets); diff --git a/soh/soh/ObjectExtension/ActorMaximumHealth.cpp b/soh/soh/ObjectExtension/ActorMaximumHealth.cpp index 9c710822f..d8c74404b 100644 --- a/soh/soh/ObjectExtension/ActorMaximumHealth.cpp +++ b/soh/soh/ObjectExtension/ActorMaximumHealth.cpp @@ -26,4 +26,4 @@ static void ActorMaximumHealth_Register() { }); } -RegisterShipInitFunc actorMaximumHealthInit(ActorMaximumHealth_Register); \ No newline at end of file +static RegisterShipInitFunc actorMaximumHealthInit(ActorMaximumHealth_Register); diff --git a/soh/soh/SohGui/Menu.cpp b/soh/soh/SohGui/Menu.cpp index 98db5d239..aa83c314b 100644 --- a/soh/soh/SohGui/Menu.cpp +++ b/soh/soh/SohGui/Menu.cpp @@ -23,12 +23,19 @@ extern void Warp(); namespace SohGui { extern std::shared_ptr mModalWindow; } +std::vector extraSearchWidgets = {}; namespace Ship { std::string disabledTempTooltip; const char* disabledTooltip; bool disabledValue = false; +bool navigateToWidget = false; +const char* navigateMainEntry = ""; +const char* navigateSidebar = ""; +std::string navigateWidgetName = ""; +bool highlightWidget = false; + bool operator==(Color_RGB8 const& l, Color_RGB8 const& r) noexcept { return l.r == r.r && l.g == r.g && l.b == r.b; } @@ -128,6 +135,7 @@ void Menu::InitElement() { poppedSize.y = CVarGetInteger(CVAR_SETTING("Menu.PoppedHeight"), 800); poppedPos.x = CVarGetInteger(CVAR_SETTING("Menu.PoppedPos.x"), 0); poppedPos.y = CVarGetInteger(CVAR_SETTING("Menu.PoppedPos.y"), 0); + menuThemeIndex = static_cast(CVarGetInteger(CVAR_SETTING("Menu.Theme"), defaultThemeIndex)); UpdateWindowBackendObjects(); } @@ -186,7 +194,12 @@ bool ModernMenuHeaderEntry(std::string label) { uint32_t Menu::DrawSearchResults(std::string& menuSearchText) { int searchCount = 0; - if (ImGui::BeginChild("Search Results")) { + std::transform(menuSearchText.begin(), menuSearchText.end(), menuSearchText.begin(), ::tolower); + menuSearchText.erase(std::remove(menuSearchText.begin(), menuSearchText.end(), ' '), menuSearchText.end()); + ImGui::SetNextWindowSizeConstraints({ ImGui::GetContentRegionAvail().x / 2, 0 }, + { ImGui::GetContentRegionAvail().x / 2, ImGui::GetContentRegionAvail().y }); + if (ImGui::BeginChild("Search Results Col 1", { ImGui::GetContentRegionAvail().x / 2, 0 }, + ImGuiChildFlags_AutoResizeY, ImGuiWindowFlags_NoTitleBar)) { for (auto& menuLabel : menuOrder) { auto& menuEntry = menuEntries.at(menuLabel); for (auto& sidebarLabel : menuEntry.sidebarOrder) { @@ -195,29 +208,63 @@ uint32_t Menu::DrawSearchResults(std::string& menuSearchText) { auto& column = sidebar.columnWidgets.at(i); for (auto& info : column) { if (info.type == WIDGET_SEARCH || info.type == WIDGET_SEPARATOR || - info.type == WIDGET_SEPARATOR_TEXT || info.isHidden) { + info.type == WIDGET_SEPARATOR_TEXT || info.isHidden || info.hideInSearch) { continue; } const char* tooltip = info.options->tooltip; std::string widgetStr = std::string(info.name) + std::string(tooltip != NULL ? tooltip : ""); - std::transform(menuSearchText.begin(), menuSearchText.end(), menuSearchText.begin(), ::tolower); - menuSearchText.erase(std::remove(menuSearchText.begin(), menuSearchText.end(), ' '), - menuSearchText.end()); std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower); widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end()); if (widgetStr.find(menuSearchText) != std::string::npos) { - MenuDrawItem(info, 90 / sidebar.columnCount, menuThemeIndex); + UIWidgets::ComponentAlignments backupAlignment; + UIWidgets::LabelPositions backupLabelPos; + if (info.type == WIDGET_COMBOBOX || info.type == WIDGET_CVAR_COMBOBOX) { + backupAlignment = + std::static_pointer_cast(info.options)->alignment; + backupLabelPos = + std::static_pointer_cast(info.options)->labelPosition; + std::static_pointer_cast(info.options)->alignment = + UIWidgets::ComponentAlignments::Left; + std::static_pointer_cast(info.options)->labelPosition = + UIWidgets::LabelPositions::Above; + } + MenuDrawItem(info, 400, menuThemeIndex); ImGui::PushStyleColor(ImGuiCol_Text, UIWidgets::ColorValues.at(UIWidgets::Colors::Gray)); std::string origin = fmt::format(" ({} -> {}, Col {})", menuEntry.label, sidebarLabel, i + 1); ImGui::Text("%s", origin.c_str()); ImGui::PopStyleColor(); searchCount++; + if (info.type == WIDGET_COMBOBOX || info.type == WIDGET_CVAR_COMBOBOX) { + std::static_pointer_cast(info.options)->alignment = + backupAlignment; + std::static_pointer_cast(info.options)->labelPosition = + backupLabelPos; + } } } } } } + for (auto& entry : extraSearchWidgets) { + if (entry.info.type == WIDGET_SEARCH || entry.info.type == WIDGET_SEPARATOR || + entry.info.type == WIDGET_SEPARATOR_TEXT || entry.info.isHidden || entry.info.hideInSearch) { + continue; + } + std::string widgetStr = + entry.info.name + entry.info.options->tooltip + entry.extraTerms + entry.sidebarName; + std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower); + widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end()); + if (widgetStr.find(menuSearchText) != std::string::npos) { + MenuDrawItem(entry.info, 400, menuThemeIndex); + ImGui::PushStyleColor(ImGuiCol_Text, UIWidgets::ColorValues.at(UIWidgets::Colors::Gray)); + std::string origin = fmt::format(" ({} -> {}, {})", entry.menuName, entry.sidebarName, entry.location); + ImGui::Text("%s", origin.c_str()); + ImGui::PopStyleColor(); + searchCount++; + } + } + ImGui::EndChild(); } return searchCount; } @@ -227,6 +274,10 @@ void Menu::AddMenuEntry(std::string entryName, const char* entryCvar) { menuOrder.push_back(entryName); } +void Menu::AddSearchWidget(SearchWidget widget) { + extraSearchWidgets.push_back(widget); +} + std::unordered_map& Menu::GetDisabledMap() { return disabledMap; } @@ -449,6 +500,20 @@ void Menu::MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors me window->DrawElement(); } } break; + case WIDGET_CVAR_COLOR_PICKER: { + auto options = std::static_pointer_cast(widget.options); + uint32_t modifiers = 0; + if (options->showLock) + modifiers |= UIWidgets::ColorPickerLockCheck; + if (options->showRandom) + modifiers |= UIWidgets::ColorPickerRandomButton; + if (options->showReset) + modifiers |= UIWidgets::ColorPickerResetButton; + if (options->showRainbow) + modifiers |= UIWidgets::ColorPickerRainbowCheck; + UIWidgets::CVarColorPicker(widget.name.c_str(), widget.cVar, options->defaultValue, options->useAlpha, + modifiers, options->color); + } break; case WIDGET_SEARCH: { UIWidgets::PushStyleButton(menuThemeIndex); if (ImGui::Button("Clear")) { @@ -473,7 +538,6 @@ void Menu::MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors me return; } DrawSearchResults(menuSearchText); - ImGui::EndChild(); } break; default: break; @@ -501,6 +565,19 @@ void Menu::DrawElement() { for (auto& [reason, info] : disabledMap) { info.active = info.evaluation(info); } + const char* headerCvar = CVAR_SETTING("Menu.ActiveHeader"); + + if (navigateToWidget) { + if (menuEntries.contains(navigateMainEntry) && + menuEntries.at(navigateMainEntry).sidebars.contains(navigateSidebar)) { + menuSearch.Clear(); + CVarSetString(headerCvar, navigateMainEntry); + const char* sidebarCvar = menuEntries.at(navigateMainEntry).sidebarCvar; + CVarSetString(sidebarCvar, navigateSidebar); + highlightWidget = true; + } + navigateToWidget = false; + } raceDisableActive = CVarGetInteger(CVAR_SETTING("DisableChanges"), 0); @@ -569,7 +646,6 @@ void Menu::DrawElement() { ImGui::PushFont(OTRGlobals::Instance->fontStandardLargest); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10.0f, 8.0f)); - const char* headerCvar = CVAR_SETTING("Menu.ActiveHeader"); std::string headerIndex = CVarGetString(headerCvar, "Settings"); ImVec2 pos = window->DC.CursorPos; float centerX = pos.x + windowWidth / 2 - (style.ItemSpacing.x * (menuEntries.size() + 1)); @@ -800,21 +876,26 @@ void Menu::DrawElement() { ImGuiWindowFlags_NoTitleBar); } if (headerSearch && menuSearchText.length() > 0) { + ImGui::AlignTextToFramePadding(); + ImGui::PushFont(OTRGlobals::Instance->fontMonoLargest); + ImGui::Text("Search Results"); + ImGui::PopFont(); + ImGui::SameLine(); + UIWidgets::ButtonOptions clearBtnOpts = {}; + clearBtnOpts.size = UIWidgets::Sizes::Inline; + if (UIWidgets::Button("Clear Search", clearBtnOpts)) { + menuSearch.Clear(); + } + ImGui::BeginChild("searchSeparator", ImVec2(ImGui::GetContentRegionAvail().x / 2, 20), + ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY); + UIWidgets::Separator(true, true, 0, 10); + ImGui::EndChild(); uint32_t searchCount = DrawSearchResults(menuSearchText); if (searchCount == 0) { ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("No results found").x) / 2); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.4f), "No results found"); } - ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("Clear Search").x) / 2 - 10.0f); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); - UIWidgets::ButtonOptions clearBtnOpts = {}; - clearBtnOpts.size = UIWidgets::Sizes::Inline; - if (UIWidgets::Button("Clear Search", clearBtnOpts)) { - menuSearch.Clear(); - } - - ImGui::EndChild(); } else { std::string menuLabel = menuEntries.at(headerIndex).label; if (MenuInit::GetUpdateFuncs().contains(menuLabel)) { diff --git a/soh/soh/SohGui/Menu.h b/soh/soh/SohGui/Menu.h index a7facffd1..1af541b8d 100644 --- a/soh/soh/SohGui/Menu.h +++ b/soh/soh/SohGui/Menu.h @@ -26,6 +26,7 @@ class Menu : public GuiWindow { void MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors menuThemeIndex); void AddMenuEntry(std::string entryName, const char* entryCvar); + void AddSearchWidget(SearchWidget widget); std::unordered_map& GetDisabledMap(); protected: diff --git a/soh/soh/SohGui/MenuTypes.h b/soh/soh/SohGui/MenuTypes.h index e96d015ef..911b688d7 100644 --- a/soh/soh/SohGui/MenuTypes.h +++ b/soh/soh/SohGui/MenuTypes.h @@ -24,10 +24,10 @@ typedef enum { struct WidgetInfo; struct disabledInfo; -using VoidFunc = void (*)(); -using DisableInfoFunc = bool (*)(disabledInfo&); +using VoidFunc = std::function; +using DisableInfoFunc = std::function; using DisableVec = std::vector; -using WidgetFunc = void (*)(WidgetInfo&); +using WidgetFunc = std::function; typedef enum { WIDGET_CHECKBOX, @@ -41,8 +41,8 @@ typedef enum { WIDGET_BUTTON, WIDGET_INPUT, WIDGET_CVAR_INPUT, - WIDGET_COLOR_24, // color picker without alpha - WIDGET_COLOR_32, // color picker with alpha + WIDGET_CVAR_COLOR_PICKER, + WIDGET_COLOR_PICKER, WIDGET_SEARCH, WIDGET_SEPARATOR, WIDGET_SEPARATOR_TEXT, @@ -72,9 +72,10 @@ typedef enum { // holds the widget values for a widget, contains all CVar types available from LUS. int32_t is used for boolean // evaluation using CVarVariant = std::variant; -using OptionsVariant = std::variant; +using OptionsVariant = + std::variant; // All the info needed for display and search of all widgets in the menu. // `name` is the label displayed, @@ -111,11 +112,13 @@ struct WidgetInfo { bool isHidden = false; bool sameLine = false; bool raceDisable = true; + bool hideInSearch = false; WidgetInfo& CVar(const char* cVar_) { cVar = cVar_; return *this; } + WidgetInfo& Options(OptionsVariant options_) { switch (type) { case WIDGET_AUDIO_BACKEND: @@ -138,6 +141,11 @@ struct WidgetInfo { options = std::make_shared(std::get(options_)); break; + case WIDGET_COLOR_PICKER: + case WIDGET_CVAR_COLOR_PICKER: + options = + std::make_shared(std::get(options_)); + break; case WIDGET_BUTTON: options = std::make_shared(std::get(options_)); break; @@ -155,48 +163,63 @@ struct WidgetInfo { } return *this; } + + WidgetInfo& Options(std::shared_ptr options_) { + options = options_; + return *this; + } + + WidgetInfo& Callback(WidgetFunc callback_) { + callback = callback_; + return *this; + } + + WidgetInfo& PreFunc(WidgetFunc preFunc_) { + preFunc = preFunc_; + return *this; + } + + WidgetInfo& PostFunc(WidgetFunc postFunc_) { + postFunc = postFunc_; + return *this; + } + + WidgetInfo& WindowName(const char* windowName_) { + windowName = windowName_; + return *this; + } + + WidgetInfo& ValuePointer(std::variant valuePointer_) { + valuePointer = valuePointer_; + return *this; + } + + WidgetInfo& SameLine(bool sameLine_) { + sameLine = sameLine_; + return *this; + } + + WidgetInfo& CustomFunction(WidgetFunc customFunction_) { + customFunction = customFunction_; + return *this; + } + + WidgetInfo& RaceDisable(bool disable) { + raceDisable = disable; + return *this; + } + + WidgetInfo& HideInSearch(bool hide) { + hideInSearch = hide; + return *this; + } + void ResetDisables() { isHidden = false; options->disabled = false; options->disabledTooltip = ""; activeDisables.clear(); } - WidgetInfo& Options(std::shared_ptr options_) { - options = options_; - return *this; - } - WidgetInfo& Callback(WidgetFunc callback_) { - callback = callback_; - return *this; - } - WidgetInfo& PreFunc(WidgetFunc preFunc_) { - preFunc = preFunc_; - return *this; - } - WidgetInfo& PostFunc(WidgetFunc postFunc_) { - postFunc = postFunc_; - return *this; - } - WidgetInfo& WindowName(const char* windowName_) { - windowName = windowName_; - return *this; - } - WidgetInfo& ValuePointer(std::variant valuePointer_) { - valuePointer = valuePointer_; - return *this; - } - WidgetInfo& SameLine(bool sameLine_) { - sameLine = sameLine_; - return *this; - } - WidgetInfo& CustomFunction(WidgetFunc customFunction_) { - customFunction = customFunction_; - return *this; - } - WidgetInfo& RaceDisable(bool disable) { - raceDisable = disable; - return *this; - } }; struct WidgetPath { @@ -269,6 +292,24 @@ struct MenuInit { } }; +struct SearchEntry { + // First four required + std::string widgetName; + std::string menuName; + std::string sidebarName; + std::string location; + std::string extraTerms = ""; +}; + +struct SearchWidget { + // First four required + WidgetInfo& info; + std::string menuName; + std::string sidebarName; + std::string location; + std::string extraTerms = ""; +}; + struct RegisterMenuInitFunc { RegisterMenuInitFunc(std::function initFunc) { auto& menuInitFuncs = MenuInit::GetInitFuncs(); diff --git a/soh/soh/SohGui/SohMenu.cpp b/soh/soh/SohGui/SohMenu.cpp index a71fd1cad..d5c2c0c1f 100644 --- a/soh/soh/SohGui/SohMenu.cpp +++ b/soh/soh/SohGui/SohMenu.cpp @@ -61,8 +61,9 @@ WidgetInfo& SohMenu::AddWidget(WidgetPath& pathInfo, std::string widgetName, Wid case WIDGET_WINDOW_BUTTON: widget.options = std::make_shared(); break; - case WIDGET_COLOR_24: - case WIDGET_COLOR_32: + case WIDGET_CVAR_COLOR_PICKER: + case WIDGET_COLOR_PICKER: + widget.options = std::make_shared(); break; case WIDGET_SEPARATOR_TEXT: case WIDGET_TEXT: diff --git a/soh/soh/SohGui/SohMenuDevTools.cpp b/soh/soh/SohGui/SohMenuDevTools.cpp index 2a0fcd62a..f9e113b55 100644 --- a/soh/soh/SohGui/SohMenuDevTools.cpp +++ b/soh/soh/SohGui/SohMenuDevTools.cpp @@ -124,6 +124,7 @@ void SohMenu::AddMenuDevTools() { .CVar(CVAR_WINDOW("SohStats")) .RaceDisable(false) .WindowName("Stats##Soh") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Stats Window.")); // Console @@ -132,6 +133,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Console", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("SohConsole")) .WindowName("Console##SoH") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Console Window.")); // Save Editor @@ -140,6 +142,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Save Editor", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("SaveEditor")) .WindowName("Save Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Save Editor Window.")); // Hook Debugger @@ -148,6 +151,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Hook Debugger", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("HookDebugger")) .WindowName("Hook Debugger") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Hook Debugger Window.")); // Collision Viewer @@ -156,6 +160,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Collision Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("CollisionViewer")) .WindowName("Collision Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Collision Viewer Window.")); // Actor Viewer @@ -164,6 +169,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Actor Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("ActorViewer")) .WindowName("Actor Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Actor Viewer Window.")); // Display List Viewer @@ -172,6 +178,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Display List Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("DisplayListViewer")) .WindowName("Display List Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Display List Viewer Window.")); // Value Viewer @@ -180,6 +187,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Value Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("ValueViewer")) .WindowName("Value Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Value Viewer Window.")); // Message Viewer @@ -188,6 +196,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Message Viewer", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("MessageViewer")) .WindowName("Message Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Message Viewer Window.")); // Gfx Debugger @@ -196,6 +205,7 @@ void SohMenu::AddMenuDevTools() { AddWidget(path, "Popout Gfx Debugger", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("SohGfxDebugger")) .WindowName("GfxDebugger##SoH") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Gfx Debugger Window.")); } diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index b72f6298e..dd965be0a 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1844,6 +1844,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("CosmeticsEditor")) .RaceDisable(false) .WindowName("Cosmetics Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Cosmetics Editor Window.")); // Audio Editor @@ -1853,6 +1854,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("AudioEditor")) .RaceDisable(false) .WindowName("Audio Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Audio Editor Window.")); // Gameplay Stats @@ -1862,6 +1864,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("GameplayStats")) .RaceDisable(false) .WindowName("Gameplay Stats") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Gameplay Stats Window.")); // Time Splits @@ -1871,6 +1874,7 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_WINDOW("TimeSplits")) .RaceDisable(false) .WindowName("Time Splits") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Time Splits Window.")); // Timers diff --git a/soh/soh/SohGui/SohMenuRandomizer.cpp b/soh/soh/SohGui/SohMenuRandomizer.cpp index 47e651408..ad688740a 100644 --- a/soh/soh/SohGui/SohMenuRandomizer.cpp +++ b/soh/soh/SohGui/SohMenuRandomizer.cpp @@ -22,6 +22,7 @@ void SohMenu::AddMenuRandomizer() { AddWidget(path, "Popout Randomizer Settings Window", WIDGET_WINDOW_BUTTON) .CVar(CVAR_WINDOW("RandomizerSettings")) .WindowName("Randomizer Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Randomizer Settings Window.")); // Enhancements @@ -104,6 +105,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("PlandomizerEditor")) .RaceDisable(false) .WindowName("Plandomizer Editor") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Randomizer Settings Window.")); // Item Tracker @@ -115,6 +117,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("ItemTracker")) .RaceDisable(false) .WindowName("Item Tracker") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Item Tracker.").EmbedWindow(false)); AddWidget(path, "Item Tracker Settings", WIDGET_SEPARATOR_TEXT); @@ -122,6 +125,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("ItemTrackerSettings")) .RaceDisable(false) .WindowName("Item Tracker Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Item Tracker Settings Window.")); // Entrance Tracker @@ -133,6 +137,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("EntranceTracker")) .RaceDisable(false) .WindowName("Entrance Tracker") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Entrance Tracker.").EmbedWindow(false)); AddWidget(path, "Entrance Tracker Settings", WIDGET_SEPARATOR_TEXT); @@ -140,6 +145,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("EntranceTrackerSettings")) .RaceDisable(false) .WindowName("Entrance Tracker Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Entrance Tracker Settings Window.")); // Check Tracker @@ -151,6 +157,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("CheckTracker")) .RaceDisable(false) .WindowName("Check Tracker") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Check Tracker.").EmbedWindow(false)); AddWidget(path, "Check Tracker Settings", WIDGET_SEPARATOR_TEXT); @@ -158,6 +165,7 @@ void SohMenu::AddMenuRandomizer() { .CVar(CVAR_WINDOW("CheckTrackerSettings")) .RaceDisable(false) .WindowName("Check Tracker Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Check Tracker Settings Window.")); } diff --git a/soh/soh/SohGui/SohMenuSettings.cpp b/soh/soh/SohGui/SohMenuSettings.cpp index 2472e325b..768370b85 100644 --- a/soh/soh/SohGui/SohMenuSettings.cpp +++ b/soh/soh/SohGui/SohMenuSettings.cpp @@ -433,6 +433,7 @@ void SohMenu::AddMenuSettings() { .CVar(CVAR_WINDOW("ControllerConfiguration")) .RaceDisable(false) .WindowName("Configure Controller") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Bindings Window.")); // Input Viewer @@ -443,6 +444,7 @@ void SohMenu::AddMenuSettings() { .CVar(CVAR_WINDOW("InputViewer")) .RaceDisable(false) .WindowName("Input Viewer") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Toggles the Input Viewer.").EmbedWindow(false)); AddWidget(path, "Input Viewer Settings", WIDGET_SEPARATOR_TEXT); @@ -450,6 +452,7 @@ void SohMenu::AddMenuSettings() { .CVar(CVAR_WINDOW("InputViewerSettings")) .RaceDisable(false) .WindowName("Input Viewer Settings") + .HideInSearch(true) .Options(WindowButtonOptions().Tooltip("Enables the separate Input Viewer Settings Window.")); // Notifications diff --git a/soh/soh/SohGui/UIWidgets.hpp b/soh/soh/SohGui/UIWidgets.hpp index 0ed88bade..95590b1ce 100644 --- a/soh/soh/SohGui/UIWidgets.hpp +++ b/soh/soh/SohGui/UIWidgets.hpp @@ -162,6 +162,64 @@ struct ButtonOptions : WidgetOptions { } }; +struct ColorPickerOptions : WidgetOptions { + ImVec2 size = Sizes::Fill; + ImVec2 padding = ImVec2(10.0f, 8.0f); + Colors color = Colors::Gray; + Color_RGBA8 defaultValue = { 255, 255, 255, 255 }; + bool useAlpha, showReset, showRandom, showRainbow, showLock; + + ColorPickerOptions& Size(ImVec2 size_) { + size = size_; + return *this; + } + + ColorPickerOptions& Padding(ImVec2 padding_) { + padding = padding_; + return *this; + } + + ColorPickerOptions& Tooltip(const char* tooltip_) { + WidgetOptions::tooltip = tooltip_; + return *this; + } + + ColorPickerOptions& ShowReset(bool showReset_ = true) { + showReset = showReset_; + return *this; + } + + ColorPickerOptions& ShowRandom(bool showRandom_ = true) { + showRandom = showRandom_; + return *this; + } + + ColorPickerOptions& ShowRainbow(bool showRainbow_ = true) { + showRainbow = showRainbow_; + return *this; + } + + ColorPickerOptions& ShowLock(bool showLock_ = true) { + showLock = showLock_; + return *this; + } + + ColorPickerOptions& UseAlpha(bool useAlpha_ = true) { + useAlpha = useAlpha_; + return *this; + } + + ColorPickerOptions& Color(Colors color_) { + color = color_; + return *this; + } + + ColorPickerOptions& DefaultValue(Color_RGBA8 defaultValue_) { + defaultValue = defaultValue_; + return *this; + } +}; + struct WindowButtonOptions : WidgetOptions { ImVec2 size = Sizes::Inline; ImVec2 padding = ImVec2(10.0f, 8.0f);