home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2000 March / maximum-cd-2000-03.iso / Quake3 Game Source / Q3AGameSource.exe / Main / ui_atoms.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-18  |  23.3 KB  |  1,163 lines

  1. // Copyright (C) 1999-2000 Id Software, Inc.
  2. //
  3. /**********************************************************************
  4.     UI_ATOMS.C
  5.  
  6.     User interface building blocks and support functions.
  7. **********************************************************************/
  8. #include "ui_local.h"
  9.  
  10. uiStatic_t        uis;
  11. qboolean        m_entersound;        // after a frame, so caching won't disrupt the sound
  12.  
  13. // these are here so the functions in q_shared.c can link
  14. #ifndef UI_HARD_LINKED
  15.  
  16. void QDECL Com_Error( int level, const char *error, ... ) {
  17.     va_list        argptr;
  18.     char        text[1024];
  19.  
  20.     va_start (argptr, error);
  21.     vsprintf (text, error, argptr);
  22.     va_end (argptr);
  23.  
  24.     trap_Error( va("%s", text) );
  25. }
  26.  
  27. void QDECL Com_Printf( const char *msg, ... ) {
  28.     va_list        argptr;
  29.     char        text[1024];
  30.  
  31.     va_start (argptr, msg);
  32.     vsprintf (text, msg, argptr);
  33.     va_end (argptr);
  34.  
  35.     trap_Print( va("%s", text) );
  36. }
  37.  
  38. #endif
  39.  
  40. /*
  41. =================
  42. UI_ClampCvar
  43. =================
  44. */
  45. float UI_ClampCvar( float min, float max, float value )
  46. {
  47.     if ( value < min ) return min;
  48.     if ( value > max ) return max;
  49.     return value;
  50. }
  51.  
  52. /*
  53. =================
  54. UI_StartDemoLoop
  55. =================
  56. */
  57. void UI_StartDemoLoop( void ) {
  58.     trap_Cmd_ExecuteText( EXEC_APPEND, "d1\n" );
  59. }
  60.  
  61. /*
  62. =================
  63. UI_PushMenu
  64. =================
  65. */
  66. void UI_PushMenu( menuframework_s *menu )
  67. {
  68.     int                i;
  69.     menucommon_s*    item;
  70.  
  71.     // avoid stacking menus invoked by hotkeys
  72.     for (i=0 ; i<uis.menusp ; i++)
  73.     {
  74.         if (uis.stack[i] == menu)
  75.         {
  76.             uis.menusp = i;
  77.             break;
  78.         }
  79.     }
  80.  
  81.     if (i == uis.menusp)
  82.     {
  83.         if (uis.menusp >= MAX_MENUDEPTH)
  84.             trap_Error("UI_PushMenu: menu stack overflow");
  85.  
  86.         uis.stack[uis.menusp++] = menu;
  87.     }
  88.  
  89.     uis.activemenu = menu;
  90.  
  91.     // default cursor position
  92.     menu->cursor      = 0;
  93.     menu->cursor_prev = 0;
  94.  
  95.     m_entersound = qtrue;
  96.  
  97.     trap_Key_SetCatcher( KEYCATCH_UI );
  98.  
  99.     // force first available item to have focus
  100.     for (i=0; i<menu->nitems; i++)
  101.     {
  102.         item = (menucommon_s *)menu->items[i];
  103.         if (!(item->flags & (QMF_GRAYED|QMF_MOUSEONLY|QMF_INACTIVE)))
  104.         {
  105.             menu->cursor_prev = -1;
  106.             Menu_SetCursor( menu, i );
  107.             break;
  108.         }
  109.     }
  110.  
  111.     uis.firstdraw = qtrue;
  112. }
  113.  
  114. /*
  115. =================
  116. UI_PopMenu
  117. =================
  118. */
  119. void UI_PopMenu (void)
  120. {
  121.     trap_S_StartLocalSound( menu_out_sound, CHAN_LOCAL_SOUND );
  122.  
  123.     uis.menusp--;
  124.  
  125.     if (uis.menusp < 0)
  126.         trap_Error ("UI_PopMenu: menu stack underflow");
  127.  
  128.     if (uis.menusp) {
  129.         uis.activemenu = uis.stack[uis.menusp-1];
  130.         uis.firstdraw = qtrue;
  131.     }
  132.     else {
  133.         UI_ForceMenuOff ();
  134.     }
  135. }
  136.  
  137. void UI_ForceMenuOff (void)
  138. {
  139.     uis.menusp     = 0;
  140.     uis.activemenu = NULL;
  141.  
  142.     trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
  143.     trap_Key_ClearStates();
  144.     trap_Cvar_Set( "cl_paused", "0" );
  145. }
  146.  
  147. /*
  148. =================
  149. UI_LerpColor
  150. =================
  151. */
  152. void UI_LerpColor(vec4_t a, vec4_t b, vec4_t c, float t)
  153. {
  154.     int i;
  155.  
  156.     // lerp and clamp each component
  157.     for (i=0; i<4; i++)
  158.     {
  159.         c[i] = a[i] + t*(b[i]-a[i]);
  160.         if (c[i] < 0)
  161.             c[i] = 0;
  162.         else if (c[i] > 1.0)
  163.             c[i] = 1.0;
  164.     }
  165. }
  166.  
  167. /*
  168. =================
  169. UI_DrawProportionalString2
  170. =================
  171. */
  172. static int    propMap[128][3] = {
  173. {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
  174. {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
  175.  
  176. {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
  177. {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
  178.  
  179. {0, 0, PROP_SPACE_WIDTH},        // SPACE
  180. {11, 122, 7},    // !
  181. {154, 181, 14},    // "
  182. {55, 122, 17},    // #
  183. {79, 122, 18},    // $
  184. {101, 122, 23},    // %
  185. {153, 122, 18},    // &
  186. {9, 93, 7},        // '
  187. {207, 122, 8},    // (
  188. {230, 122, 9},    // )
  189. {177, 122, 18},    // *
  190. {30, 152, 18},    // +
  191. {85, 181, 7},    // ,
  192. {34, 93, 11},    // -
  193. {110, 181, 6},    // .
  194. {130, 152, 14},    // /
  195.  
  196. {22, 64, 17},    // 0
  197. {41, 64, 12},    // 1
  198. {58, 64, 17},    // 2
  199. {78, 64, 18},    // 3
  200. {98, 64, 19},    // 4
  201. {120, 64, 18},    // 5
  202. {141, 64, 18},    // 6
  203. {204, 64, 16},    // 7
  204. {162, 64, 17},    // 8
  205. {182, 64, 18},    // 9
  206. {59, 181, 7},    // :
  207. {35,181, 7},    // ;
  208. {203, 152, 14},    // <
  209. {56, 93, 14},    // =
  210. {228, 152, 14},    // >
  211. {177, 181, 18},    // ?
  212.  
  213. {28, 122, 22},    // @
  214. {5, 4, 18},        // A
  215. {27, 4, 18},    // B
  216. {48, 4, 18},    // C
  217. {69, 4, 17},    // D
  218. {90, 4, 13},    // E
  219. {106, 4, 13},    // F
  220. {121, 4, 18},    // G
  221. {143, 4, 17},    // H
  222. {164, 4, 8},    // I
  223. {175, 4, 16},    // J
  224. {195, 4, 18},    // K
  225. {216, 4, 12},    // L
  226. {230, 4, 23},    // M
  227. {6, 34, 18},    // N
  228. {27, 34, 18},    // O
  229.  
  230. {48, 34, 18},    // P
  231. {68, 34, 18},    // Q
  232. {90, 34, 17},    // R
  233. {110, 34, 18},    // S
  234. {130, 34, 14},    // T
  235. {146, 34, 18},    // U
  236. {166, 34, 19},    // V
  237. {185, 34, 29},    // W
  238. {215, 34, 18},    // X
  239. {234, 34, 18},    // Y
  240. {5, 64, 14},    // Z
  241. {60, 152, 7},    // [
  242. {106, 151, 13},    // '\'
  243. {83, 152, 7},    // ]
  244. {128, 122, 17},    // ^
  245. {4, 152, 21},    // _
  246.  
  247. {134, 181, 5},    // '
  248. {5, 4, 18},        // A
  249. {27, 4, 18},    // B
  250. {48, 4, 18},    // C
  251. {69, 4, 17},    // D
  252. {90, 4, 13},    // E
  253. {106, 4, 13},    // F
  254. {121, 4, 18},    // G
  255. {143, 4, 17},    // H
  256. {164, 4, 8},    // I
  257. {175, 4, 16},    // J
  258. {195, 4, 18},    // K
  259. {216, 4, 12},    // L
  260. {230, 4, 23},    // M
  261. {6, 34, 18},    // N
  262. {27, 34, 18},    // O
  263.  
  264. {48, 34, 18},    // P
  265. {68, 34, 18},    // Q
  266. {90, 34, 17},    // R
  267. {110, 34, 18},    // S
  268. {130, 34, 14},    // T
  269. {146, 34, 18},    // U
  270. {166, 34, 19},    // V
  271. {185, 34, 29},    // W
  272. {215, 34, 18},    // X
  273. {234, 34, 18},    // Y
  274. {5, 64, 14},    // Z
  275. {153, 152, 13},    // {
  276. {11, 181, 5},    // |
  277. {180, 152, 13},    // }
  278. {79, 93, 17},    // ~
  279. {0, 0, -1}        // DEL
  280. };
  281.  
  282. static int propMapB[26][3] = {
  283. {11, 12, 33},
  284. {49, 12, 31},
  285. {85, 12, 31},
  286. {120, 12, 30},
  287. {156, 12, 21},
  288. {183, 12, 21},
  289. {207, 12, 32},
  290.  
  291. {13, 55, 30},
  292. {49, 55, 13},
  293. {66, 55, 29},
  294. {101, 55, 31},
  295. {135, 55, 21},
  296. {158, 55, 40},
  297. {204, 55, 32},
  298.  
  299. {12, 97, 31},
  300. {48, 97, 31},
  301. {82, 97, 30},
  302. {118, 97, 30},
  303. {153, 97, 30},
  304. {185, 97, 25},
  305. {213, 97, 30},
  306.  
  307. {11, 139, 32},
  308. {42, 139, 51},
  309. {93, 139, 32},
  310. {126, 139, 31},
  311. {158, 139, 25},
  312. };
  313.  
  314. #define PROPB_GAP_WIDTH        4
  315. #define PROPB_SPACE_WIDTH    12
  316. #define PROPB_HEIGHT        36
  317.  
  318. /*
  319. =================
  320. UI_DrawBannerString
  321. =================
  322. */
  323. static void UI_DrawBannerString2( int x, int y, const char* str, vec4_t color )
  324. {
  325.     const char* s;
  326.     char    ch;
  327.     float    ax;
  328.     float    ay;
  329.     float    aw;
  330.     float    ah;
  331.     float    frow;
  332.     float    fcol;
  333.     float    fwidth;
  334.     float    fheight;
  335.  
  336.     // draw the colored text
  337.     trap_R_SetColor( color );
  338.     
  339.     ax = x * uis.scale + uis.bias;
  340.     ay = y * uis.scale;
  341.  
  342.     s = str;
  343.     while ( *s )
  344.     {
  345.         ch = *s & 127;
  346.         if ( ch == ' ' ) {
  347.             ax += ((float)PROPB_SPACE_WIDTH + (float)PROPB_GAP_WIDTH)* uis.scale;
  348.         }
  349.         else if ( ch >= 'A' && ch <= 'Z' ) {
  350.             ch -= 'A';
  351.             fcol = (float)propMapB[ch][0] / 256.0f;
  352.             frow = (float)propMapB[ch][1] / 256.0f;
  353.             fwidth = (float)propMapB[ch][2] / 256.0f;
  354.             fheight = (float)PROPB_HEIGHT / 256.0f;
  355.             aw = (float)propMapB[ch][2] * uis.scale;
  356.             ah = (float)PROPB_HEIGHT * uis.scale;
  357.             trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol+fwidth, frow+fheight, uis.charsetPropB );
  358.             ax += (aw + (float)PROPB_GAP_WIDTH * uis.scale);
  359.         }
  360.         s++;
  361.     }
  362.  
  363.     trap_R_SetColor( NULL );
  364. }
  365.  
  366. void UI_DrawBannerString( int x, int y, const char* str, int style, vec4_t color ) {
  367.     const char *    s;
  368.     int                ch;
  369.     int                width;
  370.     vec4_t            drawcolor;
  371.  
  372.     // find the width of the drawn text
  373.     s = str;
  374.     width = 0;
  375.     while ( *s ) {
  376.         ch = *s;
  377.         if ( ch == ' ' ) {
  378.             width += PROPB_SPACE_WIDTH;
  379.         }
  380.         else if ( ch >= 'A' && ch <= 'Z' ) {
  381.             width += propMapB[ch - 'A'][2] + PROPB_GAP_WIDTH;
  382.         }
  383.         s++;
  384.     }
  385.     width -= PROPB_GAP_WIDTH;
  386.  
  387.     switch( style & UI_FORMATMASK ) {
  388.         case UI_CENTER:
  389.             x -= width / 2;
  390.             break;
  391.  
  392.         case UI_RIGHT:
  393.             x -= width;
  394.             break;
  395.  
  396.         case UI_LEFT:
  397.         default:
  398.             break;
  399.     }
  400.  
  401.     if ( style & UI_DROPSHADOW ) {
  402.         drawcolor[0] = drawcolor[1] = drawcolor[2] = 0;
  403.         drawcolor[3] = color[3];
  404.         UI_DrawBannerString2( x+2, y+2, str, drawcolor );
  405.     }
  406.  
  407.     UI_DrawBannerString2( x, y, str, color );
  408. }
  409.  
  410.  
  411. int UI_ProportionalStringWidth( const char* str ) {
  412.     const char *    s;
  413.     int                ch;
  414.     int                charWidth;
  415.     int                width;
  416.  
  417.     s = str;
  418.     width = 0;
  419.     while ( *s ) {
  420.         ch = *s & 127;
  421.         charWidth = propMap[ch][2];
  422.         if ( charWidth != -1 ) {
  423.             width += charWidth;
  424.             width += PROP_GAP_WIDTH;
  425.         }
  426.         s++;
  427.     }
  428.  
  429.     width -= PROP_GAP_WIDTH;
  430.     return width;
  431. }
  432.  
  433. static void UI_DrawProportionalString2( int x, int y, const char* str, vec4_t color, float sizeScale, qhandle_t charset )
  434. {
  435.     const char* s;
  436.     char    ch;
  437.     float    ax;
  438.     float    ay;
  439.     float    aw;
  440.     float    ah;
  441.     float    frow;
  442.     float    fcol;
  443.     float    fwidth;
  444.     float    fheight;
  445.  
  446.     // draw the colored text
  447.     trap_R_SetColor( color );
  448.     
  449.     ax = x * uis.scale + uis.bias;
  450.     ay = y * uis.scale;
  451.  
  452.     s = str;
  453.     while ( *s )
  454.     {
  455.         ch = *s & 127;
  456.         if ( ch == ' ' ) {
  457.             aw = (float)PROP_SPACE_WIDTH * uis.scale * sizeScale;
  458.         }
  459.         else if ( propMap[ch][2] != -1 ) {
  460.             fcol = (float)propMap[ch][0] / 256.0f;
  461.             frow = (float)propMap[ch][1] / 256.0f;
  462.             fwidth = (float)propMap[ch][2] / 256.0f;
  463.             fheight = (float)PROP_HEIGHT / 256.0f;
  464.             aw = (float)propMap[ch][2] * uis.scale * sizeScale;
  465.             ah = (float)PROP_HEIGHT * uis.scale * sizeScale;
  466.             trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol+fwidth, frow+fheight, charset );
  467.         }
  468.  
  469.         ax += (aw + (float)PROP_GAP_WIDTH * uis.scale * sizeScale);
  470.         s++;
  471.     }
  472.  
  473.     trap_R_SetColor( NULL );
  474. }
  475.  
  476. /*
  477. =================
  478. UI_ProportionalSizeScale
  479. =================
  480. */
  481. float UI_ProportionalSizeScale( int style ) {
  482.     if(  style & UI_SMALLFONT ) {
  483.         return PROP_SMALL_SIZE_SCALE;
  484.     }
  485.  
  486.     return 1.00;
  487. }
  488.  
  489.  
  490. /*
  491. =================
  492. UI_DrawProportionalString
  493. =================
  494. */
  495. void UI_DrawProportionalString( int x, int y, const char* str, int style, vec4_t color ) {
  496.     vec4_t    drawcolor;
  497.     int        width;
  498.     float    sizeScale;
  499.  
  500.     sizeScale = UI_ProportionalSizeScale( style );
  501.  
  502.     switch( style & UI_FORMATMASK ) {
  503.         case UI_CENTER:
  504.             width = UI_ProportionalStringWidth( str ) * sizeScale;
  505.             x -= width / 2;
  506.             break;
  507.  
  508.         case UI_RIGHT:
  509.             width = UI_ProportionalStringWidth( str ) * sizeScale;
  510.             x -= width;
  511.             break;
  512.  
  513.         case UI_LEFT:
  514.         default:
  515.             break;
  516.     }
  517.  
  518.     if ( style & UI_DROPSHADOW ) {
  519.         drawcolor[0] = drawcolor[1] = drawcolor[2] = 0;
  520.         drawcolor[3] = color[3];
  521.         UI_DrawProportionalString2( x+2, y+2, str, drawcolor, sizeScale, uis.charsetProp );
  522.     }
  523.  
  524.     if ( style & UI_INVERSE ) {
  525.         drawcolor[0] = color[0] * 0.7;
  526.         drawcolor[1] = color[1] * 0.7;
  527.         drawcolor[2] = color[2] * 0.7;
  528.         drawcolor[3] = color[3];
  529.         UI_DrawProportionalString2( x, y, str, drawcolor, sizeScale, uis.charsetProp );
  530.         return;
  531.     }
  532.  
  533.     if ( style & UI_PULSE ) {
  534.         drawcolor[0] = color[0] * 0.7;
  535.         drawcolor[1] = color[1] * 0.7;
  536.         drawcolor[2] = color[2] * 0.7;
  537.         drawcolor[3] = color[3];
  538.         UI_DrawProportionalString2( x, y, str, color, sizeScale, uis.charsetProp );
  539.  
  540.         drawcolor[0] = color[0];
  541.         drawcolor[1] = color[1];
  542.         drawcolor[2] = color[2];
  543.         drawcolor[3] = 0.5 + 0.5 * sin( uis.realtime / PULSE_DIVISOR );
  544.         UI_DrawProportionalString2( x, y, str, drawcolor, sizeScale, uis.charsetPropGlow );
  545.         return;
  546.     }
  547.  
  548.     UI_DrawProportionalString2( x, y, str, color, sizeScale, uis.charsetProp );
  549. }
  550.  
  551. /*
  552. =================
  553. UI_DrawString2
  554. =================
  555. */
  556. static void UI_DrawString2( int x, int y, const char* str, vec4_t color, int charw, int charh )
  557. {
  558.     const char* s;
  559.     char    ch;
  560.     int forceColor = 1; //APSFIXME;
  561.     vec4_t    tempcolor;
  562.     float    ax;
  563.     float    ay;
  564.     float    aw;
  565.     float    ah;
  566.     float    frow;
  567.     float    fcol;
  568.  
  569.     if (y < -charh)
  570.         // offscreen
  571.         return;
  572.  
  573.     // draw the colored text
  574.     trap_R_SetColor( color );
  575.     
  576.     ax = x * uis.scale + uis.bias;
  577.     ay = y * uis.scale;
  578.     aw = charw * uis.scale;
  579.     ah = charh * uis.scale;
  580.  
  581.     s = str;
  582.     while ( *s )
  583.     {
  584.         if ( Q_IsColorString( s ) )
  585.         {
  586.             if ( !forceColor )
  587.             {
  588.                 memcpy( tempcolor, g_color_table[ColorIndex(s[1])], sizeof( tempcolor ) );
  589.                 tempcolor[3] = color[3];
  590.                 trap_R_SetColor( tempcolor );
  591.             }
  592.             s += 2;
  593.             continue;
  594.         }
  595.  
  596.         ch = *s & 255;
  597.         if (ch != ' ')
  598.         {
  599.             frow = (ch>>4)*0.0625;
  600.             fcol = (ch&15)*0.0625;
  601.             trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol + 0.0625, frow + 0.0625, uis.charset );
  602.         }
  603.  
  604.         ax += aw;
  605.         s++;
  606.     }
  607.  
  608.     trap_R_SetColor( NULL );
  609. }
  610.  
  611. /*
  612. =================
  613. UI_DrawString
  614. =================
  615. */
  616. void UI_DrawString( int x, int y, const char* str, int style, vec4_t color )
  617. {
  618.     int        len;
  619.     int        charw;
  620.     int        charh;
  621.     vec4_t    newcolor;
  622.     vec4_t    lowlight;
  623.     float    *drawcolor;
  624.     vec4_t    dropcolor;
  625.  
  626.     if( !str ) {
  627.         return;
  628.     }
  629.  
  630.     if ((style & UI_BLINK) && ((uis.realtime/BLINK_DIVISOR) & 1))
  631.         return;
  632.  
  633.     if (style & UI_SMALLFONT)
  634.     {
  635.         charw =    SMALLCHAR_WIDTH;
  636.         charh =    SMALLCHAR_HEIGHT;
  637.     }
  638.     else if (style & UI_GIANTFONT)
  639.     {
  640.         charw =    GIANTCHAR_WIDTH;
  641.         charh =    GIANTCHAR_HEIGHT;
  642.     }
  643.     else
  644.     {
  645.         charw =    BIGCHAR_WIDTH;
  646.         charh =    BIGCHAR_HEIGHT;
  647.     }
  648.  
  649.     if (style & UI_PULSE)
  650.     {
  651.         lowlight[0] = 0.8*color[0]; 
  652.         lowlight[1] = 0.8*color[1];
  653.         lowlight[2] = 0.8*color[2];
  654.         lowlight[3] = 0.8*color[3];
  655.         UI_LerpColor(color,lowlight,newcolor,0.5+0.5*sin(uis.realtime/PULSE_DIVISOR));
  656.         drawcolor = newcolor;
  657.     }    
  658.     else
  659.         drawcolor = color;
  660.  
  661.     switch (style & UI_FORMATMASK)
  662.     {
  663.         case UI_CENTER:
  664.             // center justify at x
  665.             len = strlen(str);
  666.             x   = x - len*charw/2;
  667.             break;
  668.  
  669.         case UI_RIGHT:
  670.             // right justify at x
  671.             len = strlen(str);
  672.             x   = x - len*charw;
  673.             break;
  674.  
  675.         default:
  676.             // left justify at x
  677.             break;
  678.     }
  679.  
  680.     if ( style & UI_DROPSHADOW )
  681.     {
  682.         dropcolor[0] = dropcolor[1] = dropcolor[2] = 0;
  683.         dropcolor[3] = drawcolor[3];
  684.         UI_DrawString2(x+2,y+2,str,dropcolor,charw,charh);
  685.     }
  686.  
  687.     UI_DrawString2(x,y,str,drawcolor,charw,charh);
  688. }
  689.  
  690. /*
  691. =================
  692. UI_DrawChar
  693. =================
  694. */
  695. void UI_DrawChar( int x, int y, int ch, int style, vec4_t color )
  696. {
  697.     char    buff[2];
  698.  
  699.     buff[0] = ch;
  700.     buff[1] = '\0';
  701.  
  702.     UI_DrawString( x, y, buff, style, color );
  703. }
  704.  
  705. qboolean UI_IsFullscreen( void ) {
  706.     if ( uis.activemenu && ( trap_Key_GetCatcher() & KEYCATCH_UI ) ) {
  707.         return uis.activemenu->fullscreen;
  708.     }
  709.  
  710.     return qfalse;
  711. }
  712.  
  713. static void NeedCDAction( qboolean result ) {
  714.     if ( !result ) {
  715.         trap_Cmd_ExecuteText( EXEC_APPEND, "quit\n" );
  716.     }
  717. }
  718.  
  719. static void NeedCDKeyAction( qboolean result ) {
  720.     if ( !result ) {
  721.         trap_Cmd_ExecuteText( EXEC_APPEND, "quit\n" );
  722.     }
  723. }
  724.  
  725.  
  726. void UI_SetActiveMenu( uiMenuCommand_t menu ) {
  727.     // this should be the ONLY way the menu system is brought up
  728.     // enusure minumum menu data is cached
  729.     Menu_Cache();
  730.  
  731.     switch ( menu ) {
  732.     case UIMENU_NONE:
  733.         UI_ForceMenuOff();
  734.         return;
  735.     case UIMENU_MAIN:
  736.         UI_MainMenu();
  737.         return;
  738.     case UIMENU_NEED_CD:
  739.         UI_ConfirmMenu( "Insert the CD", NULL, NeedCDAction );
  740.         return;
  741.     case UIMENU_BAD_CD_KEY:
  742.         UI_ConfirmMenu( "Bad CD Key", NULL, NeedCDKeyAction );
  743.         return;
  744.     case UIMENU_INGAME:
  745.         trap_Cvar_Set( "cl_paused", "1" );
  746.         UI_InGameMenu();
  747.         return;
  748.     }
  749. }
  750.  
  751. /*
  752. =================
  753. UI_KeyEvent
  754. =================
  755. */
  756. void UI_KeyEvent( int key ) {
  757.     sfxHandle_t        s;
  758.  
  759.     if (!uis.activemenu) {
  760.         return;
  761.     }
  762.  
  763.     if (uis.activemenu->key)
  764.         s = uis.activemenu->key( key );
  765.     else
  766.         s = Menu_DefaultKey( uis.activemenu, key );
  767.  
  768.     if ((s > 0) && (s != menu_null_sound))
  769.         trap_S_StartLocalSound( s, CHAN_LOCAL_SOUND );
  770. }
  771.  
  772. /*
  773. =================
  774. UI_MouseEvent
  775. =================
  776. */
  777. void UI_MouseEvent( int dx, int dy )
  778. {
  779.     int                i;
  780.     menucommon_s*    m;
  781.  
  782.     if (!uis.activemenu)
  783.         return;
  784.  
  785.     // update mouse screen position
  786.     uis.cursorx += dx;
  787.     if (uis.cursorx < 0)
  788.         uis.cursorx = 0;
  789.     else if (uis.cursorx > SCREEN_WIDTH)
  790.         uis.cursorx = SCREEN_WIDTH;
  791.  
  792.     uis.cursory += dy;
  793.     if (uis.cursory < 0)
  794.         uis.cursory = 0;
  795.     else if (uis.cursory > SCREEN_HEIGHT)
  796.         uis.cursory = SCREEN_HEIGHT;
  797.  
  798.     // region test the active menu items
  799.     for (i=0; i<uis.activemenu->nitems; i++)
  800.     {
  801.         m = (menucommon_s*)uis.activemenu->items[i];
  802.  
  803.         if (m->flags & (QMF_GRAYED|QMF_INACTIVE))
  804.             continue;
  805.  
  806.         if ((uis.cursorx < m->left) ||
  807.             (uis.cursorx > m->right) ||
  808.             (uis.cursory < m->top) ||
  809.             (uis.cursory > m->bottom))
  810.         {
  811.             // cursor out of item bounds
  812.             continue;
  813.         }
  814.  
  815.         // set focus to item at cursor
  816.         if (uis.activemenu->cursor != i)
  817.         {
  818.             Menu_SetCursor( uis.activemenu, i );
  819.             ((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor_prev]))->flags &= ~QMF_HASMOUSEFOCUS;
  820.  
  821.             if ( !(((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor]))->flags & QMF_SILENT ) ) {
  822.                 trap_S_StartLocalSound( menu_move_sound, CHAN_LOCAL_SOUND );
  823.             }
  824.         }
  825.  
  826.         ((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor]))->flags |= QMF_HASMOUSEFOCUS;
  827.         return;
  828.     }  
  829.  
  830.     if (uis.activemenu->nitems > 0) {
  831.         // out of any region
  832.         ((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor]))->flags &= ~QMF_HASMOUSEFOCUS;
  833.     }
  834. }
  835.  
  836. char *UI_Argv( int arg ) {
  837.     static char    buffer[MAX_STRING_CHARS];
  838.  
  839.     trap_Argv( arg, buffer, sizeof( buffer ) );
  840.  
  841.     return buffer;
  842. }
  843.  
  844.  
  845. char *UI_Cvar_VariableString( const char *var_name ) {
  846.     static char    buffer[MAX_STRING_CHARS];
  847.  
  848.     trap_Cvar_VariableStringBuffer( var_name, buffer, sizeof( buffer ) );
  849.  
  850.     return buffer;
  851. }
  852.  
  853.  
  854. /*
  855. =================
  856. UI_Cache
  857. =================
  858. */
  859. void UI_Cache_f( void ) {
  860.     MainMenu_Cache();
  861.     InGame_Cache();
  862.     ConfirmMenu_Cache();
  863.     PlayerModel_Cache();
  864.     PlayerSettings_Cache();
  865.     Controls_Cache();
  866.     Demos_Cache();
  867.     UI_CinematicsMenu_Cache();
  868.     Preferences_Cache();
  869.     ServerInfo_Cache();
  870.     SpecifyServer_Cache();
  871.     ArenaServers_Cache();
  872.     StartServer_Cache();
  873.     ServerOptions_Cache();
  874.     DriverInfo_Cache();
  875.     GraphicsOptions_Cache();
  876.     UI_DisplayOptionsMenu_Cache();
  877.     UI_SoundOptionsMenu_Cache();
  878.     UI_NetworkOptionsMenu_Cache();
  879.     UI_SPLevelMenu_Cache();
  880.     UI_SPSkillMenu_Cache();
  881.     UI_SPPostgameMenu_Cache();
  882.     TeamMain_Cache();
  883.     UI_AddBots_Cache();
  884.     UI_RemoveBots_Cache();
  885.     UI_SetupMenu_Cache();
  886.     UI_LoadConfig_Cache();
  887.     UI_SaveConfigMenu_Cache();
  888.     UI_BotSelectMenu_Cache();
  889.     UI_CDKeyMenu_Cache();
  890. }
  891.  
  892.  
  893. /*
  894. =================
  895. UI_ConsoleCommand
  896. =================
  897. */
  898. qboolean UI_ConsoleCommand( void ) {
  899.     char    *cmd;
  900.  
  901.     cmd = UI_Argv( 0 );
  902.  
  903.     // ensure minimum menu data is available
  904.     Menu_Cache();
  905.  
  906.     if ( Q_stricmp (cmd, "levelselect") == 0 ) {
  907.         UI_SPLevelMenu_f();
  908.         return qtrue;
  909.     }
  910.  
  911.     if ( Q_stricmp (cmd, "postgame") == 0 ) {
  912.         UI_SPPostgameMenu_f();
  913.         return qtrue;
  914.     }
  915.  
  916.     if ( Q_stricmp (cmd, "ui_cache") == 0 ) {
  917.         UI_Cache_f();
  918.         return qtrue;
  919.     }
  920.  
  921.     if ( Q_stricmp (cmd, "ui_cinematics") == 0 ) {
  922.         UI_CinematicsMenu_f();
  923.         return qtrue;
  924.     }
  925.  
  926.     if ( Q_stricmp (cmd, "ui_teamOrders") == 0 ) {
  927.         UI_TeamOrdersMenu_f();
  928.         return qtrue;
  929.     }
  930.  
  931.     if ( Q_stricmp (cmd, "iamacheater") == 0 ) {
  932.         UI_SPUnlock_f();
  933.         return qtrue;
  934.     }
  935.  
  936.     if ( Q_stricmp (cmd, "iamamonkey") == 0 ) {
  937.         UI_SPUnlockMedals_f();
  938.         return qtrue;
  939.     }
  940.  
  941.     if ( Q_stricmp (cmd, "ui_cdkey") == 0 ) {
  942.         UI_CDKeyMenu_f();
  943.         return qtrue;
  944.     }
  945.  
  946.     return qfalse;
  947. }
  948.  
  949. /*
  950. =================
  951. UI_Shutdown
  952. =================
  953. */
  954. void UI_Shutdown( void ) {
  955. }
  956.  
  957. /*
  958. =================
  959. UI_Init
  960. =================
  961. */
  962. void UI_Init( void ) {
  963.     UI_RegisterCvars();
  964.  
  965.     UI_InitGameinfo();
  966.  
  967.     // cache redundant calulations
  968.     trap_GetGlconfig( &uis.glconfig );
  969.  
  970.     // for 640x480 virtualized screen
  971.     uis.scale = uis.glconfig.vidHeight * (1.0/480.0);
  972.     if ( uis.glconfig.vidWidth * 480 > uis.glconfig.vidHeight * 640 ) {
  973.         // wide screen
  974.         uis.bias = 0.5 * ( uis.glconfig.vidWidth - ( uis.glconfig.vidHeight * (640.0/480.0) ) );
  975.     }
  976.     else {
  977.         // no wide screen
  978.         uis.bias = 0;
  979.     }
  980.  
  981.     // initialize the menu system
  982.     Menu_Cache();
  983.  
  984.     uis.activemenu = NULL;
  985.     uis.menusp     = 0;
  986. }
  987.  
  988. /*
  989. ================
  990. UI_AdjustFrom640
  991.  
  992. Adjusted for resolution and screen aspect ratio
  993. ================
  994. */
  995. void UI_AdjustFrom640( float *x, float *y, float *w, float *h ) {
  996.     // expect valid pointers
  997.     *x = *x * uis.scale + uis.bias;
  998.     *y *= uis.scale;
  999.     *w *= uis.scale;
  1000.     *h *= uis.scale;
  1001. }
  1002.  
  1003. void UI_DrawNamedPic( float x, float y, float width, float height, const char *picname ) {
  1004.     qhandle_t    hShader;
  1005.  
  1006.     hShader = trap_R_RegisterShaderNoMip( picname );
  1007.     UI_AdjustFrom640( &x, &y, &width, &height );
  1008.     trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
  1009. }
  1010.  
  1011. void UI_DrawHandlePic( float x, float y, float w, float h, qhandle_t hShader ) {
  1012.     float    s0;
  1013.     float    s1;
  1014.     float    t0;
  1015.     float    t1;
  1016.  
  1017.     if( w < 0 ) {    // flip about vertical
  1018.         w  = -w;
  1019.         s0 = 1;
  1020.         s1 = 0;
  1021.     }
  1022.     else {
  1023.         s0 = 0;
  1024.         s1 = 1;
  1025.     }
  1026.  
  1027.     if( h < 0 ) {    // flip about horizontal
  1028.         h  = -h;
  1029.         t0 = 1;
  1030.         t1 = 0;
  1031.     }
  1032.     else {
  1033.         t0 = 0;
  1034.         t1 = 1;
  1035.     }
  1036.     
  1037.     UI_AdjustFrom640( &x, &y, &w, &h );
  1038.     trap_R_DrawStretchPic( x, y, w, h, s0, t0, s1, t1, hShader );
  1039. }
  1040.  
  1041. /*
  1042. ================
  1043. UI_FillRect
  1044.  
  1045. Coordinates are 640*480 virtual values
  1046. =================
  1047. */
  1048. void UI_FillRect( float x, float y, float width, float height, const float *color ) {
  1049.     trap_R_SetColor( color );
  1050.  
  1051.     UI_AdjustFrom640( &x, &y, &width, &height );
  1052.     trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, uis.whiteShader );
  1053.  
  1054.     trap_R_SetColor( NULL );
  1055. }
  1056.  
  1057. /*
  1058. ================
  1059. UI_DrawRect
  1060.  
  1061. Coordinates are 640*480 virtual values
  1062. =================
  1063. */
  1064. void UI_DrawRect( float x, float y, float width, float height, const float *color ) {
  1065.     trap_R_SetColor( color );
  1066.  
  1067.     UI_AdjustFrom640( &x, &y, &width, &height );
  1068.  
  1069.     trap_R_DrawStretchPic( x, y, width, 1, 0, 0, 0, 0, uis.whiteShader );
  1070.     trap_R_DrawStretchPic( x, y, 1, height, 0, 0, 0, 0, uis.whiteShader );
  1071.     trap_R_DrawStretchPic( x, y + height - 1, width, 1, 0, 0, 0, 0, uis.whiteShader );
  1072.     trap_R_DrawStretchPic( x + width - 1, y, 1, height, 0, 0, 0, 0, uis.whiteShader );
  1073.  
  1074.     trap_R_SetColor( NULL );
  1075. }
  1076.  
  1077. void UI_SetColor( const float *rgba ) {
  1078.     trap_R_SetColor( rgba );
  1079. }
  1080.  
  1081. void UI_UpdateScreen( void ) {
  1082.     trap_UpdateScreen();
  1083. }
  1084.  
  1085. /*
  1086. =================
  1087. UI_Refresh
  1088. =================
  1089. */
  1090. void UI_Refresh( int realtime )
  1091. {
  1092.     uis.frametime = realtime - uis.realtime;
  1093.     uis.realtime  = realtime;
  1094.  
  1095.     if ( !( trap_Key_GetCatcher() & KEYCATCH_UI ) ) {
  1096.         return;
  1097.     }
  1098.  
  1099.     UI_UpdateCvars();
  1100.  
  1101.     if ( uis.activemenu )
  1102.     {
  1103.         if (uis.activemenu->fullscreen)
  1104.         {
  1105.             // draw the background
  1106.             if( uis.activemenu->showlogo ) {
  1107.                 UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackShader );
  1108.             }
  1109.             else {
  1110.                 UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, uis.menuBackNoLogoShader );
  1111.             }
  1112.         }
  1113.  
  1114.         if (uis.activemenu->draw)
  1115.             uis.activemenu->draw();
  1116.         else
  1117.             Menu_Draw( uis.activemenu );
  1118.  
  1119.         if( uis.firstdraw ) {
  1120.             UI_MouseEvent( 0, 0 );
  1121.             uis.firstdraw = qfalse;
  1122.         }
  1123.     }
  1124.  
  1125.     // draw cursor
  1126.     UI_SetColor( NULL );
  1127.     UI_DrawHandlePic( uis.cursorx-16, uis.cursory-16, 32, 32, uis.cursor);
  1128.  
  1129. #ifndef NDEBUG
  1130.     if (uis.debug)
  1131.     {
  1132.         // cursor coordinates
  1133.         UI_DrawString( 0, 0, va("(%d,%d)",uis.cursorx,uis.cursory), UI_LEFT|UI_SMALLFONT, colorRed );
  1134.     }
  1135. #endif
  1136.  
  1137.     // delay playing the enter sound until after the
  1138.     // menu has been drawn, to avoid delay while
  1139.     // caching images
  1140.     if (m_entersound)
  1141.     {
  1142.         trap_S_StartLocalSound( menu_in_sound, CHAN_LOCAL_SOUND );
  1143.         m_entersound = qfalse;
  1144.     }
  1145. }
  1146.  
  1147. void UI_DrawTextBox (int x, int y, int width, int lines)
  1148. {
  1149.     UI_FillRect( x + BIGCHAR_WIDTH/2, y + BIGCHAR_HEIGHT/2, ( width + 1 ) * BIGCHAR_WIDTH, ( lines + 1 ) * BIGCHAR_HEIGHT, colorBlack );
  1150.     UI_DrawRect( x + BIGCHAR_WIDTH/2, y + BIGCHAR_HEIGHT/2, ( width + 1 ) * BIGCHAR_WIDTH, ( lines + 1 ) * BIGCHAR_HEIGHT, colorWhite );
  1151. }
  1152.  
  1153. qboolean UI_CursorInRect (int x, int y, int width, int height)
  1154. {
  1155.     if (uis.cursorx < x ||
  1156.         uis.cursory < y ||
  1157.         uis.cursorx > x+width ||
  1158.         uis.cursory > y+height)
  1159.         return qfalse;
  1160.  
  1161.     return qtrue;
  1162. }
  1163.