X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=cl_screen.c;h=dc0418a19968096b6fdf22f8af521f61bf972817;hp=c174176365bcbbdebdf3624c4f3388088c10a6a5;hb=6f4bdacc137d137d64882beb27d6dc0091de0f0e;hpb=fdfa815d659f4ceec149ce3f907c107f38022c3d diff --git a/cl_screen.c b/cl_screen.c index c1741763..dc0418a1 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -2,33 +2,42 @@ #include "quakedef.h" #include "cl_video.h" #include "jpeg.h" +#include "cl_collision.h" cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"}; -cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 10 - 170 +cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 1 - 170 cvar_t scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300 +cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"}; +cvar_t scr_conbrightness = {CVAR_SAVE, "scr_conbrightness", "0.2"}; +cvar_t scr_conforcewhiledisconnected = {CVAR_SAVE, "scr_conforcewhiledisconnected", "1"}; cvar_t scr_centertime = {0, "scr_centertime","2"}; cvar_t scr_showram = {CVAR_SAVE, "showram","1"}; cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0"}; cvar_t scr_showpause = {CVAR_SAVE, "showpause","1"}; cvar_t scr_printspeed = {0, "scr_printspeed","8"}; -cvar_t scr_2dresolution = {CVAR_SAVE, "scr_2dresolution", "1"}; +cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640"}; +cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480"}; +cvar_t vid_pixelaspect = {CVAR_SAVE, "vid_pixelaspect", "1"}; cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","0"}; -cvar_t cl_avidemo = {0, "cl_avidemo", "0"}; +cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9"}; +cvar_t scr_screenshot_gamma = {CVAR_SAVE, "scr_screenshot_gamma","2.2"}; +cvar_t scr_screenshot_name = {0, "scr_screenshot_name","dp"}; +cvar_t cl_capturevideo = {0, "cl_capturevideo", "0"}; +cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30"}; +cvar_t cl_capturevideo_rawrgb = {0, "cl_capturevideo_rawrgb", "0"}; +cvar_t cl_capturevideo_rawyv12 = {0, "cl_capturevideo_rawyv12", "0"}; +cvar_t r_textshadow = {0, "r_textshadow", "0"}; +cvar_t r_letterbox = {0, "r_letterbox", "0"}; + +int jpeg_supported = false; qboolean scr_initialized; // ready to draw float scr_con_current; -float scr_conlines; // lines of console to display -int clearconsole; -int clearnotify; - -qboolean scr_drawloading = false; - -static qbyte menuplyr_pixels[4096]; +extern int con_vislines; void DrawCrosshair(int num); -void V_CalcRefdef (void); static void SCR_ScreenShot_f (void); static void R_Envmap_f (void); @@ -58,9 +67,9 @@ Called for important messages that should stay in the center of the screen for a few moments ============== */ -void SCR_CenterPrint (char *str) +void SCR_CenterPrint(char *str) { - strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); + strlcpy (scr_centerstring, str, sizeof (scr_centerstring)); scr_centertime_off = scr_centertime.value; scr_centertime_start = cl.time; @@ -99,7 +108,7 @@ void SCR_DrawCenterString (void) do { // scan the width of the line - for (l=0 ; l<40 ; l++) + for (l=0 ; lwidth)/2, (vid.conheight - pic->height)/2, "gfx/loading.lmp", 0, 0, 1, 1, 1, 1, 0); -} - //============================================================================= @@ -237,39 +233,40 @@ SCR_SetUpToDrawConsole */ void SCR_SetUpToDrawConsole (void) { + // lines of console to display + float conlines; + Con_CheckResize (); - if (key_dest == key_game && cls.signon != SIGNONS) + if (key_dest == key_game && cls.signon != SIGNONS && scr_conforcewhiledisconnected.integer) key_consoleactive |= KEY_CONSOLEACTIVE_FORCED; else key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED; // decide on the height of the console - if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED) - scr_conlines = vid.conheight; // full screen - else if (key_consoleactive & KEY_CONSOLEACTIVE_USER) - scr_conlines = vid.conheight/2; // half screen + if (key_consoleactive & KEY_CONSOLEACTIVE_USER) + conlines = vid.conheight/2; // half screen else - scr_conlines = 0; // none visible + conlines = 0; // none visible if (scr_conspeed.value) { - if (scr_conlines < scr_con_current) + if (scr_con_current > conlines) { scr_con_current -= scr_conspeed.value*host_realframetime; - if (scr_conlines > scr_con_current) - scr_con_current = scr_conlines; + if (scr_con_current < conlines) + scr_con_current = conlines; } - else if (scr_conlines > scr_con_current) + else if (scr_con_current < conlines) { scr_con_current += scr_conspeed.value*host_realframetime; - if (scr_conlines < scr_con_current) - scr_con_current = scr_conlines; + if (scr_con_current > conlines) + scr_con_current = conlines; } } else - scr_con_current = scr_conlines; + scr_con_current = conlines; } /* @@ -279,13 +276,16 @@ SCR_DrawConsole */ void SCR_DrawConsole (void) { - if (scr_con_current) + if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED) { - Con_DrawConsole (scr_con_current); - clearconsole = 0; + // full screen + Con_DrawConsole (vid.conheight); } + else if (scr_con_current) + Con_DrawConsole (scr_con_current); else { + con_vislines = 0; if (key_dest == key_game || key_dest == key_message) Con_DrawNotify (); // only draw notify in game } @@ -299,15 +299,8 @@ SCR_BeginLoadingPlaque */ void SCR_BeginLoadingPlaque (void) { - if (scr_drawloading) - return; - - S_StopAllSounds (true); - - scr_drawloading = true; - CL_UpdateScreen (); - scr_drawloading = true; - CL_UpdateScreen (); + S_StopAllSounds (); + SCR_UpdateLoadingScreen(); } //============================================================================= @@ -352,9 +345,6 @@ void R_TimeReport(char *desc) } } -extern int c_rt_lights, c_rt_clears, c_rt_scissored; -extern int c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris; -extern int c_rtcached_shadowmeshes, c_rtcached_shadowtris; void R_TimeReport_Start(void) { r_timereport_active = r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected; @@ -362,24 +352,14 @@ void R_TimeReport_Start(void) if (r_timereport_active) { speedstringcount = 0; - AngleVectors (r_refdef.viewangles, vpn, NULL, NULL); - sprintf(r_speeds_string, - "org:'%+8.2f %+8.2f %+8.2f' ang:'%+4.0f %+4.0f %+4.0f' dir:'%+2.3f %+2.3f %+2.3f'\n" - "world:%6i faces%6i nodes%6i leafs%6i dlitwalls\n" - "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n" - "%6i modeltris%6i meshs%6i meshtris\n", - r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2], r_refdef.viewangles[0], r_refdef.viewangles[1], r_refdef.viewangles[2], vpn[0], vpn[1], vpn[2], - c_faces, c_nodes, c_leafs, c_light_polys, - c_models, c_bmodels, c_sprites, c_particles, c_dlights, - c_alias_polys, c_meshs, c_meshelements / 3); - - sprintf(r_speeds_string + strlen(r_speeds_string), - "realtime lighting:%4i lights%4i clears%4i scissored\n" - "dynamic: %6i shadowmeshes%6i shadowtris%6i lightmeshes%6i lighttris\n" - "precomputed: %6i shadowmeshes%6i shadowtris\n", - c_rt_lights, c_rt_clears, c_rt_scissored, - c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, - c_rtcached_shadowmeshes, c_rtcached_shadowtris); + sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2]); + sprintf(r_speeds_string + strlen(r_speeds_string), "world:%6i faces%6i nodes%6i leafs%6i dlitwalls\n", c_faces, c_nodes, c_leafs, c_light_polys); + sprintf(r_speeds_string + strlen(r_speeds_string), "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n", c_models, c_bmodels, c_sprites, c_particles, c_dlights); + sprintf(r_speeds_string + strlen(r_speeds_string), "%6i modeltris%6i meshs%6i meshtris\n", c_alias_polys, c_meshs, c_meshelements / 3); + sprintf(r_speeds_string + strlen(r_speeds_string), "bloom %s: %i copies (%i pixels) %i draws (%i pixels)\n", c_bloom ? "active" : "inactive", c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels); + sprintf(r_speeds_string + strlen(r_speeds_string), "realtime lighting:%4i lights%4i clears%4i scissored\n", c_rt_lights, c_rt_clears, c_rt_scissored); + sprintf(r_speeds_string + strlen(r_speeds_string), "dynamic: %6i shadowmeshes%6i shadowtris%6i lightmeshes%6i lighttris\n", c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris); + sprintf(r_speeds_string + strlen(r_speeds_string), "precomputed: %6i shadowmeshes%6i shadowtris\n", c_rtcached_shadowmeshes, c_rtcached_shadowtris); c_alias_polys = 0; c_light_polys = 0; @@ -390,8 +370,23 @@ void R_TimeReport_Start(void) c_bmodels = 0; c_sprites = 0; c_particles = 0; + c_dlights = 0; c_meshs = 0; c_meshelements = 0; + c_rt_lights = 0; + c_rt_clears = 0; + c_rt_scissored = 0; + c_rt_shadowmeshes = 0; + c_rt_shadowtris = 0; + c_rt_lightmeshes = 0; + c_rt_lighttris = 0; + c_rtcached_shadowmeshes = 0; + c_rtcached_shadowtris = 0; + c_bloom = 0; + c_bloomcopies = 0; + c_bloomcopypixels = 0; + c_bloomdraws = 0; + c_bloomdrawpixels = 0; r_timereport_start = Sys_DoubleTime(); } @@ -453,19 +448,29 @@ void SCR_SizeDown_f (void) void CL_Screen_Init(void) { - qpic_t *dat; - Cvar_RegisterVariable (&scr_fov); Cvar_RegisterVariable (&scr_viewsize); Cvar_RegisterVariable (&scr_conspeed); + Cvar_RegisterVariable (&scr_conalpha); + Cvar_RegisterVariable (&scr_conbrightness); + Cvar_RegisterVariable (&scr_conforcewhiledisconnected); Cvar_RegisterVariable (&scr_showram); Cvar_RegisterVariable (&scr_showturtle); Cvar_RegisterVariable (&scr_showpause); Cvar_RegisterVariable (&scr_centertime); Cvar_RegisterVariable (&scr_printspeed); - Cvar_RegisterVariable (&scr_2dresolution); + Cvar_RegisterVariable (&vid_conwidth); + Cvar_RegisterVariable (&vid_conheight); + Cvar_RegisterVariable (&vid_pixelaspect); Cvar_RegisterVariable (&scr_screenshot_jpeg); - Cvar_RegisterVariable (&cl_avidemo); + Cvar_RegisterVariable (&scr_screenshot_jpeg_quality); + Cvar_RegisterVariable (&scr_screenshot_gamma); + Cvar_RegisterVariable (&cl_capturevideo); + Cvar_RegisterVariable (&cl_capturevideo_fps); + Cvar_RegisterVariable (&cl_capturevideo_rawrgb); + Cvar_RegisterVariable (&cl_capturevideo_rawyv12); + Cvar_RegisterVariable (&r_textshadow); + Cvar_RegisterVariable (&r_letterbox); Cmd_AddCommand ("sizeup",SCR_SizeUp_f); Cmd_AddCommand ("sizedown",SCR_SizeDown_f); @@ -473,19 +478,6 @@ void CL_Screen_Init(void) Cmd_AddCommand ("envmap", R_Envmap_f); scr_initialized = true; - - // HACK HACK HACK - // load the image data for the player image in the config menu - dat = (qpic_t *)FS_LoadFile ("gfx/menuplyr.lmp", false); - if (!dat) - Sys_Error("unable to load gfx/menuplyr.lmp"); - SwapPic (dat); - - if (dat->width*dat->height <= 4096) - memcpy (menuplyr_pixels, dat->data, dat->width * dat->height); - else - Con_Printf("gfx/menuplyr.lmp larger than 4k buffer"); - Mem_Free(dat); } void DrawQ_Clear(void) @@ -499,7 +491,7 @@ void DrawQ_Pic(float x, float y, char *picname, float width, float height, float DrawQ_SuperPic(x,y,picname,width,height,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags); } -void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags) +void DrawQ_String_Real(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags) { int size, len; drawqueue_t *dq; @@ -514,7 +506,7 @@ void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex for (;len > 0 && string[len - 1] == ' ';len--); if (len < 1) return; - if (x >= vid.conwidth || y >= vid.conheight || x < (-scalex * maxlen) || y < (-scaley)) + if (x >= vid.conwidth || y >= vid.conheight || x < (-scalex * len) || y < (-scaley)) return; size = sizeof(*dq) + ((len + 1 + 3) & ~3); if (r_refdef.drawqueuesize + size > r_refdef.maxdrawqueuesize) @@ -538,6 +530,14 @@ void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex r_refdef.drawqueuesize += dq->size; } +void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags) +{ + if (r_textshadow.integer) + DrawQ_String_Real(x+scalex*0.25,y+scaley*0.25,string,maxlen,scalex,scaley,0,0,0,alpha*0.8,flags); + + DrawQ_String_Real(x,y,string,maxlen,scalex,scaley,red,green,blue,alpha,flags); +} + void DrawQ_Fill (float x, float y, float w, float h, float red, float green, float blue, float alpha, int flags) { DrawQ_SuperPic(x,y,NULL,w,h,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags); @@ -558,21 +558,21 @@ void DrawQ_SuperPic(float x, float y, char *picname, float width, float height, height = pic->height; mesh.texture = pic->tex; } - mesh.numtriangles = 2; - mesh.numvertices = 4; - mesh.element3i = picelements; - mesh.vertex3f = floats; - mesh.texcoord2f = floats + 12; - mesh.color4f = floats + 20; + mesh.num_triangles = 2; + mesh.num_vertices = 4; + mesh.data_element3i = picelements; + mesh.data_vertex3f = floats; + mesh.data_texcoord2f = floats + 12; + mesh.data_color4f = floats + 20; memset(floats, 0, sizeof(floats)); - mesh.vertex3f[0] = mesh.vertex3f[9] = x; - mesh.vertex3f[1] = mesh.vertex3f[4] = y; - mesh.vertex3f[3] = mesh.vertex3f[6] = x + width; - mesh.vertex3f[7] = mesh.vertex3f[10] = y + height; - mesh.texcoord2f[0] = s1;mesh.texcoord2f[1] = t1;mesh.color4f[ 0] = r1;mesh.color4f[ 1] = g1;mesh.color4f[ 2] = b1;mesh.color4f[ 3] = a1; - mesh.texcoord2f[2] = s2;mesh.texcoord2f[3] = t2;mesh.color4f[ 4] = r2;mesh.color4f[ 5] = g2;mesh.color4f[ 6] = b2;mesh.color4f[ 7] = a2; - mesh.texcoord2f[4] = s4;mesh.texcoord2f[5] = t4;mesh.color4f[ 8] = r4;mesh.color4f[ 9] = g4;mesh.color4f[10] = b4;mesh.color4f[11] = a4; - mesh.texcoord2f[6] = s3;mesh.texcoord2f[7] = t3;mesh.color4f[12] = r3;mesh.color4f[13] = g3;mesh.color4f[14] = b3;mesh.color4f[15] = a3; + mesh.data_vertex3f[0] = mesh.data_vertex3f[9] = x; + mesh.data_vertex3f[1] = mesh.data_vertex3f[4] = y; + mesh.data_vertex3f[3] = mesh.data_vertex3f[6] = x + width; + mesh.data_vertex3f[7] = mesh.data_vertex3f[10] = y + height; + mesh.data_texcoord2f[0] = s1;mesh.data_texcoord2f[1] = t1;mesh.data_color4f[ 0] = r1;mesh.data_color4f[ 1] = g1;mesh.data_color4f[ 2] = b1;mesh.data_color4f[ 3] = a1; + mesh.data_texcoord2f[2] = s2;mesh.data_texcoord2f[3] = t2;mesh.data_color4f[ 4] = r2;mesh.data_color4f[ 5] = g2;mesh.data_color4f[ 6] = b2;mesh.data_color4f[ 7] = a2; + mesh.data_texcoord2f[4] = s4;mesh.data_texcoord2f[5] = t4;mesh.data_color4f[ 8] = r4;mesh.data_color4f[ 9] = g4;mesh.data_color4f[10] = b4;mesh.data_color4f[11] = a4; + mesh.data_texcoord2f[6] = s3;mesh.data_texcoord2f[7] = t3;mesh.data_color4f[12] = r3;mesh.data_color4f[13] = g3;mesh.data_color4f[14] = b3;mesh.data_color4f[15] = a3; DrawQ_Mesh (&mesh, flags); } @@ -584,10 +584,10 @@ void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags) drawqueuemesh_t *m; size = sizeof(*dq); size += sizeof(drawqueuemesh_t); - size += sizeof(int[3]) * mesh->numtriangles; - size += sizeof(float[3]) * mesh->numvertices; - size += sizeof(float[2]) * mesh->numvertices; - size += sizeof(float[4]) * mesh->numvertices; + size += sizeof(int[3]) * mesh->num_triangles; + size += sizeof(float[3]) * mesh->num_vertices; + size += sizeof(float[2]) * mesh->num_vertices; + size += sizeof(float[4]) * mesh->num_vertices; if (r_refdef.drawqueuesize + size > r_refdef.maxdrawqueuesize) return; dq = (void *)(r_refdef.drawqueue + r_refdef.drawqueuesize); @@ -600,160 +600,413 @@ void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags) dq->scalex = 0; dq->scaley = 0; p = (void *)(dq + 1); - m = p;(qbyte *)p += sizeof(drawqueuemesh_t); - m->numtriangles = mesh->numtriangles; - m->numvertices = mesh->numvertices; + m = p;p = (qbyte*)p + sizeof(drawqueuemesh_t); + m->num_triangles = mesh->num_triangles; + m->num_vertices = mesh->num_vertices; m->texture = mesh->texture; - m->element3i = p;memcpy(m->element3i , mesh->element3i , m->numtriangles * sizeof(int[3]));(qbyte *)p += m->numtriangles * sizeof(int[3]); - m->vertex3f = p;memcpy(m->vertex3f , mesh->vertex3f , m->numvertices * sizeof(float[3]));(qbyte *)p += m->numvertices * sizeof(float[3]); - m->texcoord2f = p;memcpy(m->texcoord2f, mesh->texcoord2f, m->numvertices * sizeof(float[2]));(qbyte *)p += m->numvertices * sizeof(float[2]); - m->color4f = p;memcpy(m->color4f , mesh->color4f , m->numvertices * sizeof(float[4]));(qbyte *)p += m->numvertices * sizeof(float[4]); + m->data_element3i = p;memcpy(m->data_element3i , mesh->data_element3i , m->num_triangles * sizeof(int[3]));p = (qbyte*)p + m->num_triangles * sizeof(int[3]); + m->data_vertex3f = p;memcpy(m->data_vertex3f , mesh->data_vertex3f , m->num_vertices * sizeof(float[3]));p = (qbyte*)p + m->num_vertices * sizeof(float[3]); + m->data_texcoord2f = p;memcpy(m->data_texcoord2f, mesh->data_texcoord2f, m->num_vertices * sizeof(float[2]));p = (qbyte*)p + m->num_vertices * sizeof(float[2]); + m->data_color4f = p;memcpy(m->data_color4f , mesh->data_color4f , m->num_vertices * sizeof(float[4]));p = (qbyte*)p + m->num_vertices * sizeof(float[4]); r_refdef.drawqueuesize += dq->size; } -/* -==================== -CalcFov -==================== -*/ -float CalcFov (float fov_x, float width, float height) +void DrawQ_SetClipArea(float x, float y, float width, float height) { - // calculate vision size and alter by aspect, then convert back to angle - return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI; + drawqueue_t * dq; + if(r_refdef.drawqueuesize + (int)sizeof(*dq) > r_refdef.maxdrawqueuesize) + { + Con_DPrint("DrawQueue full !\n"); + return; + } + dq = (void*) (r_refdef.drawqueue + r_refdef.drawqueuesize); + dq->size = sizeof(*dq); + dq->command = DRAWQUEUE_SETCLIP; + dq->x = x; + dq->y = y; + dq->scalex = width; + dq->scaley = height; + dq->flags = 0; + dq->color = 0; + + r_refdef.drawqueuesize += dq->size; } -/* -================= -SCR_CalcRefdef +void DrawQ_ResetClipArea(void) +{ + drawqueue_t *dq; + if(r_refdef.drawqueuesize + (int)sizeof(*dq) > r_refdef.maxdrawqueuesize) + { + Con_DPrint("DrawQueue full !\n"); + return; + } + dq = (void*) (r_refdef.drawqueue + r_refdef.drawqueuesize); + dq->size = sizeof(*dq); + dq->command = DRAWQUEUE_RESETCLIP; + dq->x = 0; + dq->y = 0; + dq->scalex = 0; + dq->scaley = 0; + dq->flags = 0; + dq->color = 0; -Must be called whenever vid changes -Internal use only -================= + r_refdef.drawqueuesize += dq->size; +} + +/* +================== +SCR_ScreenShot_f +================== */ -static void SCR_CalcRefdef (void) +void SCR_ScreenShot_f (void) { - float size; - int contents; + static int shotnumber; + static char oldname[MAX_QPATH]; + char base[MAX_QPATH]; + char filename[MAX_QPATH]; + qbyte *buffer1; + qbyte *buffer2; + qbyte *buffer3; + qboolean jpeg = (scr_screenshot_jpeg.integer != 0); -//======================================== + sprintf (base, "screenshots/%s", scr_screenshot_name.string); -// bound viewsize - if (scr_viewsize.value < 30) - Cvar_Set ("viewsize","30"); - if (scr_viewsize.value > 120) - Cvar_Set ("viewsize","120"); + if (strcmp (oldname, scr_screenshot_name.string)) + { + sprintf(oldname, "%s", scr_screenshot_name.string); + shotnumber = 0; + } -// bound field of view - if (scr_fov.value < 10) - Cvar_Set ("fov","10"); - if (scr_fov.value > 170) - Cvar_Set ("fov","170"); + // find a file name to save it to + for (;shotnumber < 1000000;shotnumber++) + if (!FS_SysFileExists(va("%s/%s%06d.tga", fs_gamedir, base, shotnumber)) && !FS_SysFileExists(va("%s/%s%06d.jpg", fs_gamedir, base, shotnumber))) + break; + if (shotnumber >= 1000000) + { + Con_Print("SCR_ScreenShot_f: Couldn't create the image file\n"); + return; + } -// intermission is always full screen - if (cl.intermission) + sprintf(filename, "%s%06d.%s", base, shotnumber, jpeg ? "jpg" : "tga"); + + buffer1 = Mem_Alloc(tempmempool, vid.realwidth * vid.realheight * 3); + buffer2 = Mem_Alloc(tempmempool, vid.realwidth * vid.realheight * 3); + buffer3 = Mem_Alloc(tempmempool, vid.realwidth * vid.realheight * 3 + 18); + + if (SCR_ScreenShot (filename, buffer1, buffer2, buffer3, vid.realx, vid.realy, vid.realwidth, vid.realheight, false, false, false, jpeg)) + Con_Printf("Wrote %s\n", filename); + else + Con_Printf("unable to write %s\n", filename); + + Mem_Free (buffer1); + Mem_Free (buffer2); + Mem_Free (buffer3); + + shotnumber++; +} + +typedef enum capturevideoformat_e +{ + CAPTUREVIDEOFORMAT_TARGA, + CAPTUREVIDEOFORMAT_JPEG, + CAPTUREVIDEOFORMAT_RAWRGB, + CAPTUREVIDEOFORMAT_RAWYV12 +} +capturevideoformat_t; + +qboolean cl_capturevideo_active = false; +capturevideoformat_t cl_capturevideo_format; +static double cl_capturevideo_starttime = 0; +double cl_capturevideo_framerate = 0; +static int cl_capturevideo_soundrate = 0; +static int cl_capturevideo_frame = 0; +static qbyte *cl_capturevideo_buffer = NULL; +static qfile_t *cl_capturevideo_videofile = NULL; +static qfile_t *cl_capturevideo_soundfile = NULL; +static short cl_capturevideo_rgbtoyuvscaletable[3][3][256]; +static unsigned char cl_capturevideo_yuvnormalizetable[3][256]; +//static unsigned char cl_capturevideo_rgbgammatable[3][256]; + +void SCR_CaptureVideo_BeginVideo(void) +{ + double gamma, g; + unsigned int i; + qbyte out[44]; + if (cl_capturevideo_active) + return; + // soundrate is figured out on the first SoundFrame + cl_capturevideo_active = true; + cl_capturevideo_starttime = Sys_DoubleTime(); + cl_capturevideo_framerate = bound(1, cl_capturevideo_fps.value, 1000); + cl_capturevideo_soundrate = 0; + cl_capturevideo_frame = 0; + cl_capturevideo_buffer = Mem_Alloc(tempmempool, vid.realwidth * vid.realheight * (3+3+3) + 18); + gamma = 1.0/scr_screenshot_gamma.value; + + /* + for (i = 0;i < 256;i++) { - size = 1; - sb_lines = 0; + unsigned char j = (unsigned char)bound(0, 255*pow(i/255.0, gamma), 255); + cl_capturevideo_rgbgammatable[0][i] = j; + cl_capturevideo_rgbgammatable[1][i] = j; + cl_capturevideo_rgbgammatable[2][i] = j; } - else + */ +/* +R = Y + 1.4075 * (Cr - 128); +G = Y + -0.3455 * (Cb - 128) + -0.7169 * (Cr - 128); +B = Y + 1.7790 * (Cb - 128); +Y = R * .299 + G * .587 + B * .114; +Cb = R * -.169 + G * -.332 + B * .500 + 128.; +Cr = R * .500 + G * -.419 + B * -.0813 + 128.; +*/ + for (i = 0;i < 256;i++) { - if (scr_viewsize.value >= 120) - sb_lines = 0; // no status bar at all - else if (scr_viewsize.value >= 110) - sb_lines = 24; // no inventory - else - sb_lines = 24+16+8; - size = scr_viewsize.value * (1.0 / 100.0); + g = 255*pow(i/255.0, gamma); + // Y weights from RGB + cl_capturevideo_rgbtoyuvscaletable[0][0][i] = (short)(g * 0.299); + cl_capturevideo_rgbtoyuvscaletable[0][1][i] = (short)(g * 0.587); + cl_capturevideo_rgbtoyuvscaletable[0][2][i] = (short)(g * 0.114); + // Cb weights from RGB + cl_capturevideo_rgbtoyuvscaletable[1][0][i] = (short)(g * -0.169); + cl_capturevideo_rgbtoyuvscaletable[1][1][i] = (short)(g * -0.332); + cl_capturevideo_rgbtoyuvscaletable[1][2][i] = (short)(g * 0.500); + // Cr weights from RGB + cl_capturevideo_rgbtoyuvscaletable[2][0][i] = (short)(g * 0.500); + cl_capturevideo_rgbtoyuvscaletable[2][1][i] = (short)(g * -0.419); + cl_capturevideo_rgbtoyuvscaletable[2][2][i] = (short)(g * -0.0813); + // range reduction of YCbCr to valid signal range + cl_capturevideo_yuvnormalizetable[0][i] = 16 + i * (236-16) / 256; + cl_capturevideo_yuvnormalizetable[1][i] = 16 + i * (240-16) / 256; + cl_capturevideo_yuvnormalizetable[2][i] = 16 + i * (240-16) / 256; } - if (size >= 1) + if (cl_capturevideo_rawrgb.integer) { - r_refdef.width = vid.realwidth; - r_refdef.height = vid.realheight; - r_refdef.x = 0; - r_refdef.y = 0; + cl_capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB; + cl_capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true); + } + else if (cl_capturevideo_rawyv12.integer) + { + cl_capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12; + cl_capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true); + } + else if (scr_screenshot_jpeg.integer) + { + cl_capturevideo_format = CAPTUREVIDEOFORMAT_JPEG; + cl_capturevideo_videofile = NULL; } else { - r_refdef.width = vid.realwidth * size; - r_refdef.height = vid.realheight * size; - r_refdef.x = (vid.realwidth - r_refdef.width)/2; - r_refdef.y = (vid.realheight - r_refdef.height)/2; + cl_capturevideo_format = CAPTUREVIDEOFORMAT_TARGA; + cl_capturevideo_videofile = NULL; } - r_refdef.width = bound(0, r_refdef.width, vid.realwidth); - r_refdef.height = bound(0, r_refdef.height, vid.realheight); - r_refdef.x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width) + vid.realx; - r_refdef.y = bound(0, r_refdef.y, vid.realheight - r_refdef.height) + vid.realy; + cl_capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true); - // LordHavoc: viewzoom (zoom in for sniper rifles, etc) - r_refdef.fov_x = scr_fov.value * cl.viewzoom; - r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height); - - if (cl.worldmodel) - { - Mod_CheckLoaded(cl.worldmodel); - contents = cl.worldmodel ? cl.worldmodel->PointContents(cl.worldmodel, r_refdef.vieworg) : CONTENTS_EMPTY; - if (contents != CONTENTS_EMPTY && contents != CONTENTS_SOLID) - { - r_refdef.fov_x *= (sin(cl.time * 4.7) * 0.015 + 0.985); - r_refdef.fov_y *= (sin(cl.time * 3.0) * 0.015 + 0.985); - } - } + // wave header will be filled out when video ends + memset(out, 0, 44); + FS_Write (cl_capturevideo_soundfile, out, 44); } -/* -================== -SCR_ScreenShot_f -================== -*/ -void SCR_ScreenShot_f (void) +void SCR_CaptureVideo_EndVideo(void) { - static int i = 0; - char filename[16]; - char checkname[MAX_OSPATH]; - const char* extens; - qboolean jpeg = (scr_screenshot_jpeg.integer != 0); + int i, n; + qbyte out[44]; + if (!cl_capturevideo_active) + return; + cl_capturevideo_active = false; - if (jpeg) - extens = "jpg"; - else - extens = "tga"; + if (cl_capturevideo_videofile) + { + FS_Close(cl_capturevideo_videofile); + cl_capturevideo_videofile = NULL; + } - // find a file name to save it to - for (; i<=9999 ; i++) + // finish the wave file + if (cl_capturevideo_soundfile) { - sprintf (filename, "dp%04i.%s", i, extens); - sprintf (checkname, "%s/%s", fs_gamedir, filename); - if (!FS_SysFileExists(checkname)) - break; + i = FS_Tell (cl_capturevideo_soundfile); + //"RIFF", (int) unknown (chunk size), "WAVE", + //"fmt ", (int) 16 (chunk size), (short) format 1 (uncompressed PCM), (short) 2 channels, (int) unknown rate, (int) unknown bytes per second, (short) 4 bytes per sample (channels * bytes per channel), (short) 16 bits per channel + //"data", (int) unknown (chunk size) + memcpy (out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\0data****", 44); + // the length of the whole RIFF chunk + n = i - 8; + out[4] = (n) & 0xFF; + out[5] = (n >> 8) & 0xFF; + out[6] = (n >> 16) & 0xFF; + out[7] = (n >> 24) & 0xFF; + // rate + n = cl_capturevideo_soundrate; + out[24] = (n) & 0xFF; + out[25] = (n >> 8) & 0xFF; + out[26] = (n >> 16) & 0xFF; + out[27] = (n >> 24) & 0xFF; + // bytes per second (rate * channels * bytes per channel) + n = cl_capturevideo_soundrate * 2 * 2; + out[28] = (n) & 0xFF; + out[29] = (n >> 8) & 0xFF; + out[30] = (n >> 16) & 0xFF; + out[31] = (n >> 24) & 0xFF; + // the length of the data chunk + n = i - 44; + out[40] = (n) & 0xFF; + out[41] = (n >> 8) & 0xFF; + out[42] = (n >> 16) & 0xFF; + out[43] = (n >> 24) & 0xFF; + FS_Seek (cl_capturevideo_soundfile, 0, SEEK_SET); + FS_Write (cl_capturevideo_soundfile, out, 44); + FS_Close (cl_capturevideo_soundfile); + cl_capturevideo_soundfile = NULL; } - if (i==10000) + + if (cl_capturevideo_buffer) { - Con_Printf ("SCR_ScreenShot_f: Couldn't create the image file\n"); - return; - } + Mem_Free (cl_capturevideo_buffer); + cl_capturevideo_buffer = NULL; + } - if (SCR_ScreenShot (filename, vid.realx, vid.realy, vid.realwidth, vid.realheight, jpeg)) - Con_Printf ("Wrote %s\n", filename); - else - Con_Printf ("unable to write %s\n", filename); + cl_capturevideo_starttime = 0; + cl_capturevideo_framerate = 0; + cl_capturevideo_frame = 0; } -static int cl_avidemo_frame = 0; - -void SCR_CaptureAVIDemo(void) +qboolean SCR_CaptureVideo_VideoFrame(int newframenum) { + int x = vid.realx, y = vid.realy, width = vid.realwidth, height = vid.realheight; + unsigned char *b, *out; char filename[32]; - sprintf(filename, "dpavi%06d.tga", cl_avidemo_frame); - if (SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight, false)) - cl_avidemo_frame++; - else + int outoffset = (width/2)*(height/2); + //return SCR_ScreenShot(filename, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.realwidth * vid.realheight * 3, cl_capturevideo_buffer + vid.realwidth * vid.realheight * 6, vid.realx, vid.realy, vid.realwidth, vid.realheight, false, false, false, jpeg); + // speed is critical here, so do saving as directly as possible + switch (cl_capturevideo_format) + { + case CAPTUREVIDEOFORMAT_RAWYV12: + // FIXME: width/height must be multiple of 2, enforce this? + qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer); + CHECKGLERROR + // process one line at a time, and CbCr every other line at 2 pixel intervals + for (y = 0;y < height;y++) + { + // 1x1 Y + for (b = cl_capturevideo_buffer + (height-1-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + y*width, x = 0;x < width;x++, b += 3, out++) + *out = cl_capturevideo_yuvnormalizetable[0][cl_capturevideo_rgbtoyuvscaletable[0][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[0][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[0][2][b[2]]]; + if ((y & 1) == 0) + { + // 2x2 Cb and Cr planes +#if 1 + // low quality, no averaging + for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++) + { + // Cr + out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[2][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[2][2][b[2]] + 128]; + // Cb + out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[1][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[1][2][b[2]] + 128]; + } +#else + // high quality, averaging + int inpitch = width*3; + for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++) + { + int blockr, blockg, blockb; + blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2; + blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2; + blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2; + // Cr + out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[2][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[2][2][blockb] + 128]; + // Cb + out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[1][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[1][2][blockb] + 128]; + } +#endif + } + } + for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++) + if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2)) + return false; + return true; + case CAPTUREVIDEOFORMAT_RAWRGB: + qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer); + CHECKGLERROR + for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++) + if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer, width*height*3)) + return false; + return true; + case CAPTUREVIDEOFORMAT_JPEG: + qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer); + CHECKGLERROR + for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++) + { + sprintf(filename, "video/dp%06d.jpg", cl_capturevideo_frame); + if (!JPEG_SaveImage_preflipped (filename, width, height, cl_capturevideo_buffer)) + return false; + } + return true; + case CAPTUREVIDEOFORMAT_TARGA: + //return Image_WriteTGARGB_preflipped (filename, width, height, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.realwidth * vid.realheight * 3, ); + memset (cl_capturevideo_buffer, 0, 18); + cl_capturevideo_buffer[2] = 2; // uncompressed type + cl_capturevideo_buffer[12] = (width >> 0) & 0xFF; + cl_capturevideo_buffer[13] = (width >> 8) & 0xFF; + cl_capturevideo_buffer[14] = (height >> 0) & 0xFF; + cl_capturevideo_buffer[15] = (height >> 8) & 0xFF; + cl_capturevideo_buffer[16] = 24; // pixel size + qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cl_capturevideo_buffer + 18); + CHECKGLERROR + for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++) + { + sprintf(filename, "video/dp%06d.tga", cl_capturevideo_frame); + if (!FS_WriteFile (filename, cl_capturevideo_buffer, width*height*3 + 18)) + return false; + } + return true; + default: + return false; + } +} + +void SCR_CaptureVideo_SoundFrame(qbyte *bufstereo16le, size_t length, int rate) +{ + cl_capturevideo_soundrate = rate; + if (FS_Write (cl_capturevideo_soundfile, bufstereo16le, 4 * length) < 4 * length) + { + Cvar_SetValueQuick(&cl_capturevideo, 0); + Con_Printf("video sound saving failed on frame %i, out of disk space? stopping video capture.\n", cl_capturevideo_frame); + SCR_CaptureVideo_EndVideo(); + } +} + +void SCR_CaptureVideo(void) +{ + int newframenum; + if (cl_capturevideo.integer && r_render.integer) { - Cvar_SetValueQuick(&cl_avidemo, 0); - Con_Printf("avi saving failed on frame %i, out of disk space? stopping avi demo catpure.\n", cl_avidemo_frame); - cl_avidemo_frame = 0; + if (!cl_capturevideo_active) + SCR_CaptureVideo_BeginVideo(); + if (cl_capturevideo_framerate != cl_capturevideo_fps.value) + { + Con_Printf("You can not change the video framerate while recording a video.\n"); + Cvar_SetValueQuick(&cl_capturevideo_fps, cl_capturevideo_framerate); + } + newframenum = (Sys_DoubleTime() - cl_capturevideo_starttime) * cl_capturevideo_framerate; + // if falling behind more than one second, stop + if (newframenum - cl_capturevideo_frame > (int)ceil(cl_capturevideo_framerate)) + { + Cvar_SetValueQuick(&cl_capturevideo, 0); + Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cl_capturevideo_frame); + SCR_CaptureVideo_EndVideo(); + return; + } + // write frames + if (!SCR_CaptureVideo_VideoFrame(newframenum)) + { + Cvar_SetValueQuick(&cl_capturevideo, 0); + Con_Printf("video saving failed on frame %i, out of disk space? stopping video capture.\n", cl_capturevideo_frame); + SCR_CaptureVideo_EndVideo(); + } } + else if (cl_capturevideo_active) + SCR_CaptureVideo_EndVideo(); } /* @@ -767,38 +1020,49 @@ struct { float angles[3]; char *name; + qboolean flipx, flipy, flipdiagonaly; } -envmapinfo[6] = +envmapinfo[12] = { - {{ 0, 0, 0}, "ft"}, - {{ 0, 90, 0}, "rt"}, - {{ 0, 180, 0}, "bk"}, - {{ 0, 270, 0}, "lf"}, - {{-90, 90, 0}, "up"}, - {{ 90, 90, 0}, "dn"} + {{ 0, 0, 0}, "rt", true, false, false}, + {{ 0, 90, 0}, "ft", true, false, false}, + {{ 0, 180, 0}, "lf", true, false, false}, + {{ 0, 270, 0}, "bk", true, false, false}, + {{-90, 180, 0}, "up", false, true, false}, + {{ 90, 180, 0}, "dn", false, true, false}, + + {{ 0, 0, 0}, "px", true, true, true}, + {{ 0, 90, 0}, "py", false, true, false}, + {{ 0, 180, 0}, "nx", false, false, true}, + {{ 0, 270, 0}, "ny", true, false, false}, + {{-90, 180, 0}, "pz", false, false, true}, + {{ 90, 180, 0}, "nz", false, false, true} }; static void R_Envmap_f (void) { int j, size; char filename[256], basename[256]; + qbyte *buffer1; + qbyte *buffer2; + qbyte *buffer3; if (Cmd_Argc() != 3) { - Con_Printf ("envmap : save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n"); + Con_Print("envmap : save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n"); return; } - strcpy(basename, Cmd_Argv(1)); + strlcpy (basename, Cmd_Argv(1), sizeof (basename)); size = atoi(Cmd_Argv(2)); if (size != 128 && size != 256 && size != 512 && size != 1024) { - Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n"); + Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n"); return; } if (size > vid.realwidth || size > vid.realheight) { - Con_Printf("envmap: your resolution is not big enough to render that size\n"); + Con_Print("envmap: your resolution is not big enough to render that size\n"); return; } @@ -812,15 +1076,25 @@ static void R_Envmap_f (void) r_refdef.fov_x = 90; r_refdef.fov_y = 90; - for (j = 0;j < 6;j++) + buffer1 = Mem_Alloc(tempmempool, size * size * 3); + buffer2 = Mem_Alloc(tempmempool, size * size * 3); + buffer3 = Mem_Alloc(tempmempool, size * size * 3 + 18); + + for (j = 0;j < 12;j++) { sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name); - VectorCopy(envmapinfo[j].angles, r_refdef.viewangles); + Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1); R_ClearScreen(); - R_RenderView (); - SCR_ScreenShot(filename, vid.realx, vid.realy, size, size, false); + R_Mesh_Start(); + R_RenderView(); + R_Mesh_Finish(); + SCR_ScreenShot(filename, buffer1, buffer2, buffer3, vid.realx, vid.realy + vid.realheight - (r_refdef.y + r_refdef.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false); } + Mem_Free (buffer1); + Mem_Free (buffer2); + Mem_Free (buffer3); + envmap = false; } @@ -858,8 +1132,8 @@ void SHOWLMP_decodeshow(void) int i, k; qbyte lmplabel[256], picname[256]; float x, y; - strcpy(lmplabel,MSG_ReadString()); - strcpy(picname, MSG_ReadString()); + strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel)); + strlcpy (picname, MSG_ReadString(), sizeof (picname)); if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk { x = MSG_ReadByte(); @@ -886,8 +1160,8 @@ void SHOWLMP_decodeshow(void) return; // none found to replace // change existing one showlmp[k].isactive = true; - strcpy(showlmp[k].label, lmplabel); - strcpy(showlmp[k].pic, picname); + strlcpy (showlmp[k].label, lmplabel, sizeof (showlmp[k].label)); + strlcpy (showlmp[k].pic, picname, sizeof (showlmp[k].pic)); showlmp[k].x = x; showlmp[k].y = y; } @@ -909,38 +1183,31 @@ void SHOWLMP_clear(void) void CL_SetupScreenSize(void) { - static float old2dresolution = -1; + float conwidth, conheight; VID_GetWindowSize (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight); VID_UpdateGamma(false); - if (scr_2dresolution.value != old2dresolution) - { - Cvar_SetValue("scr_2dresolution", bound(0.0f, scr_2dresolution.value, 1.0f)); - old2dresolution = scr_2dresolution.value; - } + conwidth = bound(320, vid_conwidth.value, 2048); + conheight = bound(200, vid_conheight.value, 1536); + if (vid_conwidth.value != conwidth) + Cvar_SetValue("vid_conwidth", conwidth); + if (vid_conheight.value != conheight) + Cvar_SetValue("vid_conheight", conheight); - if (vid.realwidth > 320) - { - vid.conwidth = (vid.realwidth - 320) * scr_2dresolution.value + 320; - vid.conwidth = bound(320, vid.conwidth, vid.realwidth); - } - else - vid.conwidth = 320; + vid.conwidth = vid_conwidth.integer; + vid.conheight = vid_conheight.integer; - if (vid.realheight > 240) +/* if (vid.realheight > 240) { vid.conheight = (vid.realheight - 240) * scr_2dresolution.value + 240; vid.conheight = bound(240, vid.conheight, vid.realheight); } else - vid.conheight = 240; + vid.conheight = 240;*/ SCR_SetUpToDrawConsole(); - - // determine size of refresh window - SCR_CalcRefdef(); } extern void R_Shadow_EditLights_DrawSelectedLightProperties(void); @@ -949,10 +1216,45 @@ void CL_UpdateScreen(void) if (!scr_initialized || !con_initialized || vid_hidden) return; // not initialized yet - if (cl_avidemo.integer) - SCR_CaptureAVIDemo(); + // don't allow cheats in multiplayer + if (!cl.islocalgame && cl.worldmodel) + { + if (r_fullbright.integer != 0) + Cvar_Set ("r_fullbright", "0"); + if (r_ambient.value != 0) + Cvar_Set ("r_ambient", "0"); + } + + // bound viewsize + if (scr_viewsize.value < 30) + Cvar_Set ("viewsize","30"); + if (scr_viewsize.value > 120) + Cvar_Set ("viewsize","120"); + + // bound field of view + if (scr_fov.value < 1) + Cvar_Set ("fov","1"); + if (scr_fov.value > 170) + Cvar_Set ("fov","170"); + + // intermission is always full screen + if (cl.intermission) + sb_lines = 0; else - cl_avidemo_frame = 0; + { + if (scr_viewsize.value >= 120) + sb_lines = 0; // no status bar at all + else if (scr_viewsize.value >= 110) + sb_lines = 24; // no inventory + else + sb_lines = 24+16+8; + } + + r_refdef.colormask[0] = 1; + r_refdef.colormask[1] = 1; + r_refdef.colormask[2] = 1; + + SCR_CaptureVideo(); if (cls.signon == SIGNONS) R_TimeReport("other"); @@ -961,42 +1263,34 @@ void CL_UpdateScreen(void) DrawQ_Clear(); - V_UpdateBlends(); - V_CalcRefdef (); - if (cls.signon == SIGNONS) R_TimeReport("setup"); //FIXME: force menu if nothing else to look at? //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected) - if (scr_drawloading) + if (cls.signon == SIGNONS) { - scr_drawloading = false; - SCR_DrawLoading(); + SCR_DrawNet (); + SCR_DrawTurtle (); + SCR_DrawPause (); + if (!r_letterbox.value) + Sbar_Draw(); + SHOWLMP_drawall(); + SCR_CheckDrawCenterString(); } - else + MR_Draw(); + UI_Callback_Draw(); + CL_DrawVideo(); + //ui_draw(); + if (cls.signon == SIGNONS) { - if (cls.signon == SIGNONS) - { - SCR_DrawNet (); - SCR_DrawTurtle (); - SCR_DrawPause (); - Sbar_Draw(); - SHOWLMP_drawall(); - SCR_CheckDrawCenterString(); - } - ui_draw(); - CL_DrawVideo(); - M_Draw(); - if (cls.signon == SIGNONS) - { - R_TimeReport("2d"); - R_TimeReport_End(); - R_TimeReport_Start(); - } - R_Shadow_EditLights_DrawSelectedLightProperties(); + R_TimeReport("2d"); + R_TimeReport_End(); + R_TimeReport_Start(); } + R_Shadow_EditLights_DrawSelectedLightProperties(); + SCR_DrawConsole(); SCR_UpdateScreen(); @@ -1006,4 +1300,3 @@ void CL_Screen_NewMap(void) { SHOWLMP_clear(); } -