cg_drawtools.c (17669B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 // 23 // cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc 24 #include "cg_local.h" 25 26 /* 27 ================ 28 CG_AdjustFrom640 29 30 Adjusted for resolution and screen aspect ratio 31 ================ 32 */ 33 void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) { 34 #if 0 35 // adjust for wide screens 36 if ( cgs.glconfig.vidWidth * 480 > cgs.glconfig.vidHeight * 640 ) { 37 *x += 0.5 * ( cgs.glconfig.vidWidth - ( cgs.glconfig.vidHeight * 640 / 480 ) ); 38 } 39 #endif 40 // scale for screen sizes 41 *x *= cgs.screenXScale; 42 *y *= cgs.screenYScale; 43 *w *= cgs.screenXScale; 44 *h *= cgs.screenYScale; 45 } 46 47 /* 48 ================ 49 CG_FillRect 50 51 Coordinates are 640*480 virtual values 52 ================= 53 */ 54 void CG_FillRect( float x, float y, float width, float height, const float *color ) { 55 trap_R_SetColor( color ); 56 57 CG_AdjustFrom640( &x, &y, &width, &height ); 58 trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cgs.media.whiteShader ); 59 60 trap_R_SetColor( NULL ); 61 } 62 63 /* 64 ================ 65 CG_DrawSides 66 67 Coords are virtual 640x480 68 ================ 69 */ 70 void CG_DrawSides(float x, float y, float w, float h, float size) { 71 CG_AdjustFrom640( &x, &y, &w, &h ); 72 size *= cgs.screenXScale; 73 trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader ); 74 trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader ); 75 } 76 77 void CG_DrawTopBottom(float x, float y, float w, float h, float size) { 78 CG_AdjustFrom640( &x, &y, &w, &h ); 79 size *= cgs.screenYScale; 80 trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, cgs.media.whiteShader ); 81 trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, cgs.media.whiteShader ); 82 } 83 /* 84 ================ 85 UI_DrawRect 86 87 Coordinates are 640*480 virtual values 88 ================= 89 */ 90 void CG_DrawRect( float x, float y, float width, float height, float size, const float *color ) { 91 trap_R_SetColor( color ); 92 93 CG_DrawTopBottom(x, y, width, height, size); 94 CG_DrawSides(x, y, width, height, size); 95 96 trap_R_SetColor( NULL ); 97 } 98 99 100 101 /* 102 ================ 103 CG_DrawPic 104 105 Coordinates are 640*480 virtual values 106 ================= 107 */ 108 void CG_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) { 109 CG_AdjustFrom640( &x, &y, &width, &height ); 110 trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader ); 111 } 112 113 114 115 /* 116 =============== 117 CG_DrawChar 118 119 Coordinates and size in 640*480 virtual screen size 120 =============== 121 */ 122 void CG_DrawChar( int x, int y, int width, int height, int ch ) { 123 int row, col; 124 float frow, fcol; 125 float size; 126 float ax, ay, aw, ah; 127 128 ch &= 255; 129 130 if ( ch == ' ' ) { 131 return; 132 } 133 134 ax = x; 135 ay = y; 136 aw = width; 137 ah = height; 138 CG_AdjustFrom640( &ax, &ay, &aw, &ah ); 139 140 row = ch>>4; 141 col = ch&15; 142 143 frow = row*0.0625; 144 fcol = col*0.0625; 145 size = 0.0625; 146 147 trap_R_DrawStretchPic( ax, ay, aw, ah, 148 fcol, frow, 149 fcol + size, frow + size, 150 cgs.media.charsetShader ); 151 } 152 153 154 /* 155 ================== 156 CG_DrawStringExt 157 158 Draws a multi-colored string with a drop shadow, optionally forcing 159 to a fixed color. 160 161 Coordinates are at 640 by 480 virtual resolution 162 ================== 163 */ 164 void CG_DrawStringExt( int x, int y, const char *string, const float *setColor, 165 qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars ) { 166 vec4_t color; 167 const char *s; 168 int xx; 169 int cnt; 170 171 if (maxChars <= 0) 172 maxChars = 32767; // do them all! 173 174 // draw the drop shadow 175 if (shadow) { 176 color[0] = color[1] = color[2] = 0; 177 color[3] = setColor[3]; 178 trap_R_SetColor( color ); 179 s = string; 180 xx = x; 181 cnt = 0; 182 while ( *s && cnt < maxChars) { 183 if ( Q_IsColorString( s ) ) { 184 s += 2; 185 continue; 186 } 187 CG_DrawChar( xx + 2, y + 2, charWidth, charHeight, *s ); 188 cnt++; 189 xx += charWidth; 190 s++; 191 } 192 } 193 194 // draw the colored text 195 s = string; 196 xx = x; 197 cnt = 0; 198 trap_R_SetColor( setColor ); 199 while ( *s && cnt < maxChars) { 200 if ( Q_IsColorString( s ) ) { 201 if ( !forceColor ) { 202 memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) ); 203 color[3] = setColor[3]; 204 trap_R_SetColor( color ); 205 } 206 s += 2; 207 continue; 208 } 209 CG_DrawChar( xx, y, charWidth, charHeight, *s ); 210 xx += charWidth; 211 cnt++; 212 s++; 213 } 214 trap_R_SetColor( NULL ); 215 } 216 217 void CG_DrawBigString( int x, int y, const char *s, float alpha ) { 218 float color[4]; 219 220 color[0] = color[1] = color[2] = 1.0; 221 color[3] = alpha; 222 CG_DrawStringExt( x, y, s, color, qfalse, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 ); 223 } 224 225 void CG_DrawBigStringColor( int x, int y, const char *s, vec4_t color ) { 226 CG_DrawStringExt( x, y, s, color, qtrue, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 ); 227 } 228 229 void CG_DrawSmallString( int x, int y, const char *s, float alpha ) { 230 float color[4]; 231 232 color[0] = color[1] = color[2] = 1.0; 233 color[3] = alpha; 234 CG_DrawStringExt( x, y, s, color, qfalse, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 ); 235 } 236 237 void CG_DrawSmallStringColor( int x, int y, const char *s, vec4_t color ) { 238 CG_DrawStringExt( x, y, s, color, qtrue, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 ); 239 } 240 241 /* 242 ================= 243 CG_DrawStrlen 244 245 Returns character count, skiping color escape codes 246 ================= 247 */ 248 int CG_DrawStrlen( const char *str ) { 249 const char *s = str; 250 int count = 0; 251 252 while ( *s ) { 253 if ( Q_IsColorString( s ) ) { 254 s += 2; 255 } else { 256 count++; 257 s++; 258 } 259 } 260 261 return count; 262 } 263 264 /* 265 ============= 266 CG_TileClearBox 267 268 This repeats a 64*64 tile graphic to fill the screen around a sized down 269 refresh window. 270 ============= 271 */ 272 static void CG_TileClearBox( int x, int y, int w, int h, qhandle_t hShader ) { 273 float s1, t1, s2, t2; 274 275 s1 = x/64.0; 276 t1 = y/64.0; 277 s2 = (x+w)/64.0; 278 t2 = (y+h)/64.0; 279 trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, hShader ); 280 } 281 282 283 284 /* 285 ============== 286 CG_TileClear 287 288 Clear around a sized down screen 289 ============== 290 */ 291 void CG_TileClear( void ) { 292 int top, bottom, left, right; 293 int w, h; 294 295 w = cgs.glconfig.vidWidth; 296 h = cgs.glconfig.vidHeight; 297 298 if ( cg.refdef.x == 0 && cg.refdef.y == 0 && 299 cg.refdef.width == w && cg.refdef.height == h ) { 300 return; // full screen rendering 301 } 302 303 top = cg.refdef.y; 304 bottom = top + cg.refdef.height-1; 305 left = cg.refdef.x; 306 right = left + cg.refdef.width-1; 307 308 // clear above view screen 309 CG_TileClearBox( 0, 0, w, top, cgs.media.backTileShader ); 310 311 // clear below view screen 312 CG_TileClearBox( 0, bottom, w, h - bottom, cgs.media.backTileShader ); 313 314 // clear left of view screen 315 CG_TileClearBox( 0, top, left, bottom - top + 1, cgs.media.backTileShader ); 316 317 // clear right of view screen 318 CG_TileClearBox( right, top, w - right, bottom - top + 1, cgs.media.backTileShader ); 319 } 320 321 322 323 /* 324 ================ 325 CG_FadeColor 326 ================ 327 */ 328 float *CG_FadeColor( int startMsec, int totalMsec ) { 329 static vec4_t color; 330 int t; 331 332 if ( startMsec == 0 ) { 333 return NULL; 334 } 335 336 t = cg.time - startMsec; 337 338 if ( t >= totalMsec ) { 339 return NULL; 340 } 341 342 // fade out 343 if ( totalMsec - t < FADE_TIME ) { 344 color[3] = ( totalMsec - t ) * 1.0/FADE_TIME; 345 } else { 346 color[3] = 1.0; 347 } 348 color[0] = color[1] = color[2] = 1; 349 350 return color; 351 } 352 353 354 /* 355 ================ 356 CG_TeamColor 357 ================ 358 */ 359 float *CG_TeamColor( int team ) { 360 static vec4_t red = {1, 0.2f, 0.2f, 1}; 361 static vec4_t blue = {0.2f, 0.2f, 1, 1}; 362 static vec4_t other = {1, 1, 1, 1}; 363 static vec4_t spectator = {0.7f, 0.7f, 0.7f, 1}; 364 365 switch ( team ) { 366 case TEAM_RED: 367 return red; 368 case TEAM_BLUE: 369 return blue; 370 case TEAM_SPECTATOR: 371 return spectator; 372 default: 373 return other; 374 } 375 } 376 377 378 379 /* 380 ================= 381 CG_GetColorForHealth 382 ================= 383 */ 384 void CG_GetColorForHealth( int health, int armor, vec4_t hcolor ) { 385 int count; 386 int max; 387 388 // calculate the total points of damage that can 389 // be sustained at the current health / armor level 390 if ( health <= 0 ) { 391 VectorClear( hcolor ); // black 392 hcolor[3] = 1; 393 return; 394 } 395 count = armor; 396 max = health * ARMOR_PROTECTION / ( 1.0 - ARMOR_PROTECTION ); 397 if ( max < count ) { 398 count = max; 399 } 400 health += count; 401 402 // set the color based on health 403 hcolor[0] = 1.0; 404 hcolor[3] = 1.0; 405 if ( health >= 100 ) { 406 hcolor[2] = 1.0; 407 } else if ( health < 66 ) { 408 hcolor[2] = 0; 409 } else { 410 hcolor[2] = ( health - 66 ) / 33.0; 411 } 412 413 if ( health > 60 ) { 414 hcolor[1] = 1.0; 415 } else if ( health < 30 ) { 416 hcolor[1] = 0; 417 } else { 418 hcolor[1] = ( health - 30 ) / 30.0; 419 } 420 } 421 422 /* 423 ================= 424 CG_ColorForHealth 425 ================= 426 */ 427 void CG_ColorForHealth( vec4_t hcolor ) { 428 429 CG_GetColorForHealth( cg.snap->ps.stats[STAT_HEALTH], 430 cg.snap->ps.stats[STAT_ARMOR], hcolor ); 431 } 432 433 434 435 436 // bk001205 - code below duplicated in q3_ui/ui-atoms.c 437 // bk001205 - FIXME: does this belong in ui_shared.c? 438 // bk001205 - FIXME: HARD_LINKED flags not visible here 439 #ifndef Q3_STATIC // bk001205 - q_shared defines not visible here 440 /* 441 ================= 442 UI_DrawProportionalString2 443 ================= 444 */ 445 static int propMap[128][3] = { 446 {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, 447 {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, 448 449 {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, 450 {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, 451 452 {0, 0, PROP_SPACE_WIDTH}, // SPACE 453 {11, 122, 7}, // ! 454 {154, 181, 14}, // " 455 {55, 122, 17}, // # 456 {79, 122, 18}, // $ 457 {101, 122, 23}, // % 458 {153, 122, 18}, // & 459 {9, 93, 7}, // ' 460 {207, 122, 8}, // ( 461 {230, 122, 9}, // ) 462 {177, 122, 18}, // * 463 {30, 152, 18}, // + 464 {85, 181, 7}, // , 465 {34, 93, 11}, // - 466 {110, 181, 6}, // . 467 {130, 152, 14}, // / 468 469 {22, 64, 17}, // 0 470 {41, 64, 12}, // 1 471 {58, 64, 17}, // 2 472 {78, 64, 18}, // 3 473 {98, 64, 19}, // 4 474 {120, 64, 18}, // 5 475 {141, 64, 18}, // 6 476 {204, 64, 16}, // 7 477 {162, 64, 17}, // 8 478 {182, 64, 18}, // 9 479 {59, 181, 7}, // : 480 {35,181, 7}, // ; 481 {203, 152, 14}, // < 482 {56, 93, 14}, // = 483 {228, 152, 14}, // > 484 {177, 181, 18}, // ? 485 486 {28, 122, 22}, // @ 487 {5, 4, 18}, // A 488 {27, 4, 18}, // B 489 {48, 4, 18}, // C 490 {69, 4, 17}, // D 491 {90, 4, 13}, // E 492 {106, 4, 13}, // F 493 {121, 4, 18}, // G 494 {143, 4, 17}, // H 495 {164, 4, 8}, // I 496 {175, 4, 16}, // J 497 {195, 4, 18}, // K 498 {216, 4, 12}, // L 499 {230, 4, 23}, // M 500 {6, 34, 18}, // N 501 {27, 34, 18}, // O 502 503 {48, 34, 18}, // P 504 {68, 34, 18}, // Q 505 {90, 34, 17}, // R 506 {110, 34, 18}, // S 507 {130, 34, 14}, // T 508 {146, 34, 18}, // U 509 {166, 34, 19}, // V 510 {185, 34, 29}, // W 511 {215, 34, 18}, // X 512 {234, 34, 18}, // Y 513 {5, 64, 14}, // Z 514 {60, 152, 7}, // [ 515 {106, 151, 13}, // '\' 516 {83, 152, 7}, // ] 517 {128, 122, 17}, // ^ 518 {4, 152, 21}, // _ 519 520 {134, 181, 5}, // ' 521 {5, 4, 18}, // A 522 {27, 4, 18}, // B 523 {48, 4, 18}, // C 524 {69, 4, 17}, // D 525 {90, 4, 13}, // E 526 {106, 4, 13}, // F 527 {121, 4, 18}, // G 528 {143, 4, 17}, // H 529 {164, 4, 8}, // I 530 {175, 4, 16}, // J 531 {195, 4, 18}, // K 532 {216, 4, 12}, // L 533 {230, 4, 23}, // M 534 {6, 34, 18}, // N 535 {27, 34, 18}, // O 536 537 {48, 34, 18}, // P 538 {68, 34, 18}, // Q 539 {90, 34, 17}, // R 540 {110, 34, 18}, // S 541 {130, 34, 14}, // T 542 {146, 34, 18}, // U 543 {166, 34, 19}, // V 544 {185, 34, 29}, // W 545 {215, 34, 18}, // X 546 {234, 34, 18}, // Y 547 {5, 64, 14}, // Z 548 {153, 152, 13}, // { 549 {11, 181, 5}, // | 550 {180, 152, 13}, // } 551 {79, 93, 17}, // ~ 552 {0, 0, -1} // DEL 553 }; 554 555 static int propMapB[26][3] = { 556 {11, 12, 33}, 557 {49, 12, 31}, 558 {85, 12, 31}, 559 {120, 12, 30}, 560 {156, 12, 21}, 561 {183, 12, 21}, 562 {207, 12, 32}, 563 564 {13, 55, 30}, 565 {49, 55, 13}, 566 {66, 55, 29}, 567 {101, 55, 31}, 568 {135, 55, 21}, 569 {158, 55, 40}, 570 {204, 55, 32}, 571 572 {12, 97, 31}, 573 {48, 97, 31}, 574 {82, 97, 30}, 575 {118, 97, 30}, 576 {153, 97, 30}, 577 {185, 97, 25}, 578 {213, 97, 30}, 579 580 {11, 139, 32}, 581 {42, 139, 51}, 582 {93, 139, 32}, 583 {126, 139, 31}, 584 {158, 139, 25}, 585 }; 586 587 #define PROPB_GAP_WIDTH 4 588 #define PROPB_SPACE_WIDTH 12 589 #define PROPB_HEIGHT 36 590 591 /* 592 ================= 593 UI_DrawBannerString 594 ================= 595 */ 596 static void UI_DrawBannerString2( int x, int y, const char* str, vec4_t color ) 597 { 598 const char* s; 599 unsigned char ch; // bk001204 : array subscript 600 float ax; 601 float ay; 602 float aw; 603 float ah; 604 float frow; 605 float fcol; 606 float fwidth; 607 float fheight; 608 609 // draw the colored text 610 trap_R_SetColor( color ); 611 612 ax = x * cgs.screenXScale + cgs.screenXBias; 613 ay = y * cgs.screenXScale; 614 615 s = str; 616 while ( *s ) 617 { 618 ch = *s & 127; 619 if ( ch == ' ' ) { 620 ax += ((float)PROPB_SPACE_WIDTH + (float)PROPB_GAP_WIDTH)* cgs.screenXScale; 621 } 622 else if ( ch >= 'A' && ch <= 'Z' ) { 623 ch -= 'A'; 624 fcol = (float)propMapB[ch][0] / 256.0f; 625 frow = (float)propMapB[ch][1] / 256.0f; 626 fwidth = (float)propMapB[ch][2] / 256.0f; 627 fheight = (float)PROPB_HEIGHT / 256.0f; 628 aw = (float)propMapB[ch][2] * cgs.screenXScale; 629 ah = (float)PROPB_HEIGHT * cgs.screenXScale; 630 trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol+fwidth, frow+fheight, cgs.media.charsetPropB ); 631 ax += (aw + (float)PROPB_GAP_WIDTH * cgs.screenXScale); 632 } 633 s++; 634 } 635 636 trap_R_SetColor( NULL ); 637 } 638 639 void UI_DrawBannerString( int x, int y, const char* str, int style, vec4_t color ) { 640 const char * s; 641 int ch; 642 int width; 643 vec4_t drawcolor; 644 645 // find the width of the drawn text 646 s = str; 647 width = 0; 648 while ( *s ) { 649 ch = *s; 650 if ( ch == ' ' ) { 651 width += PROPB_SPACE_WIDTH; 652 } 653 else if ( ch >= 'A' && ch <= 'Z' ) { 654 width += propMapB[ch - 'A'][2] + PROPB_GAP_WIDTH; 655 } 656 s++; 657 } 658 width -= PROPB_GAP_WIDTH; 659 660 switch( style & UI_FORMATMASK ) { 661 case UI_CENTER: 662 x -= width / 2; 663 break; 664 665 case UI_RIGHT: 666 x -= width; 667 break; 668 669 case UI_LEFT: 670 default: 671 break; 672 } 673 674 if ( style & UI_DROPSHADOW ) { 675 drawcolor[0] = drawcolor[1] = drawcolor[2] = 0; 676 drawcolor[3] = color[3]; 677 UI_DrawBannerString2( x+2, y+2, str, drawcolor ); 678 } 679 680 UI_DrawBannerString2( x, y, str, color ); 681 } 682 683 684 int UI_ProportionalStringWidth( const char* str ) { 685 const char * s; 686 int ch; 687 int charWidth; 688 int width; 689 690 s = str; 691 width = 0; 692 while ( *s ) { 693 ch = *s & 127; 694 charWidth = propMap[ch][2]; 695 if ( charWidth != -1 ) { 696 width += charWidth; 697 width += PROP_GAP_WIDTH; 698 } 699 s++; 700 } 701 702 width -= PROP_GAP_WIDTH; 703 return width; 704 } 705 706 static void UI_DrawProportionalString2( int x, int y, const char* str, vec4_t color, float sizeScale, qhandle_t charset ) 707 { 708 const char* s; 709 unsigned char ch; // bk001204 - unsigned 710 float ax; 711 float ay; 712 float aw; 713 float ah; 714 float frow; 715 float fcol; 716 float fwidth; 717 float fheight; 718 719 // draw the colored text 720 trap_R_SetColor( color ); 721 722 ax = x * cgs.screenXScale + cgs.screenXBias; 723 ay = y * cgs.screenXScale; 724 725 s = str; 726 while ( *s ) 727 { 728 ch = *s & 127; 729 if ( ch == ' ' ) { 730 aw = (float)PROP_SPACE_WIDTH * cgs.screenXScale * sizeScale; 731 } else if ( propMap[ch][2] != -1 ) { 732 fcol = (float)propMap[ch][0] / 256.0f; 733 frow = (float)propMap[ch][1] / 256.0f; 734 fwidth = (float)propMap[ch][2] / 256.0f; 735 fheight = (float)PROP_HEIGHT / 256.0f; 736 aw = (float)propMap[ch][2] * cgs.screenXScale * sizeScale; 737 ah = (float)PROP_HEIGHT * cgs.screenXScale * sizeScale; 738 trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol+fwidth, frow+fheight, charset ); 739 } else { 740 aw = 0; 741 } 742 743 ax += (aw + (float)PROP_GAP_WIDTH * cgs.screenXScale * sizeScale); 744 s++; 745 } 746 747 trap_R_SetColor( NULL ); 748 } 749 750 /* 751 ================= 752 UI_ProportionalSizeScale 753 ================= 754 */ 755 float UI_ProportionalSizeScale( int style ) { 756 if( style & UI_SMALLFONT ) { 757 return 0.75; 758 } 759 760 return 1.00; 761 } 762 763 764 /* 765 ================= 766 UI_DrawProportionalString 767 ================= 768 */ 769 void UI_DrawProportionalString( int x, int y, const char* str, int style, vec4_t color ) { 770 vec4_t drawcolor; 771 int width; 772 float sizeScale; 773 774 sizeScale = UI_ProportionalSizeScale( style ); 775 776 switch( style & UI_FORMATMASK ) { 777 case UI_CENTER: 778 width = UI_ProportionalStringWidth( str ) * sizeScale; 779 x -= width / 2; 780 break; 781 782 case UI_RIGHT: 783 width = UI_ProportionalStringWidth( str ) * sizeScale; 784 x -= width; 785 break; 786 787 case UI_LEFT: 788 default: 789 break; 790 } 791 792 if ( style & UI_DROPSHADOW ) { 793 drawcolor[0] = drawcolor[1] = drawcolor[2] = 0; 794 drawcolor[3] = color[3]; 795 UI_DrawProportionalString2( x+2, y+2, str, drawcolor, sizeScale, cgs.media.charsetProp ); 796 } 797 798 if ( style & UI_INVERSE ) { 799 drawcolor[0] = color[0] * 0.8; 800 drawcolor[1] = color[1] * 0.8; 801 drawcolor[2] = color[2] * 0.8; 802 drawcolor[3] = color[3]; 803 UI_DrawProportionalString2( x, y, str, drawcolor, sizeScale, cgs.media.charsetProp ); 804 return; 805 } 806 807 if ( style & UI_PULSE ) { 808 drawcolor[0] = color[0] * 0.8; 809 drawcolor[1] = color[1] * 0.8; 810 drawcolor[2] = color[2] * 0.8; 811 drawcolor[3] = color[3]; 812 UI_DrawProportionalString2( x, y, str, color, sizeScale, cgs.media.charsetProp ); 813 814 drawcolor[0] = color[0]; 815 drawcolor[1] = color[1]; 816 drawcolor[2] = color[2]; 817 drawcolor[3] = 0.5 + 0.5 * sin( cg.time / PULSE_DIVISOR ); 818 UI_DrawProportionalString2( x, y, str, drawcolor, sizeScale, cgs.media.charsetPropGlow ); 819 return; 820 } 821 822 UI_DrawProportionalString2( x, y, str, color, sizeScale, cgs.media.charsetProp ); 823 } 824 #endif // Q3STATIC