summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Cox <garrettjcox@gmail.com>2026-01-17 16:09:50 -0600
committerGitHub <noreply@github.com>2026-01-17 16:09:50 -0600
commit48efa501af5899e5f860ea4bd027678eca68ac33 (patch)
tree99c5163bac36be38c88ff9a0305bd198ddc6a393
parent5cbb0fc3e7eeabd976b2d0e049e3eead89cbfa42 (diff)
Add more controller binding options (#1466)
-rw-r--r--mm/2s2h/BenGui/BenMenu.cpp15
-rw-r--r--mm/2s2h/BenGui/Menu.cpp4
-rw-r--r--mm/2s2h/BenGui/UIWidgets.cpp24
-rw-r--r--mm/2s2h/BenGui/UIWidgets.hpp36
-rw-r--r--mm/2s2h/DeveloperTools/DeveloperTools.cpp31
-rw-r--r--mm/2s2h/Enhancements/Player/LinkSpeedModifier.cpp5
-rw-r--r--mm/src/code/graph.c13
-rw-r--r--mm/src/overlays/actors/ovl_player_actor/z_player.c8
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) {