void R_Strobe_DrawDebugInfo( void ) { rgba_t color; int offsetY; int fixer; double curTime = Sys_DoubleTime( ); static double oldTime = 0; static int offsetX = 0; static char debugStr[2048] = {0}; if ( !r_strobe->integer ) return; if ( cls.state != ca_active ) return; if ( ( !r_strobe_debug->integer && !cl_showfps->integer ) || cl.background ) return; /* switch ( cls.scrshot_action ) { case scrshot_normal: case scrshot_snapshot: case scrshot_inactive: break; default: return; } */ if ( r_strobe_debug->integer ) { if ( ( curTime - oldTime > 0.100 ) ) { _generateDebugInfo( debugStr, sizeof( debugStr ) ); oldTime = curTime; } } else if ( cl_showfps->integer ) { Q_snprintf( debugStr, sizeof( debugStr ), "%3d eFPS", (int)round( _effectiveFPS( ) ) ); } MakeRGBA( color, 255, 255, 255, 255 ); Con_DrawStringLen( debugStr, &fixer, &offsetY ); if ( r_strobe_debug->integer ) Con_DrawString( scr_width->integer - offsetX - 50, 4, debugStr, color ); else Con_DrawString( scr_width->integer - offsetX - 2, offsetY + 8, debugStr, color ); if ( abs( fixer - offsetX ) > 50 || offsetX == 0 ) // 50 is for 1080p ! offsetX = fixer; }
/** * @sa Font_DrawString */ static void SCR_DrawString (int x, int y, const char *string) { if (Q_strnull(string)) return; Con_DrawString(string, x, y, strlen(string)); }
/* ============== SCR_NetSpeeds same as r_speeds but for network channel ============== */ void SCR_NetSpeeds( void ) { static char msg[MAX_SYSPATH]; int x, y, height; char *p, *start, *end; float time = cl.mtime[0]; rgba_t color; if( !net_speeds->integer ) return; if( cls.state != ca_active ) return; switch( net_speeds->integer ) { case 1: if( cls.netchan.compress ) { Q_snprintf( msg, sizeof( msg ), "Game Time: %02d:%02d\nTotal received from server:\n Huffman %s\nUncompressed %s\n", (int)(time / 60.0f ), (int)fmod( time, 60.0f ), Q_memprint( cls.netchan.total_received ), Q_memprint( cls.netchan.total_received_uncompressed )); } else { Q_snprintf( msg, sizeof( msg ), "Game Time: %02d:%02d\nTotal received from server:\nUncompressed %s\n", (int)(time / 60.0f ), (int)fmod( time, 60.0f ), Q_memprint( cls.netchan.total_received_uncompressed )); } break; case 2: if( cls.netchan.compress ) { Q_snprintf( msg, sizeof( msg ), "Game Time: %02d:%02d\nTotal sended to server:\nHuffman %s\nUncompressed %s\n", (int)(time / 60.0f ), (int)fmod( time, 60.0f ), Q_memprint( cls.netchan.total_sended ), Q_memprint( cls.netchan.total_sended_uncompressed )); } else { Q_snprintf( msg, sizeof( msg ), "Game Time: %02d:%02d\nTotal sended to server:\nUncompressed %s\n", (int)(time / 60.0f ), (int)fmod( time, 60.0f ), Q_memprint( cls.netchan.total_sended_uncompressed )); } break; default: return; } x = scr_width->integer - 320; y = 256; Con_DrawStringLen( NULL, NULL, &height ); MakeRGBA( color, 255, 255, 255, 255 ); p = start = msg; do { end = Q_strchr( p, '\n' ); if( end ) msg[end-start] = '\0'; Con_DrawString( x, y, p, color ); y += height; if( end ) p = end + 1; else break; } while( 1 ); }
/* ================ SCR_RSpeeds ================ */ void SCR_RSpeeds( void ) { char msg[MAX_SYSPATH]; if( R_SpeedsMessage( msg, sizeof( msg ))) { int x, y, height; char *p, *start, *end; rgba_t color; x = scr_width->integer - 320; y = 64; Con_DrawStringLen( NULL, NULL, &height ); MakeRGBA( color, 255, 255, 255, 255 ); p = start = msg; do { end = Q_strchr( p, '\n' ); if( end ) msg[end-start] = '\0'; Con_DrawString( x, y, p, color ); y += height; if( end ) p = end + 1; else break; } while( 1 ); } }
/* ============== SCR_DrawFPS ============== */ void SCR_DrawFPS( void ) { float calc; rgba_t color; static double nexttime = 0, lasttime = 0; static double framerate = 0; static int framecount = 0; static int minfps = 9999; static int maxfps = 0; double newtime; char fpsstring[64]; int offset; if( cls.state != ca_active ) return; if( !cl_showfps->integer || cl.background ) return; switch( cls.scrshot_action ) { case scrshot_normal: case scrshot_snapshot: case scrshot_inactive: break; default: return; } newtime = Sys_DoubleTime(); if( newtime >= nexttime ) { framerate = framecount / (newtime - lasttime); lasttime = newtime; nexttime = max( nexttime + 1, lasttime - 1 ); framecount = 0; } framecount++; calc = framerate; if( calc == 0 ) return; if( calc < 1.0f ) { Q_snprintf( fpsstring, sizeof( fpsstring ), "%4i spf", (int)(1.0f / calc + 0.5f)); MakeRGBA( color, 255, 0, 0, 255 ); } else { int curfps = (int)(calc + 0.5f); if( curfps < minfps ) minfps = curfps; if( curfps > maxfps ) maxfps = curfps; if( cl_showfps->integer == 2 ) Q_snprintf( fpsstring, sizeof( fpsstring ), "fps: ^1%4i min, ^3%4i cur, ^2%4i max", minfps, curfps, maxfps ); else Q_snprintf( fpsstring, sizeof( fpsstring ), "%4i fps", curfps ); MakeRGBA( color, 255, 255, 255, 255 ); } Con_DrawStringLen( fpsstring, &offset, NULL ); Con_DrawString( scr_width->integer - offset - 2, 4, fpsstring, color ); }
/* ============== SCR_DrawPos Draw local player position, angles and velocity ============== */ void SCR_DrawPos( void ) { static char msg[MAX_SYSPATH]; float speed; cl_entity_t *pPlayer; rgba_t color; if( cls.state != ca_active ) return; if( !cl_showpos->integer || cl.background ) return; pPlayer = CL_GetLocalPlayer(); speed = VectorLength( cl.frame.local.client.velocity ); Q_snprintf( msg, MAX_SYSPATH, "pos: %.2f %.2f %.2f\n" "ang: %.2f %.2f %.2f\n" "velocity: %.2f", pPlayer->origin[0], pPlayer->origin[1], pPlayer->origin[2], pPlayer->angles[0], pPlayer->angles[1], pPlayer->angles[2], speed ); MakeRGBA( color, 255, 255, 255, 255 ); Con_DrawString( scr_width->integer / 2, 4, msg, color ); }
/* ============== SCR_DrawFPS ============== */ void SCR_DrawFPS( void ) { float calc; rgba_t color; static double nexttime = 0, lasttime = 0; static double framerate = 0; static int framecount = 0; double newtime; char fpsstring[32]; if( cls.state != ca_active ) return; if( !cl_showfps->integer || cl.background ) return; if( cls.scrshot_action != scrshot_inactive ) return; newtime = Sys_DoubleTime(); if( newtime >= nexttime ) { framerate = framecount / (newtime - lasttime); lasttime = newtime; nexttime = max( nexttime + 1, lasttime - 1 ); framecount = 0; } framecount++; calc = framerate; if( calc < 1.0f ) { Q_snprintf( fpsstring, sizeof( fpsstring ), "%4i spf", (int)(1.0f / calc + 0.5)); MakeRGBA( color, 255, 0, 0, 255 ); } else { Q_snprintf( fpsstring, sizeof( fpsstring ), "%4i fps", (int)(calc + 0.5)); MakeRGBA( color, 255, 255, 255, 255 ); } Con_DrawString( scr_width->integer - 68, 4, fpsstring, color ); }
/* ================ SCR_ExecuteLayoutString ================ */ void SCR_ExecuteLayoutString (char *s) { int x, y; int value; char *token; int width; int index; clientinfo_t *ci; if (cls.state != ca_active || !cl.refresh_prepped) return; if (!s[0]) return; x = 0; y = 0; width = 3; while (s) { token = COM_Parse (&s); if (!strcmp(token, "xl")) { token = COM_Parse (&s); x = atoi(token); continue; } if (!strcmp(token, "xr")) { token = COM_Parse (&s); x = viddef.width + atoi(token); continue; } if (!strcmp(token, "xv")) { token = COM_Parse (&s); x = viddef.width/2 - 160 + atoi(token); continue; } if (!strcmp(token, "yt")) { token = COM_Parse (&s); y = atoi(token); continue; } if (!strcmp(token, "yb")) { token = COM_Parse (&s); y = viddef.height + atoi(token); continue; } if (!strcmp(token, "yv")) { token = COM_Parse (&s); y = viddef.height/2 - 120 + atoi(token); continue; } if (!strcmp(token, "pic")) { // draw a pic from a stat number token = COM_Parse (&s); value = cl.frame.playerstate.stats[atoi(token)]; if (value >= MAX_IMAGES) Com_Error (ERR_DROP, "Pic >= MAX_IMAGES"); if (cl.configstrings[CS_IMAGES+value]) { SCR_AddDirtyPoint (x, y); SCR_AddDirtyPoint (x+23, y+23); re.DrawPic (x, y, cl.configstrings[CS_IMAGES+value]); } continue; } if (!strcmp(token, "client")) { // draw a deathmatch client block int score, ping, time; token = COM_Parse (&s); x = viddef.width/2 - 160 + atoi(token); token = COM_Parse (&s); y = viddef.height/2 - 120 + atoi(token); SCR_AddDirtyPoint (x, y); SCR_AddDirtyPoint (x+159, y+31); token = COM_Parse (&s); value = atoi(token); if (value >= MAX_CLIENTS || value < 0) Com_Error (ERR_DROP, "client >= MAX_CLIENTS"); ci = &cl.clientinfo[value]; token = COM_Parse (&s); score = atoi(token); token = COM_Parse (&s); ping = atoi(token); token = COM_Parse (&s); time = atoi(token); DrawAltString (x+32, y, ci->name); #if defined (__APPLE__) || defined (MACOSX) Con_DrawString (x+32, y+8, "Score: "); #else DrawString (x+32, y+8, "Score: "); #endif /* __APPLE__ || MACOSX */ DrawAltString (x+32+7*8, y+8, va("%i", score)); #if defined (__APPLE__) || defined (MACOSX) Con_DrawString (x+32, y+16, va("Ping: %i", ping)); Con_DrawString (x+32, y+24, va("Time: %i", time)); #else DrawString (x+32, y+16, va("Ping: %i", ping)); DrawString (x+32, y+24, va("Time: %i", time)); #endif /* __APPLE__ || MACOSX */ if (!ci->icon) ci = &cl.baseclientinfo; re.DrawPic (x, y, ci->iconname); continue; } if (!strcmp(token, "ctf")) { // draw a ctf client block int score, ping; char block[80]; token = COM_Parse (&s); x = viddef.width/2 - 160 + atoi(token); token = COM_Parse (&s); y = viddef.height/2 - 120 + atoi(token); SCR_AddDirtyPoint (x, y); SCR_AddDirtyPoint (x+159, y+31); token = COM_Parse (&s); value = atoi(token); if (value >= MAX_CLIENTS || value < 0) Com_Error (ERR_DROP, "client >= MAX_CLIENTS"); ci = &cl.clientinfo[value]; token = COM_Parse (&s); score = atoi(token); token = COM_Parse (&s); ping = atoi(token); if (ping > 999) ping = 999; #if defined (__APPLE__) || defined (MACOSX) snprintf(block, 80, "%3d %3d %-12.12s", score, ping, ci->name); #else sprintf(block, "%3d %3d %-12.12s", score, ping, ci->name); #endif /* __APPLE__ || MACOSX */ if (value == cl.playernum) DrawAltString (x, y, block); else #if defined (__APPLE__) || defined (MACOSX) Con_DrawString (x, y, block); #else DrawString (x, y, block); #endif /* __APPLE__ ||ÊMACOSX */ continue; } if (!strcmp(token, "picn")) { // draw a pic from a name token = COM_Parse (&s); SCR_AddDirtyPoint (x, y); SCR_AddDirtyPoint (x+23, y+23); re.DrawPic (x, y, token); continue; } if (!strcmp(token, "num")) { // draw a number token = COM_Parse (&s); width = atoi(token); token = COM_Parse (&s); value = cl.frame.playerstate.stats[atoi(token)]; SCR_DrawField (x, y, 0, width, value); continue; } if (!strcmp(token, "hnum")) { // health number int color; width = 3; value = cl.frame.playerstate.stats[STAT_HEALTH]; if (value > 25) color = 0; // green else if (value > 0) color = (cl.frame.serverframe>>2) & 1; // flash else color = 1; if (cl.frame.playerstate.stats[STAT_FLASHES] & 1) re.DrawPic (x, y, "field_3"); SCR_DrawField (x, y, color, width, value); continue; }
/* =============== R_ShowTextures Draw all the images to the screen, on top of whatever was there. This is used to test for texture thrashing. =============== */ void R_ShowTextures( void ) { gltexture_t *image; float x, y, w, h; int i, j, k, base_w, base_h; int total, start, end; rgba_t color = { 192, 192, 192, 255 }; int charHeight, numTries = 0; static qboolean showHelp = true; string shortname; if( !gl_showtextures->integer ) return; if( showHelp ) { CL_CenterPrint( "use '<-' and '->' keys to view all the textures", 0.25f ); showHelp = false; } pglClear( GL_COLOR_BUFFER_BIT ); pglFinish(); base_w = 8; base_h = 6; rebuild_page: total = base_w * base_h; start = total * (gl_showtextures->integer - 1); end = total * gl_showtextures->integer; if( end > MAX_TEXTURES ) end = MAX_TEXTURES; w = glState.width / (float)base_w; h = glState.height / (float)base_h; Con_DrawStringLen( NULL, NULL, &charHeight ); for( i = j = 0; i < MAX_TEXTURES; i++ ) { image = R_GetTexture( i ); if( j == start ) break; // found start if( pglIsTexture( image->texnum )) j++; } if( i == MAX_TEXTURES && gl_showtextures->integer != 1 ) { // bad case, rewind to one and try again Cvar_SetFloat( "r_showtextures", max( 1, gl_showtextures->integer - 1 )); if( ++numTries < 2 ) goto rebuild_page; // to prevent infinite loop } for( k = 0; i < MAX_TEXTURES; i++ ) { if( j == end ) break; // page is full image = R_GetTexture( i ); if( !pglIsTexture( image->texnum )) continue; x = k % base_w * w; y = k / base_w * h; pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Bind( XASH_TEXTURE0, i ); // NOTE: don't use image->texnum here, because skybox has a 'wrong' indexes if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE )) pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); pglBegin( GL_QUADS ); pglTexCoord2f( 0, 0 ); pglVertex2f( x, y ); if( image->flags & TF_TEXTURE_RECTANGLE ) pglTexCoord2f( image->width, 0 ); else pglTexCoord2f( 1, 0 ); pglVertex2f( x + w, y ); if( image->flags & TF_TEXTURE_RECTANGLE ) pglTexCoord2f( image->width, image->height ); else pglTexCoord2f( 1, 1 ); pglVertex2f( x + w, y + h ); if( image->flags & TF_TEXTURE_RECTANGLE ) pglTexCoord2f( 0, image->height ); else pglTexCoord2f( 0, 1 ); pglVertex2f( x, y + h ); pglEnd(); if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE )) pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB ); FS_FileBase( image->name, shortname ); if( Q_strlen( shortname ) > 18 ) { // cutoff too long names, it looks ugly shortname[16] = '.'; shortname[17] = '.'; shortname[18] = '\0'; } Con_DrawString( x + 1, y + h - charHeight, shortname, color ); j++, k++; } CL_DrawCenterPrint (); pglFinish(); }
/* =========== NetGraph_DrawTextFields =========== */ void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke ) { static int lastout; rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 }; int ptx = max( x + w - NETGRAPH_LERP_HEIGHT - 1, 1 ); int pty = max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 1 ); int out, i = ( cls.netchan.outgoing_sequence - 1 ) & NET_TIMINGS_MASK; int j = cls.netchan.incoming_sequence & NET_TIMINGS_MASK; int last_y = y - net_graphheight->value; if( count > 0 ) { avg = avg / (float)( count - ( host.frametime * FRAMERATE_AVG_FRAC )); if( cl_updaterate->value > 0.0f ) avg -= 1000.0f / cl_updaterate->value; // can't be below zero avg = max( 0.0, avg ); } else avg = 0.0; // move rolling average framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0 - FRAMERATE_AVG_FRAC ) * framerate; Con_SetFont( 0 ); if( framerate > 0.0f ) { y -= net_graphheight->value; Con_DrawString( x, y, va( "%.1f fps" , 1.0f / framerate ), colors ); if( avg > 1.0f ) Con_DrawString( x + 75, y, va( "%i ms" , (int)avg ), colors ); y += 15; out = netstat_cmdinfo[i].size; if( !out ) out = lastout; else lastout = out; Con_DrawString( x, y, va( "in : %i %.2f k/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors ); y += 15; Con_DrawString( x, y, va( "out: %i %.2f k/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors ); y += 15; if( net_graph->value > 2 ) { int loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01 ); int choke = (int)(( packet_choke + PACKETCHOKE_AVG_FRAC ) - 0.01 ); Con_DrawString( x, y, va( "loss: %i choke: %i", loss, choke ), colors ); } } if( net_graph->value < 3 ) Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors ); Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors ); Con_RestoreFont(); }