codemp/cgame/cg_drawtools.c

Go to the documentation of this file.
00001 /*
00002 // this line must stay at top so the whole PCH thing works...
00003 #include "cg_headers.h"
00004 
00005 //#include "cg_local.h"
00006 #include "cg_media.h"
00007 #include "cg_text.h"
00008 */
00009 
00010 // Copyright (C) 1999-2000 Id Software, Inc.
00011 //
00012 // cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
00013 #include "cg_local.h"
00014 #include "../game/q_shared.h"
00015 
00016 
00017 /*
00018 ================
00019 UI_DrawRect
00020 
00021 Coordinates are 640*480 virtual values
00022 =================
00023 */
00024 void CG_DrawRect( float x, float y, float width, float height, float size, const float *color ) {
00025         trap_R_SetColor( color );
00026         
00027         CG_DrawTopBottom(x, y, width, height, size);
00028         CG_DrawSides(x, y, width, height, size);
00029         
00030         trap_R_SetColor( NULL );
00031 }
00032 
00033 
00034 
00035 /*
00036 =================
00037 CG_GetColorForHealth
00038 =================
00039 */
00040 void CG_GetColorForHealth( int health, int armor, vec4_t hcolor ) {
00041         int             count;
00042         int             max;
00043 
00044         // calculate the total points of damage that can
00045         // be sustained at the current health / armor level
00046         if ( health <= 0 ) {
00047                 VectorClear( hcolor );  // black
00048                 hcolor[3] = 1;
00049                 return;
00050         }
00051         count = armor;
00052         max = health * ARMOR_PROTECTION / ( 1.0 - ARMOR_PROTECTION );
00053         if ( max < count ) {
00054                 count = max;
00055         }
00056         health += count;
00057 
00058         // set the color based on health
00059         hcolor[0] = 1.0;
00060         hcolor[3] = 1.0;
00061         if ( health >= 100 ) {
00062                 hcolor[2] = 1.0;
00063         } else if ( health < 66 ) {
00064                 hcolor[2] = 0;
00065         } else {
00066                 hcolor[2] = ( health - 66 ) / 33.0;
00067         }
00068 
00069         if ( health > 60 ) {
00070                 hcolor[1] = 1.0;
00071         } else if ( health < 30 ) {
00072                 hcolor[1] = 0;
00073         } else {
00074                 hcolor[1] = ( health - 30 ) / 30.0;
00075         }
00076 }
00077 
00078 /*
00079 ================
00080 CG_DrawSides
00081 
00082 Coords are virtual 640x480
00083 ================
00084 */
00085 void CG_DrawSides(float x, float y, float w, float h, float size) {
00086         size *= cgs.screenXScale;
00087         trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader );
00088         trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader );
00089 }
00090 
00091 void CG_DrawTopBottom(float x, float y, float w, float h, float size) {
00092         size *= cgs.screenYScale;
00093         trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, cgs.media.whiteShader );
00094         trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, cgs.media.whiteShader );
00095 }
00096 
00097 /*
00098 -------------------------
00099 CGC_FillRect2
00100 real coords
00101 -------------------------
00102 */
00103 void CG_FillRect2( float x, float y, float width, float height, const float *color ) {
00104         trap_R_SetColor( color );
00105         trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cgs.media.whiteShader);
00106         trap_R_SetColor( NULL );
00107 }
00108 
00109 /*
00110 ================
00111 CG_FillRect
00112 
00113 Coordinates are 640*480 virtual values
00114 =================
00115 */
00116 void CG_FillRect( float x, float y, float width, float height, const float *color ) {
00117         trap_R_SetColor( color );
00118 
00119         trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cgs.media.whiteShader);
00120 
00121         trap_R_SetColor( NULL );
00122 }
00123 
00124 
00125 /*
00126 ================
00127 CG_DrawPic
00128 
00129 Coordinates are 640*480 virtual values
00130 A width of 0 will draw with the original image width
00131 =================
00132 */
00133 void CG_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) {
00134         trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
00135 }
00136 
00137 /*
00138 ================
00139 CG_DrawRotatePic
00140 
00141 Coordinates are 640*480 virtual values
00142 A width of 0 will draw with the original image width
00143 rotates around the upper right corner of the passed in point
00144 =================
00145 */
00146 void CG_DrawRotatePic( float x, float y, float width, float height,float angle, qhandle_t hShader ) {
00147         trap_R_DrawRotatePic( x, y, width, height, 0, 0, 1, 1, angle, hShader );
00148 }
00149 
00150 /*
00151 ================
00152 CG_DrawRotatePic2
00153 
00154 Coordinates are 640*480 virtual values
00155 A width of 0 will draw with the original image width
00156 Actually rotates around the center point of the passed in coordinates
00157 =================
00158 */
00159 void CG_DrawRotatePic2( float x, float y, float width, float height,float angle, qhandle_t hShader ) {
00160         trap_R_DrawRotatePic2( x, y, width, height, 0, 0, 1, 1, angle, hShader );
00161 }
00162 
00163 /*
00164 ===============
00165 CG_DrawChar
00166 
00167 Coordinates and size in 640*480 virtual screen size
00168 ===============
00169 */
00170 void CG_DrawChar( int x, int y, int width, int height, int ch ) {
00171         int row, col;
00172         float frow, fcol;
00173         float size;
00174         float   ax, ay, aw, ah;
00175         float size2;
00176 
00177         ch &= 255;
00178 
00179         if ( ch == ' ' ) {
00180                 return;
00181         }
00182 
00183         ax = x;
00184         ay = y;
00185         aw = width;
00186         ah = height;
00187 
00188         row = ch>>4;
00189         col = ch&15;
00190 
00191         frow = row*0.0625;
00192         fcol = col*0.0625;
00193         size = 0.03125;
00194         size2 = 0.0625;
00195 
00196         trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol + size, frow + size2, 
00197                 cgs.media.charsetShader );
00198 
00199 }
00200 
00201 /*
00202 ==================
00203 CG_DrawStringExt
00204 
00205 Draws a multi-colored string with a drop shadow, optionally forcing
00206 to a fixed color.
00207 
00208 Coordinates are at 640 by 480 virtual resolution
00209 ==================
00210 */
00211 #include "../../ui/menudef.h"   // for "ITEM_TEXTSTYLE_SHADOWED"
00212 void CG_DrawStringExt( int x, int y, const char *string, const float *setColor, 
00213                 qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars )
00214 {
00215         if (trap_Language_IsAsian())
00216         {
00217                 // hack-a-doodle-do (post-release quick fix code)...
00218                 //
00219                 vec4_t color;
00220                 memcpy(color,setColor, sizeof(color));  // de-const it
00221                 CG_Text_Paint(x, y, 1.0f,       // float scale, 
00222                                                 color,          // vec4_t color, 
00223                                                 string,         // const char *text, 
00224                                                 0.0f,           // float adjust, 
00225                                                 0,                      // int limit, 
00226                                                 shadow ? ITEM_TEXTSTYLE_SHADOWED : 0,   // int style, 
00227                                                 FONT_MEDIUM             // iMenuFont
00228                                                 ) ;
00229         }
00230         else
00231         {
00232                 vec4_t          color;
00233                 const char      *s;
00234                 int                     xx;
00235 
00236                 // draw the drop shadow
00237                 if (shadow) {
00238                         color[0] = color[1] = color[2] = 0;
00239                         color[3] = setColor[3];
00240                         trap_R_SetColor( color );
00241                         s = string;
00242                         xx = x;
00243                         while ( *s ) {
00244                                 if ( Q_IsColorString( s ) ) {
00245                                         s += 2;
00246                                         continue;
00247                                 }
00248                                 CG_DrawChar( xx + 2, y + 2, charWidth, charHeight, *s );
00249                                 xx += charWidth;
00250                                 s++;
00251                         }
00252                 }
00253 
00254                 // draw the colored text
00255                 s = string;
00256                 xx = x;
00257                 trap_R_SetColor( setColor );
00258                 while ( *s ) {
00259                         if ( Q_IsColorString( s ) ) {
00260                                 if ( !forceColor ) {
00261                                         memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
00262                                         color[3] = setColor[3];
00263                                         trap_R_SetColor( color );
00264                                 }
00265                                 s += 2;
00266                                 continue;
00267                         }
00268                         CG_DrawChar( xx, y, charWidth, charHeight, *s );
00269                         xx += charWidth;
00270                         s++;
00271                 }
00272                 trap_R_SetColor( NULL );
00273         }
00274 }
00275 
00276 void CG_DrawBigString( int x, int y, const char *s, float alpha ) {
00277         float   color[4];
00278 
00279         color[0] = color[1] = color[2] = 1.0;
00280         color[3] = alpha;
00281         CG_DrawStringExt( x, y, s, color, qfalse, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 );
00282 }
00283 
00284 void CG_DrawBigStringColor( int x, int y, const char *s, vec4_t color ) {
00285         CG_DrawStringExt( x, y, s, color, qtrue, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 );
00286 }
00287 
00288 void CG_DrawSmallString( int x, int y, const char *s, float alpha ) {
00289         float   color[4];
00290 
00291         color[0] = color[1] = color[2] = 1.0;
00292         color[3] = alpha;
00293         CG_DrawStringExt( x, y, s, color, qfalse, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
00294 }
00295 
00296 void CG_DrawSmallStringColor( int x, int y, const char *s, vec4_t color ) {
00297         CG_DrawStringExt( x, y, s, color, qtrue, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
00298 }
00299 
00300 /*
00301 =================
00302 CG_DrawStrlen
00303 
00304 Returns character count, skiping color escape codes
00305 =================
00306 */
00307 int CG_DrawStrlen( const char *str ) {
00308         const char *s = str;
00309         int count = 0;
00310 
00311         while ( *s ) {
00312                 if ( Q_IsColorString( s ) ) {
00313                         s += 2;
00314                 } else {
00315                         count++;
00316                         s++;
00317                 }
00318         }
00319 
00320         return count;
00321 }
00322 
00323 /*
00324 =============
00325 CG_TileClearBox
00326 
00327 This repeats a 64*64 tile graphic to fill the screen around a sized down
00328 refresh window.
00329 =============
00330 */
00331 static void CG_TileClearBox( int x, int y, int w, int h, qhandle_t hShader ) {
00332         float   s1, t1, s2, t2;
00333 
00334         s1 = x/64.0;
00335         t1 = y/64.0;
00336         s2 = (x+w)/64.0;
00337         t2 = (y+h)/64.0;
00338         trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, hShader );
00339 }
00340 
00341 
00342 
00343 /*
00344 ==============
00345 CG_TileClear
00346 
00347 Clear around a sized down screen
00348 ==============
00349 */
00350 void CG_TileClear( void ) {
00351         int             top, bottom, left, right;
00352         int             w, h;
00353 
00354         w = cgs.glconfig.vidWidth;
00355         h = cgs.glconfig.vidHeight;
00356 
00357         if ( cg.refdef.x == 0 && cg.refdef.y == 0 && 
00358                 cg.refdef.width == w && cg.refdef.height == h ) {
00359                 return;         // full screen rendering
00360         }
00361 
00362         top = cg.refdef.y;
00363         bottom = top + cg.refdef.height-1;
00364         left = cg.refdef.x;
00365         right = left + cg.refdef.width-1;
00366 
00367         // clear above view screen
00368         CG_TileClearBox( 0, 0, w, top, cgs.media.backTileShader );
00369 
00370         // clear below view screen
00371         CG_TileClearBox( 0, bottom, w, h - bottom, cgs.media.backTileShader );
00372 
00373         // clear left of view screen
00374         CG_TileClearBox( 0, top, left, bottom - top + 1, cgs.media.backTileShader );
00375 
00376         // clear right of view screen
00377         CG_TileClearBox( right, top, w - right, bottom - top + 1, cgs.media.backTileShader );
00378 }
00379 
00380 
00381 
00382 /*
00383 ================
00384 CG_FadeColor
00385 ================
00386 */
00387 float *CG_FadeColor( int startMsec, int totalMsec ) {
00388         static vec4_t           color;
00389         int                     t;
00390 
00391         if ( startMsec == 0 ) {
00392                 return NULL;
00393         }
00394 
00395         t = cg.time - startMsec;
00396 
00397         if ( t >= totalMsec ) {
00398                 return NULL;
00399         }
00400 
00401         // fade out
00402         if ( totalMsec - t < FADE_TIME ) {
00403                 color[3] = ( totalMsec - t ) * 1.0/FADE_TIME;
00404         } else {
00405                 color[3] = 1.0;
00406         }
00407         color[0] = color[1] = color[2] = 1;
00408 
00409         return color;
00410 }
00411 
00412 
00413 /*
00414 =================
00415 CG_ColorForHealth
00416 =================
00417 */
00418 void CG_ColorForGivenHealth( vec4_t hcolor, int health ) 
00419 {
00420         // set the color based on health
00421         hcolor[0] = 1.0;
00422         if ( health >= 100 ) 
00423         {
00424                 hcolor[2] = 1.0;
00425         } 
00426         else if ( health < 66 ) 
00427         {
00428                 hcolor[2] = 0;
00429         } 
00430         else 
00431         {
00432                 hcolor[2] = ( health - 66 ) / 33.0;
00433         }
00434 
00435         if ( health > 60 ) 
00436         {
00437                 hcolor[1] = 1.0;
00438         } 
00439         else if ( health < 30 ) 
00440         {
00441                 hcolor[1] = 0;
00442         } 
00443         else 
00444         {
00445                 hcolor[1] = ( health - 30 ) / 30.0;
00446         }
00447 }
00448 
00449 /*
00450 =================
00451 CG_ColorForHealth
00452 =================
00453 */
00454 void CG_ColorForHealth( vec4_t hcolor ) 
00455 {
00456         int             health;
00457         int             count;
00458         int             max;
00459 
00460         // calculate the total points of damage that can
00461         // be sustained at the current health / armor level
00462         health = cg.snap->ps.stats[STAT_HEALTH];
00463 
00464         if ( health <= 0 ) 
00465         {
00466                 VectorClear( hcolor );  // black
00467                 hcolor[3] = 1;
00468                 return;
00469         }
00470 
00471         count = cg.snap->ps.stats[STAT_ARMOR];
00472         max = health * ARMOR_PROTECTION / ( 1.0 - ARMOR_PROTECTION );
00473         if ( max < count ) 
00474         {
00475                 count = max;
00476         }
00477         health += count;
00478 
00479         hcolor[3] = 1.0;
00480         CG_ColorForGivenHealth( hcolor, health );
00481 }
00482 
00483 /*
00484 ==============
00485 CG_DrawNumField
00486 
00487 Take x,y positions as if 640 x 480 and scales them to the proper resolution
00488 
00489 ==============
00490 */
00491 void CG_DrawNumField (int x, int y, int width, int value,int charWidth,int charHeight,int style,qboolean zeroFill) 
00492 {
00493         char    num[16], *ptr;
00494         int             l;
00495         int             frame;
00496         int             xWidth;
00497         int             i = 0;
00498 
00499         if (width < 1) {
00500                 return;
00501         }
00502 
00503         // draw number string
00504         if (width > 5) {
00505                 width = 5;
00506         }
00507 
00508         switch ( width ) {
00509         case 1:
00510                 value = value > 9 ? 9 : value;
00511                 value = value < 0 ? 0 : value;
00512                 break;
00513         case 2:
00514                 value = value > 99 ? 99 : value;
00515                 value = value < -9 ? -9 : value;
00516                 break;
00517         case 3:
00518                 value = value > 999 ? 999 : value;
00519                 value = value < -99 ? -99 : value;
00520                 break;
00521         case 4:
00522                 value = value > 9999 ? 9999 : value;
00523                 value = value < -999 ? -999 : value;
00524                 break;
00525         }
00526 
00527         Com_sprintf (num, sizeof(num), "%i", value);
00528         l = strlen(num);
00529         if (l > width)
00530                 l = width;
00531 
00532         // FIXME: Might need to do something different for the chunky font??
00533         switch(style)
00534         {
00535         case NUM_FONT_SMALL:
00536                 xWidth = charWidth;
00537                 break;
00538         case NUM_FONT_CHUNKY:
00539                 xWidth = (charWidth/1.2f) + 2;
00540                 break;
00541         default:
00542         case NUM_FONT_BIG:
00543                 xWidth = (charWidth/2) + 7;//(charWidth/6);
00544                 break;
00545         }
00546 
00547         if ( zeroFill )
00548         {
00549                 for (i = 0; i < (width - l); i++ )
00550                 {
00551                         switch(style)
00552                         {
00553                         case NUM_FONT_SMALL:
00554                                 CG_DrawPic( x,y, charWidth, charHeight, cgs.media.smallnumberShaders[0] );
00555                                 break;
00556                         case NUM_FONT_CHUNKY:
00557                                 CG_DrawPic( x,y, charWidth, charHeight, cgs.media.chunkyNumberShaders[0] );
00558                                 break;
00559                         default:
00560                         case NUM_FONT_BIG:
00561                                 CG_DrawPic( x,y, charWidth, charHeight, cgs.media.numberShaders[0] );
00562                                 break;
00563                         }
00564                         x += 2 + (xWidth);
00565                 }
00566         }
00567         else
00568         {
00569                 x += 2 + (xWidth)*(width - l);
00570         }
00571 
00572         ptr = num;
00573         while (*ptr && l)
00574         {
00575                 if (*ptr == '-')
00576                         frame = STAT_MINUS;
00577                 else
00578                         frame = *ptr -'0';
00579 
00580                 switch(style)
00581                 {
00582                 case NUM_FONT_SMALL:
00583                         CG_DrawPic( x,y, charWidth, charHeight, cgs.media.smallnumberShaders[frame] );
00584                         x++;    // For a one line gap
00585                         break;
00586                 case NUM_FONT_CHUNKY:
00587                         CG_DrawPic( x,y, charWidth, charHeight, cgs.media.chunkyNumberShaders[frame] );
00588                         break;
00589                 default:
00590                 case NUM_FONT_BIG:
00591                         CG_DrawPic( x,y, charWidth, charHeight, cgs.media.numberShaders[frame] );
00592                         break;
00593                 }
00594 
00595                 x += (xWidth);
00596                 ptr++;
00597                 l--;
00598         }
00599 
00600 }
00601 
00602 #include "../ui/ui_shared.h"    // for some text style junk
00603 void UI_DrawProportionalString( int x, int y, const char* str, int style, vec4_t color ) 
00604 {
00605         // having all these different style defines (1 for UI, one for CG, and now one for the re->font stuff) 
00606         //      is dumb, but for now...
00607         //
00608         int iStyle = 0;
00609         int iMenuFont = (style & UI_SMALLFONT) ? FONT_SMALL : FONT_MEDIUM;
00610 
00611         switch (style & (UI_LEFT|UI_CENTER|UI_RIGHT))
00612         {
00613                 default:
00614                 case UI_LEFT:
00615                 {
00616                         // nada...
00617                 }
00618                 break;
00619 
00620                 case UI_CENTER:
00621                 {
00622                         x -= CG_Text_Width(str, 1.0, iMenuFont) / 2;
00623                 }
00624                 break;
00625 
00626                 case UI_RIGHT:
00627                 {
00628                         x -= CG_Text_Width(str, 1.0, iMenuFont) / 2;
00629                 }
00630                 break;
00631         }
00632 
00633         if (style & UI_DROPSHADOW)
00634         {
00635                 iStyle = ITEM_TEXTSTYLE_SHADOWED;
00636         }
00637         else
00638         if ( style & (UI_BLINK|UI_PULSE) )
00639         {
00640                 iStyle = ITEM_TEXTSTYLE_BLINK;
00641         }
00642 
00643         CG_Text_Paint(x, y, 1.0, color, str, 0, 0, iStyle, iMenuFont);
00644 }
00645 
00646 void UI_DrawScaledProportionalString( int x, int y, const char* str, int style, vec4_t color, float scale) 
00647 {
00648         // having all these different style defines (1 for UI, one for CG, and now one for the re->font stuff) 
00649         //      is dumb, but for now...
00650         //
00651         int iStyle = 0;
00652 
00653         switch (style & (UI_LEFT|UI_CENTER|UI_RIGHT))
00654         {
00655                 default:
00656                 case UI_LEFT:
00657                 {
00658                         // nada...
00659                 }
00660                 break;
00661 
00662                 case UI_CENTER:
00663                 {
00664                         x -= CG_Text_Width(str, scale, FONT_MEDIUM) / 2;
00665                 }
00666                 break;
00667 
00668                 case UI_RIGHT:
00669                 {
00670                         x -= CG_Text_Width(str, scale, FONT_MEDIUM) / 2;
00671                 }
00672                 break;
00673         }
00674 
00675         if (style & UI_DROPSHADOW)
00676         {
00677                 iStyle = ITEM_TEXTSTYLE_SHADOWED;
00678         }
00679         else
00680         if ( style & (UI_BLINK|UI_PULSE) )
00681         {
00682                 iStyle = ITEM_TEXTSTYLE_BLINK;
00683         }
00684 
00685         CG_Text_Paint(x, y, scale, color, str, 0, 0, iStyle, FONT_MEDIUM);
00686 }
00687 
00688 
00689 
00690