123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- /*
- ===========================================================================
- Copyright (C) 1999-2005 Id Software, Inc.
- This file is part of Quake III Arena source code.
- Quake III Arena source code is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
- Quake III Arena source code is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Foobar; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- ===========================================================================
- */
- // cl_scrn.c -- master for refresh, status bar, console, chat, notify, etc
- #include "client.h"
- qboolean scr_initialized; // ready to draw
- cvar_t *cl_timegraph;
- cvar_t *cl_debuggraph;
- cvar_t *cl_graphheight;
- cvar_t *cl_graphscale;
- cvar_t *cl_graphshift;
- /*
- ================
- SCR_DrawNamedPic
- Coordinates are 640*480 virtual values
- =================
- */
- void SCR_DrawNamedPic( float x, float y, float width, float height, const char *picname ) {
- qhandle_t hShader;
- assert( width != 0 );
- hShader = re.RegisterShader( picname );
- SCR_AdjustFrom640( &x, &y, &width, &height );
- re.DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
- }
- /*
- ================
- SCR_AdjustFrom640
- Adjusted for resolution and screen aspect ratio
- ================
- */
- void SCR_AdjustFrom640( float *x, float *y, float *w, float *h ) {
- float xscale;
- float yscale;
- #if 0
- // adjust for wide screens
- if ( cls.glconfig.vidWidth * 480 > cls.glconfig.vidHeight * 640 ) {
- *x += 0.5 * ( cls.glconfig.vidWidth - ( cls.glconfig.vidHeight * 640 / 480 ) );
- }
- #endif
- // scale for screen sizes
- xscale = cls.glconfig.vidWidth / 640.0;
- yscale = cls.glconfig.vidHeight / 480.0;
- if ( x ) {
- *x *= xscale;
- }
- if ( y ) {
- *y *= yscale;
- }
- if ( w ) {
- *w *= xscale;
- }
- if ( h ) {
- *h *= yscale;
- }
- }
- /*
- ================
- SCR_FillRect
- Coordinates are 640*480 virtual values
- =================
- */
- void SCR_FillRect( float x, float y, float width, float height, const float *color ) {
- re.SetColor( color );
- SCR_AdjustFrom640( &x, &y, &width, &height );
- re.DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cls.whiteShader );
- re.SetColor( NULL );
- }
- /*
- ================
- SCR_DrawPic
- Coordinates are 640*480 virtual values
- =================
- */
- void SCR_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) {
- SCR_AdjustFrom640( &x, &y, &width, &height );
- re.DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
- }
- /*
- ** SCR_DrawChar
- ** chars are drawn at 640*480 virtual screen size
- */
- static void SCR_DrawChar( int x, int y, float size, int ch ) {
- int row, col;
- float frow, fcol;
- float ax, ay, aw, ah;
- ch &= 255;
- if ( ch == ' ' ) {
- return;
- }
- if ( y < -size ) {
- return;
- }
- ax = x;
- ay = y;
- aw = size;
- ah = size;
- SCR_AdjustFrom640( &ax, &ay, &aw, &ah );
- row = ch>>4;
- col = ch&15;
- frow = row*0.0625;
- fcol = col*0.0625;
- size = 0.0625;
- re.DrawStretchPic( ax, ay, aw, ah,
- fcol, frow,
- fcol + size, frow + size,
- cls.charSetShader );
- }
- /*
- ** SCR_DrawSmallChar
- ** small chars are drawn at native screen resolution
- */
- void SCR_DrawSmallChar( int x, int y, int ch ) {
- int row, col;
- float frow, fcol;
- float size;
- ch &= 255;
- if ( ch == ' ' ) {
- return;
- }
- if ( y < -SMALLCHAR_HEIGHT ) {
- return;
- }
- row = ch>>4;
- col = ch&15;
- frow = row*0.0625;
- fcol = col*0.0625;
- size = 0.0625;
- re.DrawStretchPic( x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT,
- fcol, frow,
- fcol + size, frow + size,
- cls.charSetShader );
- }
- /*
- ==================
- SCR_DrawBigString[Color]
- Draws a multi-colored string with a drop shadow, optionally forcing
- to a fixed color.
- Coordinates are at 640 by 480 virtual resolution
- ==================
- */
- void SCR_DrawStringExt( int x, int y, float size, const char *string, float *setColor, qboolean forceColor ) {
- vec4_t color;
- const char *s;
- int xx;
- // draw the drop shadow
- color[0] = color[1] = color[2] = 0;
- color[3] = setColor[3];
- re.SetColor( color );
- s = string;
- xx = x;
- while ( *s ) {
- if ( Q_IsColorString( s ) ) {
- s += 2;
- continue;
- }
- SCR_DrawChar( xx+2, y+2, size, *s );
- xx += size;
- s++;
- }
- // draw the colored text
- s = string;
- xx = x;
- re.SetColor( setColor );
- while ( *s ) {
- if ( Q_IsColorString( s ) ) {
- if ( !forceColor ) {
- Com_Memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
- color[3] = setColor[3];
- re.SetColor( color );
- }
- s += 2;
- continue;
- }
- SCR_DrawChar( xx, y, size, *s );
- xx += size;
- s++;
- }
- re.SetColor( NULL );
- }
- void SCR_DrawBigString( int x, int y, const char *s, float alpha ) {
- float color[4];
- color[0] = color[1] = color[2] = 1.0;
- color[3] = alpha;
- SCR_DrawStringExt( x, y, BIGCHAR_WIDTH, s, color, qfalse );
- }
- void SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color ) {
- SCR_DrawStringExt( x, y, BIGCHAR_WIDTH, s, color, qtrue );
- }
- /*
- ==================
- SCR_DrawSmallString[Color]
- Draws a multi-colored string with a drop shadow, optionally forcing
- to a fixed color.
- Coordinates are at 640 by 480 virtual resolution
- ==================
- */
- void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor ) {
- vec4_t color;
- const char *s;
- int xx;
- // draw the colored text
- s = string;
- xx = x;
- re.SetColor( setColor );
- while ( *s ) {
- if ( Q_IsColorString( s ) ) {
- if ( !forceColor ) {
- Com_Memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
- color[3] = setColor[3];
- re.SetColor( color );
- }
- s += 2;
- continue;
- }
- SCR_DrawSmallChar( xx, y, *s );
- xx += SMALLCHAR_WIDTH;
- s++;
- }
- re.SetColor( NULL );
- }
- /*
- ** SCR_Strlen -- skips color escape codes
- */
- static int SCR_Strlen( const char *str ) {
- const char *s = str;
- int count = 0;
- while ( *s ) {
- if ( Q_IsColorString( s ) ) {
- s += 2;
- } else {
- count++;
- s++;
- }
- }
- return count;
- }
- /*
- ** SCR_GetBigStringWidth
- */
- int SCR_GetBigStringWidth( const char *str ) {
- return SCR_Strlen( str ) * 16;
- }
- //===============================================================================
- /*
- =================
- SCR_DrawDemoRecording
- =================
- */
- void SCR_DrawDemoRecording( void ) {
- char string[1024];
- int pos;
- if ( !clc.demorecording ) {
- return;
- }
- if ( clc.spDemoRecording ) {
- return;
- }
- pos = FS_FTell( clc.demofile );
- sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 );
- SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue );
- }
- /*
- ===============================================================================
- DEBUG GRAPH
- ===============================================================================
- */
- typedef struct
- {
- float value;
- int color;
- } graphsamp_t;
- static int current;
- static graphsamp_t values[1024];
- /*
- ==============
- SCR_DebugGraph
- ==============
- */
- void SCR_DebugGraph (float value, int color)
- {
- values[current&1023].value = value;
- values[current&1023].color = color;
- current++;
- }
- /*
- ==============
- SCR_DrawDebugGraph
- ==============
- */
- void SCR_DrawDebugGraph (void)
- {
- int a, x, y, w, i, h;
- float v;
- int color;
- //
- // draw the graph
- //
- w = cls.glconfig.vidWidth;
- x = 0;
- y = cls.glconfig.vidHeight;
- re.SetColor( g_color_table[0] );
- re.DrawStretchPic(x, y - cl_graphheight->integer,
- w, cl_graphheight->integer, 0, 0, 0, 0, cls.whiteShader );
- re.SetColor( NULL );
- for (a=0 ; a<w ; a++)
- {
- i = (current-1-a+1024) & 1023;
- v = values[i].value;
- color = values[i].color;
- v = v * cl_graphscale->integer + cl_graphshift->integer;
-
- if (v < 0)
- v += cl_graphheight->integer * (1+(int)(-v / cl_graphheight->integer));
- h = (int)v % cl_graphheight->integer;
- re.DrawStretchPic( x+w-1-a, y - h, 1, h, 0, 0, 0, 0, cls.whiteShader );
- }
- }
- //=============================================================================
- /*
- ==================
- SCR_Init
- ==================
- */
- void SCR_Init( void ) {
- cl_timegraph = Cvar_Get ("timegraph", "0", CVAR_CHEAT);
- cl_debuggraph = Cvar_Get ("debuggraph", "0", CVAR_CHEAT);
- cl_graphheight = Cvar_Get ("graphheight", "32", CVAR_CHEAT);
- cl_graphscale = Cvar_Get ("graphscale", "1", CVAR_CHEAT);
- cl_graphshift = Cvar_Get ("graphshift", "0", CVAR_CHEAT);
- scr_initialized = qtrue;
- }
- //=======================================================
- /*
- ==================
- SCR_DrawScreenField
- This will be called twice if rendering in stereo mode
- ==================
- */
- void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
- re.BeginFrame( stereoFrame );
- // wide aspect ratio screens need to have the sides cleared
- // unless they are displaying game renderings
- if ( cls.state != CA_ACTIVE ) {
- if ( cls.glconfig.vidWidth * 480 > cls.glconfig.vidHeight * 640 ) {
- re.SetColor( g_color_table[0] );
- re.DrawStretchPic( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, 0, 0, 0, cls.whiteShader );
- re.SetColor( NULL );
- }
- }
- if ( !uivm ) {
- Com_DPrintf("draw screen without UI loaded\n");
- return;
- }
- // if the menu is going to cover the entire screen, we
- // don't need to render anything under it
- if ( !VM_Call( uivm, UI_IS_FULLSCREEN )) {
- switch( cls.state ) {
- default:
- Com_Error( ERR_FATAL, "SCR_DrawScreenField: bad cls.state" );
- break;
- case CA_CINEMATIC:
- SCR_DrawCinematic();
- break;
- case CA_DISCONNECTED:
- // force menu up
- S_StopAllSounds();
- VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
- break;
- case CA_CONNECTING:
- case CA_CHALLENGING:
- case CA_CONNECTED:
- // connecting clients will only show the connection dialog
- // refresh to update the time
- VM_Call( uivm, UI_REFRESH, cls.realtime );
- VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qfalse );
- break;
- case CA_LOADING:
- case CA_PRIMED:
- // draw the game information screen and loading progress
- CL_CGameRendering( stereoFrame );
- // also draw the connection information, so it doesn't
- // flash away too briefly on local or lan games
- // refresh to update the time
- VM_Call( uivm, UI_REFRESH, cls.realtime );
- VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qtrue );
- break;
- case CA_ACTIVE:
- CL_CGameRendering( stereoFrame );
- SCR_DrawDemoRecording();
- break;
- }
- }
- // the menu draws next
- if ( cls.keyCatchers & KEYCATCH_UI && uivm ) {
- VM_Call( uivm, UI_REFRESH, cls.realtime );
- }
- // console draws next
- Con_DrawConsole ();
- // debug graph can be drawn on top of anything
- if ( cl_debuggraph->integer || cl_timegraph->integer || cl_debugMove->integer ) {
- SCR_DrawDebugGraph ();
- }
- }
- /*
- ==================
- SCR_UpdateScreen
- This is called every frame, and can also be called explicitly to flush
- text to the screen.
- ==================
- */
- void SCR_UpdateScreen( void ) {
- static int recursive;
- if ( !scr_initialized ) {
- return; // not initialized yet
- }
- if ( ++recursive > 2 ) {
- Com_Error( ERR_FATAL, "SCR_UpdateScreen: recursively called" );
- }
- recursive = 1;
- // if running in stereo, we need to draw the frame twice
- if ( cls.glconfig.stereoEnabled ) {
- SCR_DrawScreenField( STEREO_LEFT );
- SCR_DrawScreenField( STEREO_RIGHT );
- } else {
- SCR_DrawScreenField( STEREO_CENTER );
- }
- if ( com_speeds->integer ) {
- re.EndFrame( &time_frontend, &time_backend );
- } else {
- re.EndFrame( NULL, NULL );
- }
- recursive = 0;
- }
|