From af285f309ce820039995b6e7780a6f0ec85a4a41 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:28:40 -0800 Subject: [PATCH 01/20] Menus/Profiles: tweak character select interpolation --- src/k_menudraw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 55a1289c1..3f234c9b5 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -2382,7 +2382,7 @@ void M_DrawCharacterSelect(void) UINT8 priority = 0; INT16 quadx, quady; INT16 skin; - INT32 basex = optionsmenu.profile ? (64 + M_EaseWithTransition(Easing_Linear, 5 * 32)) : 0; + INT32 basex = optionsmenu.profile ? (64 + M_EaseWithTransition(Easing_InSine, 5 * 48)) : 0; boolean forceskin = M_CharacterSelectForceInAction(); if (setup_numplayers > 0) From d4fad1926fbafc4ec1e48a440c3df3ea5060a357 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:31:07 -0800 Subject: [PATCH 02/20] Menus/Profiles: interpolate accessibility menu slide in --- src/menus/options-profiles-edit-accessibility.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/menus/options-profiles-edit-accessibility.cpp b/src/menus/options-profiles-edit-accessibility.cpp index 3ef6383e7..72008807a 100644 --- a/src/menus/options-profiles-edit-accessibility.cpp +++ b/src/menus/options-profiles-edit-accessibility.cpp @@ -5,6 +5,7 @@ #include "../command.h" #include "../k_menu.h" +#include "../m_easing.h" #include "../p_local.h" // cv_tilting extern "C" consvar_t cv_mindelay; @@ -16,7 +17,7 @@ namespace void draw_routine() { - Draw row = Draw(0, currentMenu->y).font(Draw::Font::kMenu); + Draw row = Draw(M_EaseWithTransition(Easing_InSine, 5 * 48), currentMenu->y).font(Draw::Font::kMenu); M_DrawEditProfileTooltips(); From 075aa11a796c51701b1ed5bd6feb2f03e07c3b8a Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:31:40 -0800 Subject: [PATCH 03/20] Menus/Profiles: indent selected option --- src/k_menudraw.c | 8 +++++--- src/menus/options-profiles-edit-1.c | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 3f234c9b5..f03a32bc7 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4676,6 +4676,7 @@ void M_DrawEditProfile(void) UINT8 *colormap = NULL; INT32 tflag = (currentMenu->menuitems[i].status & IT_TRANSTEXT) ? V_TRANSLUCENT : 0; + INT32 cx = x; y = currentMenu->menuitems[i].mvar2; @@ -4686,13 +4687,14 @@ void M_DrawEditProfile(void) { colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); - V_DrawMenuString(x - 10 - (skullAnimCounter/5), y+1, highlightflags, "\x1C"); // left arrow + cx += Easing_OutSine(M_DueFrac(optionsmenu.offset.start, 2), 0, 5); + V_DrawMenuString(cx - 10 - (skullAnimCounter/5), y+1, highlightflags, "\x1C"); // left arrow } // Text - //V_DrawGamemodeString(x, y - 6, tflag, colormap, currentMenu->menuitems[i].text); + //V_DrawGamemodeString(cx, y - 6, tflag, colormap, currentMenu->menuitems[i].text); V_DrawStringScaled( - x * FRACUNIT, + cx * FRACUNIT, (y - 3) * FRACUNIT, FRACUNIT, FRACUNIT, diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index e56f1d750..64ccc43fe 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -1,6 +1,7 @@ /// \file menus/options-profiles-edit-1.c /// \brief Profile Editor +#include "../i_time.h" #include "../k_menu.h" #include "../s_sound.h" #include "../m_cond.h" @@ -157,6 +158,11 @@ boolean M_ProfileEditInputs(INT32 ch) return true; // No. } + if (menucmd[pid].dpad_ud != 0) + { + optionsmenu.offset.start = I_GetTime(); + } + return false; } From cbff205edc19bcf1b4f891fa6edf4006bd6a6d4a Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:21:15 -0800 Subject: [PATCH 04/20] Menus/Controls: rearrange some options - Rename RECORD LOSSLESS to RECORD GIF - Move SHOW RANKINGS above OPEN CHAT - Move OPEN CONSOLE below LUA/C - Rename EXTRA header to TEST AND CONFIRM --- src/menus/options-profiles-edit-controls.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 46d5c08dd..2c299515a 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -58,21 +58,18 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_CONTROL, "RECORD VIDEO", "Record a video with sound.", NULL, {.routine = M_ProfileSetControl}, gc_startmovie, 0}, - {IT_CONTROL, "RECORD LOSSLESS", "Record a pixel perfect GIF.", + {IT_CONTROL, "RECORD GIF", "Record a pixel perfect GIF.", NULL, {.routine = M_ProfileSetControl}, gc_startlossless, 0}, + {IT_CONTROL, "SHOW RANKINGS", "Display the current rankings mid-game.", + NULL, {.routine = M_ProfileSetControl}, gc_rankings, 0}, + {IT_CONTROL, "OPEN CHAT", "Opens full keyboard chatting for online games.", NULL, {.routine = M_ProfileSetControl}, gc_talk, 0}, {IT_CONTROL, "OPEN TEAM CHAT", "Opens team-only full chat for online games.", NULL, {.routine = M_ProfileSetControl}, gc_teamtalk, 0}, - {IT_CONTROL, "SHOW RANKINGS", "Display the current rankings mid-game.", - NULL, {.routine = M_ProfileSetControl}, gc_rankings, 0}, - - {IT_CONTROL, "OPEN CONSOLE", "Opens the developer options console.", - NULL, {.routine = M_ProfileSetControl}, gc_console, 0}, - {IT_CONTROL, "LUA/A", "May be used by add-ons.", NULL, {.routine = M_ProfileSetControl}, gc_luaa, 0}, @@ -82,7 +79,10 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_CONTROL, "LUA/C", "May be used by add-ons.", NULL, {.routine = M_ProfileSetControl}, gc_luac, 0}, - {IT_HEADER, "EXTRA", "", + {IT_CONTROL, "OPEN CONSOLE", "Opens the developer options console.", + NULL, {.routine = M_ProfileSetControl}, gc_console, 0}, + + {IT_HEADER, "TEST AND CONFIRM", "", NULL, {NULL}, 0, 0}, {IT_STRING | IT_CALL, "TRY MAPPINGS", "Test your controls.", From a902d83dce578b7fc90559f2aff3ffde731a4f8a Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:24:59 -0800 Subject: [PATCH 05/20] Menus/Controls: button controls use tooltip icons, inline description --- src/k_menudraw.c | 28 +++++++++++--- src/menus/options-profiles-edit-controls.c | 44 +++++++++++----------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index f03a32bc7..a43383988 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4810,6 +4810,7 @@ void M_DrawProfileControls(void) for (i = 0; i < currentMenu->numitems; i++) { char buf[256]; + char buf2[256]; INT32 keys[MAXINPUTMAPPING]; // cursor @@ -4838,7 +4839,8 @@ void M_DrawProfileControls(void) if (currentMenu->menuitems[i].patch) { - V_DrawScaledPatch(x+12, y+12, 0, W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE)); + V_DrawScaledPatch(x-4, y+1, 0, W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE)); + V_DrawMenuString(x+12, y+2, (i == itemOn ? highlightflags : 0), currentMenu->menuitems[i].text); drawnpatch = true; } else @@ -4884,6 +4886,7 @@ void M_DrawProfileControls(void) }; buf[0] = '\0'; + buf2[0] = '\0'; // Cool as is this, this doesn't actually help show accurate info because of how some players would set inputs with keyboard and controller at once in a volatile way... @@ -4930,6 +4933,7 @@ void M_DrawProfileControls(void) } }*/ + char *p = buf; if (buf[0]) ; else if (!set) @@ -4942,17 +4946,29 @@ void M_DrawProfileControls(void) continue; if (k > 0) - strcat(buf," / "); + strcat(p," / "); - if (k == 2 && drawnpatch) // hacky... - strcat(buf, "\n"); + if (k == 2) // hacky... + p = buf2; - strcat(buf, G_KeynumToString (keys[k])); + strcat(p, G_KeynumToString (keys[k])); + } + } + + if (i == itemOn) + { + // Extend yellow wedge down behind + // extra line. + if (buf2[0]) + { + for (j=24; j < 34; j++) + V_DrawFill(0, (y)+j, 128+j, 1, 73); } } // don't shift the text if we didn't draw a patch. - V_DrawThinString(x + (drawnpatch ? 32 : 0), y + (drawnpatch ? 2 : 12), vflags, buf); + V_DrawThinString(x + (drawnpatch ? 13 : 1), y + 12, vflags, buf); + V_DrawThinString(x + (drawnpatch ? 13 : 1), y + 22, vflags, buf2); // controller dest coords: if (itemOn == i && gc > 0 && gc <= gc_start) diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 2c299515a..47750759b 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -10,44 +10,44 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_HEADER, "MAIN CONTROLS", "That's the stuff on the controller!!", NULL, {NULL}, 0, 0}, - {IT_CONTROL, "A", "Accelerate / Confirm", - "PR_BTA", {.routine = M_ProfileSetControl}, gc_a, 0}, + {IT_CONTROL, "Accel / Confirm", "Accelerate / Confirm", + "TLB_A", {.routine = M_ProfileSetControl}, gc_a, 0}, - {IT_CONTROL, "B", "Look backwards / Back", - "PR_BTB", {.routine = M_ProfileSetControl}, gc_b, 0}, + {IT_CONTROL, "Look back", "Look backwards / Go back", + "TLB_B", {.routine = M_ProfileSetControl}, gc_b, 0}, - {IT_CONTROL, "C", "Spindash / Extra", - "PR_BTC", {.routine = M_ProfileSetControl}, gc_c, 0}, + {IT_CONTROL, "Spindash", "Spindash / Extra", + "TLB_C", {.routine = M_ProfileSetControl}, gc_c, 0}, - {IT_CONTROL, "X", "Brake / Back", - "PR_BTX", {.routine = M_ProfileSetControl}, gc_x, 0}, + {IT_CONTROL, "Brake / Go back", "Brake / Go back", + "TLB_D", {.routine = M_ProfileSetControl}, gc_x, 0}, - {IT_CONTROL, "Y", "Respawn", - "PR_BTY", {.routine = M_ProfileSetControl}, gc_y, 0}, + {IT_CONTROL, "Respawn", "Respawn", + "TLB_E", {.routine = M_ProfileSetControl}, gc_y, 0}, - {IT_CONTROL, "Z", "Multiplayer quick-chat / quick-vote", - "PR_BTZ", {.routine = M_ProfileSetControl}, gc_z, 0}, + {IT_CONTROL, "Action", "Multiplayer quick-chat / quick-vote", + "TLB_F", {.routine = M_ProfileSetControl}, gc_z, 0}, - {IT_CONTROL, "L", "Use item", - "PR_BTL", {.routine = M_ProfileSetControl}, gc_l, 0}, + {IT_CONTROL, "Use Item", "Use item", + "TLB_H", {.routine = M_ProfileSetControl}, gc_l, 0}, - {IT_CONTROL, "R", "Drift", - "PR_BTR", {.routine = M_ProfileSetControl}, gc_r, 0}, + {IT_CONTROL, "Drift", "Drift", + "TLB_I", {.routine = M_ProfileSetControl}, gc_r, 0}, {IT_CONTROL, "Turn Left", "Turn left", - "PR_PADL", {.routine = M_ProfileSetControl}, gc_left, 0}, + "TLB_M", {.routine = M_ProfileSetControl}, gc_left, 0}, {IT_CONTROL, "Turn Right", "Turn right", - "PR_PADR", {.routine = M_ProfileSetControl}, gc_right, 0}, + "TLB_L", {.routine = M_ProfileSetControl}, gc_right, 0}, {IT_CONTROL, "Aim Forward", "Aim forwards", - "PR_PADU", {.routine = M_ProfileSetControl}, gc_up, 0}, + "TLB_J", {.routine = M_ProfileSetControl}, gc_up, 0}, {IT_CONTROL, "Aim Backwards", "Aim backwards", - "PR_PADD", {.routine = M_ProfileSetControl}, gc_down, 0}, + "TLB_K", {.routine = M_ProfileSetControl}, gc_down, 0}, - {IT_CONTROL, "Start", "Open pause menu", - "PR_BTS", {.routine = M_ProfileSetControl}, gc_start, 0}, + {IT_CONTROL, "Open pause menu", "Open pause menu", + "TLB_G", {.routine = M_ProfileSetControl}, gc_start, 0}, {IT_HEADER, "OPTIONAL CONTROLS", "Take a screenshot, chat...", NULL, {NULL}, 0, 0}, From 4da25dc8819be9918c422e2457c28fb11fb8ac49 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:36:18 -0800 Subject: [PATCH 06/20] Menus/Controls: fix panning for d-pad --- src/k_menudraw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index a43383988..6eac0af67 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4724,10 +4724,10 @@ void M_DrawEditProfile(void) // Controller offsets to center on each button. INT16 controlleroffsets[][2] = { {0, 0}, // gc_none - {70, 112}, // gc_up - {70, 112}, // gc_down - {70, 112}, // gc_left - {70, 112}, // gc_right + {69, 142}, // gc_up + {69, 182}, // gc_down + {49, 162}, // gc_left + {89, 162}, // gc_right {208, 200}, // gc_a {237, 181}, // gc_b {267, 166}, // gc_c From c5bf07d252c36157ea78204bac306b0c9f8b3607 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:37:32 -0800 Subject: [PATCH 07/20] Menus/Controls: draw controller buttons --- src/k_menudraw.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 6eac0af67..effbaa1a4 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4740,20 +4740,18 @@ INT16 controlleroffsets[][2] = { }; // Controller patches for button presses. -// {patch if not pressed, patch if pressed} -// if NULL, draws nothing. // reminder that lumpnames can only be 8 chars at most. (+1 for \0) -char controllerpresspatch[9][2][9] = { - {"", "BTP_A"}, // MBT_A - {"", "BTP_B"}, // MBT_B - {"", "BTP_C"}, // MBT_C - {"", "BTP_X"}, // MBT_X - {"", "BTP_Y"}, // MBT_Y - {"", "BTP_Z"}, // MBT_Z - {"BTNP_L", "BTP_L"},// MBT_L - {"BTNP_R", "BTP_R"},// MBT_R - {"", "BTP_ST"} // MBT_START +static const char *controllerpresspatch[9][2] = { + {"PR_BTA", "PR_BTAB"}, // MBT_A + {"PR_BTB", "PR_BTBB"}, // MBT_B + {"PR_BTC", "PR_BTCB"}, // MBT_C + {"PR_BTX", "PR_BTXB"}, // MBT_X + {"PR_BTY", "PR_BTYB"}, // MBT_Y + {"PR_BTZ", "PR_BTZB"}, // MBT_Z + {"PR_BTL", "PR_BTLB"}, // MBT_L + {"PR_BTR", "PR_BTRB"}, // MBT_R + {"PR_BTS", "PR_BTSB"}, // MBT_START }; @@ -4775,16 +4773,12 @@ void M_DrawProfileControls(void) for (i = 0; i < 9; i++) { INT32 bt = 1< Date: Sat, 17 Feb 2024 20:38:20 -0800 Subject: [PATCH 08/20] Menus/Controls: draw d-pad --- src/k_menudraw.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index effbaa1a4..90fa4f4df 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4754,6 +4754,37 @@ static const char *controllerpresspatch[9][2] = { {"PR_BTS", "PR_BTSB"}, // MBT_START }; +static const char *M_GetDPadPatchName(SINT8 ud, SINT8 lr) +{ + if (ud < 0) + { + if (lr < 0) + return "PR_PADUL"; + else if (lr > 0) + return "PR_PADUR"; + else + return "PR_PADU"; + } + else if (ud > 0) + { + if (lr < 0) + return "PR_PADDL"; + else if (lr > 0) + return "PR_PADDR"; + else + return "PR_PADD"; + } + else + { + if (lr < 0) + return "PR_PADL"; + else if (lr > 0) + return "PR_PADR"; + else + return "PR_PADN"; + } +} + // the control stuff. // Dear god. @@ -4768,7 +4799,12 @@ void M_DrawProfileControls(void) V_DrawScaledPatch(BASEVIDWIDTH*2/3 - optionsmenu.contx, BASEVIDHEIGHT/2 -optionsmenu.conty, 0, W_CachePatchName("PR_CONT", PU_CACHE)); // Draw button presses... - // @TODO: Dpad when we get the sprites for it. + V_DrawScaledPatch( + BASEVIDWIDTH*2/3 - optionsmenu.contx, + BASEVIDHEIGHT/2 - optionsmenu.conty, + 0, + W_CachePatchName(M_GetDPadPatchName(menucmd[pid].dpad_ud, menucmd[pid].dpad_lr), PU_CACHE) + ); for (i = 0; i < 9; i++) { From 535bda8b88cd6fb70eeebc31a185e8d7d5a3e946 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:39:23 -0800 Subject: [PATCH 09/20] Menus/Controls: draw tooltip at bottom of the screen --- src/k_menudraw.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 90fa4f4df..9f167aeaf 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4795,6 +4795,8 @@ void M_DrawProfileControls(void) INT32 x = 8; INT32 i, j, k; const UINT8 pid = 0; + patch_t *hint = W_CachePatchName("MENUHINT", PU_CACHE); + INT32 hintofs = 3; V_DrawScaledPatch(BASEVIDWIDTH*2/3 - optionsmenu.contx, BASEVIDHEIGHT/2 -optionsmenu.conty, 0, W_CachePatchName("PR_CONT", PU_CACHE)); @@ -4826,16 +4828,16 @@ void M_DrawProfileControls(void) return; // Don't draw the rest if we're trying the controller. } - // Tooltip - // The text is slightly shifted hence why we don't just use M_DrawMenuTooltips() - V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUHINT", PU_CACHE), NULL); - if (currentMenu->menuitems[itemOn].tooltip != NULL) - { - V_DrawCenteredThinString(229, 12, 0, currentMenu->menuitems[itemOn].tooltip); - } - V_DrawFill(0, 0, 138, 200, 31); // Black border + V_SetClipRect( + 0, + 0, + BASEVIDWIDTH * FRACUNIT, + (BASEVIDHEIGHT - SHORT(hint->height) + hintofs) * FRACUNIT, + 0 + ); + // Draw the menu options... for (i = 0; i < currentMenu->numitems; i++) { @@ -5015,6 +5017,20 @@ void M_DrawProfileControls(void) } } + V_ClearClipRect(); + + // Tooltip + // Draw it at the bottom of the screen + { + static UINT8 blue[256]; + blue[31] = 253; + V_DrawMappedPatch(0, BASEVIDHEIGHT + hintofs, V_VFLIP, hint, blue); + } + if (currentMenu->menuitems[itemOn].tooltip != NULL) + { + V_DrawCenteredThinString(BASEVIDWIDTH/2, BASEVIDHEIGHT + hintofs - 9 - 12, 0, currentMenu->menuitems[itemOn].tooltip); + } + // Overlay for control binding if (optionsmenu.bindcontrol) { From c1f143062d577f14ff2e9bdda67c15a777115104 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Feb 2024 20:40:23 -0800 Subject: [PATCH 10/20] Menus/Controls: tweak Try Buttons on-screen text - In big letters, "TRY BUTTONS" - Countdown uses Medium font --- src/k_menudraw.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 9f167aeaf..ffbea11cb 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4824,7 +4824,21 @@ void M_DrawProfileControls(void) optionsmenu.tcontx = BASEVIDWIDTH*2/3 - 10; optionsmenu.tconty = BASEVIDHEIGHT/2 +70; - V_DrawCenteredString(160, 180, highlightflags, va("PRESS NOTHING FOR %d SEC TO GO BACK", optionsmenu.trycontroller/TICRATE)); + V_DrawCenteredLSTitleLowString(160, 164, 0, "TRY BUTTONS"); + + const char *msg = va("Press nothing for %d sec to go back", (optionsmenu.trycontroller + (TICRATE-1)) / TICRATE); + fixed_t w = V_StringScaledWidth(FRACUNIT, FRACUNIT, FRACUNIT, highlightflags, MED_FONT, msg); + V_DrawStringScaled( + 160*FRACUNIT - w/2, + 186*FRACUNIT, + FRACUNIT, + FRACUNIT, + FRACUNIT, + highlightflags, + NULL, + MED_FONT, + msg + ); return; // Don't draw the rest if we're trying the controller. } From 788f49f6e293ee7b71381cdae1f5d398b541ba91 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 18 Feb 2024 00:37:42 -0800 Subject: [PATCH 11/20] Menus/Controls: bind names are gray unless selected --- src/k_menudraw.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index ffbea11cb..72baa8aed 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4912,6 +4912,9 @@ void M_DrawProfileControls(void) UINT8 available = 0, set = 0; + if (i != itemOn) + vflags |= V_GRAYMAP; + // Get userbound controls... for (k = 0; k < MAXINPUTMAPPING; k++) { @@ -4983,7 +4986,11 @@ void M_DrawProfileControls(void) if (buf[0]) ; else if (!set) - strcpy(buf, "\x85NOT BOUND"); + { + vflags &= ~V_CHARCOLORMASK; + vflags |= V_REDMAP; + strcpy(buf, "NOT BOUND"); + } else { for (k = 0; k < MAXINPUTMAPPING; k++) From d2f48eda297f86daff8f6b1f1198d9739ab02113 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 18 Feb 2024 00:38:16 -0800 Subject: [PATCH 12/20] Menus/Controls: RESET TO DEFAULT and CLEAR ALL buttons --- src/k_menu.h | 2 + src/menus/options-profiles-edit-controls.c | 51 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/k_menu.h b/src/k_menu.h index a623aedb3..5218f2cd9 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1068,6 +1068,8 @@ boolean M_ProfileEditInputs(INT32 ch); void M_HandleProfileControls(void); boolean M_ProfileControlsInputs(INT32 ch); void M_ProfileSetControl(INT32 ch); +void M_ProfileDefaultControls(INT32 ch); +void M_ProfileClearControls(INT32 ch); void M_MapProfileControl(event_t *ev); void M_ProfileTryController(INT32 choice); diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 47750759b..1968c5d96 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -1,6 +1,7 @@ /// \file menus/options-profiles-edit-controls.c /// \brief Profile Controls Editor +#include "../g_input.h" #include "../k_menu.h" #include "../s_sound.h" #include "../i_joy.h" // for joystick menu controls @@ -88,6 +89,12 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_STRING | IT_CALL, "TRY MAPPINGS", "Test your controls.", NULL, {.routine = M_ProfileTryController}, 0, 0}, + {IT_STRING | IT_CALL, "RESET TO DEFAULT", "Reset all controls back to default.", + NULL, {.routine = M_ProfileDefaultControls}, 0, 0}, + + {IT_STRING | IT_CALL, "CLEAR ALL", "Unbind all controls.", + NULL, {.routine = M_ProfileClearControls}, 0, 0}, + {IT_STRING | IT_CALL, "CONFIRM", "Go back to profile setup.", NULL, {.routine = M_ProfileControlsConfirm}, 0, 0}, }; @@ -290,6 +297,50 @@ void M_ProfileSetControl(INT32 ch) optionsmenu.bindtimer = TICRATE*5; } +static void M_ProfileDefaultControlsResponse(INT32 ch) +{ + if (ch == MA_YES) + { + memcpy(&optionsmenu.tempcontrols, gamecontroldefault, sizeof optionsmenu.tempcontrols); + S_StartSound(NULL, sfx_s24f); + } +} + +void M_ProfileDefaultControls(INT32 ch) +{ + (void)ch; + M_StartMessage( + "Profiles", + "Reset all controls to the default mappings?", + &M_ProfileDefaultControlsResponse, + MM_YESNO, + NULL, + NULL + ); +} + +static void M_ProfileClearControlsResponse(INT32 ch) +{ + if (ch == MA_YES) + { + memset(&optionsmenu.tempcontrols, 0, sizeof optionsmenu.tempcontrols); + S_StartSound(NULL, sfx_s3k66); + } +} + +void M_ProfileClearControls(INT32 ch) +{ + (void)ch; + M_StartMessage( + "Profiles", + "Clear all control bindings?", + &M_ProfileClearControlsResponse, + MM_YESNO, + NULL, + NULL + ); +} + // Map the event to the profile. #define KEYHOLDFOR 1 From 726415981f4889a18e02e8a4a2ab53a54a74103b Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Feb 2024 20:21:15 -0800 Subject: [PATCH 13/20] Menus/Controls: confirm changes on go back (bypassing confirm button) --- src/menus/options-profiles-edit-controls.c | 32 +++++++++++++++++----- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 1968c5d96..5075852ab 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -193,19 +193,37 @@ static void M_ProfileControlSaveResponse(INT32 choice) { memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); } - - M_GoBack(0); } + else + { + // Revert changes + memcpy(optionsmenu.tempcontrols, optionsmenu.profile->controls, sizeof(gamecontroldefault)); + } + + M_GoBack(0); } void M_ProfileControlsConfirm(INT32 choice) { - (void)choice; + if (!memcmp(optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault))) + { + M_GoBack(0); // no change + } + else if (choice == 0) + { + M_StartMessage( + "Profiles", + "You have unsaved changes to your controls.\n" + "Please confirm if you wish to save them.\n", + &M_ProfileControlSaveResponse, + MM_YESNO, + NULL, + NULL + ); + } + else + M_ProfileControlSaveResponse(MA_YES); - //M_StartMessage("Profiles", M_GetText("Exiting will save the control changes\nfor this Profile.\nIs this okay?\n"), &M_ProfileControlSaveResponse, MM_YESNO, NULL, NULL); - // TODO: Add a graphic for controls saving, instead of obnoxious prompt. - - M_ProfileControlSaveResponse(MA_YES); // Reapply player 1's real profile. if (cv_currprofile.value > -1) From b0a5d01a1fa7f52ce2cb3236ca1d5bfba41001e9 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Feb 2024 20:32:38 -0800 Subject: [PATCH 14/20] Separate code into M_ClearCurrentControl function --- src/menus/options-profiles-edit-controls.c | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 5075852ab..60761768b 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -136,6 +136,23 @@ static void SetDeviceOnPress(void) } */ +static boolean M_ClearCurrentControl(void) +{ + // check if we're on a valid menu option... + if (currentMenu->menuitems[itemOn].mvar1) + { + // clear controls for that key + INT32 i; + + for (i = 0; i < MAXINPUTMAPPING; i++) + optionsmenu.tempcontrols[currentMenu->menuitems[itemOn].mvar1][i] = KEY_NULL; + + return true; + } + + return false; +} + void M_HandleProfileControls(void) { UINT8 maxscroll = currentMenu->numitems - 5; @@ -268,17 +285,8 @@ boolean M_ProfileControlsInputs(INT32 ch) if (M_MenuExtraPressed(pid)) { - // check if we're on a valid menu option... - if (currentMenu->menuitems[itemOn].mvar1) - { - // clear controls for that key - INT32 i; - - for (i = 0; i < MAXINPUTMAPPING; i++) - optionsmenu.tempcontrols[currentMenu->menuitems[itemOn].mvar1][i] = KEY_NULL; - + if (M_ClearCurrentControl()) S_StartSound(NULL, sfx_s3k66); - } M_SetMenuDelay(pid); return true; } From 0766e8823bcc29b147289c2063a31926f4c36549 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Feb 2024 20:40:37 -0800 Subject: [PATCH 15/20] Menus/Controls: C (clear) plays chomp sound --- src/menus/options-profiles-edit-controls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 60761768b..54d6c8c66 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -286,7 +286,7 @@ boolean M_ProfileControlsInputs(INT32 ch) if (M_MenuExtraPressed(pid)) { if (M_ClearCurrentControl()) - S_StartSound(NULL, sfx_s3k66); + S_StartSound(NULL, sfx_monch); M_SetMenuDelay(pid); return true; } From 9523fd86524dd75e165c0c93d09a32cb305058a8 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Feb 2024 21:18:02 -0800 Subject: [PATCH 16/20] Menus/Controls: add Bind Ben - Hold right to scroll binding text into Bind Ben - Release right to cancel - When the text is done scrolling, Bind Ben begins chewing - Release right to have Bind Ben swallow - After Bind Ben swallows the binding text, he does a cute pose and the control is cleared - Press up or down to skip the swallow and pose animations and clear the control immediately - Press C to have Bind Ben quickly eat the binding text and clear the control --- src/k_menu.h | 3 + src/k_menudraw.c | 111 ++++++++++++++++++++- src/menus/options-profiles-edit-controls.c | 45 +++++++++ 3 files changed, 156 insertions(+), 3 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 5218f2cd9..e7ce4cebd 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -966,6 +966,7 @@ struct modedesc_t #define MAXCOLUMNMODES 12 //max modes displayed in one column #define MAXMODEDESCS (MAXCOLUMNMODES*3) #define M_OPTIONS_OFSTIME 5 +#define M_OPTIONS_BINDBEN_QUICK 106 // Keep track of some options properties extern struct optionsmenu_s { @@ -998,6 +999,8 @@ extern struct optionsmenu_s { INT16 controlscroll; // scrolling for the control menu.... UINT8 bindcontrol; // 0: not binding, 1: binding control #1, 2: binding control #2 INT16 bindtimer; // Timer until binding is cancelled (5s) + UINT16 bindben; // Hold right timer + UINT8 bindben_swallow; // (bool) control is about to be cleared; (int) swallow/pose animation timer INT16 trycontroller; // Starts at 3*TICRATE, holding B lowers this, when at 0, cancel controller try mode. diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 72baa8aed..375d1c61c 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4785,6 +4785,74 @@ static const char *M_GetDPadPatchName(SINT8 ud, SINT8 lr) } } +static void M_DrawBindBen(INT32 x, INT32 y, INT32 scroll_remaining) +{ + // optionsmenu.bindben_swallow + const int pose_time = 30; + const int swallow_time = pose_time + 14; + + // Lid closed + int state = 'A'; + int frame = 0; + + if (optionsmenu.bindben_swallow > 100) + { + // Quick swallow (C button) + state = 'C'; + + int t = 106 - optionsmenu.bindben_swallow; + if (t < 3) + frame = 0; + else + frame = t - 3; + } + else if (scroll_remaining <= 0) + { + // Chewing (text done scrolling) + state = 'B'; + frame = I_GetTime() / 2 % 4; + + // When state changes from 'lid open' to 'chewing', + // play chomp sound. + if (!optionsmenu.bindben_swallow) + S_StartSound(NULL, sfx_monch); + + // Ready to swallow when button is released. + optionsmenu.bindben_swallow = swallow_time + 1; + } + else if (optionsmenu.bindben) + { + // Lid open (text scrolling) + frame = 1; + } + else if (optionsmenu.bindben_swallow) + { + if (optionsmenu.bindben_swallow > pose_time) + { + // Swallow + state = 'C'; + + int t = swallow_time - optionsmenu.bindben_swallow; + if (t < 8) + frame = 0; + else + frame = 1 + (t - 8) / 2 % 3; + } + else + { + // Pose + state = 'D'; + + int t = pose_time - optionsmenu.bindben_swallow; + if (t < 10) + frame = 0; + else + frame = 1 + (t - 10) / 4 % 5; + } + } + + V_DrawMappedPatch(x-30, y, 0, W_CachePatchName(va("PR_BIN%c%c", state, '1' + frame), PU_CACHE), aquamap); +} // the control stuff. // Dear god. @@ -5008,6 +5076,9 @@ void M_DrawProfileControls(void) } } + INT32 bindx = x; + INT32 benx = 142; + INT32 beny = y - 8; if (i == itemOn) { // Extend yellow wedge down behind @@ -5016,12 +5087,46 @@ void M_DrawProfileControls(void) { for (j=24; j < 34; j++) V_DrawFill(0, (y)+j, 128+j, 1, 73); + benx += 10; + beny += 10; + } + + // Scroll text into Bind Ben. + bindx += optionsmenu.bindben * 3; + + if (buf2[0]) + { + // Bind Ben: suck characters off + // the end of the first line onto + // the beginning of the second + // line. + UINT16 n = strlen(buf); + UINT16 t = min(optionsmenu.bindben, n); + memmove(&buf2[t], buf2, t + 1); + memcpy(buf2, &buf[n - t], t); + buf[n - t] = '\0'; } } - // don't shift the text if we didn't draw a patch. - V_DrawThinString(x + (drawnpatch ? 13 : 1), y + 12, vflags, buf); - V_DrawThinString(x + (drawnpatch ? 13 : 1), y + 22, vflags, buf2); + { + cliprect_t clip; + V_SaveClipRect(&clip); // preserve cliprect for tooltip + + // Clip text as it scrolls into Bind Ben. + V_SetClipRect(0, 0, (benx-14)*FRACUNIT, 200*FRACUNIT, 0); + + if (i != itemOn || !optionsmenu.bindben_swallow) + { + // don't shift the text if we didn't draw a patch. + V_DrawThinString(bindx + (drawnpatch ? 13 : 1), y + 12, vflags, buf); + V_DrawThinString(bindx + (drawnpatch ? 13 : 1), y + 22, vflags, buf2); + } + + V_RestoreClipRect(&clip); + } + + if (i == itemOn) + M_DrawBindBen(benx, beny, (benx-14) - bindx); // controller dest coords: if (itemOn == i && gc > 0 && gc <= gc_start) diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 54d6c8c66..7353d4341 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -155,6 +155,7 @@ static boolean M_ClearCurrentControl(void) void M_HandleProfileControls(void) { + const UINT8 pid = 0; UINT8 maxscroll = currentMenu->numitems - 5; M_OptionsTick(); @@ -184,6 +185,35 @@ void M_HandleProfileControls(void) } } + else if (currentMenu->menuitems[itemOn].mvar1) // check if we're on a valid menu option... + { + // Hold right to begin clearing the control. + // + // If bindben timer increases enough, bindben_swallow + // will be set. + // This is a commitment to clear the control. + // You can keep holding right to postpone the clear + // but once you let go, you are locked out of + // pressing it again until the animation finishes. + if (menucmd[pid].dpad_lr > 0 && (optionsmenu.bindben || !optionsmenu.bindben_swallow)) + { + optionsmenu.bindben++; + } + else + { + optionsmenu.bindben = 0; + + if (optionsmenu.bindben_swallow) + { + optionsmenu.bindben_swallow--; + + if (optionsmenu.bindben_swallow == 100) // special countdown for the "quick" animation + optionsmenu.bindben_swallow = 0; + else if (!optionsmenu.bindben_swallow) // long animation, clears control when done + M_ClearCurrentControl(); + } + } + } } void M_ProfileTryController(INT32 choice) @@ -287,6 +317,8 @@ boolean M_ProfileControlsInputs(INT32 ch) { if (M_ClearCurrentControl()) S_StartSound(NULL, sfx_monch); + optionsmenu.bindben = 0; + optionsmenu.bindben_swallow = M_OPTIONS_BINDBEN_QUICK; M_SetMenuDelay(pid); return true; } @@ -297,6 +329,19 @@ boolean M_ProfileControlsInputs(INT32 ch) return true; } + if (menucmd[pid].dpad_ud) + { + if (optionsmenu.bindben_swallow) + { + // Control would be cleared, but we're + // interrupting the animation so clear it + // immediately. + M_ClearCurrentControl(); + } + optionsmenu.bindben = 0; + optionsmenu.bindben_swallow = 0; + } + return false; } From ae5a20756e566dd06ac3cc266cb77254cdb03acb Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 21 Feb 2024 21:42:03 -0800 Subject: [PATCH 17/20] Menus/Controls: overhaul multiple bindings input - Replace the old method of adding each binding one at a time - Hold up to 4 inputs at once, then release to bind those inputs to the control - Changing the bindings overwrites the old bindings, instead of adding to them --- src/k_menu.h | 2 +- src/k_menudraw.c | 48 ++++- src/k_menufunc.c | 2 +- src/menus/options-profiles-edit-1.c | 1 - src/menus/options-profiles-edit-controls.c | 208 +++++---------------- 5 files changed, 91 insertions(+), 170 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index e7ce4cebd..1cf47fe78 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -997,10 +997,10 @@ extern struct optionsmenu_s { // This is only applied to the profile when you exit out of the controls menu. INT16 controlscroll; // scrolling for the control menu.... - UINT8 bindcontrol; // 0: not binding, 1: binding control #1, 2: binding control #2 INT16 bindtimer; // Timer until binding is cancelled (5s) UINT16 bindben; // Hold right timer UINT8 bindben_swallow; // (bool) control is about to be cleared; (int) swallow/pose animation timer + INT32 bindinputs[MAXINPUTMAPPING]; // Set while binding INT16 trycontroller; // Starts at 3*TICRATE, holding B lowers this, when at 0, cancel controller try mode. diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 375d1c61c..201ef185b 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4854,6 +4854,23 @@ static void M_DrawBindBen(INT32 x, INT32 y, INT32 scroll_remaining) V_DrawMappedPatch(x-30, y, 0, W_CachePatchName(va("PR_BIN%c%c", state, '1' + frame), PU_CACHE), aquamap); } +static void M_DrawBindMediumString(INT32 y, INT32 flags, const char *string) +{ + fixed_t w = V_StringScaledWidth(FRACUNIT, FRACUNIT, FRACUNIT, flags, MED_FONT, string); + fixed_t x = BASEVIDWIDTH/2 * FRACUNIT - w/2; + V_DrawStringScaled( + x, + y * FRACUNIT, + FRACUNIT, + FRACUNIT, + FRACUNIT, + flags, + NULL, + MED_FONT, + string + ); +} + // the control stuff. // Dear god. void M_DrawProfileControls(void) @@ -5158,7 +5175,7 @@ void M_DrawProfileControls(void) } // Overlay for control binding - if (optionsmenu.bindcontrol) + if (optionsmenu.bindtimer) { INT16 reversetimer = TICRATE*5 - optionsmenu.bindtimer; INT32 fade = reversetimer; @@ -5167,14 +5184,33 @@ void M_DrawProfileControls(void) if (fade > 9) fade = 9; - ypos = (BASEVIDHEIGHT/2) - 4 +16*(9 - fade); + ypos = (BASEVIDHEIGHT/2) - 20 +16*(9 - fade); V_DrawFadeScreen(31, fade); - M_DrawTextBox((BASEVIDWIDTH/2) - (120), ypos - 12, 30, 4); + M_DrawTextBox((BASEVIDWIDTH/2) - (120), ypos - 12, 30, 8); - V_DrawCenteredString(BASEVIDWIDTH/2, ypos, 0, va("Press key #%d for control", optionsmenu.bindcontrol)); - V_DrawCenteredString(BASEVIDWIDTH/2, ypos +10, 0, va("\"%s\"", currentMenu->menuitems[itemOn].text)); - V_DrawCenteredString(BASEVIDWIDTH/2, ypos +20, highlightflags, va("(WAIT %d SECONDS TO SKIP)", optionsmenu.bindtimer/TICRATE)); + V_DrawCenteredMenuString(BASEVIDWIDTH/2, ypos, V_GRAYMAP, "Hold and release inputs for"); + V_DrawCenteredMenuString(BASEVIDWIDTH/2, ypos + 10, V_GRAYMAP, va("\"%s\"", currentMenu->menuitems[itemOn].text)); + + if (optionsmenu.bindtimer > 0) + { + M_DrawBindMediumString( + ypos + 50, + highlightflags, + va("(WAIT %d SEC TO SKIP)", (optionsmenu.bindtimer + (TICRATE-1)) / TICRATE) + ); + } + else + { + for (i = 0; i < MAXINPUTMAPPING && optionsmenu.bindinputs[i]; ++i) + { + M_DrawBindMediumString( + ypos + (2 + i)*10, + highlightflags | V_FORCEUPPERCASE, + G_KeynumToString(optionsmenu.bindinputs[i]) + ); + } + } } } diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 5f21246e2..3b531879a 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -308,7 +308,7 @@ boolean M_Responder(event_t *ev) // Profiles: Control mapping. // We take the WHOLE EVENT for convenience. - if (optionsmenu.bindcontrol) + if (optionsmenu.bindtimer) { M_MapProfileControl(ev); return true; // eat events. diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index 64ccc43fe..9fe9997b3 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -225,7 +225,6 @@ void M_ProfileDeviceSelect(INT32 choice) // While we're here, setup the incoming controls menu to reset the scroll & bind status: optionsmenu.controlscroll = 0; - optionsmenu.bindcontrol = 0; optionsmenu.bindtimer = 0; optionsmenu.lastkey = 0; diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 7353d4341..bffdd9b02 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -176,14 +176,10 @@ void M_HandleProfileControls(void) optionsmenu.controlscroll = 0; // bindings, cancel if timer is depleted. - if (optionsmenu.bindcontrol) + if (optionsmenu.bindtimer) { - optionsmenu.bindtimer--; - if (!optionsmenu.bindtimer) - { - optionsmenu.bindcontrol = 0; // we've gone past the max, just stop. - } - + if (optionsmenu.bindtimer > 0) + optionsmenu.bindtimer--; } else if (currentMenu->menuitems[itemOn].mvar1) // check if we're on a valid menu option... { @@ -308,7 +304,7 @@ boolean M_ProfileControlsInputs(INT32 ch) return true; } - if (optionsmenu.bindcontrol) + if (optionsmenu.bindtimer) return true; // Eat all inputs there. We'll use a stupid hack in M_Responder instead. //SetDeviceOnPress(); // Update device constantly so that we don't stay stuck with otpions saying a device is unavailable just because we're mapping multiple devices... @@ -347,25 +343,11 @@ boolean M_ProfileControlsInputs(INT32 ch) void M_ProfileSetControl(INT32 ch) { - INT32 controln = currentMenu->menuitems[itemOn].mvar1; - UINT8 i; (void) ch; - optionsmenu.bindcontrol = 1; // Default to control #1 - - for (i = 0; i < MAXINPUTMAPPING; i++) - { - if (optionsmenu.tempcontrols[controln][i] == KEY_NULL) - { - optionsmenu.bindcontrol = i+1; - break; - } - } - - // If we could find a null key to map into, map there. - // Otherwise, this will stay at 1 which means we'll overwrite the first bound control. - optionsmenu.bindtimer = TICRATE*5; + memset(optionsmenu.bindinputs, 0, sizeof optionsmenu.bindinputs); + G_ResetAllDeviceGameKeyDown(); } static void M_ProfileDefaultControlsResponse(INT32 ch) @@ -417,157 +399,61 @@ void M_ProfileClearControls(INT32 ch) #define KEYHOLDFOR 1 void M_MapProfileControl(event_t *ev) { - INT32 c = 0; - UINT8 n = optionsmenu.bindcontrol-1; // # of input to bind - INT32 controln = currentMenu->menuitems[itemOn].mvar1; // gc_ - UINT8 where = n; // By default, we'll save the bind where we're supposed to map. - INT32 i; + if (ev->type == ev_keydown && ev->data2) // ignore repeating keys + return; + + if (optionsmenu.bindtimer > TICRATE*5 - 9) // grace period after entering the bind dialog + return; + INT32 *DeviceGameKeyDownArray = G_GetDeviceGameKeyDownArray(ev->device); if (!DeviceGameKeyDownArray) return; - //SetDeviceOnPress(); // Update player gamepad assignments - - // Only consider keydown and joystick events to make sure we ignore ev_mouse and other events - // See also G_MapEventsToControls - switch (ev->type) + // Find every held button. + boolean noinput = true; + for (INT32 c = 1; c < NUMINPUTS; ++c) { - case ev_keydown: - if (ev->data1 < NUMINPUTS) - { - c = ev->data1; - } -#ifdef PARANOIA - else - { - CONS_Debug(DBG_GAMELOGIC, "Bad downkey input %d\n", ev->data1); - } -#endif - break; - case ev_gamepad_axis: - if (ev->data1 >= JOYAXES) - { -#ifdef PARANOIA - CONS_Debug(DBG_GAMELOGIC, "Bad gamepad axis event %d\n", ev->data1); -#endif - return; - } - else - { - INT32 deadzone = deadzone = (JOYAXISRANGE * cv_deadzone[0].value) / FRACUNIT; // TODO how properly account for different deadzone cvars for different devices - boolean responsivelr = ((ev->data2 != INT32_MAX) && (abs(ev->data2) >= deadzone)); - boolean responsiveud = ((ev->data3 != INT32_MAX) && (abs(ev->data3) >= deadzone)); + if (DeviceGameKeyDownArray[c] < 3*JOYAXISRANGE/4) + continue; - i = ev->data1; + noinput = false; - if (i >= JOYANALOGS) - { - // The trigger axes are handled specially. - i -= JOYANALOGS; - - if (responsivelr) - { - c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2); - } - else if (responsiveud) - { - c = KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1; - } - } - else - { - // Actual analog sticks - - // Only consider unambiguous assignment. - if (responsivelr == responsiveud) - return; - - if (responsivelr) - { - if (ev->data2 < 0) - { - // Left - c = KEY_AXIS1 + (i * 4); - } - else - { - // Right - c = KEY_AXIS1 + (i * 4) + 1; - } - } - else //if (responsiveud) - { - if (ev->data3 < 0) - { - // Up - c = KEY_AXIS1 + (i * 4) + 2; - } - else - { - // Down - c = KEY_AXIS1 + (i * 4) + 3; - } - } - } - } - break; - default: - return; - } - - // safety result - if (!c) - return; - - // Set menu delay regardless of what we're doing to avoid stupid stuff. - M_SetMenuDelay(0); - - // Reset this input so (keyboard keys at least) are not - // buffered and caught by menucmd. - DeviceGameKeyDownArray[c] = 0; - - // Check if this particular key (c) is already bound in any slot. - // If that's the case, simply do nothing. - for (i = 0; i < MAXINPUTMAPPING; i++) - { - if (optionsmenu.tempcontrols[controln][i] == c) + for (UINT8 i = 0; i < MAXINPUTMAPPING; ++i) { - optionsmenu.bindcontrol = 0; - return; - } - } + // If this key is already bound, don't bind it again. + if (optionsmenu.bindinputs[i] == c) + break; - // With the way we do things, there cannot be instances of 'gaps' within the controls, so we don't need to pretend like we need to handle that. - // Unless of course you tamper with the cfg file, but then it's *your* fault, not mine. - - optionsmenu.tempcontrols[controln][where] = c; - optionsmenu.bindcontrol = 0; // not binding anymore - - // If possible, reapply the profile... - // 19/05/22: Actually, no, don't do that, it just fucks everything up in too many cases. - - /* - if (gamestate == GS_MENU) // In menu? Apply this to P1, no questions asked. - { - // Apply the profile's properties to player 1 but keep the last profile cv to p1's ACTUAL profile to revert once we exit. - UINT8 lastp = cv_lastprofile[0].value; - PR_ApplyProfile(PR_GetProfileNum(optionsmenu.profile), 0); - CV_StealthSetValue(&cv_lastprofile[0], lastp); - } - else // != GS_MENU - { - // ONLY apply the profile if it's in use by anything currently. - UINT8 pnum = PR_GetProfileNum(optionsmenu.profile); - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - if (cv_lastprofile[i].value == pnum) + // Find the first available slot. + if (!optionsmenu.bindinputs[i]) { - PR_ApplyProfile(pnum, i); + optionsmenu.bindinputs[i] = c; break; } } } - */ + + if (noinput) + { + { + // You can hold a button before entering this + // dialog, then buffer a keyup without pressing + // anything else. If this happens, don't wipe the + // binds, just ignore it. + const UINT8 zero[sizeof optionsmenu.bindinputs] = {0}; + if (!memcmp(zero, optionsmenu.bindinputs, sizeof zero)) + return; + } + + INT32 controln = currentMenu->menuitems[itemOn].mvar1; + memcpy(&optionsmenu.tempcontrols[controln], optionsmenu.bindinputs, sizeof optionsmenu.bindinputs); + optionsmenu.bindtimer = 0; + + // Set menu delay regardless of what we're doing to avoid stupid stuff. + M_SetMenuDelay(0); + } + else + optionsmenu.bindtimer = -1; // prevent skip countdown } #undef KEYHOLDFOR From c2eda6903ad0699655c2ea9f97896326b6708660 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 22 Feb 2024 02:25:57 -0800 Subject: [PATCH 18/20] Menus/Controls: left align tooltip, clear button legend on right - "BKSP Clear" (Goner) - "C / -> Clear" (after profile setup) --- src/k_menudraw.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 201ef185b..4f3feb2c7 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4871,6 +4871,16 @@ static void M_DrawBindMediumString(INT32 y, INT32 flags, const char *string) ); } +static INT32 M_DrawProfileLegend(INT32 x, INT32 y, const char *legend, const char *mediocre_key) +{ + INT32 w = V_ThinStringWidth(legend, 0); + V_DrawThinString(x - w, y, 0, legend); + x -= w + 2; + if (mediocre_key) + M_DrawMediocreKeyboardKey(mediocre_key, &x, y, false, true); + return x; +} + // the control stuff. // Dear god. void M_DrawProfileControls(void) @@ -5171,7 +5181,14 @@ void M_DrawProfileControls(void) } if (currentMenu->menuitems[itemOn].tooltip != NULL) { - V_DrawCenteredThinString(BASEVIDWIDTH/2, BASEVIDHEIGHT + hintofs - 9 - 12, 0, currentMenu->menuitems[itemOn].tooltip); + INT32 ypos = BASEVIDHEIGHT + hintofs - 9 - 12; + V_DrawThinString(12, ypos, V_YELLOWMAP, currentMenu->menuitems[itemOn].tooltip); + + boolean standardbuttons = gamedata->gonerlevel > GDGONER_PROFILE; + INT32 xpos = BASEVIDWIDTH - 12; + xpos = standardbuttons ? + M_DrawProfileLegend(xpos, ypos, "\xB2/ \xBC Clear", NULL) : + M_DrawProfileLegend(xpos, ypos, "Clear", "BKSP"); } // Overlay for control binding From a10cea56dc0cc8216f7a3af03f6f6ebb57fa8513 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Wed, 21 Feb 2024 20:00:41 -0700 Subject: [PATCH 19/20] Require analog magnitude for menu inputs --- src/g_game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 923e224ee..2d6052386 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -972,7 +972,7 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers) boolean G_PlayerInputDown(UINT8 p, INT32 gc, UINT8 menuPlayers) { - return (G_PlayerInputAnalog(p, gc, menuPlayers) != 0); + return (abs(G_PlayerInputAnalog(p, gc, menuPlayers)) >= JOYAXISRANGE/2); } // From ce4c69100d719c60d6ba37f8dbb51da53f44de2e Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Thu, 22 Feb 2024 05:08:16 -0700 Subject: [PATCH 20/20] Add input test sounds --- src/menus/options-profiles-edit-controls.c | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index bffdd9b02..15064b7bb 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -285,6 +285,33 @@ boolean M_ProfileControlsInputs(INT32 ch) { if (menucmd[pid].dpad_ud || menucmd[pid].dpad_lr || menucmd[pid].buttons) { + if (menucmd[pid].dpad_ud != menucmd[pid].prev_dpad_ud || menucmd[pid].dpad_lr != menucmd[pid].prev_dpad_lr) + S_StartSound(NULL, sfx_s3k5b); + + UINT32 newbuttons = menucmd[pid].buttons & ~(menucmd[pid].buttonsHeld); + + if (newbuttons & MBT_L) + S_StartSound(NULL, sfx_kc69); + if (newbuttons & MBT_R) + S_StartSound(NULL, sfx_s3ka2); + + if (newbuttons & MBT_A) + S_StartSound(NULL, sfx_kc3c); + if (newbuttons & MBT_B) + S_StartSound(NULL, sfx_3db09); + if (newbuttons & MBT_C) + S_StartSound(NULL, sfx_s1be); + + if (newbuttons & MBT_X) + S_StartSound(NULL, sfx_s1a4); + if (newbuttons & MBT_Y) + S_StartSound(NULL, sfx_s3kcas); + if (newbuttons & MBT_Z) + S_StartSound(NULL, sfx_s3kc3s); + + if (newbuttons & MBT_START) + S_StartSound(NULL, sfx_gshdc); + optionsmenu.trycontroller = 5*TICRATE; } else