/* Copyright (C) 1997-2001 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ui_local.h" /* ======================================================================= KEYS MENU ======================================================================= */ int keys_cursor; static int bind_grab; static menuframework_s s_keys_menu; // wsw : pb : automatic menu #define KEYMENU_MAX_NAME 32 #define KEYMENU_MAX_TITLE 64 typedef struct { char name[KEYMENU_MAX_NAME]; char title[KEYMENU_MAX_TITLE]; } KeyMenuItem; static KeyMenuItem KMItems[]= { // Movement {"+forward", "walk forward"}, {"+back", "backpedal"}, {"+moveleft", "step left"}, {"+moveright", "step right"}, {"+strafe", "sidestep"}, {"+speed", "run"}, {"+moveup", "up / jump"}, {"+movedown", "down / crouch"}, {"+special", "dash / wj"}, // Attack & Weapons { "+attack", "attack"}, {"weapprev", "previous weapon"}, {"weapnext", "next weapon"}, {"drop weapon", "drop weapon"}, {"use Gunblade", "use gunblade"}, {"use Riotgun", "use riotgun"}, {"use Grenade Launcher", "use grenade launcher"}, {"use Rocket Launcher", "use rocket launcher"}, {"use Plasmagun", "use plasmagun"}, {"use LaserGun", "use lasergun"}, {"use Electrobolt", "use electrobolt"}, // Misc {"score", "show score"}, {"vote yes", "vote yes"}, {"vote no", "vote no"}, {"join", "join"}, {"ready", "ready"}, {"chase", "chase cam"}, {"messagemode", "chat"}, {"messagemode2", "chat team"}, }; static int KM_NbItems= sizeof(KMItems)/sizeof(KeyMenuItem); // wsw : pb : !automatic menu static void M_UnbindCommand( char *command ) { int j; int l; char *b; l = strlen( command ); for( j = 0; j < 256; j++ ) { b = trap_Key_GetBindingBuf(j); if( !b ) continue; if( !Q_stricmp(b, command) ) trap_Key_SetBinding( j, NULL ); } } static void M_FindKeysForCommand( char *command, int *twokeys ) { int count; int j; int l; char *b; twokeys[0] = twokeys[1] = -1; l = strlen(command); count = 0; for (j=0 ; j<256 ; j++) { b = trap_Key_GetBindingBuf(j); if (!b) continue; if (!Q_stricmp (b, command) ) { twokeys[count] = j; count++; if (count == 2) break; } } } static void KeyCursorDrawFunc( menuframework_s *menu ) { menucommon_t *item; struct mufont_s *font = uis.fontSystemSmall; int picsize = trap_SCR_strHeight( font ); item = Menu_ItemAtCursor( menu ); if ( bind_grab ) trap_SCR_DrawString( menu->x + item->cursor_offset, menu->y + item->y, ALIGN_LEFT_TOP, "=", font, colorWhite ); else { if( ( int ) ( uis.time / 250 ) & 1 ) { trap_R_DrawStretchPic( menu->x + item->cursor_offset, menu->y + item->y, picsize, picsize, 0, 0, 1, 1, colorWhite, trap_R_RegisterPic( "gfx/ui/arrow_right" ) ); } } } static void DrawKeyBindingFunc( menucommon_t *menuitem ) { int keys[2]; M_FindKeysForCommand( KMItems[menuitem->localdata[0]].name, keys ); if (keys[0] == -1) { trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16, menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, "???", uis.fontSystemSmall, colorWhite ); } else { int x; char *name; name = trap_Key_KeynumToString( keys[0] ); trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16, menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, name, uis.fontSystemSmall, colorWhite ); x = trap_SCR_strWidth( name, uis.fontSystemSmall, 0 ); if (keys[1] != -1) { trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16 + 8 + x, menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, "or", uis.fontSystemSmall, colorWhite ); trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16 + 8 + x + 8*3, menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, trap_Key_KeynumToString(keys[1]), uis.fontSystemSmall, colorWhite ); } } } static void KeyBindingFunc( menucommon_t *menuitem ) { int keys[2]; M_FindKeysForCommand( KMItems[menuitem->localdata[0]].name, keys); if (keys[1] != -1) M_UnbindCommand( KMItems[menuitem->localdata[0]].name ); bind_grab = qtrue; Menu_SetStatusBar( &s_keys_menu, "press a key or button for this action" ); } static void Keys_MenuInit( void ) { int w, h; int y = 0; int i = 0; int yoffset = 0; menucommon_t *menuitem; w = uis.vidWidth; h = uis.vidHeight; s_keys_menu.x = w / 2; s_keys_menu.y = h / 2 - 80; s_keys_menu.nitems = 0; s_keys_menu.cursordraw = KeyCursorDrawFunc; for( i = 0; i < KM_NbItems; i++ ) { menuitem = UI_InitMenuItem( KMItems[i].name, KMItems[i].title, 0, y+yoffset, MTYPE_ACTION, ALIGN_RIGHT_TOP, uis.fontSystemSmall, NULL ); menuitem->localdata[0] = i; menuitem->ownerdraw = DrawKeyBindingFunc; Menu_AddItem( &s_keys_menu, menuitem ); yoffset += trap_SCR_strHeight( menuitem->font ); } Menu_Center( &s_keys_menu ); Menu_Init( &s_keys_menu ); Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" ); } static void Keys_MenuDraw( void ) { Menu_AdjustCursor( &s_keys_menu, 1 ); Menu_Draw( &s_keys_menu ); } static const char *Keys_MenuKey( int key ) { menucommon_t *menuitem = Menu_ItemAtCursor( &s_keys_menu ); if ( bind_grab ) { if ( key != K_ESCAPE && key != '`' ) { char cmd[1024]; Q_snprintfz (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", trap_Key_KeynumToString(key), KMItems[menuitem->localdata[0]].name); trap_Cmd_ExecuteText (EXEC_INSERT, cmd); } Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" ); bind_grab = qfalse; return menu_out_sound; } switch ( key ) { case KP_ENTER: case K_ENTER: case K_MOUSE1: KeyBindingFunc( menuitem ); return menu_in_sound; case K_BACKSPACE: // delete bindings case K_DEL: // delete bindings case KP_DEL: M_UnbindCommand( KMItems[menuitem->localdata[0]].name ); return menu_out_sound; default: return Default_MenuKey( &s_keys_menu, key ); } } static const char *Keys_MenuCharEvent( int key ) { return Default_MenuCharEvent( &s_keys_menu, key ); } void M_Menu_Keys_f( void ) { Keys_MenuInit(); M_PushMenu( &s_keys_menu, Keys_MenuDraw, Keys_MenuKey, Keys_MenuCharEvent ); }