From 8d3916d49d1e9a20b4252f40bb7693bc47a1ff72 Mon Sep 17 00:00:00 2001 From: cypress Date: Sun, 20 Oct 2024 13:15:40 -0700 Subject: [PATCH] MENU: Control binds menu --- progs/csqc.src | 1 + progs/menu.src | 1 + source/client/hud.qc | 21 +++++- source/client/main.qc | 14 ++++ source/menu/defs/menu_defs.qc | 4 + source/menu/m_menu.qc | 42 +++++++++++ source/menu/main.qc | 7 ++ source/menu/menu_bind.qc | 136 ++++++++++++++++++++++++++++++++++ source/menu/menu_ctrl.qc | 3 +- source/menu/sui_sys.qc | 31 +++----- 10 files changed, 234 insertions(+), 26 deletions(-) create mode 100644 source/menu/menu_bind.qc diff --git a/progs/csqc.src b/progs/csqc.src index 1034a8c..fae4885 100644 --- a/progs/csqc.src +++ b/progs/csqc.src @@ -20,6 +20,7 @@ menu_vide.qc // Video Menu menu_audi.qc // Audio Menu menu_ctrl.qc // Control Menu menu_gpad.qc // Gamepad Menu +menu_bind.qc // Bindings Menu sound_enhanced.qc weapon_stats.qc diff --git a/progs/menu.src b/progs/menu.src index 6b2de51..c593fb6 100644 --- a/progs/menu.src +++ b/progs/menu.src @@ -20,6 +20,7 @@ menu_vide.qc // Video Menu menu_audi.qc // Audio Menu menu_ctrl.qc // Control Menu menu_gpad.qc // Gamepad Menu +menu_bind.qc // Bindings Menu menu_cred.qc // Credits Menu menu_load.qc // Loading Screen diff --git a/source/client/hud.qc b/source/client/hud.qc index 5a201b1..860ac7a 100644 --- a/source/client/hud.qc +++ b/source/client/hud.qc @@ -928,16 +928,29 @@ void(float width, float height) HUD_Rounds = void(float width, float height) HUD_Useprint = { - string usestring, usebutton, usespace; + string usestring, usespace; string usecost; float print_width, x, button_width; usestring = ""; usespace = ""; usecost = ""; - - tokenize(findkeysforcommandex("+button7")); - usebutton = strtoupper(argv(0)); + + string usebutton = ""; + float argc = tokenize(findkeysforcommandex("+button7")); + + for (int i = 0; i < argc; i++) { + usebutton = strtoupper(argv(i)); + float bind_is_gamepad = Key_IsControllerGlyph(usebutton); + + if (bind_is_gamepad && last_input_was_gamepad) + break; + else if (!bind_is_gamepad && !last_input_was_gamepad) + break; + } + + if (usebutton == "") + usebutton = "UNBOUND"; // If this is a gamepad button, the space we want to reserve // in the usestring should be a fixed width. diff --git a/source/client/main.qc b/source/client/main.qc index 49ed522..a1997a6 100644 --- a/source/client/main.qc +++ b/source/client/main.qc @@ -686,7 +686,21 @@ void(float scanx, float setval) Input_Movecheck = noref float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent = { + if (evtype == IE_GYROSCOPE || evtype == IE_ACCELEROMETER) + return FALSE; + + // Ignore subtle (drift-y) joystick axes + if (evtype == IE_JOYAXIS && devid > 0 && fabs(chary) < 0.1) { + return FALSE; + } + last_input_deviceid = devid; + float last_input_storage = last_input_was_gamepad; + + if (last_input_deviceid > 0) + last_input_was_gamepad = TRUE; + else + last_input_was_gamepad = FALSE; if (current_menu != MENU_NONE) { diff --git a/source/menu/defs/menu_defs.qc b/source/menu/defs/menu_defs.qc index 2b2abd0..28356f4 100644 --- a/source/menu/defs/menu_defs.qc +++ b/source/menu/defs/menu_defs.qc @@ -42,6 +42,7 @@ enum { MENU_AUDIO, MENU_CONTROL, MENU_GAMEPAD, + MENU_BINDINGS, MENU_CREDITS, MENU_PAUSE }; @@ -67,6 +68,7 @@ void() Menu_Video; void() Menu_Audio; void() Menu_Control; void() Menu_Gamepad; +void() Menu_Bindings; #ifdef MENU @@ -92,6 +94,8 @@ string(string prev_id) Menu_Control_GetNextButton; string(string next_id) Menu_Control_GetPreviousButton; string(string prev_id) Menu_Gamepad_GetNextButton; string(string next_id) Menu_Gamepad_GetPreviousButton; +string(string prev_id) Menu_Bindings_GetNextButton; +string(string next_id) Menu_Bindings_GetPreviousButton; enum { MAP_SOLOSTOCK, diff --git a/source/menu/m_menu.qc b/source/menu/m_menu.qc index c66ac64..349fd0a 100644 --- a/source/menu/m_menu.qc +++ b/source/menu/m_menu.qc @@ -154,6 +154,47 @@ void(float order, string value) Menu_DrawOptionValue = sui_text(position, MENU_TEXT_MEDIUM, value, [1, 1, 1], 1, 0); }; +// +// Menu_DrawOptionKey(order, value) +// Draws a key/glyph at a given order. +// +void(float order, string bind) Menu_DrawOptionKey = +{ + sui_set_align([SUI_ALIGN_START, SUI_ALIGN_START]); + + vector position = [320, 50 + (order * 25)]; + float keynum = stringtokeynum(bind); + + if (keynum >= 816 && keynum <= 839) { + vector tilemap_position = [0, 0]; + + // Get the position of the button in the tilemap. + switch(keynum) { + case K_GP_A: tilemap_position = [0, 0]; break; + case K_GP_B: tilemap_position = [0.125, 0]; break; + case K_GP_X: tilemap_position = [0.250, 0]; break; + case K_GP_Y: tilemap_position = [0.375, 0]; break; + case K_GP_LSHOULDER: tilemap_position = [0.250, 0.125]; break; + case K_GP_RSHOULDER: tilemap_position = [0.375, 0.125]; break; + case K_GP_LTRIGGER: tilemap_position = [0.500, 0.125]; break; + case K_GP_RTRIGGER: tilemap_position = [0.625, 0.125]; break; + case K_GP_BACK: tilemap_position = [0.875, 0.125]; break; + case K_GP_START: tilemap_position = [0.750, 0.125]; break; + case K_GP_LTHUMB: tilemap_position = [0, 0.125]; break; + case K_GP_RTHUMB: tilemap_position = [0.125, 0.125]; break; + case K_GP_DPAD_UP: tilemap_position = [0.500, 0]; break; + case K_GP_DPAD_DOWN: tilemap_position = [0.625, 0]; break; + case K_GP_DPAD_LEFT: tilemap_position = [0.750, 0]; break; + case K_GP_DPAD_RIGHT: tilemap_position = [0.875, 0]; break; + } + + sui_subpic([position_x, position_y - 2], [MENU_TEXT_MEDIUM_x + 5, MENU_TEXT_MEDIUM_x + 5], sprintf("gfx/controller_glyphs/%s.tga", cvar_string("cl_controllerglyphs")), [1, 1, 1], tilemap_position, [0.125, 0.125], 1, 0); + } + else { + sui_text(position, MENU_TEXT_MEDIUM, bind, [1, 1, 0], 1, 0); + } +}; + // // Menu_MapButton(order, id, bsp_name) // Displays a fancy menu option that loads @@ -615,6 +656,7 @@ void(vector size) root_menu = case MENU_AUDIO: Menu_Audio(); break; case MENU_CONTROL: Menu_Control(); break; case MENU_GAMEPAD: Menu_Gamepad(); break; + case MENU_BINDINGS: Menu_Bindings(); break; default: break; } diff --git a/source/menu/main.qc b/source/menu/main.qc index f751ec1..7b748ac 100644 --- a/source/menu/main.qc +++ b/source/menu/main.qc @@ -255,12 +255,19 @@ void() m_open = float(float evtype, float scanx, float chary, float devid) Menu_InputEvent = { last_input_deviceid = devid; + float last_input_storage = last_input_was_gamepad; if (last_input_deviceid > 0) last_input_was_gamepad = TRUE; else last_input_was_gamepad = FALSE; + if (last_input_storage != last_input_was_gamepad) { + menu_bind_currentwatcher = 0; + _sui_binding_command = ""; + _sui_binding_command_name = ""; + } + float used = sui_input_event(evtype, scanx, chary, devid); if (evtype == IE_KEYDOWN && !used) diff --git a/source/menu/menu_bind.qc b/source/menu/menu_bind.qc new file mode 100644 index 0000000..7a1564a --- /dev/null +++ b/source/menu/menu_bind.qc @@ -0,0 +1,136 @@ +float menu_bind_currentwatcher; +string menu_bind_buttons[13] = {"bm_jump", "bm_spri", "bm_crou", "bm_wnex", "bm_use", "bm_relo", "bm_mele", "bm_prig", "bm_secg", "bm_fire", "bm_ads", "bm_apply", "bm_back"}; + +float(float keynum) Menu_Bindings_IsGamepad = +{ + if (keynum >= 816 && keynum <= 839) + return true; + + return false; +}; + +void(float order, string command) Menu_Bindings_PrintBindForCommand = +{ + // If we're currently watching this key, drawn an indicator ("< >") + if (menu_bind_currentwatcher == order) { + Menu_DrawOptionKey(order, "< >"); + return; + } + + string bind = ""; + float argc = tokenize(findkeysforcommandex(command)); + + for (int i = 0; i < argc; i++) { + bind = strtoupper(argv(i)); + float bind_is_gamepad = Menu_Bindings_IsGamepad(stringtokeynum(bind)); + + if (bind_is_gamepad && last_input_was_gamepad) + break; + else if (!bind_is_gamepad && !last_input_was_gamepad) + break; + } + + if (bind == "") + bind = "UNBOUND"; + + Menu_DrawOptionKey(order, bind); +}; + +void(float id, string command) Menu_Bindings_Listen = +{ + Menu_PlaySound(MENU_SND_ENTER); + menu_bind_currentwatcher = id; + _sui_binding_command = command; +}; + +void() Menu_Bindings_Back = +{ + menu_bind_currentwatcher = 0; + current_menu = MENU_CONTROL; +}; + +string(string prev_id) Menu_Bindings_GetNextButton = +{ + if (prev_id == "") + return menu_bind_buttons[0]; + + string ret = menu_bind_buttons[0]; + + for(float i = 0; i < menu_bind_buttons.length; i++) { + if (menu_bind_buttons[i] == prev_id) { + if (i + 1 >= menu_bind_buttons.length) + break; + + ret = menu_bind_buttons[i + 1]; + break; + } + } + + return ret; +}; + +string(string next_id) Menu_Bindings_GetPreviousButton = +{ + if (next_id == "") + return menu_bind_buttons[menu_bind_buttons.length - 1]; + + string ret = menu_bind_buttons[menu_bind_buttons.length - 1]; + + for(float i = menu_bind_buttons.length - 1; i > 0; i--) { + if (menu_bind_buttons[i] == next_id) { + if (i - 1 < 0) + break; + + ret = menu_bind_buttons[i - 1]; + break; + } + } + + return ret; +}; + +void() Menu_Bindings = +{ + Menu_DrawBackground(); + Menu_DrawTitle("CONTROL BINDINGS"); + Menu_DrawMapPanel(); + + Menu_Button(1, "bm_jump", "JUMP", "") ? Menu_Bindings_Listen(1, "impulse 10") : 0; + Menu_Bindings_PrintBindForCommand(1, "impulse 10"); + + Menu_Button(2, "bm_spri", "SPRINT", "") ? Menu_Bindings_Listen(2, "impulse 23") : 0; + Menu_Bindings_PrintBindForCommand(2, "impulse 23"); + + Menu_Button(3, "bm_crou", "CHANGE STANCE", "") ? Menu_Bindings_Listen(3, "impulse 30") : 0; + Menu_Bindings_PrintBindForCommand(3, "impulse 30"); + + Menu_Button(4, "bm_wnex", "SWAP WEAPON", "") ? Menu_Bindings_Listen(4, "+button4") : 0; + Menu_Bindings_PrintBindForCommand(4, "+button4"); + + Menu_Button(5, "bm_use", "INTERACT", "") ? Menu_Bindings_Listen(5, "+button7") : 0; + Menu_Bindings_PrintBindForCommand(5, "+button7"); + + Menu_Button(6, "bm_relo", "RELOAD", "") ? Menu_Bindings_Listen(6, "+button5") : 0; + Menu_Bindings_PrintBindForCommand(6, "+button5"); + + Menu_Button(7, "bm_mele", "MELEE", "") ? Menu_Bindings_Listen(7, "+button6") : 0; + Menu_Bindings_PrintBindForCommand(7, "+button6"); + + Menu_Button(8, "bm_prig", "PRIMARY GRENADE", "") ? Menu_Bindings_Listen(8, "+button3") : 0; + Menu_Bindings_PrintBindForCommand(8, "+button3"); + + Menu_Button(9, "bm_secg", "SECONDARY GRENADE", "") ? Menu_Bindings_Listen(9, "impulse 33") : 0; + Menu_Bindings_PrintBindForCommand(9, "impulse 33"); + + Menu_Button(10, "bm_fire", "WEAPON FIRE", "") ? Menu_Bindings_Listen(10, "+attack") : 0; + Menu_Bindings_PrintBindForCommand(10, "+attack"); + + Menu_Button(11, "bm_ads", "AIM DOWN SIGHTS", "") ? Menu_Bindings_Listen(11, "+button8") : 0; + Menu_Bindings_PrintBindForCommand(11, "+button8"); + + Menu_DrawDivider(12.25); + Menu_Button(-2, "bm_apply", "APPLY", "Save & Apply Settings.") ? Menu_Gamepad_ApplySettings() : 0; + Menu_Button(-1, "bm_back", "BACK", "Return to Control Options.") ? Menu_Bindings_Back() : 0; + + sui_pop_frame(); +}; \ No newline at end of file diff --git a/source/menu/menu_ctrl.qc b/source/menu/menu_ctrl.qc index 0421b00..00845c2 100644 --- a/source/menu/menu_ctrl.qc +++ b/source/menu/menu_ctrl.qc @@ -1,4 +1,4 @@ -string menu_ctrl_buttons[6] = {"cm_adsm", "cm_sens", "cm_invs", "cm_gpad", "cm_apply", "cm_back"}; +string menu_ctrl_buttons[7] = {"cm_adsm", "cm_sens", "cm_invs", "cm_gpad", "cm_bind", "cm_apply", "cm_back"}; float menu_ctrl_init; @@ -135,6 +135,7 @@ void() Menu_Control = Menu_DrawOptionValue(3, invert_string); Menu_Button(4, "cm_gpad", "GAMEPAD", "Gamepad specific options.") ? current_menu = MENU_GAMEPAD : 0; + Menu_Button(5, "cm_bind", "BINDINGS", "Change Input Bindings.") ? current_menu = MENU_BINDINGS : 0; Menu_DrawDivider(12.25); Menu_Button(-2, "cm_apply", "APPLY", "Save & Apply Settings.") ? Menu_Control_ApplySettings() : 0; diff --git a/source/menu/sui_sys.qc b/source/menu/sui_sys.qc index aa6d606..b6d1e17 100644 --- a/source/menu/sui_sys.qc +++ b/source/menu/sui_sys.qc @@ -428,6 +428,9 @@ void() _sui_menukey_downarrow = case MENU_GAMEPAD: _hover_actions[0] = Menu_Gamepad_GetNextButton(current_hovered_option); break; + case MENU_BINDINGS: + _hover_actions[0] = Menu_Bindings_GetNextButton(current_hovered_option); + break; default: break; } @@ -474,6 +477,9 @@ void() _sui_menukey_uparrow = case MENU_GAMEPAD: _hover_actions[0] = Menu_Gamepad_GetPreviousButton(current_hovered_option); break; + case MENU_BINDINGS: + _hover_actions[0] = Menu_Bindings_GetPreviousButton(current_hovered_option); + break; default: break; } @@ -722,6 +728,7 @@ void(string command) _sui_unbind = localcmd(sprintf("unbind %s\n", altkeyname)); }; +float menu_bind_currentwatcher; void(float scan, string command) _sui_do_keybind = { if (scan == K_ESCAPE) @@ -742,6 +749,7 @@ void(float scan, string command) _sui_do_keybind = localcmd(sprintf("bind %s %s\n", keyname, command)); _sui_binding_command = ""; _sui_binding_command_name = ""; + menu_bind_currentwatcher = 0; }; void(string command, string command_name) sui_start_bind = @@ -772,7 +780,7 @@ float(float evtype, float scanx, float chary, float devid) sui_input_event = case IE_KEYDOWN: if (_sui_binding_command != "") { - // Nothing + _sui_do_keybind(scanx, _sui_binding_command); return TRUE; } else if (scanx == K_MOUSE1) @@ -806,7 +814,7 @@ float(float evtype, float scanx, float chary, float devid) sui_input_event = case IE_KEYUP: if (_sui_binding_command != "") { - _sui_do_keybind(scanx, _sui_binding_command); + // Nothing return TRUE; } else if (scanx == K_MOUSE1) @@ -834,14 +842,10 @@ void(float width, float height) sui_begin = sui_push_frame([0, 0], [width, height]); } -void() sui_draw_bind_overlay; - // void() sui_end // Call after your menu code per frame in your draw/updateview. void() sui_end = { - // Todo: move overlay drawing elsewhere: - sui_draw_bind_overlay(); // Dirty part: _sui_draw_initialized = FALSE; // reset "once" type actions @@ -1066,19 +1070,4 @@ string(string id, vector pos, vector size, string name, string command) sui_bind return keyname; }; -void() sui_draw_bind_overlay = -{ - if (_sui_binding_command != "") - { - vector size = sui_current_frame_size(); - sui_fill([0, 0], size, '0 0 0', 0.5, 0); - sui_set_align([SUI_ALIGN_CENTER, SUI_ALIGN_CENTER]); - float textsize = 16; - sui_text([0, -16], [textsize, textsize], "Press a key for", '1 1 1', 1, 0); - sui_text([0, 0], [textsize, textsize], sprintf("'%s'", _sui_binding_command_name), '1 1 1', 1, 0); - sui_text([0, 16], [textsize - 4, textsize - 4], "ESC to cancel, BACKSPACE to remove", '1 1 1', 1, 0); - } -}; - - // -------------------- END OF SUI SYSTEM STUFF -------------------- \ No newline at end of file