]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
fixed an improperly filed change request
[xonotic/darkplaces.git] / cl_screen.c
index 63a8e52f781698837669bd65b58482d94973bcd7..7c2b09bf00a499483acce2c37c77597af529eea5 100644 (file)
@@ -4,6 +4,7 @@
 #include "image.h"
 #include "jpeg.h"
 #include "cl_collision.h"
+#include "libcurl.h"
 #include "csprogs.h"
 
 cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100", "how large the view should be, 110 disables inventory bar, 120 disables status bar"};
@@ -26,10 +27,10 @@ cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","
 cvar_t scr_screenshot_gammaboost = {CVAR_SAVE, "scr_screenshot_gammaboost","1", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
 // scr_screenshot_name is defined in fs.c
 cvar_t cl_capturevideo = {0, "cl_capturevideo", "0", "enables saving of video to a file or files (default is .tga files, if scr_screenshot_jpeg is on it saves .jpg files (VERY SLOW), if any rawrgb or rawyv12 are on it saves those formats instead, note that scr_screenshot_gammaboost affects the brightness of the output)"};
-cvar_t cl_capturevideo_sound = {0, "cl_capturevideo_sound", "0", "enables saving of sound to a .wav file (warning: this requires exact sync, if your hard drive can't keep up it will abort, if your graphics can't keep up it will save duplicate frames to maintain sound sync)"};
 cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30", "how many frames per second to save (29.97 for NTSC, 30 for typical PC video, 15 can be useful)"};
 cvar_t cl_capturevideo_rawrgb = {0, "cl_capturevideo_rawrgb", "0", "saves a single .rgb video file containing raw RGB images (you'll need special processing tools to encode this to something more useful)"};
 cvar_t cl_capturevideo_rawyv12 = {0, "cl_capturevideo_rawyv12", "0", "saves a single .yv12 video file containing raw YV12 (luma plane, then half resolution chroma planes, first chroma blue then chroma red, this is the format used internally by many encoders, some tools can read it directly)"};
+cvar_t cl_capturevideo_number = {CVAR_SAVE, "cl_capturevideo_number", "1", "number to append to video filename, incremented each time a capture begins"};
 cvar_t r_letterbox = {0, "r_letterbox", "0", "reduces vertical height of view to simulate a letterboxed movie effect (can be used by mods for cutscenes)"};
 cvar_t r_stereo_separation = {0, "r_stereo_separation", "4", "separation of eyes in the world (try negative values too)"};
 cvar_t r_stereo_sidebyside = {0, "r_stereo_sidebyside", "0", "side by side views (for those who can't afford glasses but can afford eye strain)"};
@@ -50,7 +51,6 @@ float         scr_con_current;
 
 extern int     con_vislines;
 
-void DrawCrosshair(int num);
 static void SCR_ScreenShot_f (void);
 static void R_Envmap_f (void);
 
@@ -125,11 +125,19 @@ void SCR_DrawCenterString (void)
        color = -1;
        do
        {
-       // scan the width of the line
+               // scan the number of characters on the line, not counting color codes
+               int chars = 0;
                for (l=0 ; l<vid_conwidth.integer/8 ; l++)
+               {
                        if (start[l] == '\n' || !start[l])
                                break;
-               x = (vid_conwidth.integer - l*8)/2;
+                       // color codes add no visible characters, so don't count them
+                       if (start[l] == '^' && (start[l+1] >= '0' && start[l+1] <= '9'))
+                               l++;
+                       else
+                               chars++;
+               }
+               x = (vid_conwidth.integer - chars*8)/2;
                if (l > 0)
                {
                        if (remaining < l)
@@ -295,27 +303,88 @@ void SCR_DrawBrand (void)
 
 /*
 ==============
-SCR_DrawDownload
+SCR_DrawQWDownload
 ==============
 */
-static void SCR_DrawDownload(void)
+static int SCR_DrawQWDownload(int offset)
 {
        int len;
        float x, y;
        float size = 8;
        char temp[256];
        if (!cls.qw_downloadname[0])
-               return;
+               return 0;
        dpsnprintf(temp, sizeof(temp), "Downloading %s ...  %3i%%\n", cls.qw_downloadname, cls.qw_downloadpercent);
        len = (int)strlen(temp);
        x = (vid_conwidth.integer - len*size) / 2;
-       y = vid_conheight.integer - size;
+       y = vid_conheight.integer - size - offset;
        DrawQ_Pic(0, y, NULL, vid_conwidth.integer, size, 0, 0, 0, 0.5, 0);
        DrawQ_String(x, y, temp, len, size, size, 1, 1, 1, 1, 0);
+       return 8;
 }
 
-//=============================================================================
+/*
+==============
+SCR_DrawCurlDownload
+==============
+*/
+static int SCR_DrawCurlDownload(int offset)
+{
+       int len;
+       int nDownloads;
+       int i;
+       float x, y;
+       float size = 8;
+       Curl_downloadinfo_t *downinfo;
+       char temp[256];
+       const char *addinfo;
+
+       downinfo = Curl_GetDownloadInfo(&nDownloads, &addinfo);
+       if(!downinfo)
+               return 0;
+
+       y = vid_conheight.integer - size * nDownloads - offset;
+
+       if(addinfo)
+       {
+               len = (int)strlen(addinfo);
+               x = (vid_conwidth.integer - len*size) / 2;
+               DrawQ_Pic(0, y - size, NULL, vid_conwidth.integer, size, 1, 1, 1, 0.8, 0);
+               DrawQ_String(x, y - size, addinfo, len, size, size, 0, 0, 0, 1, 0);
+       }
+
+       for(i = 0; i != nDownloads; ++i)
+       {
+               if(downinfo[i].queued)
+                       dpsnprintf(temp, sizeof(temp), "Still in queue: %s\n", downinfo[i].filename);
+               else if(downinfo[i].progress <= 0)
+                       dpsnprintf(temp, sizeof(temp), "Downloading %s ...  ???.?%% @ %.1f KiB/s\n", downinfo[i].filename, downinfo[i].speed / 1024.0);
+               else
+                       dpsnprintf(temp, sizeof(temp), "Downloading %s ...  %5.1f%% @ %.1f KiB/s\n", downinfo[i].filename, 100.0 * downinfo[i].progress, downinfo[i].speed / 1024.0);
+               len = (int)strlen(temp);
+               x = (vid_conwidth.integer - len*size) / 2;
+               DrawQ_Pic(0, y + i * size, NULL, vid_conwidth.integer, size, 0, 0, 0, 0.8, 0);
+               DrawQ_String(x, y + i * size, temp, len, size, size, 1, 1, 1, 1, 0);
+       }
+
+       Z_Free(downinfo);
+
+       return 8 * (nDownloads + (addinfo ? 1 : 0));
+}
+
+/*
+==============
+SCR_DrawDownload
+==============
+*/
+static void SCR_DrawDownload()
+{
+       int offset = 0;
+       offset += SCR_DrawQWDownload(offset);
+       offset += SCR_DrawCurlDownload(offset);
+}
 
+//=============================================================================
 
 /*
 ==================
@@ -371,7 +440,7 @@ void SCR_DrawConsole (void)
        else
        {
                con_vislines = 0;
-               if (key_dest == key_game || key_dest == key_message)
+               if ((key_dest == key_game || key_dest == key_message) && !r_letterbox.value)
                        Con_DrawNotify ();      // only draw notify in game
        }
 }
@@ -528,10 +597,10 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
        Cvar_RegisterVariable (&scr_screenshot_gammaboost);
        Cvar_RegisterVariable (&cl_capturevideo);
-       Cvar_RegisterVariable (&cl_capturevideo_sound);
        Cvar_RegisterVariable (&cl_capturevideo_fps);
        Cvar_RegisterVariable (&cl_capturevideo_rawrgb);
        Cvar_RegisterVariable (&cl_capturevideo_rawyv12);
+       Cvar_RegisterVariable (&cl_capturevideo_number);
        Cvar_RegisterVariable (&r_letterbox);
        Cvar_RegisterVariable(&r_stereo_separation);
        Cvar_RegisterVariable(&r_stereo_sidebyside);
@@ -618,6 +687,8 @@ void SCR_CaptureVideo_BeginVideo(void)
        cls.capturevideo_frame = 0;
        cls.capturevideo_buffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * (3+3+3) + 18);
        gamma = 1.0/scr_screenshot_gammaboost.value;
+       dpsnprintf(cls.capturevideo_basename, sizeof(cls.capturevideo_basename), "video/dpvideo%03i", cl_capturevideo_number.integer);
+       Cvar_SetValueQuick(&cl_capturevideo_number, cl_capturevideo_number.integer + 1);
 
        /*
        for (i = 0;i < 256;i++)
@@ -660,12 +731,12 @@ Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
        if (cl_capturevideo_rawrgb.integer)
        {
                cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB;
-               cls.capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true);
+               cls.capturevideo_videofile = FS_Open (va("%s.rgb", cls.capturevideo_basename), "wb", false, true);
        }
        else if (cl_capturevideo_rawyv12.integer)
        {
                cls.capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12;
-               cls.capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true);
+               cls.capturevideo_videofile = FS_Open (va("%s.yv12", cls.capturevideo_basename), "wb", false, true);
        }
        else if (scr_screenshot_jpeg.integer)
        {
@@ -678,15 +749,15 @@ Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
                cls.capturevideo_videofile = NULL;
        }
 
-       if (cl_capturevideo_sound.integer)
+       cls.capturevideo_soundfile = FS_Open (va("%s.wav", cls.capturevideo_basename), "wb", false, true);
+       if (cls.capturevideo_soundfile)
        {
-               cls.capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true);
                // wave header will be filled out when video ends
                memset(out, 0, 44);
                FS_Write (cls.capturevideo_soundfile, out, 44);
        }
        else
-               cls.capturevideo_soundfile = NULL;
+               Con_Printf("Could not open video/dpvideo.wav for writing, sound capture disabled\n");
 }
 
 void SCR_CaptureVideo_EndVideo(void)
@@ -764,6 +835,9 @@ qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
        switch (cls.capturevideo_format)
        {
        case CAPTUREVIDEOFORMAT_RAWYV12:
+               // if there's no videofile we have to just give up, and abort saving if there's no video or sound file
+               if (!cls.capturevideo_videofile)
+                       return cls.capturevideo_soundfile != NULL;
                // FIXME: width/height must be multiple of 2, enforce this?
                qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);CHECKGLERROR
                // process one line at a time, and CbCr every other line at 2 pixel intervals
@@ -806,6 +880,9 @@ qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
                                return false;
                return true;
        case CAPTUREVIDEOFORMAT_RAWRGB:
+               // if there's no videofile we have to just give up, and abort saving if there's no video or sound file
+               if (!cls.capturevideo_videofile)
+                       return cls.capturevideo_soundfile != NULL;
                qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);CHECKGLERROR
                for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
                        if (!FS_Write (cls.capturevideo_videofile, cls.capturevideo_buffer, width*height*3))
@@ -815,7 +892,7 @@ qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
                qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo_buffer);CHECKGLERROR
                for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
                {
-                       sprintf(filename, "video/dp%06d.jpg", cls.capturevideo_frame);
+                       sprintf(filename, "%s_%06d.jpg", cls.capturevideo_basename, cls.capturevideo_frame);
                        if (!JPEG_SaveImage_preflipped (filename, width, height, cls.capturevideo_buffer))
                                return false;
                }
@@ -832,7 +909,7 @@ qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
                qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cls.capturevideo_buffer + 18);CHECKGLERROR
                for (;cls.capturevideo_frame < newframenum;cls.capturevideo_frame++)
                {
-                       sprintf(filename, "video/dp%06d.tga", cls.capturevideo_frame);
+                       sprintf(filename, "%s_%06d.tga", cls.capturevideo_basename, cls.capturevideo_frame);
                        if (!FS_WriteFile (filename, cls.capturevideo_buffer, width*height*3 + 18))
                                return false;
                }
@@ -867,12 +944,14 @@ void SCR_CaptureVideo(void)
                        Con_Printf("You can not change the video framerate while recording a video.\n");
                        Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo_framerate);
                }
+#if 0
                if (cls.capturevideo_soundfile)
                {
                        // preserve sound sync by duplicating frames when running slow
                        newframenum = (int)((Sys_DoubleTime() - cls.capturevideo_starttime) * cls.capturevideo_framerate);
                }
                else
+#endif
                        newframenum = cls.capturevideo_frame + 1;
                // if falling behind more than one second, stop
                if (newframenum - cls.capturevideo_frame > (int)ceil(cls.capturevideo_framerate))
@@ -1114,37 +1193,35 @@ qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *b
 
 void R_ClearScreen(void)
 {
-       if (r_render.integer)
+       // clear to black
+       CHECKGLERROR
+       if (r_refdef.fogenabled)
        {
-               // clear to black
-               CHECKGLERROR
-               if (r_refdef.fogenabled)
-               {
-                       qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
-               }
-               else
-               {
-                       qglClearColor(0,0,0,0);CHECKGLERROR
-               }
-               qglClearDepth(1);CHECKGLERROR
-               if (gl_stencil)
-               {
-                       // LordHavoc: we use a stencil centered around 128 instead of 0,
-                       // to avoid clamping interfering with strange shadow volume
-                       // drawing orders
-                       qglClearStencil(128);CHECKGLERROR
-               }
-               // clear the screen
+               qglClearColor(r_refdef.fogcolor[0],r_refdef.fogcolor[1],r_refdef.fogcolor[2],0);CHECKGLERROR
+       }
+       else
+       {
+               qglClearColor(0,0,0,0);CHECKGLERROR
+       }
+       qglClearDepth(1);CHECKGLERROR
+       if (gl_stencil)
+       {
+               // LordHavoc: we use a stencil centered around 128 instead of 0,
+               // to avoid clamping interfering with strange shadow volume
+               // drawing orders
+               qglClearStencil(128);CHECKGLERROR
+       }
+       // clear the screen
+       if (r_render.integer)
                GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | (gl_stencil ? GL_STENCIL_BUFFER_BIT : 0));
-               // set dithering mode
-               if (gl_dither.integer)
-               {
-                       qglEnable(GL_DITHER);CHECKGLERROR
-               }
-               else
-               {
-                       qglDisable(GL_DITHER);CHECKGLERROR
-               }
+       // set dithering mode
+       if (gl_dither.integer)
+       {
+               qglEnable(GL_DITHER);CHECKGLERROR
+       }
+       else
+       {
+               qglDisable(GL_DITHER);CHECKGLERROR
        }
 }