]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_screen.c
implemented sv_gameplayfix_delayprojectiles -1 (force move on first
[xonotic/darkplaces.git] / cl_screen.c
index 9caa2cd708dc4feffa5504063a317092d4ac3cc5..c3c10953112926cb4b8763d8774198a64bcef5d4 100644 (file)
@@ -41,6 +41,7 @@ cvar_t cl_capturevideo_fps = {CVAR_SAVE, "cl_capturevideo_fps", "30", "how many
 cvar_t cl_capturevideo_nameformat = {CVAR_SAVE, "cl_capturevideo_nameformat", "dpvideo", "prefix for saved videos (the date is encoded using strftime escapes)"};
 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 cl_capturevideo_ogg = {CVAR_SAVE, "cl_capturevideo_ogg", "1", "save captured video data as Ogg/Vorbis/Theora streams"};
+cvar_t cl_capturevideo_framestep = {CVAR_SAVE, "cl_capturevideo_framestep", "1", "when set to n >= 1, render n frames to capture one (useful for motion blur like effects)"};
 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 distance of eyes in the world (negative values are only useful for cross-eyed viewing)"};
 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 (note: use a negative r_stereo_separation if you want cross-eyed viewing)"};
@@ -54,11 +55,13 @@ cvar_t scr_zoomwindow_viewsizey = {CVAR_SAVE, "scr_zoomwindow_viewsizey", "20",
 cvar_t scr_zoomwindow_fov = {CVAR_SAVE, "scr_zoomwindow_fov", "20", "fov of zoom window"};
 cvar_t scr_stipple = {0, "scr_stipple", "0", "interlacing-like stippling of the display"};
 cvar_t scr_refresh = {0, "scr_refresh", "1", "allows you to completely shut off rendering for benchmarking purposes"};
+cvar_t scr_screenshot_name_in_mapdir = {CVAR_SAVE, "scr_screenshot_name_in_mapdir", "0", "if set to 1, screenshots are placed in a subdirectory named like the map they are from"};
 cvar_t shownetgraph = {CVAR_SAVE, "shownetgraph", "0", "shows a graph of packet sizes and other information, 0 = off, 1 = show client netgraph, 2 = show client and server netgraphs (when hosting a server)"};
 cvar_t cl_demo_mousegrab = {0, "cl_demo_mousegrab", "0", "Allows reading the mouse input while playing demos. Useful for camera mods developed in csqc. (0: never, 1: always)"};
 
 extern cvar_t r_glsl;
 extern cvar_t v_glslgamma;
+extern cvar_t sbar_info_pos;
 #define WANT_SCREENSHOT_HWGAMMA (scr_screenshot_hwgamma.integer && !(r_glsl.integer && v_glslgamma.integer))
 
 int jpeg_supported = false;
@@ -305,7 +308,7 @@ void SCR_DrawNetGraph (void)
 
        index = 0;
        netgraph_x = (vid_conwidth.integer + separator2) - (1 + (index % netgraphsperrow)) * (barwidth * NETGRAPH_PACKETS * 2 + separator1 + separator2);
-       netgraph_y = (vid_conheight.integer - 48 + separator2) - (1 + (index / netgraphsperrow)) * (barheight + textsize + separator2);
+       netgraph_y = (vid_conheight.integer - 48 - sbar_info_pos.integer + separator2) - (1 + (index / netgraphsperrow)) * (barheight + textsize + separator2);
        SCR_DrawNetGraph_DrawConnection_Client(cls.netcon, netgraph_x, netgraph_y, barwidth, barheight, bardivide, "incoming", separator1, "outgoing", textsize);
        index++;
 
@@ -557,7 +560,7 @@ static int SCR_DrawCurlDownload(int offset)
 SCR_DrawInfobar
 ==============
 */
-static void SCR_DrawInfobar()
+static void SCR_DrawInfobar(void)
 {
        int offset = 0;
        if(scr_infobartime_off > 0)
@@ -568,7 +571,7 @@ static void SCR_DrawInfobar()
                Con_DPrintf("broken console margin calculation: %d != %d\n", offset, scr_con_margin_bottom);
 }
 
-static int SCR_InfobarHeight()
+static int SCR_InfobarHeight(void)
 {
        int offset = 0;
        Curl_downloadinfo_t *downinfo;
@@ -743,6 +746,7 @@ void R_TimeReport_EndFrame(void)
        int i, j, lines, y;
        cl_locnode_t *loc;
        char string[1024+4096];
+       mleaf_t *viewleaf;
 
        string[0] = 0;
        if (r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected)
@@ -750,12 +754,13 @@ void R_TimeReport_EndFrame(void)
                // put the location name in the r_speeds display as it greatly helps
                // when creating loc files
                loc = CL_Locs_FindNearest(cl.movement_origin);
+               viewleaf = (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.PointInLeaf) ? r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, r_refdef.view.origin) : NULL;
                dpsnprintf(string, sizeof(string),
 "%s%s\n"
 "%3i renders org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n"
 "%7i surfaces%7i triangles %5i entities (%7i surfaces%7i triangles)\n"
 "%5i leafs%5i portals%6i/%6i particles%6i/%6i decals %3i%% quality\n"
-"%7i lightmap updates (%7i pixels)\n"
+"%7i lightmap updates (%7i pixels)%s\n"
 "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n"
 "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n"
 "%s"
@@ -763,7 +768,7 @@ void R_TimeReport_EndFrame(void)
 , r_refdef.stats.renders, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], r_refdef.view.forward[0], r_refdef.view.forward[1], r_refdef.view.forward[2]
 , r_refdef.stats.world_surfaces, r_refdef.stats.world_triangles, r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles
 , r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles, cl.num_particles, r_refdef.stats.decals, cl.num_decals, (int)(100 * r_refdef.view.quality)
-, r_refdef.stats.lightmapupdates, r_refdef.stats.lightmapupdatepixels
+, r_refdef.stats.lightmapupdates, r_refdef.stats.lightmapupdatepixels, viewleaf ? va(" clusterindex%6i", viewleaf->clusterindex) : ""
 , r_refdef.stats.lights, r_refdef.stats.lights_clears, r_refdef.stats.lights_scissored, r_refdef.stats.lights_lighttriangles, r_refdef.stats.lights_shadowtriangles, r_refdef.stats.lights_dynamicshadowtriangles
 , r_refdef.stats.meshes, r_refdef.stats.meshes_elements / 3, r_refdef.stats.bloom_copypixels, r_refdef.stats.bloom_drawpixels
 , r_speeds_timestring);
@@ -858,6 +863,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
        Cvar_RegisterVariable (&scr_screenshot_gammaboost);
        Cvar_RegisterVariable (&scr_screenshot_hwgamma);
+       Cvar_RegisterVariable (&scr_screenshot_name_in_mapdir);
        Cvar_RegisterVariable (&cl_capturevideo);
        Cvar_RegisterVariable (&cl_capturevideo_printfps);
        Cvar_RegisterVariable (&cl_capturevideo_width);
@@ -867,6 +873,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&cl_capturevideo_nameformat);
        Cvar_RegisterVariable (&cl_capturevideo_number);
        Cvar_RegisterVariable (&cl_capturevideo_ogg);
+       Cvar_RegisterVariable (&cl_capturevideo_framestep);
        Cvar_RegisterVariable (&r_letterbox);
        Cvar_RegisterVariable(&r_stereo_separation);
        Cvar_RegisterVariable(&r_stereo_sidebyside);
@@ -905,12 +912,22 @@ void SCR_ScreenShot_f (void)
        static char old_prefix_name[MAX_QPATH];
        char prefix_name[MAX_QPATH];
        char filename[MAX_QPATH];
+       char mapname[MAX_QPATH];
        unsigned char *buffer1;
        unsigned char *buffer2;
        unsigned char *buffer3;
        qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
 
-       dpsnprintf (prefix_name, sizeof(prefix_name), "%s", Sys_TimeString(scr_screenshot_name.string));
+       // TODO maybe make capturevideo and screenshot use similar name patterns?
+       if (scr_screenshot_name_in_mapdir.integer && cl.worldmodel && *cl.worldmodel->name) {
+               // figure out the map's filename without path or extension
+               strlcpy(mapname, FS_FileWithoutPath(cl.worldmodel->name), sizeof(mapname));
+               if (strrchr(mapname, '.'))
+                       *(strrchr(mapname, '.')) = 0;
+               dpsnprintf (prefix_name, sizeof(prefix_name), "%s/%s", mapname, Sys_TimeString(scr_screenshot_name.string));
+       } else {
+               dpsnprintf (prefix_name, sizeof(prefix_name), "%s", Sys_TimeString(scr_screenshot_name.string));
+       }
 
        if (strcmp(old_prefix_name, prefix_name))
        {
@@ -975,7 +992,8 @@ void SCR_CaptureVideo_BeginVideo(void)
        cls.capturevideo.width = width;
        cls.capturevideo.height = height;
        cls.capturevideo.active = true;
-       cls.capturevideo.framerate = bound(1, cl_capturevideo_fps.value, 1001);
+       cls.capturevideo.framerate = bound(1, cl_capturevideo_fps.value, 1001) * bound(1, cl_capturevideo_framestep.integer, 64);
+       cls.capturevideo.framestep = cl_capturevideo_framestep.integer;
        cls.capturevideo.soundrate = S_GetSoundRate();
        cls.capturevideo.soundchannels = S_GetSoundChannels();
        cls.capturevideo.startrealtime = realtime;
@@ -1138,11 +1156,14 @@ static void SCR_ScaleDownBGRA(unsigned char *in, int inw, int inh, unsigned char
        }
 }
 
-void SCR_CaptureVideo_VideoFrame(int newframenum)
+void SCR_CaptureVideo_VideoFrame(int newframestepframenum)
 {
        int x = 0, y = 0;
        int width = cls.capturevideo.width, height = cls.capturevideo.height;
 
+       if(newframestepframenum == cls.capturevideo.framestepframe)
+               return;
+
        CHECKGLERROR
        //return SCR_ScreenShot(filename, cls.capturevideo.buffer, cls.capturevideo.buffer + vid.width * vid.height * 3, cls.capturevideo.buffer + vid.width * vid.height * 6, 0, 0, vid.width, vid.height, false, false, false, jpeg, true);
        // speed is critical here, so do saving as directly as possible
@@ -1150,8 +1171,8 @@ void SCR_CaptureVideo_VideoFrame(int newframenum)
        qglReadPixels (x, y, vid.width, vid.height, GL_BGRA, GL_UNSIGNED_BYTE, cls.capturevideo.screenbuffer);CHECKGLERROR
        SCR_ScaleDownBGRA (cls.capturevideo.screenbuffer, vid.width, vid.height, cls.capturevideo.outbuffer, width, height);
 
-       cls.capturevideo.videoframes(newframenum - cls.capturevideo.frame);
-       cls.capturevideo.frame = newframenum;
+       cls.capturevideo.videoframes(newframestepframenum - cls.capturevideo.framestepframe);
+       cls.capturevideo.framestepframe = newframestepframenum;
 
        if(cl_capturevideo_printfps.integer)
        {
@@ -1182,10 +1203,10 @@ void SCR_CaptureVideo(void)
        {
                if (!cls.capturevideo.active)
                        SCR_CaptureVideo_BeginVideo();
-               if (cls.capturevideo.framerate != cl_capturevideo_fps.value)
+               if (cls.capturevideo.framerate != cl_capturevideo_fps.value * cl_capturevideo_framestep.integer)
                {
                        Con_Printf("You can not change the video framerate while recording a video.\n");
-                       Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo.framerate);
+                       Cvar_SetValueQuick(&cl_capturevideo_fps, cls.capturevideo.framerate / (double) cl_capturevideo_framestep.integer);
                }
                // for AVI saving we have to make sure that sound is saved before video
                if (cls.capturevideo.soundrate && !cls.capturevideo.soundsampleframe)
@@ -1206,7 +1227,8 @@ void SCR_CaptureVideo(void)
                        return;
                }
                // write frames
-               SCR_CaptureVideo_VideoFrame(newframenum);
+               SCR_CaptureVideo_VideoFrame(newframenum / cls.capturevideo.framestep);
+               cls.capturevideo.frame = newframenum;
                if (cls.capturevideo.error)
                {
                        Cvar_SetValueQuick(&cl_capturevideo, 0);
@@ -1627,15 +1649,15 @@ rtexture_t *loadingscreentexture = NULL;
 static float loadingscreentexture_vertex3f[12];
 static float loadingscreentexture_texcoord2f[8];
 
-static void SCR_ClearLoadingScreenTexture()
+static void SCR_ClearLoadingScreenTexture(void)
 {
        if(loadingscreentexture)
                R_FreeTexture(loadingscreentexture);
        loadingscreentexture = NULL;
 }
 
-extern rtexturepool_t r_main_texturepool;
-static void SCR_SetLoadingScreenTexture()
+extern rtexturepool_t *r_main_texturepool;
+static void SCR_SetLoadingScreenTexture(void)
 {
        int w, h;
        float loadingscreentexture_w;
@@ -1655,7 +1677,7 @@ static void SCR_SetLoadingScreenTexture()
                loadingscreentexture_h = vid.height / (float) h;
        }
 
-       loadingscreentexture = R_LoadTexture2D(&r_main_texturepool, "loadingscreentexture", w, h, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+       loadingscreentexture = R_LoadTexture2D(r_main_texturepool, "loadingscreentexture", w, h, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
        R_Mesh_TexBind(0, R_GetTexture(loadingscreentexture));
        GL_ActiveTexture(0);
        CHECKGLERROR
@@ -1672,7 +1694,7 @@ static void SCR_SetLoadingScreenTexture()
        loadingscreentexture_texcoord2f[6] = 0;loadingscreentexture_texcoord2f[7] = 0;
 }
 
-void SCR_UpdateLoadingScreenIfShown()
+void SCR_UpdateLoadingScreenIfShown(void)
 {
        if(realtime == loadingscreentime)
                SCR_UpdateLoadingScreen(loadingscreencleared);
@@ -1758,7 +1780,7 @@ static float SCR_DrawLoadingStack_r(loadingscreenstack_t *s, float y)
                len = strlen(s->msg);
                x = (vid_conwidth.integer - DrawQ_TextWidth_Font(s->msg, len, true, FONT_INFOBAR) * size) / 2;
                y -= size;
-               DrawQ_Fill(0, y, vid_conwidth.integer, size, 0, 0, 0, 0.5, 0);
+               DrawQ_Fill(0, y, vid_conwidth.integer, size, 0, 0, 0, 1, 0);
                DrawQ_String_Font(x, y, s->msg, len, size, size, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
                total += size;
        }
@@ -1766,7 +1788,7 @@ static float SCR_DrawLoadingStack_r(loadingscreenstack_t *s, float y)
        return total;
 }
 
-static void SCR_DrawLoadingStack()
+static void SCR_DrawLoadingStack(void)
 {
        float verts[12];
        float colors[16];
@@ -1925,6 +1947,16 @@ void SCR_UpdateLoadingScreen (qboolean clear)
        key_consoleactive = old_key_consoleactive;
 }
 
+qboolean R_Stereo_ColorMasking(void)
+{
+       return r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer;
+}
+
+qboolean R_Stereo_Active(void)
+{
+       return (vid.stereobuffer || r_stereo_sidebyside.integer || R_Stereo_ColorMasking());
+}
+
 extern cvar_t cl_minfps;
 extern cvar_t cl_minfps_fade;
 extern cvar_t cl_minfps_qualitymax;
@@ -1959,8 +1991,8 @@ void CL_UpdateScreen(void)
 
        rendertime1 = Sys_DoubleTime();
 
-       conwidth = bound(320, vid_conwidth.value, 2048);
-       conheight = bound(200, vid_conheight.value, 1536);
+       conwidth = bound(160, vid_conwidth.value, 32768);
+       conheight = bound(90, vid_conheight.value, 24576);
        if (vid_conwidth.value != conwidth)
                Cvar_SetValue("vid_conwidth", conwidth);
        if (vid_conheight.value != conheight)
@@ -2041,7 +2073,7 @@ void CL_UpdateScreen(void)
        else
                qglDisable(GL_POLYGON_STIPPLE);
 
-       if (vid.stereobuffer || r_stereo_redblue.integer || r_stereo_redgreen.integer || r_stereo_redcyan.integer || r_stereo_sidebyside.integer)
+       if (R_Stereo_Active())
        {
                matrix4x4_t originalmatrix = r_refdef.view.matrix;
                matrix4x4_t offsetmatrix;