Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

ui_controls2.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 //
00023 /*
00024 =======================================================================
00025 
00026 CONTROLS MENU
00027 
00028 =======================================================================
00029 */
00030 
00031 
00032 #include "ui_local.h"
00033 
00034 #define ART_BACK0           "menu/art/back_0"
00035 #define ART_BACK1           "menu/art/back_1"
00036 #define ART_FRAMEL          "menu/art/frame2_l"
00037 #define ART_FRAMER          "menu/art/frame1_r"
00038 
00039 
00040 typedef struct {
00041     char    *command;
00042     char    *label;
00043     int     id;
00044     int     anim;
00045     int     defaultbind1;
00046     int     defaultbind2;
00047     int     bind1;
00048     int     bind2;
00049 } bind_t;
00050 
00051 typedef struct
00052 {
00053     char*   name;
00054     float   defaultvalue;
00055     float   value;  
00056 } configcvar_t;
00057 
00058 #define SAVE_NOOP       0
00059 #define SAVE_YES        1
00060 #define SAVE_NO         2
00061 #define SAVE_CANCEL     3
00062 
00063 // control sections
00064 #define C_MOVEMENT      0
00065 #define C_LOOKING       1
00066 #define C_WEAPONS       2
00067 #define C_MISC          3
00068 #define C_MAX           4
00069 
00070 #define ID_MOVEMENT     100
00071 #define ID_LOOKING      101
00072 #define ID_WEAPONS      102
00073 #define ID_MISC         103
00074 #define ID_DEFAULTS     104
00075 #define ID_BACK         105
00076 #define ID_SAVEANDEXIT  106
00077 #define ID_EXIT         107
00078 
00079 // bindable actions
00080 #define ID_SHOWSCORES   0
00081 #define ID_USEITEM      1   
00082 #define ID_SPEED        2   
00083 #define ID_FORWARD      3   
00084 #define ID_BACKPEDAL    4
00085 #define ID_MOVELEFT     5
00086 #define ID_MOVERIGHT    6
00087 #define ID_MOVEUP       7   
00088 #define ID_MOVEDOWN     8
00089 #define ID_LEFT         9   
00090 #define ID_RIGHT        10  
00091 #define ID_STRAFE       11  
00092 #define ID_LOOKUP       12  
00093 #define ID_LOOKDOWN     13
00094 #define ID_MOUSELOOK    14
00095 #define ID_CENTERVIEW   15
00096 #define ID_ZOOMVIEW     16
00097 #define ID_WEAPON1      17  
00098 #define ID_WEAPON2      18  
00099 #define ID_WEAPON3      19  
00100 #define ID_WEAPON4      20  
00101 #define ID_WEAPON5      21  
00102 #define ID_WEAPON6      22  
00103 #define ID_WEAPON7      23  
00104 #define ID_WEAPON8      24  
00105 #define ID_WEAPON9      25  
00106 #define ID_ATTACK       26
00107 #define ID_WEAPPREV     27
00108 #define ID_WEAPNEXT     28
00109 #define ID_GESTURE      29
00110 #define ID_CHAT         30
00111 #define ID_CHAT2        31
00112 #define ID_CHAT3        32
00113 #define ID_CHAT4        33
00114 
00115 // all others
00116 #define ID_FREELOOK     34
00117 #define ID_INVERTMOUSE  35
00118 #define ID_ALWAYSRUN    36
00119 #define ID_AUTOSWITCH   37
00120 #define ID_MOUSESPEED   38
00121 #define ID_JOYENABLE    39
00122 #define ID_JOYTHRESHOLD 40
00123 #define ID_SMOOTHMOUSE  41
00124 
00125 #define ANIM_IDLE       0
00126 #define ANIM_RUN        1
00127 #define ANIM_WALK       2
00128 #define ANIM_BACK       3
00129 #define ANIM_JUMP       4
00130 #define ANIM_CROUCH     5
00131 #define ANIM_STEPLEFT   6
00132 #define ANIM_STEPRIGHT  7
00133 #define ANIM_TURNLEFT   8
00134 #define ANIM_TURNRIGHT  9
00135 #define ANIM_LOOKUP     10
00136 #define ANIM_LOOKDOWN   11
00137 #define ANIM_WEAPON1    12
00138 #define ANIM_WEAPON2    13
00139 #define ANIM_WEAPON3    14
00140 #define ANIM_WEAPON4    15
00141 #define ANIM_WEAPON5    16
00142 #define ANIM_WEAPON6    17
00143 #define ANIM_WEAPON7    18
00144 #define ANIM_WEAPON8    19
00145 #define ANIM_WEAPON9    20
00146 #define ANIM_WEAPON10   21
00147 #define ANIM_ATTACK     22
00148 #define ANIM_GESTURE    23
00149 #define ANIM_DIE        24
00150 #define ANIM_CHAT       25
00151 
00152 typedef struct
00153 {
00154     menuframework_s     menu;
00155 
00156     menutext_s          banner;
00157     menubitmap_s        framel;
00158     menubitmap_s        framer;
00159     menubitmap_s        player;
00160 
00161     menutext_s          movement;
00162     menutext_s          looking;
00163     menutext_s          weapons;
00164     menutext_s          misc;
00165 
00166     menuaction_s        walkforward;
00167     menuaction_s        backpedal;
00168     menuaction_s        stepleft;
00169     menuaction_s        stepright;
00170     menuaction_s        moveup;
00171     menuaction_s        movedown;
00172     menuaction_s        turnleft;
00173     menuaction_s        turnright;
00174     menuaction_s        sidestep;
00175     menuaction_s        run;
00176     menuaction_s        machinegun;
00177     menuaction_s        chainsaw;
00178     menuaction_s        shotgun;
00179     menuaction_s        grenadelauncher;
00180     menuaction_s        rocketlauncher;
00181     menuaction_s        lightning;
00182     menuaction_s        railgun;
00183     menuaction_s        plasma;
00184     menuaction_s        bfg;
00185     menuaction_s        attack;
00186     menuaction_s        prevweapon;
00187     menuaction_s        nextweapon;
00188     menuaction_s        lookup;
00189     menuaction_s        lookdown;
00190     menuaction_s        mouselook;
00191     menuradiobutton_s   freelook;
00192     menuaction_s        centerview;
00193     menuaction_s        zoomview;
00194     menuaction_s        gesture;
00195     menuradiobutton_s   invertmouse;
00196     menuslider_s        sensitivity;
00197     menuradiobutton_s   smoothmouse;
00198     menuradiobutton_s   alwaysrun;
00199     menuaction_s        showscores;
00200     menuradiobutton_s   autoswitch;
00201     menuaction_s        useitem;
00202     playerInfo_t        playerinfo;
00203     qboolean            changesmade;
00204     menuaction_s        chat;
00205     menuaction_s        chat2;
00206     menuaction_s        chat3;
00207     menuaction_s        chat4;
00208     menuradiobutton_s   joyenable;
00209     menuslider_s        joythreshold;
00210     int                 section;
00211     qboolean            waitingforkey;
00212     char                playerModel[64];
00213     vec3_t              playerViewangles;
00214     vec3_t              playerMoveangles;
00215     int                 playerLegs;
00216     int                 playerTorso;
00217     int                 playerWeapon;
00218     qboolean            playerChat;
00219 
00220     menubitmap_s        back;
00221     menutext_s          name;
00222 } controls_t;   
00223 
00224 static controls_t s_controls;
00225 
00226 static vec4_t controls_binding_color  = {1.00f, 0.43f, 0.00f, 1.00f}; // bk: Win32 C4305
00227 
00228 static bind_t g_bindings[] = 
00229 {
00230     {"+scores",         "show scores",      ID_SHOWSCORES,  ANIM_IDLE,      K_TAB,          -1,     -1, -1},
00231     {"+button2",        "use item",         ID_USEITEM,     ANIM_IDLE,      K_ENTER,        -1,     -1, -1},
00232     {"+speed",          "run / walk",       ID_SPEED,       ANIM_RUN,       K_SHIFT,        -1,     -1, -1},
00233     {"+forward",        "walk forward",     ID_FORWARD,     ANIM_WALK,      K_UPARROW,      -1,     -1, -1},
00234     {"+back",           "backpedal",        ID_BACKPEDAL,   ANIM_BACK,      K_DOWNARROW,    -1,     -1, -1},
00235     {"+moveleft",       "step left",        ID_MOVELEFT,    ANIM_STEPLEFT,  ',',            -1,     -1, -1},
00236     {"+moveright",      "step right",       ID_MOVERIGHT,   ANIM_STEPRIGHT, '.',            -1,     -1, -1},
00237     {"+moveup",         "up / jump",        ID_MOVEUP,      ANIM_JUMP,      K_SPACE,        -1,     -1, -1},
00238     {"+movedown",       "down / crouch",    ID_MOVEDOWN,    ANIM_CROUCH,    'c',            -1,     -1, -1},
00239     {"+left",           "turn left",        ID_LEFT,        ANIM_TURNLEFT,  K_LEFTARROW,    -1,     -1, -1},
00240     {"+right",          "turn right",       ID_RIGHT,       ANIM_TURNRIGHT, K_RIGHTARROW,   -1,     -1, -1},
00241     {"+strafe",         "sidestep / turn",  ID_STRAFE,      ANIM_IDLE,      K_ALT,          -1,     -1, -1},
00242     {"+lookup",         "look up",          ID_LOOKUP,      ANIM_LOOKUP,    K_PGDN,         -1,     -1, -1},
00243     {"+lookdown",       "look down",        ID_LOOKDOWN,    ANIM_LOOKDOWN,  K_DEL,          -1,     -1, -1},
00244     {"+mlook",          "mouse look",       ID_MOUSELOOK,   ANIM_IDLE,      '/',            -1,     -1, -1},
00245     {"centerview",      "center view",      ID_CENTERVIEW,  ANIM_IDLE,      K_END,          -1,     -1, -1},
00246     {"+zoom",           "zoom view",        ID_ZOOMVIEW,    ANIM_IDLE,      -1,             -1,     -1, -1},
00247     {"weapon 1",        "gauntlet",         ID_WEAPON1,     ANIM_WEAPON1,   '1',            -1,     -1, -1},
00248     {"weapon 2",        "machinegun",       ID_WEAPON2,     ANIM_WEAPON2,   '2',            -1,     -1, -1},
00249     {"weapon 3",        "shotgun",          ID_WEAPON3,     ANIM_WEAPON3,   '3',            -1,     -1, -1},
00250     {"weapon 4",        "grenade launcher", ID_WEAPON4,     ANIM_WEAPON4,   '4',            -1,     -1, -1},
00251     {"weapon 5",        "rocket launcher",  ID_WEAPON5,     ANIM_WEAPON5,   '5',            -1,     -1, -1},
00252     {"weapon 6",        "lightning",        ID_WEAPON6,     ANIM_WEAPON6,   '6',            -1,     -1, -1},
00253     {"weapon 7",        "railgun",          ID_WEAPON7,     ANIM_WEAPON7,   '7',            -1,     -1, -1},
00254     {"weapon 8",        "plasma gun",       ID_WEAPON8,     ANIM_WEAPON8,   '8',            -1,     -1, -1},
00255     {"weapon 9",        "BFG",              ID_WEAPON9,     ANIM_WEAPON9,   '9',            -1,     -1, -1},
00256     {"+attack",         "attack",           ID_ATTACK,      ANIM_ATTACK,    K_CTRL,         -1,     -1, -1},
00257     {"weapprev",        "prev weapon",      ID_WEAPPREV,    ANIM_IDLE,      '[',            -1,     -1, -1},
00258     {"weapnext",        "next weapon",      ID_WEAPNEXT,    ANIM_IDLE,      ']',            -1,     -1, -1},
00259     {"+button3",        "gesture",          ID_GESTURE,     ANIM_GESTURE,   K_MOUSE3,       -1,     -1, -1},
00260     {"messagemode",     "chat",             ID_CHAT,        ANIM_CHAT,      't',            -1,     -1, -1},
00261     {"messagemode2",    "chat - team",      ID_CHAT2,       ANIM_CHAT,      -1,             -1,     -1, -1},
00262     {"messagemode3",    "chat - target",    ID_CHAT3,       ANIM_CHAT,      -1,             -1,     -1, -1},
00263     {"messagemode4",    "chat - attacker",  ID_CHAT4,       ANIM_CHAT,      -1,             -1,     -1, -1},
00264     {(char*)NULL,       (char*)NULL,        0,              0,              -1,             -1,     -1, -1},
00265 };
00266 
00267 static configcvar_t g_configcvars[] =
00268 {
00269     {"cl_run",          0,                  0},
00270     {"m_pitch",         0,                  0},
00271     {"cg_autoswitch",   0,                  0},
00272     {"sensitivity",     0,                  0},
00273     {"in_joystick",     0,                  0},
00274     {"joy_threshold",   0,                  0},
00275     {"m_filter",        0,                  0},
00276     {"cl_freelook",     0,                  0},
00277     {NULL,              0,                  0}
00278 };
00279 
00280 static menucommon_s *g_movement_controls[] =
00281 {
00282     (menucommon_s *)&s_controls.alwaysrun,     
00283     (menucommon_s *)&s_controls.run,            
00284     (menucommon_s *)&s_controls.walkforward,
00285     (menucommon_s *)&s_controls.backpedal,
00286     (menucommon_s *)&s_controls.stepleft,      
00287     (menucommon_s *)&s_controls.stepright,     
00288     (menucommon_s *)&s_controls.moveup,        
00289     (menucommon_s *)&s_controls.movedown,      
00290     (menucommon_s *)&s_controls.turnleft,      
00291     (menucommon_s *)&s_controls.turnright,     
00292     (menucommon_s *)&s_controls.sidestep,
00293     NULL
00294 };
00295 
00296 static menucommon_s *g_weapons_controls[] = {
00297     (menucommon_s *)&s_controls.attack,           
00298     (menucommon_s *)&s_controls.nextweapon,
00299     (menucommon_s *)&s_controls.prevweapon,
00300     (menucommon_s *)&s_controls.autoswitch,    
00301     (menucommon_s *)&s_controls.chainsaw,         
00302     (menucommon_s *)&s_controls.machinegun,
00303     (menucommon_s *)&s_controls.shotgun,          
00304     (menucommon_s *)&s_controls.grenadelauncher,
00305     (menucommon_s *)&s_controls.rocketlauncher,   
00306     (menucommon_s *)&s_controls.lightning,   
00307     (menucommon_s *)&s_controls.railgun,          
00308     (menucommon_s *)&s_controls.plasma,           
00309     (menucommon_s *)&s_controls.bfg,              
00310     NULL,
00311 };
00312 
00313 static menucommon_s *g_looking_controls[] = {
00314     (menucommon_s *)&s_controls.sensitivity,
00315     (menucommon_s *)&s_controls.smoothmouse,
00316     (menucommon_s *)&s_controls.invertmouse,
00317     (menucommon_s *)&s_controls.lookup,
00318     (menucommon_s *)&s_controls.lookdown,
00319     (menucommon_s *)&s_controls.mouselook,
00320     (menucommon_s *)&s_controls.freelook,
00321     (menucommon_s *)&s_controls.centerview,
00322     (menucommon_s *)&s_controls.zoomview,
00323     (menucommon_s *)&s_controls.joyenable,
00324     (menucommon_s *)&s_controls.joythreshold,
00325     NULL,
00326 };
00327 
00328 static menucommon_s *g_misc_controls[] = {
00329     (menucommon_s *)&s_controls.showscores, 
00330     (menucommon_s *)&s_controls.useitem,
00331     (menucommon_s *)&s_controls.gesture,
00332     (menucommon_s *)&s_controls.chat,
00333     (menucommon_s *)&s_controls.chat2,
00334     (menucommon_s *)&s_controls.chat3,
00335     (menucommon_s *)&s_controls.chat4,
00336     NULL,
00337 };
00338 
00339 static menucommon_s **g_controls[] = {
00340     g_movement_controls,
00341     g_looking_controls,
00342     g_weapons_controls,
00343     g_misc_controls,
00344 };
00345 
00346 /*
00347 =================
00348 Controls_InitCvars
00349 =================
00350 */
00351 static void Controls_InitCvars( void )
00352 {
00353     int             i;
00354     configcvar_t*   cvarptr;
00355 
00356     cvarptr = g_configcvars;
00357     for (i=0; ;i++,cvarptr++)
00358     {
00359         if (!cvarptr->name)
00360             break;
00361 
00362         // get current value
00363         cvarptr->value = trap_Cvar_VariableValue( cvarptr->name );
00364 
00365         // get default value
00366         trap_Cvar_Reset( cvarptr->name );
00367         cvarptr->defaultvalue = trap_Cvar_VariableValue( cvarptr->name );
00368 
00369         // restore current value
00370         trap_Cvar_SetValue( cvarptr->name, cvarptr->value );
00371     }
00372 }
00373 
00374 /*
00375 =================
00376 Controls_GetCvarDefault
00377 =================
00378 */
00379 static float Controls_GetCvarDefault( char* name )
00380 {
00381     configcvar_t*   cvarptr;
00382     int             i;
00383 
00384     cvarptr = g_configcvars;
00385     for (i=0; ;i++,cvarptr++)
00386     {
00387         if (!cvarptr->name)
00388             return (0);
00389 
00390         if (!strcmp(cvarptr->name,name))
00391             break;
00392     }
00393 
00394     return (cvarptr->defaultvalue);
00395 }
00396 
00397 /*
00398 =================
00399 Controls_GetCvarValue
00400 =================
00401 */
00402 static float Controls_GetCvarValue( char* name )
00403 {
00404     configcvar_t*   cvarptr;
00405     int             i;
00406 
00407     cvarptr = g_configcvars;
00408     for (i=0; ;i++,cvarptr++)
00409     {
00410         if (!cvarptr->name)
00411             return (0);
00412 
00413         if (!strcmp(cvarptr->name,name))
00414             break;
00415     }
00416 
00417     return (cvarptr->value);
00418 }
00419 
00420 
00421 /*
00422 =================
00423 Controls_UpdateModel
00424 =================
00425 */
00426 static void Controls_UpdateModel( int anim ) {
00427     VectorClear( s_controls.playerViewangles );
00428     VectorClear( s_controls.playerMoveangles );
00429     s_controls.playerViewangles[YAW] = 180 - 30;
00430     s_controls.playerMoveangles[YAW] = s_controls.playerViewangles[YAW];
00431     s_controls.playerLegs            = LEGS_IDLE;
00432     s_controls.playerTorso           = TORSO_STAND;
00433     s_controls.playerWeapon          = -1;
00434     s_controls.playerChat            = qfalse;
00435 
00436     switch( anim ) {
00437     case ANIM_RUN:  
00438         s_controls.playerLegs = LEGS_RUN;
00439         break;
00440 
00441     case ANIM_WALK: 
00442         s_controls.playerLegs = LEGS_WALK;
00443         break;
00444 
00445     case ANIM_BACK: 
00446         s_controls.playerLegs = LEGS_BACK;
00447         break;
00448 
00449     case ANIM_JUMP: 
00450         s_controls.playerLegs = LEGS_JUMP;
00451         break;
00452 
00453     case ANIM_CROUCH:   
00454         s_controls.playerLegs = LEGS_IDLECR;
00455         break;
00456 
00457     case ANIM_TURNLEFT:
00458         s_controls.playerViewangles[YAW] += 90;
00459         break;
00460 
00461     case ANIM_TURNRIGHT:
00462         s_controls.playerViewangles[YAW] -= 90;
00463         break;
00464 
00465     case ANIM_STEPLEFT:
00466         s_controls.playerLegs = LEGS_WALK;
00467         s_controls.playerMoveangles[YAW] = s_controls.playerViewangles[YAW] + 90;
00468         break;
00469 
00470     case ANIM_STEPRIGHT:
00471         s_controls.playerLegs = LEGS_WALK;
00472         s_controls.playerMoveangles[YAW] = s_controls.playerViewangles[YAW] - 90;
00473         break;
00474 
00475     case ANIM_LOOKUP:
00476         s_controls.playerViewangles[PITCH] = -45;
00477         break;
00478 
00479     case ANIM_LOOKDOWN:
00480         s_controls.playerViewangles[PITCH] = 45;
00481         break;
00482 
00483     case ANIM_WEAPON1:
00484         s_controls.playerWeapon = WP_GAUNTLET;
00485         break;
00486 
00487     case ANIM_WEAPON2:
00488         s_controls.playerWeapon = WP_MACHINEGUN;
00489         break;
00490 
00491     case ANIM_WEAPON3:
00492         s_controls.playerWeapon = WP_SHOTGUN;
00493         break;
00494 
00495     case ANIM_WEAPON4:
00496         s_controls.playerWeapon = WP_GRENADE_LAUNCHER;
00497         break;
00498 
00499     case ANIM_WEAPON5:
00500         s_controls.playerWeapon = WP_ROCKET_LAUNCHER;
00501         break;
00502 
00503     case ANIM_WEAPON6:
00504         s_controls.playerWeapon = WP_LIGHTNING;
00505         break;
00506 
00507     case ANIM_WEAPON7:
00508         s_controls.playerWeapon = WP_RAILGUN;
00509         break;
00510 
00511     case ANIM_WEAPON8:
00512         s_controls.playerWeapon = WP_PLASMAGUN;
00513         break;
00514 
00515     case ANIM_WEAPON9:
00516         s_controls.playerWeapon = WP_BFG;
00517         break;
00518 
00519     case ANIM_WEAPON10:
00520         s_controls.playerWeapon = WP_GRAPPLING_HOOK;
00521         break;
00522 
00523     case ANIM_ATTACK:
00524         s_controls.playerTorso = TORSO_ATTACK;
00525         break;
00526 
00527     case ANIM_GESTURE:
00528         s_controls.playerTorso = TORSO_GESTURE;
00529         break;
00530 
00531     case ANIM_DIE:
00532         s_controls.playerLegs = BOTH_DEATH1;
00533         s_controls.playerTorso = BOTH_DEATH1;
00534         s_controls.playerWeapon = WP_NONE;
00535         break;
00536 
00537     case ANIM_CHAT:
00538         s_controls.playerChat = qtrue;
00539         break;
00540 
00541     default:
00542         break;
00543     }
00544 
00545     UI_PlayerInfo_SetInfo( &s_controls.playerinfo, s_controls.playerLegs, s_controls.playerTorso, s_controls.playerViewangles, s_controls.playerMoveangles, s_controls.playerWeapon, s_controls.playerChat );
00546 }
00547 
00548 
00549 /*
00550 =================
00551 Controls_Update
00552 =================
00553 */
00554 static void Controls_Update( void ) {
00555     int     i;
00556     int     j;
00557     int     y;
00558     menucommon_s    **controls;
00559     menucommon_s    *control;
00560 
00561     // disable all controls in all groups
00562     for( i = 0; i < C_MAX; i++ ) {
00563         controls = g_controls[i];
00564         // bk001204 - parentheses
00565         for( j = 0;  (control = controls[j]) ; j++ ) {
00566             control->flags |= (QMF_HIDDEN|QMF_INACTIVE);
00567         }
00568     }
00569 
00570     controls = g_controls[s_controls.section];
00571 
00572     // enable controls in active group (and count number of items for vertical centering)
00573     // bk001204 - parentheses
00574     for( j = 0;  (control = controls[j]) ; j++ ) {
00575         control->flags &= ~(QMF_GRAYED|QMF_HIDDEN|QMF_INACTIVE);
00576     }
00577 
00578     // position controls
00579     y = ( SCREEN_HEIGHT - j * SMALLCHAR_HEIGHT ) / 2;
00580     // bk001204 - parentheses
00581     for( j = 0; (control = controls[j]) ; j++, y += SMALLCHAR_HEIGHT ) {
00582         control->x      = 320;
00583         control->y      = y;
00584         control->left   = 320 - 19*SMALLCHAR_WIDTH;
00585         control->right  = 320 + 21*SMALLCHAR_WIDTH;
00586         control->top    = y;
00587         control->bottom = y + SMALLCHAR_HEIGHT;
00588     }
00589 
00590     if( s_controls.waitingforkey ) {
00591         // disable everybody
00592         for( i = 0; i < s_controls.menu.nitems; i++ ) {
00593             ((menucommon_s*)(s_controls.menu.items[i]))->flags |= QMF_GRAYED;
00594         }
00595 
00596         // enable action item
00597         ((menucommon_s*)(s_controls.menu.items[s_controls.menu.cursor]))->flags &= ~QMF_GRAYED;
00598 
00599         // don't gray out player's name
00600         s_controls.name.generic.flags &= ~QMF_GRAYED;
00601 
00602         return;
00603     }
00604 
00605     // enable everybody
00606     for( i = 0; i < s_controls.menu.nitems; i++ ) {
00607         ((menucommon_s*)(s_controls.menu.items[i]))->flags &= ~QMF_GRAYED;
00608     }
00609 
00610     // makes sure flags are right on the group selection controls
00611     s_controls.looking.generic.flags  &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00612     s_controls.movement.generic.flags &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00613     s_controls.weapons.generic.flags  &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00614     s_controls.misc.generic.flags     &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00615 
00616     s_controls.looking.generic.flags  |= QMF_PULSEIFFOCUS;
00617     s_controls.movement.generic.flags |= QMF_PULSEIFFOCUS;
00618     s_controls.weapons.generic.flags  |= QMF_PULSEIFFOCUS;
00619     s_controls.misc.generic.flags     |= QMF_PULSEIFFOCUS;
00620 
00621     // set buttons
00622     switch( s_controls.section ) {
00623     case C_MOVEMENT:
00624         s_controls.movement.generic.flags &= ~QMF_PULSEIFFOCUS;
00625         s_controls.movement.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00626         break;
00627     
00628     case C_LOOKING:
00629         s_controls.looking.generic.flags &= ~QMF_PULSEIFFOCUS;
00630         s_controls.looking.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00631         break;
00632     
00633     case C_WEAPONS:
00634         s_controls.weapons.generic.flags &= ~QMF_PULSEIFFOCUS;
00635         s_controls.weapons.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00636         break;      
00637 
00638     case C_MISC:
00639         s_controls.misc.generic.flags &= ~QMF_PULSEIFFOCUS;
00640         s_controls.misc.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS);
00641         break;
00642     }
00643 }
00644 
00645 
00646 /*
00647 =================
00648 Controls_DrawKeyBinding
00649 =================
00650 */
00651 static void Controls_DrawKeyBinding( void *self )
00652 {
00653     menuaction_s*   a;
00654     int             x;
00655     int             y;
00656     int             b1;
00657     int             b2;
00658     qboolean        c;
00659     char            name[32];
00660     char            name2[32];
00661 
00662     a = (menuaction_s*) self;
00663 
00664     x = a->generic.x;
00665     y = a->generic.y;
00666 
00667     c = (Menu_ItemAtCursor( a->generic.parent ) == a);
00668 
00669     b1 = g_bindings[a->generic.id].bind1;
00670     if (b1 == -1)
00671         strcpy(name,"???");
00672     else
00673     {
00674         trap_Key_KeynumToStringBuf( b1, name, 32 );
00675         Q_strupr(name);
00676 
00677         b2 = g_bindings[a->generic.id].bind2;
00678         if (b2 != -1)
00679         {
00680             trap_Key_KeynumToStringBuf( b2, name2, 32 );
00681             Q_strupr(name2);
00682 
00683             strcat( name, " or " );
00684             strcat( name, name2 );
00685         }
00686     }
00687 
00688     if (c)
00689     {
00690         UI_FillRect( a->generic.left, a->generic.top, a->generic.right-a->generic.left+1, a->generic.bottom-a->generic.top+1, listbar_color ); 
00691 
00692         UI_DrawString( x - SMALLCHAR_WIDTH, y, g_bindings[a->generic.id].label, UI_RIGHT|UI_SMALLFONT, text_color_highlight );
00693         UI_DrawString( x + SMALLCHAR_WIDTH, y, name, UI_LEFT|UI_SMALLFONT|UI_PULSE, text_color_highlight );
00694 
00695         if (s_controls.waitingforkey)
00696         {
00697             UI_DrawChar( x, y, '=', UI_CENTER|UI_BLINK|UI_SMALLFONT, text_color_highlight);
00698             UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.80, "Waiting for new key ... ESCAPE to cancel", UI_SMALLFONT|UI_CENTER|UI_PULSE, colorWhite );
00699         }
00700         else
00701         {
00702             UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, text_color_highlight);
00703             UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.78, "Press ENTER or CLICK to change", UI_SMALLFONT|UI_CENTER, colorWhite );
00704             UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.82, "Press BACKSPACE to clear", UI_SMALLFONT|UI_CENTER, colorWhite );
00705         }
00706     }
00707     else
00708     {
00709         if (a->generic.flags & QMF_GRAYED)
00710         {
00711             UI_DrawString( x - SMALLCHAR_WIDTH, y, g_bindings[a->generic.id].label, UI_RIGHT|UI_SMALLFONT, text_color_disabled );
00712             UI_DrawString( x + SMALLCHAR_WIDTH, y, name, UI_LEFT|UI_SMALLFONT, text_color_disabled );
00713         }
00714         else
00715         {
00716             UI_DrawString( x - SMALLCHAR_WIDTH, y, g_bindings[a->generic.id].label, UI_RIGHT|UI_SMALLFONT, controls_binding_color );
00717             UI_DrawString( x + SMALLCHAR_WIDTH, y, name, UI_LEFT|UI_SMALLFONT, controls_binding_color );
00718         }
00719     }
00720 }
00721 
00722 /*
00723 =================
00724 Controls_StatusBar
00725 =================
00726 */
00727 static void Controls_StatusBar( void *self )
00728 {
00729     UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.80, "Use Arrow Keys or CLICK to change", UI_SMALLFONT|UI_CENTER, colorWhite );
00730 }
00731 
00732 
00733 /*
00734 =================
00735 Controls_DrawPlayer
00736 =================
00737 */
00738 static void Controls_DrawPlayer( void *self ) {
00739     menubitmap_s    *b;
00740     char            buf[MAX_QPATH];
00741 
00742     trap_Cvar_VariableStringBuffer( "model", buf, sizeof( buf ) );
00743     if ( strcmp( buf, s_controls.playerModel ) != 0 ) {
00744         UI_PlayerInfo_SetModel( &s_controls.playerinfo, buf );
00745         strcpy( s_controls.playerModel, buf );
00746         Controls_UpdateModel( ANIM_IDLE );
00747     }
00748 
00749     b = (menubitmap_s*) self;
00750     UI_DrawPlayer( b->generic.x, b->generic.y, b->width, b->height, &s_controls.playerinfo, uis.realtime/2 );
00751 }
00752 
00753 
00754 /*
00755 =================
00756 Controls_GetKeyAssignment
00757 =================
00758 */
00759 static void Controls_GetKeyAssignment (char *command, int *twokeys)
00760 {
00761     int     count;
00762     int     j;
00763     char    b[256];
00764 
00765     twokeys[0] = twokeys[1] = -1;
00766     count = 0;
00767 
00768     for ( j = 0; j < 256; j++ )
00769     {
00770         trap_Key_GetBindingBuf( j, b, 256 );
00771         if ( *b == 0 ) {
00772             continue;
00773         }
00774         if ( !Q_stricmp( b, command ) ) {
00775             twokeys[count] = j;
00776             count++;
00777             if (count == 2)
00778                 break;
00779         }
00780     }
00781 }
00782 
00783 /*
00784 =================
00785 Controls_GetConfig
00786 =================
00787 */
00788 static void Controls_GetConfig( void )
00789 {
00790     int     i;
00791     int     twokeys[2];
00792     bind_t* bindptr;
00793 
00794     // put the bindings into a local store
00795     bindptr = g_bindings;
00796 
00797     // iterate each command, get its numeric binding
00798     for (i=0; ;i++,bindptr++)
00799     {
00800         if (!bindptr->label)
00801             break;
00802 
00803         Controls_GetKeyAssignment(bindptr->command, twokeys);
00804 
00805         bindptr->bind1 = twokeys[0];
00806         bindptr->bind2 = twokeys[1];
00807     }
00808 
00809     s_controls.invertmouse.curvalue  = Controls_GetCvarValue( "m_pitch" ) < 0;
00810     s_controls.smoothmouse.curvalue  = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "m_filter" ) );
00811     s_controls.alwaysrun.curvalue    = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_run" ) );
00812     s_controls.autoswitch.curvalue   = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cg_autoswitch" ) );
00813     s_controls.sensitivity.curvalue  = UI_ClampCvar( 2, 30, Controls_GetCvarValue( "sensitivity" ) );
00814     s_controls.joyenable.curvalue    = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "in_joystick" ) );
00815     s_controls.joythreshold.curvalue = UI_ClampCvar( 0.05f, 0.75f, Controls_GetCvarValue( "joy_threshold" ) );
00816     s_controls.freelook.curvalue     = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_freelook" ) );
00817 }
00818 
00819 /*
00820 =================
00821 Controls_SetConfig
00822 =================
00823 */
00824 static void Controls_SetConfig( void )
00825 {
00826     int     i;
00827     bind_t* bindptr;
00828 
00829     // set the bindings from the local store
00830     bindptr = g_bindings;
00831 
00832     // iterate each command, get its numeric binding
00833     for (i=0; ;i++,bindptr++)
00834     {
00835         if (!bindptr->label)
00836             break;
00837 
00838         if (bindptr->bind1 != -1)
00839         {   
00840             trap_Key_SetBinding( bindptr->bind1, bindptr->command );
00841 
00842             if (bindptr->bind2 != -1)
00843                 trap_Key_SetBinding( bindptr->bind2, bindptr->command );
00844         }
00845     }
00846 
00847     if ( s_controls.invertmouse.curvalue )
00848         trap_Cvar_SetValue( "m_pitch", -fabs( trap_Cvar_VariableValue( "m_pitch" ) ) );
00849     else
00850         trap_Cvar_SetValue( "m_pitch", fabs( trap_Cvar_VariableValue( "m_pitch" ) ) );
00851 
00852     trap_Cvar_SetValue( "m_filter", s_controls.smoothmouse.curvalue );
00853     trap_Cvar_SetValue( "cl_run", s_controls.alwaysrun.curvalue );
00854     trap_Cvar_SetValue( "cg_autoswitch", s_controls.autoswitch.curvalue );
00855     trap_Cvar_SetValue( "sensitivity", s_controls.sensitivity.curvalue );
00856     trap_Cvar_SetValue( "in_joystick", s_controls.joyenable.curvalue );
00857     trap_Cvar_SetValue( "joy_threshold", s_controls.joythreshold.curvalue );
00858     trap_Cvar_SetValue( "cl_freelook", s_controls.freelook.curvalue );
00859     trap_Cmd_ExecuteText( EXEC_APPEND, "in_restart\n" );
00860 }
00861 
00862 /*
00863 =================
00864 Controls_SetDefaults
00865 =================
00866 */
00867 static void Controls_SetDefaults( void )
00868 {
00869     int i;
00870     bind_t* bindptr;
00871 
00872     // set the bindings from the local store
00873     bindptr = g_bindings;
00874 
00875     // iterate each command, set its default binding
00876     for (i=0; ;i++,bindptr++)
00877     {
00878         if (!bindptr->label)
00879             break;
00880 
00881         bindptr->bind1 = bindptr->defaultbind1;
00882         bindptr->bind2 = bindptr->defaultbind2;
00883     }
00884 
00885     s_controls.invertmouse.curvalue  = Controls_GetCvarDefault( "m_pitch" ) < 0;
00886     s_controls.smoothmouse.curvalue  = Controls_GetCvarDefault( "m_filter" );
00887     s_controls.alwaysrun.curvalue    = Controls_GetCvarDefault( "cl_run" );
00888     s_controls.autoswitch.curvalue   = Controls_GetCvarDefault( "cg_autoswitch" );
00889     s_controls.sensitivity.curvalue  = Controls_GetCvarDefault( "sensitivity" );
00890     s_controls.joyenable.curvalue    = Controls_GetCvarDefault( "in_joystick" );
00891     s_controls.joythreshold.curvalue = Controls_GetCvarDefault( "joy_threshold" );
00892     s_controls.freelook.curvalue     = Controls_GetCvarDefault( "cl_freelook" );
00893 }
00894 
00895 /*
00896 =================
00897 Controls_MenuKey
00898 =================
00899 */
00900 static sfxHandle_t Controls_MenuKey( int key )
00901 {
00902     int         id;
00903     int         i;
00904     qboolean    found;
00905     bind_t*     bindptr;
00906     found = qfalse;
00907 
00908     if (!s_controls.waitingforkey)
00909     {
00910         switch (key)
00911         {
00912             case K_BACKSPACE:
00913             case K_DEL:
00914             case K_KP_DEL:
00915                 key = -1;
00916                 break;
00917         
00918             case K_MOUSE2:
00919             case K_ESCAPE:
00920                 if (s_controls.changesmade)
00921                     Controls_SetConfig();
00922                 goto ignorekey; 
00923 
00924             default:
00925                 goto ignorekey;
00926         }
00927     }
00928     else
00929     {
00930         if (key & K_CHAR_FLAG)
00931             goto ignorekey;
00932 
00933         switch (key)
00934         {
00935             case K_ESCAPE:
00936                 s_controls.waitingforkey = qfalse;
00937                 Controls_Update();
00938                 return (menu_out_sound);
00939     
00940             case '`':
00941                 goto ignorekey;
00942         }
00943     }
00944 
00945     s_controls.changesmade = qtrue;
00946     
00947     if (key != -1)
00948     {
00949         // remove from any other bind
00950         bindptr = g_bindings;
00951         for (i=0; ;i++,bindptr++)
00952         {
00953             if (!bindptr->label)    
00954                 break;
00955 
00956             if (bindptr->bind2 == key)
00957                 bindptr->bind2 = -1;
00958 
00959             if (bindptr->bind1 == key)
00960             {
00961                 bindptr->bind1 = bindptr->bind2;    
00962                 bindptr->bind2 = -1;
00963             }
00964         }
00965     }
00966 
00967     // assign key to local store
00968     id      = ((menucommon_s*)(s_controls.menu.items[s_controls.menu.cursor]))->id;
00969     bindptr = g_bindings;
00970     for (i=0; ;i++,bindptr++)
00971     {
00972         if (!bindptr->label)    
00973             break;
00974         
00975         if (bindptr->id == id)
00976         {
00977             found = qtrue;
00978             if (key == -1)
00979             {
00980                 if( bindptr->bind1 != -1 ) {
00981                     trap_Key_SetBinding( bindptr->bind1, "" );
00982                     bindptr->bind1 = -1;
00983                 }
00984                 if( bindptr->bind2 != -1 ) {
00985                     trap_Key_SetBinding( bindptr->bind2, "" );
00986                     bindptr->bind2 = -1;
00987                 }
00988             }
00989             else if (bindptr->bind1 == -1) {
00990                 bindptr->bind1 = key;
00991             }
00992             else if (bindptr->bind1 != key && bindptr->bind2 == -1) {
00993                 bindptr->bind2 = key;
00994             }
00995             else
00996             {
00997                 trap_Key_SetBinding( bindptr->bind1, "" );
00998                 trap_Key_SetBinding( bindptr->bind2, "" );
00999                 bindptr->bind1 = key;
01000                 bindptr->bind2 = -1;
01001             }                       
01002             break;
01003         }
01004     }               
01005         
01006     s_controls.waitingforkey = qfalse;
01007 
01008     if (found)
01009     {   
01010         Controls_Update();
01011         return (menu_out_sound);
01012     }
01013 
01014 ignorekey:
01015     return Menu_DefaultKey( &s_controls.menu, key );
01016 }
01017 
01018 /*
01019 =================
01020 Controls_ResetDefaults_Action
01021 =================
01022 */
01023 static void Controls_ResetDefaults_Action( qboolean result ) {
01024     if( !result ) {
01025         return;
01026     }
01027 
01028     s_controls.changesmade = qtrue;
01029     Controls_SetDefaults();
01030     Controls_Update();
01031 }
01032 
01033 /*
01034 ====