00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "ui_local.h"
00035
00036 uiInfo_t uiInfo;
00037
00038 static const char *MonthAbbrev[] = {
00039 "Jan","Feb","Mar",
00040 "Apr","May","Jun",
00041 "Jul","Aug","Sep",
00042 "Oct","Nov","Dec"
00043 };
00044
00045
00046 static const char *skillLevels[] = {
00047 "I Can Win",
00048 "Bring It On",
00049 "Hurt Me Plenty",
00050 "Hardcore",
00051 "Nightmare"
00052 };
00053
00054 static const int numSkillLevels = sizeof(skillLevels) / sizeof(const char*);
00055
00056
00057 static const char *netSources[] = {
00058 "Local",
00059 "Mplayer",
00060 "Internet",
00061 "Favorites"
00062 };
00063 static const int numNetSources = sizeof(netSources) / sizeof(const char*);
00064
00065 static const serverFilter_t serverFilters[] = {
00066 {"All", "" },
00067 {"Quake 3 Arena", "" },
00068 {"Team Arena", "missionpack" },
00069 {"Rocket Arena", "arena" },
00070 {"Alliance", "alliance20" },
00071 {"Weapons Factory Arena", "wfa" },
00072 {"OSP", "osp" },
00073 };
00074
00075 static const char *teamArenaGameTypes[] = {
00076 "FFA",
00077 "TOURNAMENT",
00078 "SP",
00079 "TEAM DM",
00080 "CTF",
00081 "1FCTF",
00082 "OVERLOAD",
00083 "HARVESTER",
00084 "TEAMTOURNAMENT"
00085 };
00086
00087 static int const numTeamArenaGameTypes = sizeof(teamArenaGameTypes) / sizeof(const char*);
00088
00089
00090 static const char *teamArenaGameNames[] = {
00091 "Free For All",
00092 "Tournament",
00093 "Single Player",
00094 "Team Deathmatch",
00095 "Capture the Flag",
00096 "One Flag CTF",
00097 "Overload",
00098 "Harvester",
00099 "Team Tournament",
00100 };
00101
00102 static int const numTeamArenaGameNames = sizeof(teamArenaGameNames) / sizeof(const char*);
00103
00104
00105 static const int numServerFilters = sizeof(serverFilters) / sizeof(serverFilter_t);
00106
00107 static const char *sortKeys[] = {
00108 "Server Name",
00109 "Map Name",
00110 "Open Player Spots",
00111 "Game Type",
00112 "Ping Time"
00113 };
00114 static const int numSortKeys = sizeof(sortKeys) / sizeof(const char*);
00115
00116 static char* netnames[] = {
00117 "???",
00118 "UDP",
00119 "IPX",
00120 NULL
00121 };
00122
00123 #ifndef MISSIONPACK // bk001206
00124 static char quake3worldMessage[] = "Visit www.quake3world.com - News, Community, Events, Files";
00125 #endif
00126
00127 static int gamecodetoui[] = {4,2,3,0,5,1,6};
00128 static int uitogamecode[] = {4,6,2,3,1,5,7};
00129
00130
00131 static void UI_StartServerRefresh(qboolean full);
00132 static void UI_StopServerRefresh( void );
00133 static void UI_DoServerRefresh( void );
00134 static void UI_FeederSelection(float feederID, int index);
00135 static void UI_BuildServerDisplayList(qboolean force);
00136 static void UI_BuildServerStatus(qboolean force);
00137 static void UI_BuildFindPlayerList(qboolean force);
00138 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 );
00139 static int UI_MapCountByGameType(qboolean singlePlayer);
00140 static int UI_HeadCountByTeam( void );
00141 static void UI_ParseGameInfo(const char *teamFile);
00142 static void UI_ParseTeamInfo(const char *teamFile);
00143 static const char *UI_SelectedMap(int index, int *actual);
00144 static const char *UI_SelectedHead(int index, int *actual);
00145 static int UI_GetIndexFromSelection(int actual);
00146
00147 int ProcessNewUI( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 );
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 vmCvar_t ui_new;
00158 vmCvar_t ui_debug;
00159 vmCvar_t ui_initialized;
00160 vmCvar_t ui_teamArenaFirstRun;
00161
00162 void _UI_Init( qboolean );
00163 void _UI_Shutdown( void );
00164 void _UI_KeyEvent( int key, qboolean down );
00165 void _UI_MouseEvent( int dx, int dy );
00166 void _UI_Refresh( int realtime );
00167 qboolean _UI_IsFullscreen( void );
00168 int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 ) {
00169 switch ( command ) {
00170 case UI_GETAPIVERSION:
00171 return UI_API_VERSION;
00172
00173 case UI_INIT:
00174 _UI_Init(arg0);
00175 return 0;
00176
00177 case UI_SHUTDOWN:
00178 _UI_Shutdown();
00179 return 0;
00180
00181 case UI_KEY_EVENT:
00182 _UI_KeyEvent( arg0, arg1 );
00183 return 0;
00184
00185 case UI_MOUSE_EVENT:
00186 _UI_MouseEvent( arg0, arg1 );
00187 return 0;
00188
00189 case UI_REFRESH:
00190 _UI_Refresh( arg0 );
00191 return 0;
00192
00193 case UI_IS_FULLSCREEN:
00194 return _UI_IsFullscreen();
00195
00196 case UI_SET_ACTIVE_MENU:
00197 _UI_SetActiveMenu( arg0 );
00198 return 0;
00199
00200 case UI_CONSOLE_COMMAND:
00201 return UI_ConsoleCommand(arg0);
00202
00203 case UI_DRAW_CONNECT_SCREEN:
00204 UI_DrawConnectScreen( arg0 );
00205 return 0;
00206 case UI_HASUNIQUECDKEY:
00207 return qtrue;
00208
00209 }
00210
00211 return -1;
00212 }
00213
00214
00215
00216 void AssetCache() {
00217 int n;
00218
00219
00220
00221
00222 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR );
00223 uiInfo.uiDC.Assets.fxBasePic = trap_R_RegisterShaderNoMip( ART_FX_BASE );
00224 uiInfo.uiDC.Assets.fxPic[0] = trap_R_RegisterShaderNoMip( ART_FX_RED );
00225 uiInfo.uiDC.Assets.fxPic[1] = trap_R_RegisterShaderNoMip( ART_FX_YELLOW );
00226 uiInfo.uiDC.Assets.fxPic[2] = trap_R_RegisterShaderNoMip( ART_FX_GREEN );
00227 uiInfo.uiDC.Assets.fxPic[3] = trap_R_RegisterShaderNoMip( ART_FX_TEAL );
00228 uiInfo.uiDC.Assets.fxPic[4] = trap_R_RegisterShaderNoMip( ART_FX_BLUE );
00229 uiInfo.uiDC.Assets.fxPic[5] = trap_R_RegisterShaderNoMip( ART_FX_CYAN );
00230 uiInfo.uiDC.Assets.fxPic[6] = trap_R_RegisterShaderNoMip( ART_FX_WHITE );
00231 uiInfo.uiDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
00232 uiInfo.uiDC.Assets.scrollBarArrowDown = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
00233 uiInfo.uiDC.Assets.scrollBarArrowUp = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP );
00234 uiInfo.uiDC.Assets.scrollBarArrowLeft = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT );
00235 uiInfo.uiDC.Assets.scrollBarArrowRight = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT );
00236 uiInfo.uiDC.Assets.scrollBarThumb = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
00237 uiInfo.uiDC.Assets.sliderBar = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
00238 uiInfo.uiDC.Assets.sliderThumb = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
00239
00240 for( n = 0; n < NUM_CROSSHAIRS; n++ ) {
00241 uiInfo.uiDC.Assets.crosshairShader[n] = trap_R_RegisterShaderNoMip( va("gfx/2d/crosshair%c", 'a' + n ) );
00242 }
00243
00244 uiInfo.newHighScoreSound = trap_S_RegisterSound("sound/feedback/voc_newhighscore.wav", qfalse);
00245 }
00246
00247 void _UI_DrawSides(float x, float y, float w, float h, float size) {
00248 UI_AdjustFrom640( &x, &y, &w, &h );
00249 size *= uiInfo.uiDC.xscale;
00250 trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00251 trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00252 }
00253
00254 void _UI_DrawTopBottom(float x, float y, float w, float h, float size) {
00255 UI_AdjustFrom640( &x, &y, &w, &h );
00256 size *= uiInfo.uiDC.yscale;
00257 trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00258 trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 void _UI_DrawRect( float x, float y, float width, float height, float size, const float *color ) {
00268 trap_R_SetColor( color );
00269
00270 _UI_DrawTopBottom(x, y, width, height, size);
00271 _UI_DrawSides(x, y, width, height, size);
00272
00273 trap_R_SetColor( NULL );
00274 }
00275
00276 int Text_Width(const char *text, float scale, int limit) {
00277 int count,len;
00278 float out;
00279 glyphInfo_t *glyph;
00280 float useScale;
00281 const char *s = text;
00282 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00283 if (scale <= ui_smallFont.value) {
00284 font = &uiInfo.uiDC.Assets.smallFont;
00285 } else if (scale >= ui_bigFont.value) {
00286 font = &uiInfo.uiDC.Assets.bigFont;
00287 }
00288 useScale = scale * font->glyphScale;
00289 out = 0;
00290 if (text) {
00291 len = strlen(text);
00292 if (limit > 0 && len > limit) {
00293 len = limit;
00294 }
00295 count = 0;
00296 while (s && *s && count < len) {
00297 if ( Q_IsColorString(s) ) {
00298 s += 2;
00299 continue;
00300 } else {
00301 glyph = &font->glyphs[(int)*s];
00302 out += glyph->xSkip;
00303 s++;
00304 count++;
00305 }
00306 }
00307 }
00308 return out * useScale;
00309 }
00310
00311 int Text_Height(const char *text, float scale, int limit) {
00312 int len, count;
00313 float max;
00314 glyphInfo_t *glyph;
00315 float useScale;
00316 const char *s = text;
00317 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00318 if (scale <= ui_smallFont.value) {
00319 font = &uiInfo.uiDC.Assets.smallFont;
00320 } else if (scale >= ui_bigFont.value) {
00321 font = &uiInfo.uiDC.Assets.bigFont;
00322 }
00323 useScale = scale * font->glyphScale;
00324 max = 0;
00325 if (text) {
00326 len = strlen(text);
00327 if (limit > 0 && len > limit) {
00328 len = limit;
00329 }
00330 count = 0;
00331 while (s && *s && count < len) {
00332 if ( Q_IsColorString(s) ) {
00333 s += 2;
00334 continue;
00335 } else {
00336 glyph = &font->glyphs[(int)*s];
00337 if (max < glyph->height) {
00338 max = glyph->height;
00339 }
00340 s++;
00341 count++;
00342 }
00343 }
00344 }
00345 return max * useScale;
00346 }
00347
00348 void Text_PaintChar(float x, float y, float width, float height, float scale, float s, float t, float s2, float t2, qhandle_t hShader) {
00349 float w, h;
00350 w = width * scale;
00351 h = height * scale;
00352 UI_AdjustFrom640( &x, &y, &w, &h );
00353 trap_R_DrawStretchPic( x, y, w, h, s, t, s2, t2, hShader );
00354 }
00355
00356 void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style) {
00357 int len, count;
00358 vec4_t newColor;
00359 glyphInfo_t *glyph;
00360 float useScale;
00361 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00362 if (scale <= ui_smallFont.value) {
00363 font = &uiInfo.uiDC.Assets.smallFont;
00364 } else if (scale >= ui_bigFont.value) {
00365 font = &uiInfo.uiDC.Assets.bigFont;
00366 }
00367 useScale = scale * font->glyphScale;
00368 if (text) {
00369 const char *s = text;
00370 trap_R_SetColor( color );
00371 memcpy(&newColor[0], &color[0], sizeof(vec4_t));
00372 len = strlen(text);
00373 if (limit > 0 && len > limit) {
00374 len = limit;
00375 }
00376 count = 0;
00377 while (s && *s && count < len) {
00378 glyph = &font->glyphs[(int)*s];
00379
00380
00381 if ( Q_IsColorString( s ) ) {
00382 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
00383 newColor[3] = color[3];
00384 trap_R_SetColor( newColor );
00385 s += 2;
00386 continue;
00387 } else {
00388 float yadj = useScale * glyph->top;
00389 if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {
00390 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
00391 colorBlack[3] = newColor[3];
00392 trap_R_SetColor( colorBlack );
00393 Text_PaintChar(x + ofs, y - yadj + ofs,
00394 glyph->imageWidth,
00395 glyph->imageHeight,
00396 useScale,
00397 glyph->s,
00398 glyph->t,
00399 glyph->s2,
00400 glyph->t2,
00401 glyph->glyph);
00402 trap_R_SetColor( newColor );
00403 colorBlack[3] = 1.0;
00404 }
00405 Text_PaintChar(x, y - yadj,
00406 glyph->imageWidth,
00407 glyph->imageHeight,
00408 useScale,
00409 glyph->s,
00410 glyph->t,
00411 glyph->s2,
00412 glyph->t2,
00413 glyph->glyph);
00414
00415 x += (glyph->xSkip * useScale) + adjust;
00416 s++;
00417 count++;
00418 }
00419 }
00420 trap_R_SetColor( NULL );
00421 }
00422 }
00423
00424 void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style) {
00425 int len, count;
00426 vec4_t newColor;
00427 glyphInfo_t *glyph, *glyph2;
00428 float yadj;
00429 float useScale;
00430 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00431 if (scale <= ui_smallFont.value) {
00432 font = &uiInfo.uiDC.Assets.smallFont;
00433 } else if (scale >= ui_bigFont.value) {
00434 font = &uiInfo.uiDC.Assets.bigFont;
00435 }
00436 useScale = scale * font->glyphScale;
00437 if (text) {
00438 const char *s = text;
00439 trap_R_SetColor( color );
00440 memcpy(&newColor[0], &color[0], sizeof(vec4_t));
00441 len = strlen(text);
00442 if (limit > 0 && len > limit) {
00443 len = limit;
00444 }
00445 count = 0;
00446 glyph2 = &font->glyphs[ (int) cursor];
00447 while (s && *s && count < len) {
00448 glyph = &font->glyphs[(int)*s];
00449
00450
00451 if ( Q_IsColorString( s ) ) {
00452 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
00453 newColor[3] = color[3];
00454 trap_R_SetColor( newColor );
00455 s += 2;
00456 continue;
00457 } else {
00458 yadj = useScale * glyph->top;
00459 if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {
00460 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
00461 colorBlack[3] = newColor[3];
00462 trap_R_SetColor( colorBlack );
00463 Text_PaintChar(x + ofs, y - yadj + ofs,
00464 glyph->imageWidth,
00465 glyph->imageHeight,
00466 useScale,
00467 glyph->s,
00468 glyph->t,
00469 glyph->s2,
00470 glyph->t2,
00471 glyph->glyph);
00472 colorBlack[3] = 1.0;
00473 trap_R_SetColor( newColor );
00474 }
00475 Text_PaintChar(x, y - yadj,
00476 glyph->imageWidth,
00477 glyph->imageHeight,
00478 useScale,
00479 glyph->s,
00480 glyph->t,
00481 glyph->s2,
00482 glyph->t2,
00483 glyph->glyph);
00484
00485 yadj = useScale * glyph2->top;
00486 if (count == cursorPos && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {
00487 Text_PaintChar(x, y - yadj,
00488 glyph2->imageWidth,
00489 glyph2->imageHeight,
00490 useScale,
00491 glyph2->s,
00492 glyph2->t,
00493 glyph2->s2,
00494 glyph2->t2,
00495 glyph2->glyph);
00496 }
00497
00498 x += (glyph->xSkip * useScale);
00499 s++;
00500 count++;
00501 }
00502 }
00503
00504 if (cursorPos == len && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {
00505 yadj = useScale * glyph2->top;
00506 Text_PaintChar(x, y - yadj,
00507 glyph2->imageWidth,
00508 glyph2->imageHeight,
00509 useScale,
00510 glyph2->s,
00511 glyph2->t,
00512 glyph2->s2,
00513 glyph2->t2,
00514 glyph2->glyph);
00515
00516 }
00517
00518 trap_R_SetColor( NULL );
00519 }
00520 }
00521
00522
00523 static void Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t color, const char* text, float adjust, int limit) {
00524 int len, count;
00525 vec4_t newColor;
00526 glyphInfo_t *glyph;
00527 if (text) {
00528 const char *s = text;
00529 float max = *maxX;
00530 float useScale;
00531 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00532 if (scale <= ui_smallFont.value) {
00533 font = &uiInfo.uiDC.Assets.smallFont;
00534 } else if (scale > ui_bigFont.value) {
00535 font = &uiInfo.uiDC.Assets.bigFont;
00536 }
00537 useScale = scale * font->glyphScale;
00538 trap_R_SetColor( color );
00539 len = strlen(text);
00540 if (limit > 0 && len > limit) {
00541 len = limit;
00542 }
00543 count = 0;
00544 while (s && *s && count < len) {
00545 glyph = &font->glyphs[(int)*s];
00546 if ( Q_IsColorString( s ) ) {
00547 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
00548 newColor[3] = color[3];
00549 trap_R_SetColor( newColor );
00550 s += 2;
00551 continue;
00552 } else {
00553 float yadj = useScale * glyph->top;
00554 if (Text_Width(s, useScale, 1) + x > max) {
00555 *maxX = 0;
00556 break;
00557 }
00558 Text_PaintChar(x, y - yadj,
00559 glyph->imageWidth,
00560 glyph->imageHeight,
00561 useScale,
00562 glyph->s,
00563 glyph->t,
00564 glyph->s2,
00565 glyph->t2,
00566 glyph->glyph);
00567 x += (glyph->xSkip * useScale) + adjust;
00568 *maxX = x;
00569 count++;
00570 s++;
00571 }
00572 }
00573 trap_R_SetColor( NULL );
00574 }
00575
00576 }
00577
00578
00579 void UI_ShowPostGame(qboolean newHigh) {
00580 trap_Cvar_Set ("cg_cameraOrbit", "0");
00581 trap_Cvar_Set("cg_thirdPerson", "0");
00582 trap_Cvar_Set( "sv_killserver", "1" );
00583 uiInfo.soundHighScore = newHigh;
00584 _UI_SetActiveMenu(UIMENU_POSTGAME);
00585 }
00586
00587
00588
00589
00590
00591
00592 void UI_DrawCenteredPic(qhandle_t image, int w, int h) {
00593 int x, y;
00594 x = (SCREEN_WIDTH - w) / 2;
00595 y = (SCREEN_HEIGHT - h) / 2;
00596 UI_DrawHandlePic(x, y, w, h, image);
00597 }
00598
00599 int frameCount = 0;
00600 int startTime;
00601
00602 #define UI_FPS_FRAMES 4
00603 void _UI_Refresh( int realtime )
00604 {
00605 static int index;
00606 static int previousTimes[UI_FPS_FRAMES];
00607
00608
00609
00610
00611
00612 uiInfo.uiDC.frameTime = realtime - uiInfo.uiDC.realTime;
00613 uiInfo.uiDC.realTime = realtime;
00614
00615 previousTimes[index % UI_FPS_FRAMES] = uiInfo.uiDC.frameTime;
00616 index++;
00617 if ( index > UI_FPS_FRAMES ) {
00618 int i, total;
00619
00620 total = 0;
00621 for ( i = 0 ; i < UI_FPS_FRAMES ; i++ ) {
00622 total += previousTimes[i];
00623 }
00624 if ( !total ) {
00625 total = 1;
00626 }
00627 uiInfo.uiDC.FPS = 1000 * UI_FPS_FRAMES / total;
00628 }
00629
00630
00631
00632 UI_UpdateCvars();
00633
00634 if (Menu_Count() > 0) {
00635
00636 Menu_PaintAll();
00637
00638 UI_DoServerRefresh();
00639
00640 UI_BuildServerStatus(qfalse);
00641
00642 UI_BuildFindPlayerList(qfalse);
00643 }
00644
00645
00646 UI_SetColor( NULL );
00647 if (Menu_Count() > 0) {
00648 UI_DrawHandlePic( uiInfo.uiDC.cursorx-16, uiInfo.uiDC.cursory-16, 32, 32, uiInfo.uiDC.Assets.cursor);
00649 }
00650
00651 #ifndef NDEBUG
00652 if (uiInfo.uiDC.debug)
00653 {
00654
00655
00656
00657 }
00658 #endif
00659
00660 }
00661
00662
00663
00664
00665
00666
00667 void _UI_Shutdown( void ) {
00668 trap_LAN_SaveCachedServers();
00669 }
00670
00671 char *defaultMenu = NULL;
00672
00673 char *GetMenuBuffer(const char *filename) {
00674 int len;
00675 fileHandle_t f;
00676 static char buf[MAX_MENUFILE];
00677
00678 len = trap_FS_FOpenFile( filename, &f, FS_READ );
00679 if ( !f ) {
00680 trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) );
00681 return defaultMenu;
00682 }
00683 if ( len >= MAX_MENUFILE ) {
00684 trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", filename, len, MAX_MENUFILE ) );
00685 trap_FS_FCloseFile( f );
00686 return defaultMenu;
00687 }
00688
00689 trap_FS_Read( buf, len, f );
00690 buf[len] = 0;
00691 trap_FS_FCloseFile( f );
00692
00693 return buf;
00694
00695 }
00696
00697 qboolean Asset_Parse(int handle) {
00698 pc_token_t token;
00699 const char *tempStr;
00700
00701 if (!trap_PC_ReadToken(handle, &token))
00702 return qfalse;
00703 if (Q_stricmp(token.string, "{") != 0) {
00704 return qfalse;
00705 }
00706
00707 while ( 1 ) {
00708
00709 memset(&token, 0, sizeof(pc_token_t));
00710
00711 if (!trap_PC_ReadToken(handle, &token))
00712 return qfalse;
00713
00714 if (Q_stricmp(token.string, "}") == 0) {
00715 return qtrue;
00716 }
00717
00718
00719 if (Q_stricmp(token.string, "font") == 0) {
00720 int pointSize;
00721 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {
00722 return qfalse;
00723 }
00724 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.textFont);
00725 uiInfo.uiDC.Assets.fontRegistered = qtrue;
00726 continue;
00727 }
00728
00729 if (Q_stricmp(token.string, "smallFont") == 0) {
00730 int pointSize;
00731 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {
00732 return qfalse;
00733 }
00734 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.smallFont);
00735 continue;
00736 }
00737
00738 if (Q_stricmp(token.string, "bigFont") == 0) {
00739 int pointSize;
00740 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {
00741 return qfalse;
00742 }
00743 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.bigFont);
00744 continue;
00745 }
00746
00747
00748
00749 if (Q_stricmp(token.string, "gradientbar") == 0) {
00750 if (!PC_String_Parse(handle, &tempStr)) {
00751 return qfalse;
00752 }
00753 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip(tempStr);
00754 continue;
00755 }
00756
00757
00758 if (Q_stricmp(token.string, "menuEnterSound") == 0) {
00759 if (!PC_String_Parse(handle, &tempStr)) {
00760 return qfalse;
00761 }
00762 uiInfo.uiDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr, qfalse );
00763 continue;
00764 }
00765
00766
00767 if (Q_stricmp(token.string, "menuExitSound") == 0) {
00768 if (!PC_String_Parse(handle, &tempStr)) {
00769 return qfalse;
00770 }
00771 uiInfo.uiDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr, qfalse );
00772 continue;
00773 }
00774
00775
00776 if (Q_stricmp(token.string, "itemFocusSound") == 0) {
00777 if (!PC_String_Parse(handle, &tempStr)) {
00778 return qfalse;
00779 }
00780 uiInfo.uiDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr, qfalse );
00781 continue;
00782 }
00783
00784
00785 if (Q_stricmp(token.string, "menuBuzzSound") == 0) {
00786 if (!PC_String_Parse(handle, &tempStr)) {
00787 return qfalse;
00788 }
00789 uiInfo.uiDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr, qfalse );
00790 continue;
00791 }
00792
00793 if (Q_stricmp(token.string, "cursor") == 0) {
00794 if (!PC_String_Parse(handle, &uiInfo.uiDC.Assets.cursorStr)) {
00795 return qfalse;
00796 }
00797 uiInfo.uiDC.Assets.cursor = trap_R_RegisterShaderNoMip( uiInfo.uiDC.Assets.cursorStr);
00798 continue;
00799 }
00800
00801 if (Q_stricmp(token.string, "fadeClamp") == 0) {
00802 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeClamp)) {
00803 return qfalse;
00804 }
00805 continue;
00806 }
00807
00808 if (Q_stricmp(token.string, "fadeCycle") == 0) {
00809 if (!PC_Int_Parse(handle, &uiInfo.uiDC.Assets.fadeCycle)) {
00810 return qfalse;
00811 }
00812 continue;
00813 }
00814
00815 if (Q_stricmp(token.string, "fadeAmount") == 0) {
00816 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeAmount)) {
00817 return qfalse;
00818 }
00819 continue;
00820 }
00821
00822 if (Q_stricmp(token.string, "shadowX") == 0) {
00823 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowX)) {
00824 return qfalse;
00825 }
00826 continue;
00827 }
00828
00829 if (Q_stricmp(token.string, "shadowY") == 0) {
00830 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowY)) {
00831 return qfalse;
00832 }
00833 continue;
00834 }
00835
00836 if (Q_stricmp(token.string, "shadowColor") == 0) {
00837 if (!PC_Color_Parse(handle, &uiInfo.uiDC.Assets.shadowColor)) {
00838 return qfalse;
00839 }
00840 uiInfo.uiDC.Assets.shadowFadeClamp = uiInfo.uiDC.Assets.shadowColor[3];
00841 continue;
00842 }
00843
00844 }
00845 return qfalse;
00846 }
00847
00848 void Font_Report() {
00849 int i;
00850 Com_Printf("Font Info\n");
00851 Com_Printf("=========\n");
00852 for ( i = 32; i < 96; i++) {
00853 Com_Printf("Glyph handle %i: %i\n", i, uiInfo.uiDC.Assets.textFont.glyphs[i].glyph);
00854 }
00855 }
00856
00857 void UI_Report() {
00858 String_Report();
00859
00860
00861 }
00862
00863 void UI_ParseMenu(const char *menuFile) {
00864 int handle;
00865 pc_token_t token;
00866
00867 Com_Printf("Parsing menu file:%s\n", menuFile);
00868
00869 handle = trap_PC_LoadSource(menuFile);
00870 if (!handle) {
00871 return;
00872 }
00873
00874 while ( 1 ) {
00875 memset(&token, 0, sizeof(pc_token_t));
00876 if (!trap_PC_ReadToken( handle, &token )) {
00877 break;
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 if ( token.string[0] == '}' ) {
00891 break;
00892 }
00893
00894 if (Q_stricmp(token.string, "assetGlobalDef") == 0) {
00895 if (Asset_Parse(handle)) {
00896 continue;
00897 } else {
00898 break;
00899 }
00900 }
00901
00902 if (Q_stricmp(token.string, "menudef") == 0) {
00903
00904 Menu_New(handle);
00905 }
00906 }
00907 trap_PC_FreeSource(handle);
00908 }
00909
00910 qboolean Load_Menu(int handle) {
00911 pc_token_t token;
00912
00913 if (!trap_PC_ReadToken(handle, &token))
00914 return qfalse;
00915 if (token.string[0] != '{') {
00916 return qfalse;
00917 }
00918
00919 while ( 1 ) {
00920
00921 if (!trap_PC_ReadToken(handle, &token))
00922 return qfalse;
00923
00924 if ( token.string[0] == 0 ) {
00925 return qfalse;
00926 }
00927
00928 if ( token.string[0] == '}' ) {
00929 return qtrue;
00930 }
00931
00932 UI_ParseMenu(token.string);
00933 }
00934 return qfalse;
00935 }
00936
00937 void UI_LoadMenus(const char *menuFile, qboolean reset) {
00938 pc_token_t token;
00939 int handle;
00940 int start;
00941
00942 start = trap_Milliseconds();
00943
00944 handle = trap_PC_LoadSource( menuFile );
00945 if (!handle) {
00946 trap_Error( va( S_COLOR_YELLOW "menu file not found: %s, using default\n", menuFile ) );
00947 handle = trap_PC_LoadSource( "ui/menus.txt" );
00948 if (!handle) {
00949 trap_Error( va( S_COLOR_RED "default menu file not found: ui/menus.txt, unable to continue!\n", menuFile ) );
00950 }
00951 }
00952
00953 ui_new.integer = 1;
00954
00955 if (reset) {
00956 Menu_Reset();
00957 }
00958
00959 while ( 1 ) {
00960 if (!trap_PC_ReadToken(handle, &token))
00961 break;
00962 if( token.string[0] == 0 || token.string[0] == '}') {
00963 break;
00964 }
00965
00966 if ( token.string[0] == '}' ) {
00967 break;
00968 }
00969
00970 if (Q_stricmp(token.string, "loadmenu") == 0) {
00971 if (Load_Menu(handle)) {
00972 continue;
00973 } else {
00974 break;
00975 }
00976 }
00977 }
00978
00979 Com_Printf("UI menu load time = %d milli seconds\n", trap_Milliseconds() - start);
00980
00981 trap_PC_FreeSource( handle );
00982 }
00983
00984 void UI_Load() {
00985 char lastName[1024];
00986 menuDef_t *menu = Menu_GetFocused();
00987 char *menuSet = UI_Cvar_VariableString("ui_menuFiles");
00988 if (menu && menu->window.name) {
00989 strcpy(lastName, menu->window.name);
00990 }
00991 if (menuSet == NULL || menuSet[0] == '\0') {
00992 menuSet = "ui/menus.txt";
00993 }
00994
00995 String_Init();
00996
00997 #ifdef PRE_RELEASE_TADEMO
00998 UI_ParseGameInfo("demogameinfo.txt");
00999 #else
01000 UI_ParseGameInfo("gameinfo.txt");
01001 UI_LoadArenas();
01002 #endif
01003
01004 UI_LoadMenus(menuSet, qtrue);
01005 Menus_CloseAll();
01006 Menus_ActivateByName(lastName);
01007
01008 }
01009
01010 static const char *handicapValues[] = {"None","95","90","85","80","75","70","65","60","55","50","45","40","35","30","25","20","15","10","5",NULL};
01011 #ifndef MISSIONPACK // bk001206
01012 static int numHandicaps = sizeof(handicapValues) / sizeof(const char*);
01013 #endif
01014
01015 static void UI_DrawHandicap(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01016 int i, h;
01017
01018 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );
01019 i = 20 - h / 5;
01020
01021 Text_Paint(rect->x, rect->y, scale, color, handicapValues[i], 0, 0, textStyle);
01022 }
01023
01024 static void UI_DrawClanName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01025 Text_Paint(rect->x, rect->y, scale, color, UI_Cvar_VariableString("ui_teamName"), 0, 0, textStyle);
01026 }
01027
01028
01029 static void UI_SetCapFragLimits(qboolean uiVars) {
01030 int cap = 5;
01031 int frag = 10;
01032 if (uiInfo.gameTypes[ui_gameType.integer].gtEnum == GT_OBELISK) {
01033 cap = 4;
01034 } else if (uiInfo.gameTypes[ui_gameType.integer].gtEnum == GT_HARVESTER) {
01035 cap = 15;
01036 }
01037 if (uiVars) {
01038 trap_Cvar_Set("ui_captureLimit", va("%d", cap));
01039 trap_Cvar_Set("ui_fragLimit", va("%d", frag));
01040 } else {
01041 trap_Cvar_Set("capturelimit", va("%d", cap));
01042 trap_Cvar_Set("fraglimit", va("%d", frag));
01043 }
01044 }
01045
01046 static void UI_DrawGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01047 Text_Paint(rect->x, rect->y, scale, color, uiInfo.gameTypes[ui_gameType.integer].gameType, 0, 0, textStyle);
01048 }
01049
01050 static void UI_DrawNetGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01051 if (ui_netGameType.integer < 0 || ui_netGameType.integer > uiInfo.numGameTypes) {
01052 trap_Cvar_Set("ui_netGameType", "0");
01053 trap_Cvar_Set("ui_actualNetGameType", "0");
01054 }
01055 Text_Paint(rect->x, rect->y, scale, color, uiInfo.