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

ui_qmenu.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     UI_QMENU.C
00025 
00026     Quake's menu framework system.
00027 **********************************************************************/
00028 #include "ui_local.h"
00029 
00030 sfxHandle_t menu_in_sound;
00031 sfxHandle_t menu_move_sound;
00032 sfxHandle_t menu_out_sound;
00033 sfxHandle_t menu_buzz_sound;
00034 sfxHandle_t menu_null_sound;
00035 sfxHandle_t weaponChangeSound;
00036 
00037 static qhandle_t    sliderBar;
00038 static qhandle_t    sliderButton_0;
00039 static qhandle_t    sliderButton_1;
00040 
00041 vec4_t menu_text_color      = {1.0f, 1.0f, 1.0f, 1.0f};
00042 vec4_t menu_dim_color       = {0.0f, 0.0f, 0.0f, 0.75f};
00043 vec4_t color_black      = {0.00f, 0.00f, 0.00f, 1.00f};
00044 vec4_t color_white      = {1.00f, 1.00f, 1.00f, 1.00f};
00045 vec4_t color_yellow     = {1.00f, 1.00f, 0.00f, 1.00f};
00046 vec4_t color_blue       = {0.00f, 0.00f, 1.00f, 1.00f};
00047 vec4_t color_lightOrange    = {1.00f, 0.68f, 0.00f, 1.00f };
00048 vec4_t color_orange     = {1.00f, 0.43f, 0.00f, 1.00f};
00049 vec4_t color_red        = {1.00f, 0.00f, 0.00f, 1.00f};
00050 vec4_t color_dim        = {0.00f, 0.00f, 0.00f, 0.25f};
00051 
00052 // current color scheme
00053 vec4_t pulse_color          = {1.00f, 1.00f, 1.00f, 1.00f};
00054 vec4_t text_color_disabled  = {0.50f, 0.50f, 0.50f, 1.00f}; // light gray
00055 vec4_t text_color_normal    = {1.00f, 0.43f, 0.00f, 1.00f}; // light orange
00056 vec4_t text_color_highlight = {1.00f, 1.00f, 0.00f, 1.00f}; // bright yellow
00057 vec4_t listbar_color        = {1.00f, 0.43f, 0.00f, 0.30f}; // transluscent orange
00058 vec4_t text_color_status    = {1.00f, 1.00f, 1.00f, 1.00f}; // bright white 
00059 
00060 // action widget
00061 static void Action_Init( menuaction_s *a );
00062 static void Action_Draw( menuaction_s *a );
00063 
00064 // radio button widget
00065 static void RadioButton_Init( menuradiobutton_s *rb );
00066 static void RadioButton_Draw( menuradiobutton_s *rb );
00067 static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key );
00068 
00069 // slider widget
00070 static void Slider_Init( menuslider_s *s );
00071 static sfxHandle_t Slider_Key( menuslider_s *s, int key );
00072 static void Slider_Draw( menuslider_s *s );
00073 
00074 // spin control widget
00075 static void SpinControl_Init( menulist_s *s );
00076 static void SpinControl_Draw( menulist_s *s );
00077 static sfxHandle_t SpinControl_Key( menulist_s *l, int key );
00078 
00079 // text widget
00080 static void Text_Init( menutext_s *b );
00081 static void Text_Draw( menutext_s *b );
00082 
00083 // scrolllist widget
00084 static void ScrollList_Init( menulist_s *l );
00085 sfxHandle_t ScrollList_Key( menulist_s *l, int key );
00086 
00087 // proportional text widget
00088 static void PText_Init( menutext_s *b );
00089 static void PText_Draw( menutext_s *b );
00090 
00091 // proportional banner text widget
00092 static void BText_Init( menutext_s *b );
00093 static void BText_Draw( menutext_s *b );
00094 
00095 /*
00096 =================
00097 Text_Init
00098 =================
00099 */
00100 static void Text_Init( menutext_s *t )
00101 {
00102     t->generic.flags |= QMF_INACTIVE;
00103 }
00104 
00105 /*
00106 =================
00107 Text_Draw
00108 =================
00109 */
00110 static void Text_Draw( menutext_s *t )
00111 {
00112     int     x;
00113     int     y;
00114     char    buff[512];  
00115     float*  color;
00116 
00117     x = t->generic.x;
00118     y = t->generic.y;
00119 
00120     buff[0] = '\0';
00121 
00122     // possible label
00123     if (t->generic.name)
00124         strcpy(buff,t->generic.name);
00125 
00126     // possible value
00127     if (t->string)
00128         strcat(buff,t->string);
00129         
00130     if (t->generic.flags & QMF_GRAYED)
00131         color = text_color_disabled;
00132     else
00133         color = t->color;
00134 
00135     UI_DrawString( x, y, buff, t->style, color );
00136 }
00137 
00138 /*
00139 =================
00140 BText_Init
00141 =================
00142 */
00143 static void BText_Init( menutext_s *t )
00144 {
00145     t->generic.flags |= QMF_INACTIVE;
00146 }
00147 
00148 /*
00149 =================
00150 BText_Draw
00151 =================
00152 */
00153 static void BText_Draw( menutext_s *t )
00154 {
00155     int     x;
00156     int     y;
00157     float*  color;
00158 
00159     x = t->generic.x;
00160     y = t->generic.y;
00161 
00162     if (t->generic.flags & QMF_GRAYED)
00163         color = text_color_disabled;
00164     else
00165         color = t->color;
00166 
00167     UI_DrawBannerString( x, y, t->string, t->style, color );
00168 }
00169 
00170 /*
00171 =================
00172 PText_Init
00173 =================
00174 */
00175 static void PText_Init( menutext_s *t )
00176 {
00177     int x;
00178     int y;
00179     int w;
00180     int h;
00181     float   sizeScale;
00182 
00183     sizeScale = UI_ProportionalSizeScale( t->style );
00184 
00185     x = t->generic.x;
00186     y = t->generic.y;
00187     w = UI_ProportionalStringWidth( t->string ) * sizeScale;
00188     h = PROP_HEIGHT * sizeScale;
00189 
00190     if( t->generic.flags & QMF_RIGHT_JUSTIFY ) {
00191         x -= w;
00192     }
00193     else if( t->generic.flags & QMF_CENTER_JUSTIFY ) {
00194         x -= w / 2;
00195     }
00196 
00197     t->generic.left   = x - PROP_GAP_WIDTH * sizeScale;
00198     t->generic.right  = x + w + PROP_GAP_WIDTH * sizeScale;
00199     t->generic.top    = y;
00200     t->generic.bottom = y + h;
00201 }
00202 
00203 /*
00204 =================
00205 PText_Draw
00206 =================
00207 */
00208 static void PText_Draw( menutext_s *t )
00209 {
00210     int     x;
00211     int     y;
00212     float * color;
00213     int     style;
00214 
00215     x = t->generic.x;
00216     y = t->generic.y;
00217 
00218     if (t->generic.flags & QMF_GRAYED)
00219         color = text_color_disabled;
00220     else
00221         color = t->color;
00222 
00223     style = t->style;
00224     if( t->generic.flags & QMF_PULSEIFFOCUS ) {
00225         if( Menu_ItemAtCursor( t->generic.parent ) == t ) {
00226             style |= UI_PULSE;
00227         }
00228         else {
00229             style |= UI_INVERSE;
00230         }
00231     }
00232 
00233     UI_DrawProportionalString( x, y, t->string, style, color );
00234 }
00235 
00236 /*
00237 =================
00238 Bitmap_Init
00239 =================
00240 */
00241 void Bitmap_Init( menubitmap_s *b )
00242 {
00243     int x;
00244     int y;
00245     int w;
00246     int h;
00247 
00248     x = b->generic.x;
00249     y = b->generic.y;
00250     w = b->width;
00251     h = b->height;
00252     if( w < 0 ) {
00253         w = -w;
00254     }
00255     if( h < 0 ) {
00256         h = -h;
00257     }
00258 
00259     if (b->generic.flags & QMF_RIGHT_JUSTIFY)
00260     {
00261         x = x - w;
00262     }
00263     else if (b->generic.flags & QMF_CENTER_JUSTIFY)
00264     {
00265         x = x - w/2;
00266     }
00267 
00268     b->generic.left   = x;
00269     b->generic.right  = x + w;
00270     b->generic.top    = y;
00271     b->generic.bottom = y + h;
00272 
00273     b->shader      = 0;
00274     b->focusshader = 0;
00275 }
00276 
00277 /*
00278 =================
00279 Bitmap_Draw
00280 =================
00281 */
00282 void Bitmap_Draw( menubitmap_s *b )
00283 {
00284     float   x;
00285     float   y;
00286     float   w;
00287     float   h;
00288     vec4_t  tempcolor;
00289     float*  color;
00290 
00291     x = b->generic.x;
00292     y = b->generic.y;
00293     w = b->width;
00294     h = b->height;
00295 
00296     if (b->generic.flags & QMF_RIGHT_JUSTIFY)
00297     {
00298         x = x - w;
00299     }
00300     else if (b->generic.flags & QMF_CENTER_JUSTIFY)
00301     {
00302         x = x - w/2;
00303     }
00304 
00305     // used to refresh shader
00306     if (b->generic.name && !b->shader)
00307     {
00308         b->shader = trap_R_RegisterShaderNoMip( b->generic.name );
00309         if (!b->shader && b->errorpic)
00310             b->shader = trap_R_RegisterShaderNoMip( b->errorpic );
00311     }
00312 
00313     if (b->focuspic && !b->focusshader)
00314         b->focusshader = trap_R_RegisterShaderNoMip( b->focuspic );
00315 
00316     if (b->generic.flags & QMF_GRAYED)
00317     {
00318         if (b->shader)
00319         {
00320             trap_R_SetColor( colorMdGrey );
00321             UI_DrawHandlePic( x, y, w, h, b->shader );
00322             trap_R_SetColor( NULL );
00323         }
00324     }
00325     else
00326     {
00327         if (b->shader)
00328             UI_DrawHandlePic( x, y, w, h, b->shader );
00329 
00330         // bk001204 - parentheses
00331         if (  ( (b->generic.flags & QMF_PULSE) 
00332             || (b->generic.flags & QMF_PULSEIFFOCUS) )
00333               && (Menu_ItemAtCursor( b->generic.parent ) == b))
00334         {   
00335             if (b->focuscolor)          
00336             {
00337                 tempcolor[0] = b->focuscolor[0];
00338                 tempcolor[1] = b->focuscolor[1];
00339                 tempcolor[2] = b->focuscolor[2];
00340                 color        = tempcolor;   
00341             }
00342             else
00343                 color = pulse_color;
00344             color[3] = 0.5+0.5*sin(uis.realtime/PULSE_DIVISOR);
00345 
00346             trap_R_SetColor( color );
00347             UI_DrawHandlePic( x, y, w, h, b->focusshader );
00348             trap_R_SetColor( NULL );
00349         }
00350         else if ((b->generic.flags & QMF_HIGHLIGHT) || ((b->generic.flags & QMF_HIGHLIGHT_IF_FOCUS) && (Menu_ItemAtCursor( b->generic.parent ) == b)))
00351         {   
00352             if (b->focuscolor)
00353             {
00354                 trap_R_SetColor( b->focuscolor );
00355                 UI_DrawHandlePic( x, y, w, h, b->focusshader );
00356                 trap_R_SetColor( NULL );
00357             }
00358             else
00359                 UI_DrawHandlePic( x, y, w, h, b->focusshader );
00360         }
00361     }
00362 }
00363 
00364 /*
00365 =================
00366 Action_Init
00367 =================
00368 */
00369 static void Action_Init( menuaction_s *a )
00370 {
00371     int len;
00372 
00373     // calculate bounds
00374     if (a->generic.name)
00375         len = strlen(a->generic.name);
00376     else
00377         len = 0;
00378 
00379     // left justify text
00380     a->generic.left   = a->generic.x; 
00381     a->generic.right  = a->generic.x + len*BIGCHAR_WIDTH;
00382     a->generic.top    = a->generic.y;
00383     a->generic.bottom = a->generic.y + BIGCHAR_HEIGHT;
00384 }
00385 
00386 /*
00387 =================
00388 Action_Draw
00389 =================
00390 */
00391 static void Action_Draw( menuaction_s *a )
00392 {
00393     int     x, y;
00394     int     style;
00395     float*  color;
00396 
00397     style = 0;
00398     color = menu_text_color;
00399     if ( a->generic.flags & QMF_GRAYED )
00400     {
00401         color = text_color_disabled;
00402     }
00403     else if (( a->generic.flags & QMF_PULSEIFFOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition ))
00404     {
00405         color = text_color_highlight;
00406         style = UI_PULSE;
00407     }
00408     else if (( a->generic.flags & QMF_HIGHLIGHT_IF_FOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition ))
00409     {
00410         color = text_color_highlight;
00411     }
00412     else if ( a->generic.flags & QMF_BLINK )
00413     {
00414         style = UI_BLINK;
00415         color = text_color_highlight;
00416     }
00417 
00418     x = a->generic.x;
00419     y = a->generic.y;
00420 
00421     UI_DrawString( x, y, a->generic.name, UI_LEFT|style, color );
00422 
00423     if ( a->generic.parent->cursor == a->generic.menuPosition )
00424     {
00425         // draw cursor
00426         UI_DrawChar( x - BIGCHAR_WIDTH, y, 13, UI_LEFT|UI_BLINK, color);
00427     }
00428 }
00429 
00430 /*
00431 =================
00432 RadioButton_Init
00433 =================
00434 */
00435 static void RadioButton_Init( menuradiobutton_s *rb )
00436 {
00437     int len;
00438 
00439     // calculate bounds
00440     if (rb->generic.name)
00441         len = strlen(rb->generic.name);
00442     else
00443         len = 0;
00444 
00445     rb->generic.left   = rb->generic.x - (len+1)*SMALLCHAR_WIDTH;
00446     rb->generic.right  = rb->generic.x + 6*SMALLCHAR_WIDTH;
00447     rb->generic.top    = rb->generic.y;
00448     rb->generic.bottom = rb->generic.y + SMALLCHAR_HEIGHT;
00449 }
00450 
00451 /*
00452 =================
00453 RadioButton_Key
00454 =================
00455 */
00456 static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key )
00457 {
00458     switch (key)
00459     {
00460         case K_MOUSE1:
00461             if (!(rb->generic.flags & QMF_HASMOUSEFOCUS))
00462                 break;
00463 
00464         case K_JOY1:
00465         case K_JOY2:
00466         case K_JOY3:
00467         case K_JOY4:
00468         case K_ENTER:
00469         case K_KP_ENTER:
00470         case K_KP_LEFTARROW:
00471         case K_LEFTARROW:
00472         case K_KP_RIGHTARROW:
00473         case K_RIGHTARROW:
00474             rb->curvalue = !rb->curvalue;
00475             if ( rb->generic.callback )
00476                 rb->generic.callback( rb, QM_ACTIVATED );
00477 
00478             return (menu_move_sound);
00479     }
00480 
00481     // key not handled
00482     return 0;
00483 }
00484 
00485 /*
00486 =================
00487 RadioButton_Draw
00488 =================
00489 */
00490 static void RadioButton_Draw( menuradiobutton_s *rb )
00491 {
00492     int x;
00493     int y;
00494     float *color;
00495     int style;
00496     qboolean focus;
00497 
00498     x = rb->generic.x;
00499     y = rb->generic.y;
00500 
00501     focus = (rb->generic.parent->cursor == rb->generic.menuPosition);
00502 
00503     if ( rb->generic.flags & QMF_GRAYED )
00504     {
00505         color = text_color_disabled;
00506         style = UI_LEFT|UI_SMALLFONT;
00507     }
00508     else if ( focus )
00509     {
00510         color = text_color_highlight;
00511         style = UI_LEFT|UI_PULSE|UI_SMALLFONT;
00512     }
00513     else
00514     {
00515         color = text_color_normal;
00516         style = UI_LEFT|UI_SMALLFONT;
00517     }
00518 
00519     if ( focus )
00520     {
00521         // draw cursor
00522         UI_FillRect( rb->generic.left, rb->generic.top, rb->generic.right-rb->generic.left+1, rb->generic.bottom-rb->generic.top+1, listbar_color ); 
00523         UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color);
00524     }
00525 
00526     if ( rb->generic.name )
00527         UI_DrawString( x - SMALLCHAR_WIDTH, y, rb->generic.name, UI_RIGHT|UI_SMALLFONT, color );
00528 
00529     if ( !rb->curvalue )
00530     {
00531         UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_off);
00532         UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "off", style, color );
00533     }
00534     else
00535     {
00536         UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_on );
00537         UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "on", style, color );
00538     }
00539 }
00540 
00541 /*
00542 =================
00543 Slider_Init
00544 =================
00545 */
00546 static void Slider_Init( menuslider_s *s )
00547 {
00548     int len;
00549 
00550     // calculate bounds
00551     if (s->generic.name)
00552         len = strlen(s->generic.name);
00553     else
00554         len = 0;
00555 
00556     s->generic.left   = s->generic.x - (len+1)*SMALLCHAR_WIDTH; 
00557     s->generic.right  = s->generic.x + (SLIDER_RANGE+2+1)*SMALLCHAR_WIDTH;
00558     s->generic.top    = s->generic.y;
00559     s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT;
00560 }
00561 
00562 /*
00563 =================
00564 Slider_Key
00565 =================
00566 */
00567 static sfxHandle_t Slider_Key( menuslider_s *s, int key )
00568 {
00569     sfxHandle_t sound;
00570     int         x;
00571     int         oldvalue;
00572 
00573     switch (key)
00574     {
00575         case K_MOUSE1:
00576             x           = uis.cursorx - s->generic.x - 2*SMALLCHAR_WIDTH;
00577             oldvalue    = s->curvalue;
00578             s->curvalue = (x/(float)(SLIDER_RANGE*SMALLCHAR_WIDTH)) * (s->maxvalue-s->minvalue) + s->minvalue;
00579 
00580             if (s->curvalue < s->minvalue)
00581                 s->curvalue = s->minvalue;
00582             else if (s->curvalue > s->maxvalue)
00583                 s->curvalue = s->maxvalue;
00584             if (s->curvalue != oldvalue)
00585                 sound = menu_move_sound;
00586             else
00587                 sound = 0;
00588             break;
00589 
00590         case K_KP_LEFTARROW:
00591         case K_LEFTARROW:
00592             if (s->curvalue > s->minvalue)
00593             {
00594                 s->curvalue--;
00595                 sound = menu_move_sound;
00596             }
00597             else
00598                 sound = menu_buzz_sound;
00599             break;          
00600 
00601         case K_KP_RIGHTARROW:
00602         case K_RIGHTARROW:
00603             if (s->curvalue < s->maxvalue)
00604             {
00605                 s->curvalue++;
00606                 sound = menu_move_sound;
00607             }
00608             else
00609                 sound = menu_buzz_sound;
00610             break;          
00611 
00612         default:
00613             // key not handled
00614             sound = 0;
00615             break;
00616     }
00617 
00618     if ( sound && s->generic.callback )
00619         s->generic.callback( s, QM_ACTIVATED );
00620 
00621     return (sound);
00622 }
00623 
00624 #if 1
00625 /*
00626 =================
00627 Slider_Draw
00628 =================
00629 */
00630 static void Slider_Draw( menuslider_s *s ) {
00631     int         x;
00632     int         y;
00633     int         style;
00634     float       *color;
00635     int         button;
00636     qboolean    focus;
00637     
00638     x = s->generic.x;
00639     y = s->generic.y;
00640     focus = (s->generic.parent->cursor == s->generic.menuPosition);
00641 
00642     if( s->generic.flags & QMF_GRAYED ) {
00643         color = text_color_disabled;
00644         style = UI_SMALLFONT;
00645     }
00646     else if( focus ) {
00647         color  = text_color_highlight;
00648         style = UI_SMALLFONT | UI_PULSE;
00649     }
00650     else {
00651         color = text_color_normal;
00652         style = UI_SMALLFONT;
00653     }
00654 
00655     // draw label
00656     UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color );
00657 
00658     // draw slider
00659     UI_SetColor( color );
00660     UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y, 96, 16, sliderBar );
00661     UI_SetColor( NULL );
00662 
00663     // clamp thumb
00664     if( s->maxvalue > s->minvalue ) {
00665         s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue );
00666         if( s->range < 0 ) {
00667             s->range = 0;
00668         }
00669         else if( s->range > 1) {
00670             s->range = 1;
00671         }
00672     }
00673     else {
00674         s->range = 0;
00675     }
00676 
00677     // draw thumb
00678     if( style & UI_PULSE) {
00679         button = sliderButton_1;
00680     }
00681     else {
00682         button = sliderButton_0;
00683     }
00684 
00685     UI_DrawHandlePic( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ) - 2, y - 2, 12, 20, button );
00686 }
00687 #else
00688 /*
00689 =================
00690 Slider_Draw
00691 =================
00692 */
00693 static void Slider_Draw( menuslider_s *s )
00694 {
00695     float *color;
00696     int style;
00697     int i;
00698     int x;
00699     int y;
00700     qboolean focus;
00701     
00702     x = s->generic.x;
00703     y = s->generic.y;
00704     focus = (s->generic.parent->cursor == s->generic.menuPosition);
00705 
00706     style = UI_SMALLFONT;
00707     if ( s->generic.flags & QMF_GRAYED )
00708     {
00709         color = text_color_disabled;
00710     }
00711     else if (focus)
00712     {
00713         color  = text_color_highlight;
00714         style |= UI_PULSE;
00715     }
00716     else
00717     {
00718         color = text_color_normal;
00719     }
00720 
00721     if ( focus )
00722     {
00723         // draw cursor
00724         UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color ); 
00725         UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color);
00726     }
00727 
00728     // draw label
00729     UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color );
00730 
00731     // draw slider
00732     UI_DrawChar( x + SMALLCHAR_WIDTH, y, 128, UI_LEFT|style, color);
00733     for ( i = 0; i < SLIDER_RANGE; i++ )
00734         UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 129, UI_LEFT|style, color);
00735     UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 130, UI_LEFT|style, color);
00736 
00737     // clamp thumb
00738     if (s->maxvalue > s->minvalue)
00739     {
00740         s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue );
00741         if ( s->range < 0)
00742             s->range = 0;
00743         else if ( s->range > 1)
00744             s->range = 1;
00745     }
00746     else
00747         s->range = 0;
00748 
00749     // draw thumb
00750     if (style & UI_PULSE) {
00751         style &= ~UI_PULSE;
00752         style |= UI_BLINK;
00753     }
00754     UI_DrawChar( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ), y, 131, UI_LEFT|style, color);
00755 }
00756 #endif
00757 
00758 /*
00759 =================
00760 SpinControl_Init
00761 =================
00762 */
00763 static void SpinControl_Init( menulist_s *s ) {
00764     int len;
00765     int l;
00766     const char* str;
00767 
00768     if (s->generic.name)
00769         len = strlen(s->generic.name) * SMALLCHAR_WIDTH;
00770     else
00771         len = 0;
00772 
00773     s->generic.left = s->generic.x - SMALLCHAR_WIDTH - len;
00774 
00775     len = s->numitems = 0;
00776     while ( (str = s->itemnames[s->numitems]) != 0 )
00777     {
00778         l = strlen(str);
00779         if (l > len)
00780             len = l;
00781 
00782         s->numitems++;
00783     }       
00784 
00785     s->generic.top    = s->generic.y;
00786     s->generic.right  = s->generic.x + (len+1)*SMALLCHAR_WIDTH;
00787     s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT;
00788 }
00789 
00790 /*
00791 =================
00792 SpinControl_Key
00793 =================
00794 */
00795 static sfxHandle_t SpinControl_Key( menulist_s *s, int key )
00796 {
00797     sfxHandle_t sound;
00798 
00799     sound = 0;
00800     switch (key)
00801     {
00802         case K_MOUSE1:
00803             s->curvalue++;
00804             if (s->curvalue >= s->numitems)
00805                 s->curvalue = 0;
00806             sound = menu_move_sound;
00807             break;
00808         
00809         case K_KP_LEFTARROW:
00810         case K_LEFTARROW:
00811             if (s->curvalue > 0)
00812             {
00813                 s->curvalue--;
00814                 sound = menu_move_sound;
00815             }
00816             else
00817                 sound = menu_buzz_sound;
00818             break;
00819 
00820         case K_KP_RIGHTARROW:
00821         case K_RIGHTARROW:
00822             if (s->curvalue < s->numitems-1)
00823             {
00824                 s->curvalue++;
00825                 sound = menu_move_sound;
00826             }
00827             else
00828                 sound = menu_buzz_sound;
00829             break;
00830     }
00831 
00832     if ( sound && s->generic.callback )
00833         s->generic.callback( s, QM_ACTIVATED );
00834 
00835     return (sound);
00836 }
00837 
00838 /*
00839 =================
00840 SpinControl_Draw
00841 =================
00842 */
00843 static void SpinControl_Draw( menulist_s *s )
00844 {
00845     float *color;
00846     int x,y;
00847     int style;
00848     qboolean focus;
00849 
00850     x = s->generic.x;
00851     y = s->generic.y;
00852 
00853     style = UI_SMALLFONT;
00854     focus = (s->generic.parent->cursor == s->generic.menuPosition);
00855 
00856     if ( s->generic.flags & QMF_GRAYED )
00857         color = text_color_disabled;
00858     else if ( focus )
00859     {
00860         color = text_color_highlight;
00861         style |= UI_PULSE;
00862     }
00863     else if ( s->generic.flags & QMF_BLINK )
00864     {
00865         color = text_color_highlight;
00866         style |= UI_BLINK;
00867     }
00868     else
00869         color = text_color_normal;
00870 
00871     if ( focus )
00872     {
00873         // draw cursor
00874         UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color ); 
00875         UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color);
00876     }
00877 
00878     UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, style|UI_RIGHT, color );
00879     UI_DrawString( x + SMALLCHAR_WIDTH, y, s->itemnames[s->curvalue], style|UI_LEFT, color );
00880 }
00881 
00882 /*
00883 =================
00884 ScrollList_Init
00885 =================
00886 */
00887 static void ScrollList_Init( menulist_s *l )
00888 {
00889     int     w;
00890 
00891     l->oldvalue = 0;
00892     l->curvalue = 0;
00893     l->top      = 0;
00894 
00895     if( !l->columns ) {
00896         l->columns = 1;
00897         l->seperation = 0;
00898     }
00899     else if( !l->seperation ) {
00900         l->seperation = 3;
00901     }
00902 
00903     w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH;
00904 
00905     l->generic.left   = l->generic.x;
00906     l->generic.top    = l->generic.y;   
00907     l->generic.right  = l->generic.x + w;
00908     l->generic.bottom = l->generic.y + l->height * SMALLCHAR_HEIGHT;
00909 
00910     if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
00911         l->generic.left -= w / 2;
00912         l->generic.right -= w / 2;
00913     }
00914 }
00915 
00916 /*
00917 =================
00918 ScrollList_Key
00919 =================
00920 */
00921 sfxHandle_t ScrollList_Key( menulist_s *l, int key )
00922 {
00923     int x;
00924     int y;
00925     int w;
00926     int i;
00927     int j;  
00928     int c;
00929     int cursorx;
00930     int cursory;
00931     int column;
00932     int index;
00933 
00934     switch (key)
00935     {
00936         case K_MOUSE1:
00937             if (l->generic.flags & QMF_HASMOUSEFOCUS)
00938             {
00939                 // check scroll region
00940                 x = l->generic.x;
00941                 y = l->generic.y;
00942                 w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH;
00943                 if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
00944                     x -= w / 2;
00945                 }
00946                 if (UI_CursorInRect( x, y, w, l->height*SMALLCHAR_HEIGHT ))
00947                 {
00948                     cursorx = (uis.cursorx - x)/SMALLCHAR_WIDTH;
00949                     column = cursorx / (l->width + l->seperation);
00950                     cursory = (uis.cursory - y)/SMALLCHAR_HEIGHT;
00951                     index = column * l->height + cursory;
00952                     if (l->top + index < l->numitems)
00953                     {
00954                         l->oldvalue = l->curvalue;
00955                         l->curvalue = l->top + index;
00956 
00957                         if (l->oldvalue != l->curvalue && l->generic.callback)
00958                         {
00959                             l->generic.callback( l, QM_GOTFOCUS );
00960                             return (menu_move_sound);
00961                         }
00962                     }
00963                 }
00964             
00965                 // absorbed, silent sound effect
00966                 return (menu_null_sound);
00967             }
00968             break;
00969 
00970         case K_KP_HOME:
00971         case K_HOME:
00972             l->oldvalue = l->curvalue;
00973             l->curvalue = 0;
00974             l->top      = 0;
00975 
00976             if (l->oldvalue != l->curvalue && l->generic.callback)
00977             {
00978                 l->generic.callback( l, QM_GOTFOCUS );
00979                 return (menu_move_sound);
00980             }
00981             return (menu_buzz_sound);
00982 
00983         case K_KP_END:
00984         case K_END:
00985             l->oldvalue = l->curvalue;
00986             l->curvalue = l->numitems-1;
00987             if( l->columns > 1 ) {
00988                 c = (l->curvalue / l->height + 1) * l->height;
00989                 l->top = c - (l->columns * l->height);
00990             }
00991             else {
00992                 l->top = l->curvalue - (l->height - 1);
00993             }
00994             if (l->top < 0)
00995                 l->top = 0;         
00996 
00997             if (l->oldvalue != l->curvalue && l->generic.callback)
00998             {
00999                 l->generic.callback( l, QM_GOTFOCUS );
01000                 return (menu_move_sound);
01001             }
01002             return (menu_buzz_sound);
01003 
01004         case K_PGUP:
01005         case K_KP_PGUP:
01006             if( l->columns > 1 ) {
01007                 return menu_null_sound;
01008             }
01009 
01010             if (l->curvalue > 0)
01011             {
01012                 l->oldvalue = l->curvalue;
01013                 l->curvalue -= l->height-1;
01014                 if (l->curvalue < 0)
01015                     l->curvalue = 0;
01016                 l->top = l->curvalue;
01017                 if (l->top < 0)
01018                     l->top = 0;
01019 
01020                 if (l->generic.callback)
01021                     l->generic.callback( l, QM_GOTFOCUS );
01022 
01023                 return (menu_move_sound);
01024             }
01025             return (menu_buzz_sound);
01026 
01027         case K_PGDN:
01028         case K_KP_PGDN:
01029             if( l->columns > 1 ) {
01030                 return menu_null_sound;
01031             }
01032 
01033             if (l->curvalue < l->numitems-1)
01034             {
01035                 l->oldvalue = l->curvalue;
01036                 l->curvalue += l->height-1;
01037                 if (l->curvalue > l->numitems-1)
01038                     l->curvalue = l->numitems-1;
01039                 l->top = l->curvalue - (l->height-1);
01040                 if (l->top < 0)
01041                     l->top = 0;
01042 
01043                 if (l->generic.callback)
01044                     l->generic.callback( l, QM_GOTFOCUS );
01045 
01046                 return (menu_move_sound);
01047             }
01048             return (menu_buzz_sound);
01049 
01050         case K_KP_UPARROW:
01051         case K_UPARROW:
01052             if( l->curvalue == 0 ) {
01053                 return menu_buzz_sound;
01054             }
01055 
01056             l->oldvalue = l->curvalue;
01057             l->curvalue--;
01058 
01059             if( l->curvalue < l->top ) {
01060                 if( l->columns == 1 ) {
01061                     l->top--;
01062                 }
01063                 else {
01064                     l->top -= l->height;
01065                 }
01066             }
01067 
01068             if( l->generic.callback ) {
01069                 l->generic.callback( l, QM_GOTFOCUS );
01070             }
01071 
01072             return (menu_move_sound);
01073 
01074         case K_KP_DOWNARROW:
01075         case K_DOWNARROW:
01076             if( l->curvalue == l->numitems - 1 ) {
01077                 return menu_buzz_sound;
01078             }
01079 
01080             l->oldvalue = l->curvalue;
01081             l->curvalue++;
01082 
01083             if( l->curvalue >= l->top + l->columns * l->height ) {
01084                 if( l->columns == 1 ) {
01085                     l->top++;
01086                 }
01087                 else {
01088                     l->top += l->height;
01089                 }
01090             }
01091 
01092             if( l->generic.callback ) {
01093                 l->generic.callback( l, QM_GOTFOCUS );
01094             }
01095 
01096             return menu_move_sound;
01097 
01098         case K_KP_LEFTARROW:
01099         case K_LEFTARROW:
01100             if( l->columns == 1 ) {
01101                 return menu_null_sound;
01102             }
01103 
01104             if( l->curvalue < l->height ) {
01105                 return menu_buzz_sound;
01106             }
01107 
01108             l->oldvalue = l->curvalue;
01109             l->curvalue -= l->height;
01110 
01111             if( l->curvalue < l->top ) {
01112                 l->top -= l->height;
01113             }
01114 
01115             if( l->generic.callback ) {
01116                 l->generic.callback( l, QM_GOTFOCUS );
01117             }
01118 
01119             return menu_move_sound;
01120 
01121         case K_KP_RIGHTARROW:
01122         case K_RIGHTARROW:
01123             if( l->columns == 1 ) {
01124                 return menu_null_sound;
01125             }
01126 
01127             c = l->curvalue + l->height;
01128 
01129             if( c >= l->numitems ) {
01130                 return menu_buzz_sound;
01131             }
01132 
01133             l->oldvalue = l->curvalue;
01134             l->curvalue = c;
01135 
01136             if( l->curvalue > l->top + l->columns * l->height - 1 ) {
01137                 l->top += l->height;
01138             }
01139 
01140             if( l->generic.callback ) {
01141                 l->generic.callback( l, QM_GOTFOCUS );
01142             }
01143 
01144             return menu_move_sound;
01145     }
01146 
01147     // cycle look for ascii key inside list items
01148     if ( !Q_isprint( key ) )
01149         return (0);
01150 
01151     // force to lower for case insensitive compare
01152     if ( Q_isupper( key ) )
01153     {
01154         key -= 'A' - 'a';
01155     }
01156 
01157     // iterate list items
01158     for (i=1; i<=l->numitems; i++)
01159     {
01160         j = (l->curvalue + i) % l->numitems;
01161         c = l->itemnames[j][0];
01162         if ( Q_isupper( c ) )
01163         {
01164             c -= 'A' - 'a';
01165         }
01166 
01167         if (c == key)
01168         {
01169             // set current item, mimic windows listbox scroll behavior
01170             if (j < l->top)
01171             {
01172                 // behind top most item, set this as new top
01173                 l->top = j;
01174             }
01175             else if (j > l->top+l->height-1)
01176             {
01177                 // past end of list box, do page down
01178                 l->top = (j+1) - l->height;
01179             }
01180             
01181             if (l->curvalue != j)
01182             {
01183                 l->oldvalue = l->curvalue;
01184                 l->curvalue = j;
01185                 if (l->generic.callback)
01186                     l->generic.callback( l, QM_GOTFOCUS );
01187                 return ( menu_move_sound );         
01188             }
01189 
01190             return (menu_buzz_sound);
01191         }
01192     }
01193 
01194     return (menu_buzz_sound);
01195 }
01196 
01197 /*
01198 =================
01199 ScrollList_Draw
01200 =================
01201 */
01202 void ScrollList_Draw( menulist_s *l )
01203 {
01204     int         x;
01205     int         u;
01206     int         y;
01207     int         i;
01208     int         base;
01209     int         column;
01210     float*      color;
01211     qboolean    hasfocus;
01212     int         style;
01213 
01214     hasfocus = (l->generic.parent->cursor == l->generic.menuPosition);
01215 
01216     x = l->generic.x;
01217     for( column = 0; column < l->columns; column++ ) {
01218         y = l->generic.y;
01219         base = l->top + column * l->height;
01220         for( i = base; i < base + l->height; i++) {
01221             if (i >= l->numitems)
01222                 break;
01223 
01224             if (i == l->curvalue)
01225             {
01226                 u = x - 2;
01227                 if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
01228                     u -= (l->width * SMALLCHAR_WIDTH) / 2 + 1;
01229                 }
01230 
01231                 UI_FillRect(u,y,l->width*SMALLCHAR_WIDTH,SMALLCHAR_HEIGHT+2,listbar_color);
01232                 color = text_color_highlight;
01233 
01234                 if (hasfocus)
01235                     style = UI_PULSE|UI_LEFT|UI_SMALLFONT;
01236                 else
01237                     style = UI_LEFT|UI_SMALLFONT;
01238             }
01239             else
01240             {
01241                 color = text_color_normal;
01242                 style = UI_LEFT|UI_SMALLFONT;
01243             }
01244             if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
01245                 style |= UI_CENTER;
01246             }
01247 
01248             UI_DrawString(
01249                 x,
01250                 y,
01251                 l->itemnames[i],
01252                 style,
01253                 color);
01254 
01255             y += SMALLCHAR_HEIGHT;
01256         }
01257         x += (l->width + l->seperation) * SMALLCHAR_WIDTH;
01258     }
01259 }
01260 
01261 /*
01262 =================
01263 Menu_AddItem
01264 =================
01265 */
01266 void Menu_AddItem( menuframework_s *menu, void *item )
01267 {
01268     menucommon_s    *itemptr;
01269 
01270     if (menu->nitems >= MAX_MENUITEMS)
01271         trap_Error ("Menu_AddItem: excessive items");
01272 
01273     menu->items[menu->nitems] = item;
01274     ((menucommon_s*)menu->items[menu->nitems])->parent        = menu;
01275     ((menucommon_s*)menu->items[menu->nitems])->menuPosition  = menu->nitems;
01276     ((menucommon_s*)menu->items[menu->nitems])->flags        &= ~QMF_HASMOUSEFOCUS;
01277 
01278     // perform any item specific initializations
01279     itemptr = (menucommon_s*)item;
01280     if (!(itemptr->flags & QMF_NODEFAULTINIT))
01281     {
01282         switch (itemptr->type)
01283         {
01284             case MTYPE_ACTION:
01285                 Action_Init((menuaction_s*)item);
01286                 break;
01287 
01288             case MTYPE_FIELD:
01289                 MenuField_Init((menufield_s*)item);
01290                 break;
01291 
01292             case MTYPE_SPINCONTROL:
01293                 SpinControl_Init((menulist_s*)item);
01294                 break;
01295 
01296             case MTYPE_RADIOBUTTON:
01297                 RadioButton_Init((menuradiobutton_s*)item);
01298                 break;
01299 
01300             case MTYPE_SLIDER:
01301                 Slider_Init((menuslider_s*)item);
01302                 break;
01303 
01304             case MTYPE_BITMAP:
01305                 Bitmap_Init((menubitmap_s*)item);
01306                 break;
01307 
01308             case MTYPE_TEXT:
01309                 Text_Init((menutext_s*)item);
01310                 break;
01311 
01312             case MTYPE_SCROLLLIST:
01313                 ScrollList_Init((menulist_s*)item);
01314                 break;
01315 
01316             case MTYPE_PTEXT:
01317                 PText_Init((menutext_s*)item);
01318                 break;
01319 
01320             case MTYPE_BTEXT:
01321                 BText_Init((menutext_s*)item);
01322                 break;
01323 
01324             default:
01325                 trap_Error( va("Menu_Init: unknown type %d", itemptr->type) );
01326         }
01327     }
01328 
01329     menu->nitems++;
01330 }
01331 
01332 /*
01333 =================
01334 Menu_CursorMoved
01335 =================
01336 */
01337 void Menu_CursorMoved( menuframework_s *m )
01338 {
01339     void (*callback)( void *self, int notification );
01340     
01341     if (m->cursor_prev == m->cursor)
01342         return;
01343 
01344     if (m->cursor_prev >= 0 && m->cursor_prev < m->nitems)
01345     {
01346         callback = ((menucommon_s*)(m->items[m->cursor_prev]))->callback;
01347         if (callback)
01348             callback(m->items[m->cursor_prev],QM_LOSTFOCUS);
01349     }
01350     
01351     if (m->cursor >= 0 && m->cursor < m->nitems)
01352     {
01353         callback = ((menucommon_s*)(m->items[m->cursor]))->callback;
01354         if (callback)
01355             callback(m->items[m->cursor],QM_GOTFOCUS);
01356     }
01357 }
01358 
01359 /*
01360 =================
01361 Menu_SetCursor
01362 =================
01363 */
01364 void Menu_SetCursor( menuframework_s *m, int cursor )
01365 {
01366     if (((menucommon_s*)(m->items[cursor]))->flags & (QMF_GRAYED|QMF_INACTIVE))
01367     {
01368         // cursor can't go there
01369         return;
01370     }
01371 
01372     m->cursor_prev = m->cursor;
01373     m->cursor      = cursor;
01374 
01375     Menu_CursorMoved( m );
01376 }
01377 
01378 /*
01379 =================
01380 Menu_SetCursorToItem
01381 =================
01382 */
01383 void Menu_SetCursorToItem( menuframework_s *m, void* ptr )
01384 {
01385     int i;
01386 
01387     for (i=0; i<m->nitems; i++)
01388     {
01389         if (m->items[i] == ptr)
01390         {
01391             Menu_SetCursor( m, i );
01392             return;
01393         }
01394     }
01395 }
01396 
01397 /*
01398 ** Menu_AdjustCursor
01399 **
01400 ** This function takes the given menu, the direction, and attempts
01401 ** to adjust the menu's cursor so that it's at the next available
01402 ** slot.
01403 */
01404 void Menu_AdjustCursor( menuframework_s *m, int dir ) {
01405     menucommon_s    *item = NULL;
01406     qboolean        wrapped = qfalse;
01407 
01408 wrap:
01409     while ( m->cursor >= 0 && m->cursor < m->nitems ) {
01410         item = ( menucommon_s * ) m->items[m->cursor];
01411         if (( item->flags & (QMF_GRAYED|QMF_MOUSEONLY|QMF_INACTIVE) ) ) {
01412             m->cursor += dir;
01413         }
01414         else {
01415             break;
01416         }
01417     }
01418 
01419     if ( dir == 1 ) {
01420         if ( m->cursor >= m->nitems ) {
01421             if ( m->wrapAround ) {
01422                 if ( wrapped ) {
01423                     m->cursor = m->cursor_prev;
01424                     return;
01425                 }
01426                 m->cursor = 0;
01427                 wrapped = qtrue;
01428                 goto wrap;
01429             }
01430             m->cursor = m->cursor_prev;
01431         }
01432     }
01433     else {
01434         if ( m->cursor < 0 ) {
01435             if ( m->wrapAround ) {
01436                 if ( wrapped ) {
01437                     m->cursor = m->cursor_prev;
01438                     return;
01439                 }
01440                 m->cursor = m->nitems - 1;
01441                 wrapped = qtrue;
01442                 goto wrap;
01443             }
01444             m->cursor = m->cursor_prev;
01445         }
01446     }
01447 }
01448 
01449 /*
01450 =================
01451 Menu_Draw
01452 =================
01453 */
01454 void Menu_Draw( menuframework_s *menu )
01455 {
01456     int             i;
01457     menucommon_s    *itemptr;
01458 
01459     // draw menu
01460     for (i=0; i<menu->nitems; i++)
01461     {
01462         itemptr = (menucommon_s*)menu->items[i];
01463 
01464         if (itemptr->flags & QMF_HIDDEN)
01465             continue;
01466 
01467         if (itemptr->ownerdraw)
01468         {
01469             // total subclassing, owner draws everything
01470             itemptr->ownerdraw( itemptr );
01471         }   
01472         else 
01473         {
01474             switch (itemptr->type)
01475             {   
01476                 case MTYPE_RADIOBUTTON:
01477                     RadioButton_Draw( (menuradiobutton_s*)itemptr );
01478                     break;
01479 
01480                 case MTYPE_FIELD:
01481                     MenuField_Draw( (menufield_s*)itemptr );
01482                     break;
01483         
01484                 case MTYPE_SLIDER:
01485                     Slider_Draw( (menuslider_s*)itemptr );
01486                     break;
01487  
01488                 case MTYPE_SPINCONTROL:
01489                     SpinControl_Draw( (menulist_s*)itemptr );
01490                     break;
01491         
01492                 case MTYPE_ACTION:
01493                     Action_Draw( (menuaction_s*)itemptr );
01494                     break;
01495         
01496                 case MTYPE_BITMAP:
01497                     Bitmap_Draw( (menubitmap_s*)itemptr );
01498                     break;
01499 
01500                 case MTYPE_TEXT:
01501                     Text_Draw( (menutext_s*)itemptr );
01502                     break;
01503 
01504                 case MTYPE_SCROLLLIST:
01505                     ScrollList_Draw( (menulist_s*)itemptr );
01506                     break;
01507                 
01508                 case MTYPE_PTEXT:
01509                     PText_Draw( (menutext_s*)itemptr );
01510                     break;
01511 
01512                 case MTYPE_BTEXT:
01513                     BText_Draw( (menutext_s*)itemptr );
01514                     break;
01515 
01516                 default:
01517                     trap_Error( va("Menu_Draw: unknown type %d", itemptr->type) );
01518             }
01519         }
01520 #ifndef NDEBUG
01521         if( uis.debug ) {
01522             int x;
01523             int y;
01524             int w;
01525             int h;
01526 
01527             if( !( itemptr->flags & QMF_INACTIVE ) ) {
01528                 x = itemptr->left;
01529                 y = itemptr->top;
01530                 w = itemptr->right - itemptr->left + 1;
01531                 h = itemptr->bottom - itemptr->top + 1;
01532 
01533                 if (itemptr->flags & QMF_HASMOUSEFOCUS) {
01534                     UI_DrawRect(x, y, w, h, colorYellow );
01535                 }
01536                 else {
01537                     UI_DrawRect(x, y, w, h, colorWhite );
01538                 }
01539             }
01540         }
01541 #endif
01542     }
01543 
01544     itemptr = Menu_ItemAtCursor( menu );
01545     if ( itemptr && itemptr->statusbar)
01546         itemptr->statusbar( ( void * ) itemptr );
01547 }
01548 
01549 /*
01550 =================
01551 Menu_ItemAtCursor
01552 =================
01553 */
01554 void *Menu_ItemAtCursor( menuframework_s *m )
01555 {
01556     if ( m->cursor < 0 || m->cursor >= m->nitems )
01557         return 0;
01558 
01559     return m->items[m->cursor];
01560 }
01561 
01562 /*
01563 =================
01564 Menu_ActivateItem
01565 =================
01566 */
01567 sfxHandle_t Menu_ActivateItem( menuframework_s *s, menucommon_s* item ) {
01568     if ( item->callback ) {
01569         item->callback( item, QM_ACTIVATED );
01570         if( !( item->flags & QMF_SILENT ) ) {
01571             return menu_move_sound;
01572         }
01573     }
01574 
01575     return 0;
01576 }
01577 
01578 /*
01579 =================
01580 Menu_DefaultKey
01581 =================
01582 */
01583 sfxHandle_t Menu_DefaultKey( menuframework_s *m, int key )
01584 {
01585     sfxHandle_t     sound = 0;
01586     menucommon_s    *item;
01587     int             cursor_prev;
01588 
01589     // menu system keys
01590     switch ( key )
01591     {
01592         case K_MOUSE2:
01593         case K_ESCAPE:
01594             UI_PopMenu();
01595             return menu_out_sound;
01596     }
01597 
01598     if (!m || !m->nitems)
01599         return 0;
01600 
01601     // route key stimulus to widget
01602     item = Menu_ItemAtCursor( m );
01603     if (item && !(item->flags & (QMF_GRAYED|QMF_INACTIVE)))
01604     {
01605         switch (item->type)
01606         {
01607             case MTYPE_SPINCONTROL:
01608                 sound = SpinControl_Key( (menulist_s*)item, key );
01609                 break;
01610 
01611             case MTYPE_RADIOBUTTON:
01612                 sound = RadioButton_Key( (menuradiobutton_s*)item, key );
01613                 break;
01614 
01615             case MTYPE_SLIDER:
01616                 sound = Slider_Key( (menuslider_s*)item, key );
01617                 break;
01618 
01619             case MTYPE_SCROLLLIST:
01620                 sound = ScrollList_Key( (menulist_s*)item, key );
01621                 break;
01622 
01623             case MTYPE_FIELD:
01624                 sound = MenuField_Key( (menufield_s*)item, &key );
01625                 break;
01626         }
01627 
01628         if (sound) {
01629             // key was handled
01630             return sound;       
01631         }
01632     }
01633 
01634     // default handling
01635     switch ( key )
01636     {
01637 #ifndef NDEBUG
01638         case K_F11:
01639             uis.debug ^= 1;
01640             break;
01641 
01642         case K_F12:
01643             trap_Cmd_ExecuteText(EXEC_APPEND, "screenshot\n");
01644             break;
01645 #endif
01646         case K_KP_UPARROW:
01647         case K_UPARROW:
01648             cursor_prev    = m->cursor;
01649             m->cursor_prev = m->cursor;
01650             m->cursor--;
01651             Menu_AdjustCursor( m, -1 );
01652             if ( cursor_prev != m->cursor ) {
01653                 Menu_CursorMoved( m );
01654                 sound = menu_move_sound;
01655             }
01656             break;
01657 
01658         case K_TAB:
01659         case K_KP_DOWNARROW:
01660         case K_DOWNARROW:
01661             cursor_prev    = m->cursor;
01662             m->cursor_prev = m->cursor;
01663             m->cursor++;
01664             Menu_AdjustCursor( m, 1 );
01665             if ( cursor_prev != m->cursor ) {
01666                 Menu_CursorMoved( m );
01667                 sound = menu_move_sound;
01668             }
01669             break;
01670 
01671         case K_MOUSE1:
01672         case K_MOUSE3:
01673             if (item)
01674                 if ((item->flags & QMF_HASMOUSEFOCUS) && !(item->flags & (QMF_GRAYED|QMF_INACTIVE)))
01675                     return (Menu_ActivateItem( m, item ));
01676             break;
01677 
01678         case K_JOY1:
01679         case K_JOY2:
01680         case K_JOY3:
01681         case K_JOY4:
01682         case K_AUX1:
01683         case K_AUX2:
01684         case K_AUX3:
01685         case K_AUX4:
01686         case K_AUX5:
01687         case K_AUX6:
01688         case K_AUX7:
01689         case K_AUX8:
01690         case K_AUX9:
01691         case K_AUX10:
01692         case K_AUX11:
01693         case K_AUX12:
01694         case K_AUX13:
01695         case K_AUX14:
01696         case K_AUX15:
01697         case K_AUX16:
01698         case K_KP_ENTER:
01699         case K_ENTER:
01700             if (item)
01701                 if (!(item->flags & (QMF_MOUSEONLY|QMF_GRAYED|QMF_INACTIVE)))
01702                     return (Menu_ActivateItem( m, item ));
01703             break;
01704     }
01705 
01706     return sound;
01707 }
01708 
01709 /*
01710 =================
01711 Menu_Cache
01712 =================
01713 */
01714 void Menu_Cache( void )
01715 {
01716     uis.charset         = trap_R_RegisterShaderNoMip( "gfx/2d/bigchars" );
01717     uis.charsetProp     = trap_R_RegisterShaderNoMip( "menu/art/font1_prop.tga" );
01718     uis.charsetPropGlow = trap_R_RegisterShaderNoMip( "menu/art/font1_prop_glo.tga" );
01719     uis.charsetPropB    = trap_R_RegisterShaderNoMip( "menu/art/font2_prop.tga" );
01720     uis.cursor          = trap_R_RegisterShaderNoMip( "menu/art/3_cursor2" );
01721     uis.rb_on           = trap_R_RegisterShaderNoMip( "menu/art/switch_on" );
01722     uis.rb_off          = trap_R_RegisterShaderNoMip( "menu/art/switch_off" );
01723 
01724     uis.whiteShader = trap_R_RegisterShaderNoMip( "white" );
01725     if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) {
01726         // the blend effect turns to shit with the normal 
01727         uis.menuBackShader  = trap_R_RegisterShaderNoMip( "menubackRagePro" );
01728     } else {
01729         uis.menuBackShader  = trap_R_RegisterShaderNoMip( "menuback" );
01730     }
01731     uis.menuBackNoLogoShader = trap_R_RegisterShaderNoMip( "menubacknologo" );
01732 
01733     menu_in_sound   = trap_S_RegisterSound( "sound/misc/menu1.wav", qfalse );
01734     menu_move_sound = trap_S_RegisterSound( "sound/misc/menu2.wav", qfalse );
01735     menu_out_sound  = trap_S_RegisterSound( "sound/misc/menu3.wav", qfalse );
01736     menu_buzz_sound = trap_S_RegisterSound( "sound/misc/menu4.wav", qfalse );
01737     weaponChangeSound   = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse );
01738 
01739     // need a nonzero sound, make an empty sound for this
01740     menu_null_sound = -1;
01741 
01742     sliderBar = trap_R_RegisterShaderNoMip( "menu/art/slider2" );
01743     sliderButton_0 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_0" );
01744     sliderButton_1 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_1" );
01745 }
01746     

Generated on Thu Aug 25 12:37:43 2005 for Quake III Arena by  doxygen 1.3.9.1