diff options
| author | Garrett Cox <garrettjcox@gmail.com> | 2026-01-17 16:09:50 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-17 16:09:50 -0600 |
| commit | 48efa501af5899e5f860ea4bd027678eca68ac33 (patch) | |
| tree | 99c5163bac36be38c88ff9a0305bd198ddc6a393 | |
| parent | 5cbb0fc3e7eeabd976b2d0e049e3eead89cbfa42 (diff) | |
Add more controller binding options (#1466)
| -rw-r--r-- | mm/2s2h/BenGui/BenMenu.cpp | 15 | ||||
| -rw-r--r-- | mm/2s2h/BenGui/Menu.cpp | 4 | ||||
| -rw-r--r-- | mm/2s2h/BenGui/UIWidgets.cpp | 24 | ||||
| -rw-r--r-- | mm/2s2h/BenGui/UIWidgets.hpp | 36 | ||||
| -rw-r--r-- | mm/2s2h/DeveloperTools/DeveloperTools.cpp | 31 | ||||
| -rw-r--r-- | mm/2s2h/Enhancements/Player/LinkSpeedModifier.cpp | 5 | ||||
| -rw-r--r-- | mm/src/code/graph.c | 13 | ||||
| -rw-r--r-- | mm/src/overlays/actors/ovl_player_actor/z_player.c | 8 |
8 files changed, 105 insertions, 31 deletions
diff --git a/mm/2s2h/BenGui/BenMenu.cpp b/mm/2s2h/BenGui/BenMenu.cpp index 58e57a6a4..92effed55 100644 --- a/mm/2s2h/BenGui/BenMenu.cpp +++ b/mm/2s2h/BenGui/BenMenu.cpp @@ -208,6 +208,9 @@ WidgetInfo& BenMenu::AddWidget(WidgetPath& pathInfo, std::string widgetName, Wid case WIDGET_CVAR_SLIDER_FLOAT: widget.options = std::make_shared<FloatSliderOptions>(); break; + case WIDGET_CVAR_BTN_SELECTOR: + widget.options = std::make_shared<BtnSelectorOptions>(); + break; case WIDGET_SLIDER_INT: case WIDGET_CVAR_SLIDER_INT: widget.options = std::make_shared<IntSliderOptions>(); @@ -347,6 +350,9 @@ void BenMenu::AddSettings() { .CVar("gEnhancements.Mods.AlternateAssetsHotkey") .Options( CheckboxOptions().Tooltip("Allows pressing the Tab key to toggle alternate assets.").DefaultValue(true)); + AddWidget(path, "Reset Button Combination:", WIDGET_CVAR_BTN_SELECTOR) + .CVar("gSettings.ResetBtn") + .Options(BtnSelectorOptions().DefaultValue(BTN_CUSTOM_MODIFIER2)); AddWidget(path, "Open App Files Folder", WIDGET_BUTTON) .Callback([](WidgetInfo& info) { std::string filesPath = Ship::Context::GetInstance()->GetAppDirectoryPath(); @@ -952,6 +958,7 @@ void BenMenu::AddEnhancements() { .Options(FloatSliderOptions().Format("%.1fx").Min(0.0f).Max(6.0f).DefaultValue(1.0f)); AddWidget(path, "Button Combination:", WIDGET_CVAR_BTN_SELECTOR) .CVar("gCheats.SpeedModifier.Btn") + .Options(BtnSelectorOptions().DefaultValue(BTN_CUSTOM_MODIFIER1)) .PreFunc([](WidgetInfo& info) { info.isHidden = CVarGetInteger("gCheats.SpeedModifier.Mode", 0) < 2; }); //// Gameplay Enhancements @@ -1815,6 +1822,14 @@ void BenMenu::AddDevTools() { .Options(CheckboxOptions().Tooltip( "Overrides the original map select with a translated, more user-friendly version.")) .PreFunc([](WidgetInfo& info) { info.isHidden = mBenMenu->disabledMap.at(DISABLE_FOR_DEBUG_MODE_OFF).active; }); + AddWidget(path, "Map Select Button Combination:", WIDGET_CVAR_BTN_SELECTOR) + .CVar("gDeveloperTools.MapSelectBtn") + .Options(BtnSelectorOptions().DefaultValue(BTN_R | BTN_L | BTN_Z)) + .PreFunc([](WidgetInfo& info) { info.isHidden = mBenMenu->disabledMap.at(DISABLE_FOR_DEBUG_MODE_OFF).active; }); + AddWidget(path, "No Clip Button Combination:", WIDGET_CVAR_BTN_SELECTOR) + .CVar("gDeveloperTools.NoClipBtn") + .Options(BtnSelectorOptions().DefaultValue(BTN_L | BTN_DRIGHT)) + .PreFunc([](WidgetInfo& info) { info.isHidden = mBenMenu->disabledMap.at(DISABLE_FOR_DEBUG_MODE_OFF).active; }); AddWidget(path, "Debug Save File Mode", WIDGET_CVAR_COMBOBOX) .CVar("gDeveloperTools.DebugSaveFileMode") .Options(ComboboxOptions() diff --git a/mm/2s2h/BenGui/Menu.cpp b/mm/2s2h/BenGui/Menu.cpp index 9b35cadfa..f63d4589b 100644 --- a/mm/2s2h/BenGui/Menu.cpp +++ b/mm/2s2h/BenGui/Menu.cpp @@ -442,7 +442,9 @@ void Menu::MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors me } } break; case WIDGET_CVAR_BTN_SELECTOR: { - if (UIWidgets::CVarBtnSelector(widget.name.c_str(), widget.cVar)) { + auto options = std::static_pointer_cast<UIWidgets::BtnSelectorOptions>(widget.options); + options->color = menuThemeIndex; + if (UIWidgets::CVarBtnSelector(widget.name.c_str(), widget.cVar, *options)) { if (widget.callback != nullptr) { widget.callback(widget); } diff --git a/mm/2s2h/BenGui/UIWidgets.cpp b/mm/2s2h/BenGui/UIWidgets.cpp index f9139d66f..677519ce5 100644 --- a/mm/2s2h/BenGui/UIWidgets.cpp +++ b/mm/2s2h/BenGui/UIWidgets.cpp @@ -1334,15 +1334,16 @@ std::map<std::string, int32_t> buttonMap = { { "Modifier 1", BTN_CUSTOM_MODIFIER1 }, { "Modifier 2", BTN_CUSTOM_MODIFIER2 }, }; -bool BtnSelector(const char* label, int32_t* value) { +bool BtnSelector(const char* label, int32_t* value, const BtnSelectorOptions& options) { bool dirty = false; ImGui::PushID(label); ImGui::BeginGroup(); ImGui::AlignTextToFramePadding(); ImGui::Text("%s", label); ImGui::BeginDisabled(false); - PushStyleCombobox(UIWidgets::Colors::DarkGray); - ImGui::BeginGroup(); + PushStyleCombobox(options.color); + ImGui::BeginChild("ButtonCombo", ImVec2(0, ImGui::GetFrameHeightWithSpacing() + 14.0f), ImGuiChildFlags_None, + ImGuiWindowFlags_HorizontalScrollbar); int32_t currentValue = *value; int index = 0; for (const auto& [buttonName, buttonMask] : buttonMap) { @@ -1364,7 +1365,8 @@ bool BtnSelector(const char* label, int32_t* value) { } } if (UIWidgets::Button("+", UIWidgets::ButtonOptions({ { .tooltip = "Add a button to the combination" } }) - .Size(UIWidgets::Sizes::Inline))) { + .Size(UIWidgets::Sizes::Inline) + .Color(options.color))) { ImGui::OpenPopup("Add Button"); } if (ImGui::BeginPopup("Add Button")) { @@ -1380,7 +1382,13 @@ bool BtnSelector(const char* label, int32_t* value) { UIWidgets::PopStyleMenuItem(); ImGui::EndPopup(); } - ImGui::EndGroup(); + ImGui::SameLine(); + if (UIWidgets::Button(ICON_FA_UNDO, + UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(options.color))) { + currentValue = options.defaultValue; + dirty = true; + } + ImGui::EndChild(); PopStyleCombobox(); ImGui::EndDisabled(); ImGui::EndGroup(); @@ -1392,10 +1400,10 @@ bool BtnSelector(const char* label, int32_t* value) { return dirty; } -bool CVarBtnSelector(const char* label, const char* cvarName) { +bool CVarBtnSelector(const char* label, const char* cvarName, const BtnSelectorOptions& options) { bool dirty = false; - int32_t value = CVarGetInteger(cvarName, 0); - if (BtnSelector(label, &value)) { + int32_t value = CVarGetInteger(cvarName, options.defaultValue); + if (BtnSelector(label, &value, options)) { CVarSetInteger(cvarName, value); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); ShipInit::Init(cvarName); diff --git a/mm/2s2h/BenGui/UIWidgets.hpp b/mm/2s2h/BenGui/UIWidgets.hpp index 0dccf4ea9..d55e051f0 100644 --- a/mm/2s2h/BenGui/UIWidgets.hpp +++ b/mm/2s2h/BenGui/UIWidgets.hpp @@ -476,6 +476,38 @@ struct FloatSliderOptions : WidgetOptions { } }; +struct BtnSelectorOptions : WidgetOptions { + s32 defaultValue = 0; + ComponentAlignment alignment = ComponentAlignment::Left; + LabelPosition labelPosition = LabelPosition::Above; + Colors color = Colors::Gray; + + BtnSelectorOptions& DefaultValue(float defaultValue_) { + defaultValue = defaultValue_; + return *this; + } + + BtnSelectorOptions& ComponentAlignment(ComponentAlignment alignment_) { + alignment = alignment_; + return *this; + } + + BtnSelectorOptions& LabelPosition(LabelPosition labelPosition_) { + labelPosition = labelPosition_; + return *this; + } + + BtnSelectorOptions& Tooltip(const char* tooltip_) { + WidgetOptions::tooltip = tooltip_; + return *this; + } + + BtnSelectorOptions& Color(Colors color_) { + WidgetOptions::color = color = color_; + return *this; + } +}; + struct RadioButtonsOptions : WidgetOptions { std::unordered_map<int32_t, const char*> buttonMap; int32_t defaultIndex = 0; @@ -1159,8 +1191,8 @@ void DrawFlagArray16(const std::string& name, uint16_t& flags, Colors color = Co void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t& flags); void DrawFlagTableArray8(const FlagTable& flagTable, uint16_t row, uint8_t& flags); void DrawFlagTableArray8Mask(const FlagTable& flagTable, uint16_t row, uint8_t& flags); -bool BtnSelector(const char* label, int32_t* value); -bool CVarBtnSelector(const char* label, const char* cvarName); +bool BtnSelector(const char* label, int32_t* value, const BtnSelectorOptions& options); +bool CVarBtnSelector(const char* label, const char* cvarName, const BtnSelectorOptions& options); } // namespace UIWidgets ImVec4 GetRandomValue(); diff --git a/mm/2s2h/DeveloperTools/DeveloperTools.cpp b/mm/2s2h/DeveloperTools/DeveloperTools.cpp index 2bcaeb9e8..8cd632cef 100644 --- a/mm/2s2h/DeveloperTools/DeveloperTools.cpp +++ b/mm/2s2h/DeveloperTools/DeveloperTools.cpp @@ -10,6 +10,7 @@ extern "C" { #include "z64save.h" #include "variables.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" +#include "overlays/gamestates/ovl_select/z_select.h" void Sram_InitDebugSave(void); void Flags_SetWeekEventReg(s32 flag); @@ -158,6 +159,36 @@ void RegisterDebugMode() { gPlayState->frameAdvCtx.enabled = false; } } + + COND_HOOK(OnGameStateMainStart, CVAR_DEBUG_MODE, []() { + Input* input = CONTROLLER1(gGameState); + + auto mask = CVarGetInteger("gDeveloperTools.MapSelectBtn", BTN_Z | BTN_L | BTN_R); + + if (CHECK_BTN_ANY(gGameState->input[0].press.button, mask) && + CHECK_BTN_ALL(gGameState->input[0].cur.button, mask)) { + STOP_GAMESTATE(gGameState); + gSaveContext.gameMode = GAMEMODE_NORMAL; + gSaveContext.nextDayTime = NEXT_TIME_NONE; + gSaveContext.nextTransitionType = TRANS_NEXT_TYPE_DEFAULT; + gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL; + SET_NEXT_GAMESTATE(gGameState, MapSelect_Init, sizeof(MapSelectState)); + } + }); + + // For lack of a better place, sticking this here now + COND_HOOK(OnGameStateMainStart, true, []() { + Input* input = CONTROLLER1(gGameState); + + auto mask = CVarGetInteger("gSettings.ResetBtn", BTN_CUSTOM_MODIFIER2); + + if (CHECK_BTN_ANY(gGameState->input[0].press.button, mask) && + CHECK_BTN_ALL(gGameState->input[0].cur.button, mask)) { + std::reinterpret_pointer_cast<Ship::ConsoleWindow>( + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) + ->Dispatch("reset"); + } + }); } RegisterShipInitFunc initFuncDebugMode(RegisterDebugMode, { CVAR_DEBUG_MODE_NAME }); diff --git a/mm/2s2h/Enhancements/Player/LinkSpeedModifier.cpp b/mm/2s2h/Enhancements/Player/LinkSpeedModifier.cpp index 3a06cb43c..68972e309 100644 --- a/mm/2s2h/Enhancements/Player/LinkSpeedModifier.cpp +++ b/mm/2s2h/Enhancements/Player/LinkSpeedModifier.cpp @@ -15,7 +15,7 @@ extern Input* sPlayerControlInput; #define CVAR_SPEED_MODIFIER_MODE CVarGetInteger(CVAR_SPEED_MODIFIER_MODE_NAME, 0) #define CVAR_SPEED_MODIFIER_TOGGLE CVarGetInteger(CVAR_SPEED_MODIFIER_TOGGLE_NAME, 0) #define CVAR_SPEED_MODIFIER_VALUE CVarGetFloat(CVAR_SPEED_MODIFIER_VALUE_NAME, 1.0f) -#define CVAR_SPEED_MODIFIER_BTN CVarGetInteger(CVAR_SPEED_MODIFIER_BTN_NAME, 0) +#define CVAR_SPEED_MODIFIER_BTN CVarGetInteger(CVAR_SPEED_MODIFIER_BTN_NAME, BTN_CUSTOM_MODIFIER1) bool btnHeldOrToggled = false; @@ -60,7 +60,8 @@ void RegisterLinkSpeedModifier() { btnHeldOrToggled = false; } } else { - if (CHECK_BTN_ALL(input->press.button, CVAR_SPEED_MODIFIER_BTN)) { + if (CHECK_BTN_ALL(input->cur.button, CVAR_SPEED_MODIFIER_BTN) && + CHECK_BTN_ANY(input->press.button, CVAR_SPEED_MODIFIER_BTN)) { btnHeldOrToggled = !btnHeldOrToggled; } } diff --git a/mm/src/code/graph.c b/mm/src/code/graph.c index 414f4299b..e8157c874 100644 --- a/mm/src/code/graph.c +++ b/mm/src/code/graph.c @@ -358,19 +358,6 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) { Graph_UpdateGame(gameState); Graph_ExecuteAndDraw(gfxCtx, gameState); - - // 2S2H [Debug] Decomp didn't contain the original code that would allow for this, so this is stolen from ship - if (CVarGetInteger("gDeveloperTools.DebugEnabled", 0)) { - if (CHECK_BTN_ALL(gameState->input[0].press.button, BTN_Z) && - CHECK_BTN_ALL(gameState->input[0].cur.button, BTN_L | BTN_R)) { - STOP_GAMESTATE(gameState); - gSaveContext.gameMode = GAMEMODE_NORMAL; - gSaveContext.nextDayTime = NEXT_TIME_NONE; - gSaveContext.nextTransitionType = TRANS_NEXT_TYPE_DEFAULT; - gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL; - SET_NEXT_GAMESTATE(gameState, MapSelect_Init, sizeof(MapSelectState)); - } - } } static struct RunFrameContext { diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c index 542af15de..b1ffdfbf0 100644 --- a/mm/src/overlays/actors/ovl_player_actor/z_player.c +++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c @@ -13031,11 +13031,9 @@ s32 Player_UpdateNoclip(Player* this, PlayState* play) { return true; } - if ((CHECK_BTN_ALL(sPlayerControlInput->cur.button, BTN_L | BTN_R | BTN_A) && - CHECK_BTN_ALL(sPlayerControlInput->press.button, BTN_B)) || - (CHECK_BTN_ALL(sPlayerControlInput->cur.button, BTN_L) && - CHECK_BTN_ALL(sPlayerControlInput->press.button, BTN_DRIGHT))) { - + s32 mask = CVarGetInteger("gDeveloperTools.NoClipBtn", BTN_L | BTN_DRIGHT); + if (CHECK_BTN_ALL(sPlayerControlInput->cur.button, mask) && + CHECK_BTN_ANY(sPlayerControlInput->press.button, mask)) { sNoclipEnabled ^= 1; if (sNoclipEnabled) { |
