Annotation of quake2/client/cl_scrn.c, revision 1.1.1.1

1.1       root        1: // cl_scrn.c -- master for refresh, status bar, console, chat, notify, etc
                      2: /*
                      3:   full screen console
                      4:   put up loading plaque
                      5:   blanked background with loading plaque
                      6:   blanked background with menu
                      7:   cinematics
                      8:   full screen image for quit and victory
                      9:   end of unit intermissions
                     10:   */
                     11: #include "client.h"
                     12: float          scr_con_current;        // aproaches scr_conlines at scr_conspeed
                     13: float          scr_conlines;           // 0.0 to 1.0 lines of console to display
                     14: qboolean       scr_initialized;                // ready to draw
                     15: int                    scr_draw_loading;
                     16: vrect_t                scr_vrect;              // position of render window on screen
                     17: cvar_t         *scr_viewsize;
                     18: cvar_t         *scr_conspeed;
                     19: cvar_t         *scr_centertime;
                     20: cvar_t         *scr_showturtle;
                     21: cvar_t         *scr_showpause;
                     22: cvar_t         *scr_printspeed;
                     23: cvar_t         *scr_netgraph;
                     24: cvar_t         *scr_timegraph;
                     25: cvar_t         *scr_debuggraph;
                     26: cvar_t         *scr_graphheight;
                     27: cvar_t         *scr_graphscale;
                     28: cvar_t         *scr_graphshift;
                     29: cvar_t         *scr_drawall;
                     30: typedef struct
                     31: {
                     32:        int             x1, y1, x2, y2;
                     33: } dirty_t;
                     34: dirty_t                scr_dirty, scr_old_dirty[2];
                     35: 
                     36: char           crosshair_pic[MAX_QPATH];
                     37: int                    crosshair_width, crosshair_height;
                     38: void SCR_TimeRefresh_f (void);
                     39: void SCR_Loading_f (void);
                     40: /*
                     41: ===============================================================================
                     42: BAR GRAPHS
                     43: ===============================================================================
                     44: */
                     45: 
                     46: /*
                     47: ==============
                     48: CL_AddNetgraph
                     49: 
                     50: A new packet was just parsed
                     51: ==============
                     52: */
                     53: void CL_AddNetgraph (void)
                     54: {
                     55:        int             i;
                     56:        int             in;
                     57:        int             ping;
                     58: 
                     59:        // if using the debuggraph for something else, don't
                     60:        // add the net lines
                     61:        if (scr_debuggraph->value || scr_timegraph->value)
                     62:                return;
                     63: 
                     64:        for (i=0 ; i<cls.netchan.dropped ; i++)
                     65:                SCR_DebugGraph (30, 0x40);
                     66: 
                     67:        for (i=0 ; i<cl.surpressCount ; i++)
                     68:                SCR_DebugGraph (30, 0xdf);
                     69: 
                     70:        // see what the latency was on this packet
                     71:        in = cls.netchan.incoming_acknowledged & (CMD_BACKUP-1);
                     72:        ping = cls.realtime - cl.cmd_time[in];
                     73:        ping /= 30;
                     74:        if (ping > 30)
                     75:                ping = 30;
                     76:        SCR_DebugGraph (ping, 0xd0);
                     77: }
                     78: typedef struct
                     79: {
                     80:        float   value;
                     81:        int             color;
                     82: } graphsamp_t;
                     83: static int                     current;
                     84: static graphsamp_t     values[1024];
                     85: /*
                     86: ==============
                     87: SCR_DebugGraph
                     88: ==============
                     89: */
                     90: void SCR_DebugGraph (float value, int color)
                     91: {
                     92:        values[current&1023].value = value;
                     93:        values[current&1023].color = color;
                     94:        current++;
                     95: }
                     96: /*
                     97: ==============
                     98: SCR_DrawDebugGraph
                     99: ==============
                    100: */
                    101: void SCR_DrawDebugGraph (void)
                    102: {
                    103:        int             a, x, y, w, i, h;
                    104:        float   v;
                    105:        int             color;
                    106:        //
                    107:        // draw the graph
                    108:        //
                    109:        w = scr_vrect.width;
                    110:        x = scr_vrect.x;
                    111:        y = scr_vrect.y+scr_vrect.height;
                    112:        re.DrawFill (x, y-scr_graphheight->value,
                    113:                w, scr_graphheight->value, 8);
                    114:        for (a=0 ; a<w ; a++)
                    115:        {
                    116:                i = (current-1-a+1024) & 1023;
                    117:                v = values[i].value;
                    118:                color = values[i].color;
                    119:                v = v*scr_graphscale->value + scr_graphshift->value;
                    120:                
                    121:                if (v < 0)
                    122:                        v += scr_graphheight->value * (1+(int)(-v/scr_graphheight->value));
                    123:                h = (int)v % (int)scr_graphheight->value;
                    124:                re.DrawFill (x+w-1-a, y - h, 1, h, color);
                    125:        }
                    126: }
                    127: /*
                    128: ===============================================================================
                    129: CENTER PRINTING
                    130: ===============================================================================
                    131: */
                    132: char           scr_centerstring[1024];
                    133: float          scr_centertime_start;   // for slow victory printing
                    134: float          scr_centertime_off;
                    135: int                    scr_center_lines;
                    136: int                    scr_erase_center;
                    137: /*
                    138: ==============
                    139: SCR_CenterPrint
                    140: Called for important messages that should stay in the center of the screen
                    141: for a few moments
                    142: ==============
                    143: */
                    144: void SCR_CenterPrint (char *str)
                    145: {
                    146:        char    *s;
                    147:        char    line[64];
                    148:        int             i, j, l;
                    149:        strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1);
                    150:        scr_centertime_off = scr_centertime->value;
                    151:        scr_centertime_start = cl.time;
                    152:        // count the number of lines for centering
                    153:        scr_center_lines = 1;
                    154:        s = str;
                    155:        while (*s)
                    156:        {
                    157:                if (*s == '\n')
                    158:                        scr_center_lines++;
                    159:                s++;
                    160:        }
                    161: 
                    162:        // echo it to the console
                    163:        Com_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
                    164: 
                    165:        s = str;
                    166:        do      
                    167:        {
                    168:        // scan the width of the line
                    169:                for (l=0 ; l<40 ; l++)
                    170:                        if (s[l] == '\n' || !s[l])
                    171:                                break;
                    172:                for (i=0 ; i<(40-l)/2 ; i++)
                    173:                        line[i] = ' ';
                    174: 
                    175:                for (j=0 ; j<l ; j++)
                    176:                {
                    177:                        line[i++] = s[j];
                    178:                }
                    179: 
                    180:                line[i] = '\n';
                    181:                line[i+1] = 0;
                    182: 
                    183:                Com_Printf ("%s", line);
                    184: 
                    185:                while (*s && *s != '\n')
                    186:                        s++;
                    187: 
                    188:                if (!*s)
                    189:                        break;
                    190:                s++;            // skip the \n
                    191:        } while (1);
                    192:        Com_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
                    193:        Con_ClearNotify ();
                    194: }
                    195: void SCR_DrawCenterString (void)
                    196: {
                    197:        char    *start;
                    198:        int             l;
                    199:        int             j;
                    200:        int             x, y;
                    201:        int             remaining;
                    202: // the finale prints the characters one at a time
                    203:        remaining = 9999;
                    204:        scr_erase_center = 0;
                    205:        start = scr_centerstring;
                    206:        if (scr_center_lines <= 4)
                    207:                y = viddef.height*0.35;
                    208:        else
                    209:                y = 48;
                    210:        do      
                    211:        {
                    212:        // scan the width of the line
                    213:                for (l=0 ; l<40 ; l++)
                    214:                        if (start[l] == '\n' || !start[l])
                    215:                                break;
                    216:                x = (viddef.width - l*8)/2;
                    217:                SCR_AddDirtyPoint (x, y);
                    218:                for (j=0 ; j<l ; j++, x+=8)
                    219:                {
                    220:                        re.DrawChar (x, y, start[j]);   
                    221:                        if (!remaining--)
                    222:                                return;
                    223:                }
                    224:                SCR_AddDirtyPoint (x, y+8);
                    225:                        
                    226:                y += 8;
                    227:                while (*start && *start != '\n')
                    228:                        start++;
                    229:                if (!*start)
                    230:                        break;
                    231:                start++;                // skip the \n
                    232:        } while (1);
                    233: }
                    234: void SCR_CheckDrawCenterString (void)
                    235: {
                    236:        scr_centertime_off -= cls.frametime;
                    237:        
                    238:        if (scr_centertime_off <= 0)
                    239:                return;
                    240:        SCR_DrawCenterString ();
                    241: }
                    242: //=============================================================================
                    243: /*
                    244: =================
                    245: SCR_CalcVrect
                    246: Sets scr_vrect, the coordinates of the rendered window
                    247: =================
                    248: */
                    249: static void SCR_CalcVrect (void)
                    250: {
                    251:        int             size;
                    252:        // bound viewsize
                    253:        if (scr_viewsize->value < 40)
                    254:                Cvar_Set ("viewsize","40");
                    255:        if (scr_viewsize->value > 100)
                    256:                Cvar_Set ("viewsize","100");
                    257:        size = scr_viewsize->value;
                    258:        scr_vrect.width = viddef.width*size/100;
                    259:        scr_vrect.width &= ~7;
                    260:        scr_vrect.height = viddef.height*size/100;
                    261:        scr_vrect.height &= ~1;
                    262:        scr_vrect.x = (viddef.width - scr_vrect.width)/2;
                    263:        scr_vrect.y = (viddef.height - scr_vrect.height)/2;
                    264: }
                    265: /*
                    266: =================
                    267: SCR_SizeUp_f
                    268: Keybinding command
                    269: =================
                    270: */
                    271: void SCR_SizeUp_f (void)
                    272: {
                    273:        Cvar_SetValue ("viewsize",scr_viewsize->value+10);
                    274: }
                    275: /*
                    276: =================
                    277: SCR_SizeDown_f
                    278: Keybinding command
                    279: =================
                    280: */
                    281: void SCR_SizeDown_f (void)
                    282: {
                    283:        Cvar_SetValue ("viewsize",scr_viewsize->value-10);
                    284: }
                    285: /*
                    286: =================
                    287: SCR_Sky_f
                    288: Set a specific sky and rotation speed
                    289: =================
                    290: */
                    291: void SCR_Sky_f (void)
                    292: {
                    293:        float   rotate;
                    294:        vec3_t  axis;
                    295:        if (Cmd_Argc() < 2)
                    296:        {
                    297:                Com_Printf ("Usage: sky <basename> <rotate> <axis x y z>\n");
                    298:                return;
                    299:        }
                    300:        if (Cmd_Argc() > 2)
                    301:                rotate = atof(Cmd_Argv(2));
                    302:        else
                    303:                rotate = 0;
                    304:        if (Cmd_Argc() == 6)
                    305:        {
                    306:                axis[0] = atof(Cmd_Argv(3));
                    307:                axis[1] = atof(Cmd_Argv(4));
                    308:                axis[2] = atof(Cmd_Argv(5));
                    309:        }
                    310:        else
                    311:        {
                    312:                axis[0] = 0;
                    313:                axis[1] = 0;
                    314:                axis[2] = 1;
                    315:        }
                    316:        re.SetSky (Cmd_Argv(1), rotate, axis);
                    317: }
                    318: //============================================================================
                    319: /*
                    320: ==================
                    321: SCR_Init
                    322: ==================
                    323: */
                    324: void SCR_Init (void)
                    325: {
                    326:        scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE);
                    327:        scr_conspeed = Cvar_Get ("scr_conspeed", "3", 0);
                    328:        scr_showturtle = Cvar_Get ("scr_showturtle", "0", 0);
                    329:        scr_showpause = Cvar_Get ("scr_showpause", "1", 0);
                    330:        scr_centertime = Cvar_Get ("scr_centertime", "2.5", 0);
                    331:        scr_printspeed = Cvar_Get ("scr_printspeed", "8", 0);
                    332:        scr_netgraph = Cvar_Get ("netgraph", "0", 0);
                    333:        scr_timegraph = Cvar_Get ("timegraph", "0", 0);
                    334:        scr_debuggraph = Cvar_Get ("debuggraph", "0", 0);
                    335:        scr_graphheight = Cvar_Get ("graphheight", "32", 0);
                    336:        scr_graphscale = Cvar_Get ("graphscale", "1", 0);
                    337:        scr_graphshift = Cvar_Get ("graphshift", "0", 0);
                    338:        scr_drawall = Cvar_Get ("scr_drawall", "0", 0);
                    339: //
                    340: // register our commands
                    341: //
                    342:        Cmd_AddCommand ("timerefresh",SCR_TimeRefresh_f);
                    343:        Cmd_AddCommand ("loading",SCR_Loading_f);
                    344:        Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
                    345:        Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
                    346:        Cmd_AddCommand ("sky",SCR_Sky_f);
                    347:        scr_initialized = true;
                    348: }
                    349: /*
                    350: ==============
                    351: SCR_DrawNet
                    352: ==============
                    353: */
                    354: void SCR_DrawNet (void)
                    355: {
                    356:        if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged 
                    357:                < CMD_BACKUP-1)
                    358:                return;
                    359:        re.DrawPic (scr_vrect.x+64, scr_vrect.y, "net");
                    360: }
                    361: /*
                    362: ==============
                    363: SCR_DrawPause
                    364: ==============
                    365: */
                    366: void SCR_DrawPause (void)
                    367: {
                    368:        int             w, h;
                    369:        if (!scr_showpause->value)              // turn off for screenshots
                    370:                return;
                    371:        if (!cl_paused->value)
                    372:                return;
                    373:        re.DrawGetPicSize (&w, &h, "pause");
                    374:        re.DrawPic ((viddef.width-w)/2, viddef.height/2 + 8, "pause");
                    375: }
                    376: /*
                    377: ==============
                    378: SCR_DrawLoading
                    379: ==============
                    380: */
                    381: void SCR_DrawLoading (void)
                    382: {
                    383:        int             w, h;
                    384:                
                    385:        if (!scr_draw_loading)
                    386:                return;
                    387:        scr_draw_loading = false;
                    388:        re.DrawGetPicSize (&w, &h, "loading");
                    389:        re.DrawPic ((viddef.width-w)/2, (viddef.height-h)/2, "loading");
                    390: }
                    391: //=============================================================================
                    392: /*
                    393: ==================
                    394: SCR_RunConsole
                    395: Scroll it up or down
                    396: ==================
                    397: */
                    398: void SCR_RunConsole (void)
                    399: {
                    400: // decide on the height of the console
                    401:        if (cls.key_dest == key_console)
                    402:                scr_conlines = 0.5;             // half screen
                    403:        else
                    404:                scr_conlines = 0;                               // none visible
                    405:        
                    406:        if (scr_conlines < scr_con_current)
                    407:        {
                    408:                scr_con_current -= scr_conspeed->value*cls.frametime;
                    409:                if (scr_conlines > scr_con_current)
                    410:                        scr_con_current = scr_conlines;
                    411:        }
                    412:        else if (scr_conlines > scr_con_current)
                    413:        {
                    414:                scr_con_current += scr_conspeed->value*cls.frametime;
                    415:                if (scr_conlines < scr_con_current)
                    416:                        scr_con_current = scr_conlines;
                    417:        }
                    418: }
                    419: /*
                    420: ==================
                    421: SCR_DrawConsole
                    422: ==================
                    423: */
                    424: void SCR_DrawConsole (void)
                    425: {
                    426:        Con_CheckResize ();
                    427:        
                    428:        if (cls.state == ca_disconnected || cls.state == ca_connecting)
                    429:        {       // forced full screen console
                    430:                Con_DrawConsole (1.0);
                    431:                return;
                    432:        }
                    433:        if (cls.state != ca_active || !cl.refresh_prepped)
                    434:        {       // connected, but can't render
                    435:                Con_DrawConsole (0.5);
                    436:                re.DrawFill (0, viddef.height/2, viddef.width, viddef.height/2, 0);
                    437:                return;
                    438:        }
                    439:        if (scr_con_current)
                    440:        {
                    441:                Con_DrawConsole (scr_con_current);
                    442:        }
                    443:        else
                    444:        {
                    445:                if (cls.key_dest == key_game || cls.key_dest == key_message)
                    446:                        Con_DrawNotify ();      // only draw notify in game
                    447:        }
                    448: }
                    449: //=============================================================================
                    450: /*
                    451: ================
                    452: SCR_BeginLoadingPlaque
                    453: ================
                    454: */
                    455: void SCR_BeginLoadingPlaque (void)
                    456: {
                    457:        S_StopAllSounds ();
                    458:        cl.sound_prepped = false;               // don't play ambients
                    459:        CDAudio_Stop ();
                    460:        if (cls.disable_screen)
                    461:                return;
                    462:        if (developer->value)
                    463:                return;
                    464:        if (cls.state == ca_disconnected)
                    465:                return; // if at console, don't bring up the plaque
                    466:        if (cls.key_dest == key_console)
                    467:                return;
                    468:        if (cl.cinematictime > 0)
                    469:                scr_draw_loading = 2;   // clear to balack first
                    470:        else
                    471:                scr_draw_loading = 1;
                    472:        SCR_UpdateScreen ();
                    473:        cls.disable_screen = Sys_Milliseconds ();
                    474:        cls.disable_servercount = cl.servercount;
                    475: }
                    476: /*
                    477: ================
                    478: SCR_EndLoadingPlaque
                    479: ================
                    480: */
                    481: void SCR_EndLoadingPlaque (void)
                    482: {
                    483:        cls.disable_screen = 0;
                    484:        Con_ClearNotify ();
                    485: }
                    486: /*
                    487: ================
                    488: SCR_Loading_f
                    489: ================
                    490: */
                    491: void SCR_Loading_f (void)
                    492: {
                    493:        SCR_BeginLoadingPlaque ();
                    494: }
                    495: /*
                    496: ================
                    497: SCR_TimeRefresh_f
                    498: ================
                    499: */
                    500: int entitycmpfnc( const entity_t *a, const entity_t *b )
                    501: {
                    502:        /*
                    503:        ** all other models are sorted by model then skin
                    504:        */
                    505:        if ( a->model == b->model )
                    506:        {
                    507:                return ( ( int ) a->skin - ( int ) b->skin );
                    508:        }
                    509:        else
                    510:        {
                    511:                return ( ( int ) a->model - ( int ) b->model );
                    512:        }
                    513: }
                    514: 
                    515: void SCR_TimeRefresh_f (void)
                    516: {
                    517:        int             i;
                    518:        int             start, stop;
                    519:        float   time;
                    520: 
                    521:        if ( cls.state != ca_active )
                    522:                return;
                    523:        start = Sys_Milliseconds ();
                    524:        if (Cmd_Argc() == 2)
                    525:        {       // run without page flipping
                    526:                re.BeginFrame( 0 );
                    527:                for (i=0 ; i<128 ; i++)
                    528:                {
                    529:                        cl.refdef.viewangles[1] = i/128.0*360.0;
                    530:                        re.RenderFrame (&cl.refdef);
                    531:                }
                    532:                re.EndFrame();
                    533:        }
                    534:        else
                    535:        {
                    536:                for (i=0 ; i<128 ; i++)
                    537:                {
                    538:                        cl.refdef.viewangles[1] = i/128.0*360.0;
                    539:                        re.BeginFrame( 0 );
                    540:                        re.RenderFrame (&cl.refdef);
                    541:                        re.EndFrame();
                    542:                }
                    543:        }
                    544:        stop = Sys_Milliseconds ();
                    545:        time = (stop-start)/1000.0;
                    546:        Com_Printf ("%f seconds (%f fps)\n", time, 128/time);
                    547: }
                    548: /*
                    549: =================
                    550: SCR_AddDirtyPoint
                    551: =================
                    552: */
                    553: void SCR_AddDirtyPoint (int x, int y)
                    554: {
                    555:        if (x < scr_dirty.x1)
                    556:                scr_dirty.x1 = x;
                    557:        if (x > scr_dirty.x2)
                    558:                scr_dirty.x2 = x;
                    559:        if (y < scr_dirty.y1)
                    560:                scr_dirty.y1 = y;
                    561:        if (y > scr_dirty.y2)
                    562:                scr_dirty.y2 = y;
                    563: }
                    564: void SCR_DirtyScreen (void)
                    565: {
                    566:        SCR_AddDirtyPoint (0, 0);
                    567:        SCR_AddDirtyPoint (viddef.width-1, viddef.height-1);
                    568: }
                    569: /*
                    570: ==============
                    571: SCR_TileClear
                    572: Clear any parts of the tiled background that were drawn on last frame
                    573: ==============
                    574: */
                    575: void SCR_TileClear (void)
                    576: {
                    577:        int             i;
                    578:        int             top, bottom, left, right;
                    579:        dirty_t clear;
                    580: 
                    581:        if (scr_drawall->value)
                    582:                SCR_DirtyScreen ();     // for power vr or broken page flippers...
                    583:        if (scr_con_current == 1.0)
                    584:                return;         // full screen console
                    585:        if (scr_viewsize->value == 100)
                    586:                return;         // full screen rendering
                    587:        if (cl.cinematictime > 0)
                    588:                return;         // full screen cinematic
                    589:        // erase rect will be the union of the past three frames
                    590:        // so tripple buffering works properly
                    591:        clear = scr_dirty;
                    592:        for (i=0 ; i<2 ; i++)
                    593:        {
                    594:                if (scr_old_dirty[i].x1 < clear.x1)
                    595:                        clear.x1 = scr_old_dirty[i].x1;
                    596:                if (scr_old_dirty[i].x2 > clear.x2)
                    597:                        clear.x2 = scr_old_dirty[i].x2;
                    598:                if (scr_old_dirty[i].y1 < clear.y1)
                    599:                        clear.y1 = scr_old_dirty[i].y1;
                    600:                if (scr_old_dirty[i].y2 > clear.y2)
                    601:                        clear.y2 = scr_old_dirty[i].y2;
                    602:        }
                    603:        scr_old_dirty[1] = scr_old_dirty[0];
                    604:        scr_old_dirty[0] = scr_dirty;
                    605:        scr_dirty.x1 = 9999;
                    606:        scr_dirty.x2 = -9999;
                    607:        scr_dirty.y1 = 9999;
                    608:        scr_dirty.y2 = -9999;
                    609:        // don't bother with anything convered by the console)
                    610:        top = scr_con_current*viddef.height;
                    611:        if (top >= clear.y1)
                    612:                clear.y1 = top;
                    613:        if (clear.y2 <= clear.y1)
                    614:                return;         // nothing disturbed
                    615:        top = scr_vrect.y;
                    616:        bottom = top + scr_vrect.height-1;
                    617:        left = scr_vrect.x;
                    618:        right = left + scr_vrect.width-1;
                    619:        if (clear.y1 < top)
                    620:        {       // clear above view screen
                    621:                i = clear.y2 < top-1 ? clear.y2 : top-1;
                    622:                re.DrawTileClear (clear.x1 , clear.y1,
                    623:                        clear.x2 - clear.x1 + 1, i - clear.y1+1, "backtile");
                    624:                clear.y1 = top;
                    625:        }
                    626:        if (clear.y2 > bottom)
                    627:        {       // clear below view screen
                    628:                i = clear.y1 > bottom+1 ? clear.y1 : bottom+1;
                    629:                re.DrawTileClear (clear.x1, i,
                    630:                        clear.x2-clear.x1+1, clear.y2-i+1, "backtile");
                    631:                clear.y2 = bottom;
                    632:        }
                    633:        if (clear.x1 < left)
                    634:        {       // clear left of view screen
                    635:                i = clear.x2 < left-1 ? clear.x2 : left-1;
                    636:                re.DrawTileClear (clear.x1, clear.y1,
                    637:                        i-clear.x1+1, clear.y2 - clear.y1 + 1, "backtile");
                    638:                clear.x1 = left;
                    639:        }
                    640:        if (clear.x2 > right)
                    641:        {       // clear left of view screen
                    642:                i = clear.x1 > right+1 ? clear.x1 : right+1;
                    643:                re.DrawTileClear (i, clear.y1,
                    644:                        clear.x2-i+1, clear.y2 - clear.y1 + 1, "backtile");
                    645:                clear.x2 = right;
                    646:        }
                    647: }
                    648: //===============================================================
                    649: #define STAT_MINUS             10      // num frame for '-' stats digit
                    650: char           *sb_nums[2][11] = 
                    651: {
                    652:        {"num_0", "num_1", "num_2", "num_3", "num_4", "num_5",
                    653:        "num_6", "num_7", "num_8", "num_9", "num_minus"},
                    654:        {"anum_0", "anum_1", "anum_2", "anum_3", "anum_4", "anum_5",
                    655:        "anum_6", "anum_7", "anum_8", "anum_9", "anum_minus"}
                    656: };
                    657: #define        ICON_WIDTH      24
                    658: #define        ICON_HEIGHT     24
                    659: #define        CHAR_WIDTH      16
                    660: #define        ICON_SPACE      8
                    661: /*
                    662: ================
                    663: SizeHUDString
                    664: Allow embedded \n in the string
                    665: ================
                    666: */
                    667: void SizeHUDString (char *string, int *w, int *h)
                    668: {
                    669:        int             lines, width, current;
                    670:        lines = 1;
                    671:        width = 0;
                    672:        current = 0;
                    673:        while (*string)
                    674:        {
                    675:                if (*string == '\n')
                    676:                {
                    677:                        lines++;
                    678:                        current = 0;
                    679:                }
                    680:                else
                    681:                {
                    682:                        current++;
                    683:                        if (current > width)
                    684:                                width = current;
                    685:                }
                    686:                string++;
                    687:        }
                    688:        *w = width * 8;
                    689:        *h = lines * 8;
                    690: }
                    691: void DrawHUDString (char *string, int x, int y, int centerwidth, int xor)
                    692: {
                    693:        int             margin;
                    694:        char    line[1024];
                    695:        int             width;
                    696:        int             i;
                    697:        margin = x;
                    698:        while (*string)
                    699:        {
                    700:                // scan out one line of text from the string
                    701:                width = 0;
                    702:                while (*string && *string != '\n')
                    703:                        line[width++] = *string++;
                    704:                line[width] = 0;
                    705:                if (centerwidth)
                    706:                        x = margin + (centerwidth - width*8)/2;
                    707:                else
                    708:                        x = margin;
                    709:                for (i=0 ; i<width ; i++)
                    710:                {
                    711:                        re.DrawChar (x, y, line[i]^xor);
                    712:                        x += 8;
                    713:                }
                    714:                if (*string)
                    715:                {
                    716:                        string++;       // skip the \n
                    717:                        x = margin;
                    718:                        y += 8;
                    719:                }
                    720:        }
                    721: }
                    722: /*
                    723: ==============
                    724: SCR_DrawField
                    725: ==============
                    726: */
                    727: void SCR_DrawField (int x, int y, int color, int width, int value)
                    728: {
                    729:        char    num[16], *ptr;
                    730:        int             l;
                    731:        int             frame;
                    732:        if (width < 1)
                    733:                return;
                    734:        // draw number string
                    735:        if (width > 5)
                    736:                width = 5;
                    737:        SCR_AddDirtyPoint (x, y);
                    738:        SCR_AddDirtyPoint (x+width*CHAR_WIDTH+2, y+23);
                    739: 
                    740:        Com_sprintf (num, sizeof(num), "%i", value);
                    741:        l = strlen(num);
                    742:        if (l > width)
                    743:                l = width;
                    744:        x += 2 + CHAR_WIDTH*(width - l);
                    745:        ptr = num;
                    746:        while (*ptr && l)
                    747:        {
                    748:                if (*ptr == '-')
                    749:                        frame = STAT_MINUS;
                    750:                else
                    751:                        frame = *ptr -'0';
                    752:                re.DrawPic (x,y,sb_nums[color][frame]);
                    753:                x += CHAR_WIDTH;
                    754:                ptr++;
                    755:                l--;
                    756:        }
                    757: }
                    758: /*
                    759: ===============
                    760: SCR_TouchPics
                    761: Allows rendering code to cache all needed sbar graphics
                    762: ===============
                    763: */
                    764: void SCR_TouchPics (void)
                    765: {
                    766:        int             i, j;
                    767:        for (i=0 ; i<2 ; i++)
                    768:                for (j=0 ; j<11 ; j++)
                    769:                        re.RegisterPic (sb_nums[i][j]);
                    770: 
                    771:        if (crosshair->value)
                    772:        {
                    773:                if (crosshair->value > 3 || crosshair->value < 0)
                    774:                        crosshair->value = 3;
                    775: 
                    776:                Com_sprintf (crosshair_pic, sizeof(crosshair_pic), "ch%i", (int)(crosshair->value));
                    777:                re.DrawGetPicSize (&crosshair_width, &crosshair_height, crosshair_pic);
                    778:                if (!crosshair_width)
                    779:                        crosshair_pic[0] = 0;
                    780:        }
                    781: }
                    782: /*
                    783: ================
                    784: SCR_ExecuteLayoutString 
                    785: ================
                    786: */
                    787: void SCR_ExecuteLayoutString (char *s)
                    788: {
                    789:        int             x, y;
                    790:        int             value;
                    791:        char    *token;
                    792:        int             width;
                    793:        int             index;
                    794:        clientinfo_t    *ci;
                    795:        if (cls.state != ca_active || !cl.refresh_prepped)
                    796:                return;
                    797:        if (!s[0])
                    798:                return;
                    799:        x = 0;
                    800:        y = 0;
                    801:        width = 3;
                    802:        while (s)
                    803:        {
                    804:                token = COM_Parse (&s);
                    805:                if (!strcmp(token, "xl"))
                    806:                {
                    807:                        token = COM_Parse (&s);
                    808:                        x = atoi(token);
                    809:                        continue;
                    810:                }
                    811:                if (!strcmp(token, "xr"))
                    812:                {
                    813:                        token = COM_Parse (&s);
                    814:                        x = viddef.width + atoi(token);
                    815:                        continue;
                    816:                }
                    817:                if (!strcmp(token, "xv"))
                    818:                {
                    819:                        token = COM_Parse (&s);
                    820:                        x = viddef.width/2 - 160 + atoi(token);
                    821:                        continue;
                    822:                }
                    823:                if (!strcmp(token, "yt"))
                    824:                {
                    825:                        token = COM_Parse (&s);
                    826:                        y = atoi(token);
                    827:                        continue;
                    828:                }
                    829:                if (!strcmp(token, "yb"))
                    830:                {
                    831:                        token = COM_Parse (&s);
                    832:                        y = viddef.height + atoi(token);
                    833:                        continue;
                    834:                }
                    835:                if (!strcmp(token, "yv"))
                    836:                {
                    837:                        token = COM_Parse (&s);
                    838:                        y = viddef.height/2 - 120 + atoi(token);
                    839:                        continue;
                    840:                }
                    841:                if (!strcmp(token, "pic"))
                    842:                {       // draw a pic from a stat number
                    843:                        token = COM_Parse (&s);
                    844:                        value = cl.frame.playerstate.stats[atoi(token)];
                    845:                        if (value >= MAX_IMAGES)
                    846:                                Com_Error (ERR_DROP, "Pic >= MAX_IMAGES");
                    847:                        if (cl.configstrings[CS_IMAGES+value])
                    848:                        {
                    849:                                SCR_AddDirtyPoint (x, y);
                    850:                                SCR_AddDirtyPoint (x+23, y+23);
                    851:                                re.DrawPic (x, y, cl.configstrings[CS_IMAGES+value]);
                    852:                        }
                    853:                        continue;
                    854:                }
                    855: 
                    856:                if (!strcmp(token, "client"))
                    857:                {       // draw a deathmatch client block
                    858:                        int             score, ping, time;
                    859: 
                    860:                        token = COM_Parse (&s);
                    861:                        x = viddef.width/2 - 160 + atoi(token);
                    862:                        token = COM_Parse (&s);
                    863:                        y = viddef.height/2 - 120 + atoi(token);
                    864:                        SCR_AddDirtyPoint (x, y);
                    865:                        SCR_AddDirtyPoint (x+159, y+31);
                    866: 
                    867:                        token = COM_Parse (&s);
                    868:                        value = atoi(token);
                    869:                        if (value >= MAX_CLIENTS || value < 0)
                    870:                                Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
                    871:                        ci = &cl.clientinfo[value];
                    872: 
                    873:                        token = COM_Parse (&s);
                    874:                        score = atoi(token);
                    875: 
                    876:                        token = COM_Parse (&s);
                    877:                        ping = atoi(token);
                    878: 
                    879:                        token = COM_Parse (&s);
                    880:                        time = atoi(token);
                    881: 
                    882:                        DrawAltString (x+32, y, ci->name);
                    883:                        DrawString (x+32, y+8,  "Score: ");
                    884:                        DrawAltString (x+32+7*8, y+8,  va("%i", score));
                    885:                        DrawString (x+32, y+16, va("Ping:  %i", ping));
                    886:                        DrawString (x+32, y+24, va("Time:  %i", time));
                    887: 
                    888:                        if (!ci->icon)
                    889:                                ci = &cl.baseclientinfo;
                    890:                        re.DrawPic (x, y, ci->iconname);
                    891:                        continue;
                    892:                }
                    893: 
                    894:                if (!strcmp(token, "ctf"))
                    895:                {       // draw a ctf client block
                    896:                        int             score, ping;
                    897:                        char    block[80];
                    898: 
                    899:                        token = COM_Parse (&s);
                    900:                        x = viddef.width/2 - 160 + atoi(token);
                    901:                        token = COM_Parse (&s);
                    902:                        y = viddef.height/2 - 120 + atoi(token);
                    903:                        SCR_AddDirtyPoint (x, y);
                    904:                        SCR_AddDirtyPoint (x+159, y+31);
                    905: 
                    906:                        token = COM_Parse (&s);
                    907:                        value = atoi(token);
                    908:                        if (value >= MAX_CLIENTS || value < 0)
                    909:                                Com_Error (ERR_DROP, "client >= MAX_CLIENTS");
                    910:                        ci = &cl.clientinfo[value];
                    911: 
                    912:                        token = COM_Parse (&s);
                    913:                        score = atoi(token);
                    914: 
                    915:                        token = COM_Parse (&s);
                    916:                        ping = atoi(token);
                    917:                        if (ping > 999)
                    918:                                ping = 999;
                    919: 
                    920:                        sprintf(block, "%3d %3d %-12.12s", score, ping, ci->name);
                    921: 
                    922:                        if (value == cl.playernum)
                    923:                                DrawAltString (x, y, block);
                    924:                        else
                    925:                                DrawString (x, y, block);
                    926:                        continue;
                    927:                }
                    928: 
                    929:                if (!strcmp(token, "picn"))
                    930:                {       // draw a pic from a name
                    931:                        token = COM_Parse (&s);
                    932:                        SCR_AddDirtyPoint (x, y);
                    933:                        SCR_AddDirtyPoint (x+23, y+23);
                    934:                        re.DrawPic (x, y, token);
                    935:                        continue;
                    936:                }
                    937:                if (!strcmp(token, "num"))
                    938:                {       // draw a number
                    939:                        token = COM_Parse (&s);
                    940:                        width = atoi(token);
                    941:                        token = COM_Parse (&s);
                    942:                        value = cl.frame.playerstate.stats[atoi(token)];
                    943:                        SCR_DrawField (x, y, 0, width, value);
                    944:                        continue;
                    945:                }
                    946: 
                    947:                if (!strcmp(token, "hnum"))
                    948:                {       // health number
                    949:                        int             color;
                    950: 
                    951:                        width = 3;
                    952:                        value = cl.frame.playerstate.stats[STAT_HEALTH];
                    953:                        if (value > 25)
                    954:                                color = 0;      // green
                    955:                        else if (value > 0)
                    956:                                color = (cl.frame.serverframe>>2) & 1;          // flash
                    957:                        else
                    958:                                color = 1;
                    959: 
                    960:                        if (cl.frame.playerstate.stats[STAT_FLASHES] & 1)
                    961:                                re.DrawPic (x, y, "field_3");
                    962: 
                    963:                        SCR_DrawField (x, y, color, width, value);
                    964:                        continue;
                    965:                }
                    966: 
                    967:                if (!strcmp(token, "anum"))
                    968:                {       // ammo number
                    969:                        int             color;
                    970: 
                    971:                        width = 3;
                    972:                        value = cl.frame.playerstate.stats[STAT_AMMO];
                    973:                        if (value > 5)
                    974:                                color = 0;      // green
                    975:                        else if (value >= 0)
                    976:                                color = (cl.frame.serverframe>>2) & 1;          // flash
                    977:                        else
                    978:                                continue;       // negative number = don't show
                    979: 
                    980:                        if (cl.frame.playerstate.stats[STAT_FLASHES] & 4)
                    981:                                re.DrawPic (x, y, "field_3");
                    982: 
                    983:                        SCR_DrawField (x, y, color, width, value);
                    984:                        continue;
                    985:                }
                    986: 
                    987:                if (!strcmp(token, "rnum"))
                    988:                {       // armor number
                    989:                        int             color;
                    990: 
                    991:                        width = 3;
                    992:                        value = cl.frame.playerstate.stats[STAT_ARMOR];
                    993:                        if (value < 1)
                    994:                                continue;
                    995: 
                    996:                        color = 0;      // green
                    997: 
                    998:                        if (cl.frame.playerstate.stats[STAT_FLASHES] & 2)
                    999:                                re.DrawPic (x, y, "field_3");
                   1000: 
                   1001:                        SCR_DrawField (x, y, color, width, value);
                   1002:                        continue;
                   1003:                }
                   1004: 
                   1005: 
                   1006:                if (!strcmp(token, "stat_string"))
                   1007:                {
                   1008:                        token = COM_Parse (&s);
                   1009:                        index = atoi(token);
                   1010:                        if (index < 0 || index >= MAX_CONFIGSTRINGS)
                   1011:                                Com_Error (ERR_DROP, "Bad stat_string index");
                   1012:                        index = cl.frame.playerstate.stats[index];
                   1013:                        if (index < 0 || index >= MAX_CONFIGSTRINGS)
                   1014:                                Com_Error (ERR_DROP, "Bad stat_string index");
                   1015:                        DrawString (x, y, cl.configstrings[index]);
                   1016:                        continue;
                   1017:                }
                   1018:                if (!strcmp(token, "cstring"))
                   1019:                {
                   1020:                        token = COM_Parse (&s);
                   1021:                        DrawHUDString (token, x, y, 320, 0);
                   1022:                        continue;
                   1023:                }
                   1024:                if (!strcmp(token, "string"))
                   1025:                {
                   1026:                        token = COM_Parse (&s);
                   1027:                        DrawString (x, y, token);
                   1028:                        continue;
                   1029:                }
                   1030: 
                   1031:                if (!strcmp(token, "cstring2"))
                   1032:                {
                   1033:                        token = COM_Parse (&s);
                   1034:                        DrawHUDString (token, x, y, 320,0x80);
                   1035:                        continue;
                   1036:                }
                   1037: 
                   1038:                if (!strcmp(token, "string2"))
                   1039:                {
                   1040:                        token = COM_Parse (&s);
                   1041:                        DrawAltString (x, y, token);
                   1042:                        continue;
                   1043:                }
                   1044:                if (!strcmp(token, "if"))
                   1045:                {       // draw a number
                   1046:                        token = COM_Parse (&s);
                   1047:                        value = cl.frame.playerstate.stats[atoi(token)];
                   1048:                        if (!value)
                   1049:                        {       // skip to endif
                   1050:                                while (s && strcmp(token, "endif") )
                   1051:                                {
                   1052:                                        token = COM_Parse (&s);
                   1053:                                }
                   1054:                        }
                   1055:                        continue;
                   1056:                }
                   1057:        }
                   1058: }
                   1059: /*
                   1060: ================
                   1061: SCR_DrawStats
                   1062: The status bar is a small layout program that
                   1063: is based on the stats array
                   1064: ================
                   1065: */
                   1066: void SCR_DrawStats (void)
                   1067: {
                   1068:        SCR_ExecuteLayoutString (cl.configstrings[CS_STATUSBAR]);
                   1069: }
                   1070: /*
                   1071: ================
                   1072: SCR_DrawLayout
                   1073: ================
                   1074: */
                   1075: #define        STAT_LAYOUTS            13
                   1076: void SCR_DrawLayout (void)
                   1077: {
                   1078:        if (!cl.frame.playerstate.stats[STAT_LAYOUTS])
                   1079:                return;
                   1080:        SCR_ExecuteLayoutString (cl.layout);
                   1081: }
                   1082: //=======================================================
                   1083: /*
                   1084: ==================
                   1085: SCR_UpdateScreen
                   1086: This is called every frame, and can also be called explicitly to flush
                   1087: text to the screen.
                   1088: ==================
                   1089: */
                   1090: void SCR_UpdateScreen (void)
                   1091: {
                   1092:        int numframes;
                   1093:        int i;
                   1094:        float separation[2] = { 0, 0 };
                   1095: 
                   1096:        // if the screen is disabled (loading plaque is up, or vid mode changing)
                   1097:        // do nothing at all
                   1098:        if (cls.disable_screen)
                   1099:        {
                   1100:                if (Sys_Milliseconds() - cls.disable_screen > 120000)
                   1101:                {
                   1102:                        cls.disable_screen = 0;
                   1103:                        Com_Printf ("Loading plaque timed out.\n");
                   1104:                }
                   1105:                return;
                   1106:        }
                   1107: 
                   1108:        if (!scr_initialized || !con.initialized)
                   1109:                return;                         // not initialized yet
                   1110: 
                   1111:        /*
                   1112:        ** range check cl_camera_separation so we don't inadvertently fry someone's
                   1113:        ** brain
                   1114:        */
                   1115:        if ( cl_stereo_separation->value > 1.0 )
                   1116:                Cvar_SetValue( "cl_stereo_separation", 1.0 );
                   1117:        else if ( cl_stereo_separation->value < 0 )
                   1118:                Cvar_SetValue( "cl_stereo_separation", 0.0 );
                   1119: 
                   1120:        if ( cl_stereo->value )
                   1121:        {
                   1122:                numframes = 2;
                   1123:                separation[0] = -cl_stereo_separation->value / 2;
                   1124:                separation[1] =  cl_stereo_separation->value / 2;
                   1125:        }               
                   1126:        else
                   1127:        {
                   1128:                separation[0] = 0;
                   1129:                separation[1] = 0;
                   1130:                numframes = 1;
                   1131:        }
                   1132:        for ( i = 0; i < numframes; i++ )
                   1133:        {
                   1134:                re.BeginFrame( separation[i] );
                   1135:                if (scr_draw_loading == 2)
                   1136:                {       //  loading plaque over black screen
                   1137:                        int             w, h;
                   1138:                        re.CinematicSetPalette(NULL);
                   1139:                        scr_draw_loading = false;
                   1140:                        re.DrawGetPicSize (&w, &h, "loading");
                   1141:                        re.DrawPic ((viddef.width-w)/2, (viddef.height-h)/2, "loading");
                   1142: //                     re.EndFrame();
                   1143: //                     return;
                   1144:                } 
                   1145:                // if a cinematic is supposed to be running, handle menus
                   1146:                // and console specially
                   1147:                else if (cl.cinematictime > 0)
                   1148:                {
                   1149:                        if (cls.key_dest == key_menu)
                   1150:                        {
                   1151:                                if (cl.cinematicpalette_active)
                   1152:                                {
                   1153:                                        re.CinematicSetPalette(NULL);
                   1154:                                        cl.cinematicpalette_active = false;
                   1155:                                }
                   1156:                                M_Draw ();
                   1157: //                             re.EndFrame();
                   1158: //                             return;
                   1159:                        }
                   1160:                        else if (cls.key_dest == key_console)
                   1161:                        {
                   1162:                                if (cl.cinematicpalette_active)
                   1163:                                {
                   1164:                                        re.CinematicSetPalette(NULL);
                   1165:                                        cl.cinematicpalette_active = false;
                   1166:                                }
                   1167:                                SCR_DrawConsole ();
                   1168: //                             re.EndFrame();
                   1169: //                             return;
                   1170:                        }
                   1171:                        else
                   1172:                        {
                   1173:                                SCR_DrawCinematic();
                   1174: //                             re.EndFrame();
                   1175: //                             return;
                   1176:                        }
                   1177:                }
                   1178:                else 
                   1179:                {
                   1180:                        // make sure the game palette is active
                   1181:                        if (cl.cinematicpalette_active)
                   1182:                        {
                   1183:                                re.CinematicSetPalette(NULL);
                   1184:                                cl.cinematicpalette_active = false;
                   1185:                        }
                   1186:                        // do 3D refresh drawing, and then update the screen
                   1187:                        SCR_CalcVrect ();
                   1188:                        // clear any dirty part of the background
                   1189:                        SCR_TileClear ();
                   1190:                        V_RenderView ( separation[i] );
                   1191:                        SCR_DrawStats ();
                   1192:                        if (cl.frame.playerstate.stats[STAT_LAYOUTS] & 1)
                   1193:                                SCR_DrawLayout ();
                   1194:                        if (cl.frame.playerstate.stats[STAT_LAYOUTS] & 2)
                   1195:                                CL_DrawInventory ();
                   1196: 
                   1197:                        SCR_DrawNet ();
                   1198:                        SCR_CheckDrawCenterString ();
                   1199:                        if (scr_timegraph->value)
                   1200:                                SCR_DebugGraph (cls.frametime*300, 0);
                   1201:                        if (scr_debuggraph->value || scr_timegraph->value || scr_netgraph->value)
                   1202:                                SCR_DrawDebugGraph ();
                   1203:                        SCR_DrawPause ();
                   1204:                        SCR_DrawConsole ();
                   1205:                        M_Draw ();
                   1206:                        SCR_DrawLoading ();
                   1207:                }
                   1208:        }
                   1209:        re.EndFrame();
                   1210: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.