summaryrefslogtreecommitdiff
path: root/mm/2s2h/BenGui/BenMenu.cpp
diff options
context:
space:
mode:
authorMalkierian <malkierian@gmail.com>2025-05-05 15:34:55 -0700
committerGitHub <noreply@github.com>2025-05-05 17:34:55 -0500
commit667edb04d0f1425977f4a298aa0e37c3f99b4b87 (patch)
tree9466a8f8ef7277932f0af2551a140d6a29d63e1e /mm/2s2h/BenGui/BenMenu.cpp
parent1bb16c5cb3a5404c7059b7733ee207253c267a84 (diff)
Menu Modularize & MenuInit (#968)
* MenuEntries now uses unordered_map for storage, and vector for draw order. AddMenuEntry is now used for main menu entries (settings, enhancements, etc). MenuInit (based off of ShipInit) added to be able to register update and init functions (init can handle widgets, new sidebars in existing menu entries, or entirely new menu entries). Fixed top search modification to headerWidth to restore proper scrollbar functionality. Advanced resolution options now use MenuInit to handle update and init (options still hidden in push because of framebuffer issues). * Don't need `protected:` in BenMenu.h anymore. * Fix header define typo. * Fix search aggregation (was only checking first column). * Harden index OOB for header and sidebar indices. * Fix fullscreen checkbox. Make slider clamping opt-out. * Fix merge issues and change rando registration to MenuInit. * Bit of header cleanup. * Resolve merge errors. * Fix LUS ref * clang
Diffstat (limited to 'mm/2s2h/BenGui/BenMenu.cpp')
-rw-r--r--mm/2s2h/BenGui/BenMenu.cpp136
1 files changed, 60 insertions, 76 deletions
diff --git a/mm/2s2h/BenGui/BenMenu.cpp b/mm/2s2h/BenGui/BenMenu.cpp
index 4ad8deda7..fa70e05e2 100644
--- a/mm/2s2h/BenGui/BenMenu.cpp
+++ b/mm/2s2h/BenGui/BenMenu.cpp
@@ -11,6 +11,10 @@
#include <variant>
#include "StringHelper.h"
#include <spdlog/fmt/fmt.h>
+#include "variables.h"
+#include <variant>
+#include <tuple>
+#include "ResolutionEditor.h"
#include "2s2h/Rando/Rando.h"
extern "C" {
@@ -34,40 +38,24 @@ void FreeLookPitchMinMax() {
using namespace UIWidgets;
void BenMenu::AddSidebarEntry(std::string sectionName, std::string sidebarName, uint32_t columnCount) {
- if (sectionName == "Settings") {
- settingsSidebar.emplace(sidebarName, SidebarEntry{ .columnCount = columnCount });
- settingsOrder.push_back(sidebarName);
- } else if (sectionName == "Enhancements") {
- enhancementsSidebar.emplace(sidebarName, SidebarEntry{ .columnCount = columnCount });
- enhancementsOrder.push_back(sidebarName);
- } else if (sectionName == "Dev Tools") {
- devToolsSidebar.emplace(sidebarName, SidebarEntry{ .columnCount = columnCount });
- devToolsOrder.push_back(sidebarName);
- } else if (sectionName == "Rando") {
- randoSidebar.emplace(sidebarName, SidebarEntry{ .columnCount = columnCount });
- randoOrder.push_back(sidebarName);
- }
+ assert(!sectionName.empty());
+ assert(!sidebarName.empty());
+ menuEntries.at(sectionName).sidebars.emplace(sidebarName, SidebarEntry{ .columnCount = columnCount });
+ menuEntries.at(sectionName).sidebarOrder.push_back(sidebarName);
}
WidgetInfo& BenMenu::AddWidget(WidgetPath& pathInfo, std::string widgetName, WidgetType widgetType) {
- assert(widgetName != ""); // Must be unique
- std::unordered_map<std::string, SidebarEntry>* sidebar;
- if (pathInfo.sectionName == "Settings") {
- sidebar = &settingsSidebar;
- } else if (pathInfo.sectionName == "Enhancements") {
- sidebar = &enhancementsSidebar;
- } else if (pathInfo.sectionName == "Dev Tools") {
- sidebar = &devToolsSidebar;
- } else if (pathInfo.sectionName == "Rando") {
- sidebar = &randoSidebar;
- }
- uint8_t column = pathInfo.column - 1;
- if (sidebar->contains(pathInfo.sidebarName)) {
- while (sidebar->at(pathInfo.sidebarName).columnWidgets.size() < column + 1) {
- sidebar->at(pathInfo.sidebarName).columnWidgets.push_back({});
+ assert(!widgetName.empty()); // Must be unique
+ assert(menuEntries.contains(pathInfo.sectionName)); // Section/header must already exist
+ assert(menuEntries.at(pathInfo.sectionName).sidebars.contains(pathInfo.sidebarName)); // Sidebar must already exist
+ std::unordered_map<std::string, SidebarEntry>& sidebar = menuEntries.at(pathInfo.sectionName).sidebars;
+ uint8_t column = pathInfo.column;
+ if (sidebar.contains(pathInfo.sidebarName)) {
+ while (sidebar.at(pathInfo.sidebarName).columnWidgets.size() < column + 1) {
+ sidebar.at(pathInfo.sidebarName).columnWidgets.push_back({});
}
}
- SidebarEntry& entry = sidebar->at(pathInfo.sidebarName);
+ SidebarEntry& entry = sidebar.at(pathInfo.sidebarName);
entry.columnWidgets.at(column).push_back({ .name = widgetName, .type = widgetType });
WidgetInfo& widget = entry.columnWidgets.at(column).back();
switch (widgetType) {
@@ -109,10 +97,11 @@ WidgetInfo& BenMenu::AddWidget(WidgetPath& pathInfo, std::string widgetName, Wid
}
void BenMenu::AddSettings() {
-
+ // Add Settings menu
+ AddMenuEntry("Settings", "gSettings.Menu.SettingsSidebarSection");
// General Settings
AddSidebarEntry("Settings", "General", 3);
- WidgetPath path = { "Settings", "General", 1 };
+ WidgetPath path = { "Settings", "General", SECTION_COLUMN_1 };
AddWidget(path, "Menu Theme", WIDGET_CVAR_COMBOBOX)
.CVar("gSettings.Menu.Theme")
.Options(ComboboxOptions()
@@ -357,7 +346,7 @@ void BenMenu::AddSettings() {
});
})
.Options(ButtonOptions().Tooltip("Displays a test notification."));
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "In-Game Timer", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Toggle Display Overlay", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.DisplayOverlay")
@@ -376,7 +365,7 @@ void BenMenu::AddSettings() {
.Format("%.1f")
.Step(0.1f));
- path.column = 1;
+ path.column = SECTION_COLUMN_1;
path.sidebarName = "Presets";
AddSidebarEntry("Settings", "Presets", 1);
AddWidget(path, "Presets", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { PresetManager_Draw(); });
@@ -384,7 +373,8 @@ void BenMenu::AddSettings() {
int32_t motionBlurStrength;
void BenMenu::AddEnhancements() {
- WidgetPath path = { "Enhancements", "Camera", 1 };
+ AddMenuEntry("Enhancements", "gSettings.Menu.EnhancementsSidebarSection");
+ WidgetPath path = { "Enhancements", "Camera", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Camera", 3);
// Camera Snap Fix
AddWidget(path, "Fixes", WIDGET_SEPARATOR_TEXT);
@@ -491,7 +481,7 @@ void BenMenu::AddEnhancements() {
.Min(0.01f)
.Max(2.0f));
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "Cameras", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Free Look", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Camera.FreeLook.Enable")
@@ -600,7 +590,7 @@ void BenMenu::AddEnhancements() {
.Min(0.1f)
.Max(3.0f));
- path = { "Enhancements", "Cheats", 1 };
+ path = { "Enhancements", "Cheats", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Cheats", 3);
AddWidget(path, "Infinite Health", WIDGET_CVAR_CHECKBOX)
.CVar("gCheats.InfiniteHealth")
@@ -653,7 +643,7 @@ void BenMenu::AddEnhancements() {
.ComboMap(timeStopOptions));
//// Gameplay Enhancements
- path = { "Enhancements", "Gameplay", 1 };
+ path = { "Enhancements", "Gameplay", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Gameplay", 3);
AddWidget(path, "Player", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Fast Deku Flower Launch", WIDGET_CVAR_CHECKBOX)
@@ -713,7 +703,7 @@ void BenMenu::AddEnhancements() {
.Options(
CheckboxOptions().Tooltip("When a bomb drop is spawned, it has a 50% chance to be a Bombchu instead."));
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "Modes", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Play as Kafei", WIDGET_CVAR_CHECKBOX)
.CVar("gModes.PlayAsKafei")
@@ -852,7 +842,7 @@ void BenMenu::AddEnhancements() {
.Options(CheckboxOptions().Tooltip(
"Play the complete Ballad after playing in one form if you have all three transformation masks."));
- path.column = 3;
+ path.column = SECTION_COLUMN_3;
AddWidget(path, "Saving", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "3rd Save File Slot", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Saving.FileSlot3")
@@ -919,7 +909,7 @@ void BenMenu::AddEnhancements() {
"cause issues when attempting the 0th Day Glitch."));
//// Graphics Enhancements
- path = { "Enhancements", "Graphics", 1 };
+ path = { "Enhancements", "Graphics", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Graphics", 3);
AddWidget(path, "Clock", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Clock Type", WIDGET_CVAR_COMBOBOX)
@@ -972,7 +962,7 @@ void BenMenu::AddEnhancements() {
mBenMenu->disabledMap.at(DISABLE_FOR_MOTION_BLUR_OFF).active;
});
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "Other", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "3D Item Drops", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Graphics.3DItemDrops")
@@ -1012,7 +1002,7 @@ void BenMenu::AddEnhancements() {
.Max(5)
.DefaultValue(1));
- path = { "Enhancements", "Items/Songs", 1 };
+ path = { "Enhancements", "Items/Songs", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Items/Songs", 3);
// Mask Enhancements
AddWidget(path, "Masks", WIDGET_SEPARATOR_TEXT);
@@ -1041,7 +1031,7 @@ void BenMenu::AddEnhancements() {
.Options(CheckboxOptions().Tooltip("Speeds up the wind-up towards spiky rolling to be near instant."));
// Song Enhancements
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "Ocarina", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Better Song of Double Time", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Songs.BetterSongOfDoubleTime")
@@ -1086,7 +1076,7 @@ void BenMenu::AddEnhancements() {
.Options(CheckboxOptions().Tooltip("Skips the cutscenes when playing any of the Song of Time songs."));
// Time Savers
- path = { "Enhancements", "Time Savers", 1 };
+ path = { "Enhancements", "Time Savers", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Time Savers", 3);
// Cutscene Skips
AddWidget(path, "Cutscenes", WIDGET_SEPARATOR_TEXT);
@@ -1133,7 +1123,7 @@ void BenMenu::AddEnhancements() {
.ComboMap(skipGetItemCutscenesOptions));
// Dialogue Enhancements
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "Dialogue", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Fast Bank Selection", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Dialogue.FastBankSelection")
@@ -1147,7 +1137,8 @@ void BenMenu::AddEnhancements() {
AddWidget(path, "Auto Bombers' Code", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Dialogue.AutoBombersCode")
.Options(CheckboxOptions().Tooltip("Automatically fill in the Bombers' code once you've got the notebook."));
- path.column = 3;
+
+ path.column = SECTION_COLUMN_3;
AddWidget(path, "Other", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Swamp Boat Timesaver", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.Timesavers.SwampBoatSpeed")
@@ -1168,7 +1159,7 @@ void BenMenu::AddEnhancements() {
.Options(CheckboxOptions().Tooltip("Fade in and out more quickly when moving between areas."));
// Fixes
- path = { "Enhancements", "Fixes", 1 };
+ path = { "Enhancements", "Fixes", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Fixes", 3);
AddWidget(path, "Fixes", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Fix Console Crashes", WIDGET_CVAR_CHECKBOX)
@@ -1216,7 +1207,7 @@ void BenMenu::AddEnhancements() {
"fill a new heart container."));
// Restorations
- path = { "Enhancements", "Restorations", 1 };
+ path = { "Enhancements", "Restorations", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Restorations", 3);
AddWidget(path, "Restorations", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Constant Distance Backflips and Sidehops", WIDGET_CVAR_CHECKBOX)
@@ -1264,7 +1255,7 @@ void BenMenu::AddEnhancements() {
.DefaultValue(0));
// Difficulty Options
- path = { "Enhancements", "Difficulty Options", 1 };
+ path = { "Enhancements", "Difficulty Options", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Difficulty Options", 3);
AddWidget(path, "Disable Takkuri Steal", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.DifficultyOptions.DisableTakkuriSteal")
@@ -1299,7 +1290,7 @@ void BenMenu::AddEnhancements() {
.DefaultIndex(GibdoTradeSequenceOptions::GIBDO_TRADE_SEQUENCE_VANILLA)
.ComboMap(gibdoTradeSequenceOptions));
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "Hyper Enemies", WIDGET_CVAR_CHECKBOX)
.CVar("gEnhancements.DifficultyOptions.HyperEnemies")
.Options(CheckboxOptions().Tooltip("Double the rate at which enemies are updated, making them more difficult"));
@@ -1328,7 +1319,7 @@ void BenMenu::AddEnhancements() {
.DefaultValue(60));
// HUD Editor
- path = { "Enhancements", "HUD Editor", 1 };
+ path = { "Enhancements", "HUD Editor", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "HUD Editor", 1);
AddWidget(path, "Popout HUD Editor", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.HudEditor")
@@ -1338,7 +1329,7 @@ void BenMenu::AddEnhancements() {
.Size(Sizes::Inline));
// Cosmetics Editor
- path = { "Enhancements", "Cosmetic Editor", 1 };
+ path = { "Enhancements", "Cosmetic Editor", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Cosmetic Editor", 1);
AddWidget(path, "Popout Cosmetic Editor", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.CosmeticEditor")
@@ -1348,14 +1339,14 @@ void BenMenu::AddEnhancements() {
.Size(Sizes::Inline));
// Item Tracker Settings
- path = { "Enhancements", "Item Tracker", 1 };
+ path = { "Enhancements", "Item Tracker", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Item Tracker", 1);
AddWidget(path, "Popout Settings", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.ItemTrackerSettings")
.WindowName("Item Tracker Settings");
// Audio Editor
- path = { "Enhancements", "Audio Editor", 1 };
+ path = { "Enhancements", "Audio Editor", SECTION_COLUMN_1 };
AddSidebarEntry("Enhancements", "Audio Editor", 1);
AddWidget(path, "Popout Audio Editor", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.AudioEditor")
@@ -1363,8 +1354,9 @@ void BenMenu::AddEnhancements() {
}
void BenMenu::AddDevTools() {
- WidgetPath path = { "Dev Tools", "General", 1 };
+ AddMenuEntry("Dev Tools", "gSettings.Menu.DevToolsSidebarSection");
AddSidebarEntry("Dev Tools", "General", 3);
+ WidgetPath path = { "Dev Tools", "General", SECTION_COLUMN_1 };
AddWidget(path, "Popout Menu", WIDGET_CVAR_CHECKBOX)
.CVar("gSettings.Menu.Popout")
.Options(CheckboxOptions().Tooltip("Changes the menu display from overlay to windowed."));
@@ -1449,18 +1441,18 @@ void BenMenu::AddDevTools() {
}
})
.SameLine(true);
- path.column = 2;
+ path.column = SECTION_COLUMN_2;
AddWidget(path, "Warp Point", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { RenderWarpPointSection(); });
// dev tools windows
- path = { "Dev Tools", "Collision Viewer", 1 };
+ path = { "Dev Tools", "Collision Viewer", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Collision Viewer", 1);
AddWidget(path, "Popout Collision Viewer", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.CollisionViewer")
.Options(ButtonOptions().Tooltip("Makes collision visible on screen.").Size(Sizes::Inline))
.WindowName("Collision Viewer");
- path = { "Dev Tools", "Stats", 1 };
+ path = { "Dev Tools", "Stats", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Stats", 1);
AddWidget(path, "Popout Stats", WIDGET_WINDOW_BUTTON)
.CVar("gOpenWindows.Stats")
@@ -1468,7 +1460,7 @@ void BenMenu::AddDevTools() {
"Shows the Stats window, with your FPS and frametimes, and the OS you're playing on."))
.WindowName("Stats");
- path = { "Dev Tools", "Console", 1 };
+ path = { "Dev Tools", "Console", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Console", 1);
AddWidget(path, "Popout Console", WIDGET_WINDOW_BUTTON)
.CVar("gOpenWindows.Console")
@@ -1476,7 +1468,7 @@ void BenMenu::AddDevTools() {
"Enables the Console window, allowing you to input commands. Type help for some examples."))
.WindowName("Console");
- path = { "Dev Tools", "Gfx Debugger", 1 };
+ path = { "Dev Tools", "Gfx Debugger", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Gfx Debugger", 1);
AddWidget(path, "Popout Gfx Debugger", WIDGET_WINDOW_BUTTON)
.CVar("gOpenWindows.GfxDebugger")
@@ -1484,28 +1476,28 @@ void BenMenu::AddDevTools() {
"Enables the Gfx Debugger window, allowing you to input commands, type help for some examples."))
.WindowName("GfxDebuggerWindow");
- path = { "Dev Tools", "Hook Debugger", 1 };
+ path = { "Dev Tools", "Hook Debugger", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Hook Debugger", 1);
AddWidget(path, "Popout Hook Debugger", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.HookDebugger")
.Options(ButtonOptions().Tooltip("Enables the Hook Debugger window, for viewing info about registered hooks."))
.WindowName("Hook Debugger");
- path = { "Dev Tools", "Save Editor", 1 };
+ path = { "Dev Tools", "Save Editor", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Save Editor", 1);
AddWidget(path, "Popout Save Editor", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.SaveEditor")
.Options(ButtonOptions().Tooltip("Enables the Save Editor window, allowing you to edit your save file."))
.WindowName("Save Editor");
- path = { "Dev Tools", "Actor Viewer", 1 };
+ path = { "Dev Tools", "Actor Viewer", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Actor Viewer", 1);
AddWidget(path, "Popout Actor Viewer", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.ActorViewer")
.Options(ButtonOptions().Tooltip("Enables the Actor Viewer window, allowing you to view actors in the world."))
.WindowName("Actor Viewer");
- path = { "Dev Tools", "Event Log", 1 };
+ path = { "Dev Tools", "Event Log", SECTION_COLUMN_1 };
AddSidebarEntry("Dev Tools", "Event Log", 1);
AddWidget(path, "Popout Event Log", WIDGET_WINDOW_BUTTON)
.CVar("gWindows.EventLog")
@@ -1522,19 +1514,15 @@ void BenMenu::InitElement() {
AddSettings();
AddEnhancements();
AddDevTools();
- // RegisterResolutionWidgets();
- Rando::RegisterMenu();
-
- menuEntries = { { "Settings", settingsSidebar, "gSettings.Menu.SettingsSidebarSection", settingsOrder },
- { "Enhancements", enhancementsSidebar, "gSettings.Menu.EnhancementsSidebarSection",
- enhancementsOrder },
- { "Developer Tools", devToolsSidebar, "gSettings.Menu.DevToolsSidebarSection", devToolsOrder },
- { "Rando", randoSidebar, "gSettings.Menu.RandoSidebarSection", randoOrder } };
if (CVarGetInteger("gSettings.Menu.SidebarSearch", 0)) {
InsertSidebarSearch();
}
+ for (auto& initFunc : MenuInit::GetInitFuncs()) {
+ initFunc();
+ }
+
disabledMap = {
{ DISABLE_FOR_CAMERAS_OFF,
{ [](disabledInfo& info) -> bool {
@@ -1639,10 +1627,6 @@ void BenMenu::UpdateElement() {
}
void BenMenu::Draw() {
- // if (CVarGetInteger("gSettings.Menu.SelectedHeader", 0) &&
- // CVarGetInteger("gSettings.Menu.EnhancementsSidebarSection", 0)) {
- // UpdateResolutionVars();
- // }
Ship::Menu::Draw();
}