X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=cl_screen.c;h=a56acc4dd9718e3a8efe23a41830685511ef4390;hb=1ec20a24b6b91569198dc3e397ddaf7d0605572d;hp=0d6ba443c6e847178cfad605424b91ab606b7d47;hpb=e0c4a25c4f501b06bda21b1223f402aa22e684ce;p=xonotic%2Fdarkplaces.git diff --git a/cl_screen.c b/cl_screen.c index 0d6ba443..a56acc4d 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -1,12 +1,526 @@ #include "quakedef.h" -static byte menuplyr_pixels[4096]; +cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"}; +cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 10 - 170 +cvar_t scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300 +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"}; + +qboolean scr_initialized; // ready to draw + +float scr_con_current; +float scr_conlines; // lines of console to display + +int clearconsole; +int clearnotify; + +qboolean scr_disabled_for_loading; +//qboolean scr_drawloading; +//float scr_disabled_time; + +static qbyte menuplyr_pixels[4096]; + +/* +=============================================================================== + +CENTER PRINTING + +=============================================================================== +*/ + +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; + +/* +============== +SCR_CenterPrint + +Called for important messages that should stay in the center of the screen +for a few moments +============== +*/ +void SCR_CenterPrint (char *str) +{ + strncpy (scr_centerstring, str, sizeof(scr_centerstring)-1); + scr_centertime_off = scr_centertime.value; + scr_centertime_start = cl.time; + +// count the number of lines for centering + scr_center_lines = 1; + while (*str) + { + if (*str == '\n') + scr_center_lines++; + str++; + } +} + + +void SCR_DrawCenterString (void) +{ + char *start; + int l; + int x, y; + int remaining; + +// the finale prints the characters one at a time + if (cl.intermission) + remaining = scr_printspeed.value * (cl.time - scr_centertime_start); + else + remaining = 9999; + + scr_erase_center = 0; + start = scr_centerstring; + + if (scr_center_lines <= 4) + y = vid.conheight*0.35; + else + y = 48; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.conwidth - l*8)/2; + if (l > 0) + { + if (remaining < l) + l = remaining; + DrawQ_String(x, y, start, l, 8, 8, 1, 1, 1, 1, 0); + remaining -= l; + if (remaining <= 0) + return; + } + + y += 8; + + while (*start && *start != '\n') + start++; + + if (!*start) + break; + start++; // skip the \n + } while (1); +} + +void SCR_CheckDrawCenterString (void) +{ + if (scr_center_lines > scr_erase_lines) + scr_erase_lines = scr_center_lines; + + scr_centertime_off -= host_frametime; + + if (scr_centertime_off <= 0 && !cl.intermission) + return; + if (key_dest != key_game) + return; + + SCR_DrawCenterString (); +} + +/* +============== +SCR_DrawRam +============== +*/ +void SCR_DrawRam (void) +{ +// if (!scr_showram.integer) +// return; +// DrawQ_Pic (32, 0, "ram", 0, 0, 1, 1, 1, 1, 0); +} + +/* +============== +SCR_DrawTurtle +============== +*/ +void SCR_DrawTurtle (void) +{ + static int count; + + if (cls.state != ca_connected) + return; + + if (!scr_showturtle.integer) + return; + + if (host_frametime < 0.1) + { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + DrawQ_Pic (0, 0, "turtle", 0, 0, 1, 1, 1, 1, 0); +} + +/* +============== +SCR_DrawNet +============== +*/ +void SCR_DrawNet (void) +{ + if (cls.state != ca_connected) + return; + if (realtime - cl.last_received_message < 0.3) + return; + if (cls.demoplayback) + return; + + DrawQ_Pic (64, 0, "net", 0, 0, 1, 1, 1, 1, 0); +} + +/* +============== +DrawPause +============== +*/ +void SCR_DrawPause (void) +{ + cachepic_t *pic; + + if (cls.state != ca_connected) + return; + + if (!scr_showpause.integer) // turn off for screenshots + return; + + if (!cl.paused) + return; + + pic = Draw_CachePic ("gfx/pause.lmp"); + DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/pause.lmp", 0, 0, 1, 1, 1, 1, 0); +} + + + +/* +============== +SCR_DrawLoading +============== +*/ +/* +void SCR_DrawLoading (void) +{ + cachepic_t *pic; + + if (!scr_drawloading) + return; + + pic = Draw_CachePic ("gfx/loading.lmp"); + DrawQ_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, "gfx/loading.lmp", 0, 0, 1, 1, 1, 1, 0); +} +*/ + + + +//============================================================================= + + +/* +================== +SCR_SetUpToDrawConsole +================== +*/ +void SCR_SetUpToDrawConsole (void) +{ + Con_CheckResize (); + +// decide on the height of the console + con_forcedup = !cl.worldmodel || cls.signon != SIGNONS; + + if (con_forcedup) + { + scr_conlines = vid.conheight; // full screen + scr_con_current = scr_conlines; + } + else if (key_dest == key_console) + scr_conlines = vid.conheight/2; // half screen + else + scr_conlines = 0; // none visible + + if (scr_conlines < scr_con_current) + { + scr_con_current -= scr_conspeed.value*host_realframetime; + if (scr_conlines > scr_con_current) + scr_con_current = scr_conlines; + + } + else if (scr_conlines > scr_con_current) + { + scr_con_current += scr_conspeed.value*host_realframetime; + if (scr_conlines < scr_con_current) + scr_con_current = scr_conlines; + } +} + +/* +================== +SCR_DrawConsole +================== +*/ +void SCR_DrawConsole (void) +{ + if (scr_con_current) + { + Con_DrawConsole (scr_con_current); + clearconsole = 0; + } + else + { + if (key_dest == key_game || key_dest == key_message) + Con_DrawNotify (); // only draw notify in game + } +} + +/* +=============== +SCR_BeginLoadingPlaque + +================ +*/ +/* +void SCR_BeginLoadingPlaque (void) +{ + S_StopAllSounds (true); + +// if (cls.state != ca_connected) +// return; +// if (cls.signon != SIGNONS) +// return; + +// redraw with no console and the loading plaque +// Con_ClearNotify (); +// scr_centertime_off = 0; +// scr_con_current = 0; + + scr_drawloading = true; + SCR_UpdateScreen (); + +// scr_disabled_for_loading = true; +// scr_disabled_time = realtime; +} +*/ + +/* +=============== +SCR_EndLoadingPlaque + +================ +*/ +/* +void SCR_EndLoadingPlaque (void) +{ +// scr_disabled_for_loading = false; + scr_drawloading = false; + Con_ClearNotify (); +} +*/ + +//============================================================================= + +char *scr_notifystring; + +void SCR_DrawNotifyString (void) +{ + char *start; + int l; + int x, y; + + start = scr_notifystring; + + y = vid.conheight*0.35; + + do + { + // scan the width of the line + for (l=0 ; l<40 ; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.conwidth - l*8)/2; + DrawQ_String (x, y, start, l, 8, 8, 1, 1, 1, 1, 0); + + y += 8; + + while (*start && *start != '\n') + start++; + + if (!*start) + break; + start++; // skip the \n + } + while (1); +} + +void DrawCrosshair(int num); + +char r_speeds_string[1024]; +int speedstringcount, r_timereport_active; +double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0; + +void R_TimeReport(char *desc) +{ + char tempbuf[256]; + int length; + int t; + + if (!r_timereport_active) + return; + + r_timereport_temp = r_timereport_current; + r_timereport_current = Sys_DoubleTime(); + t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0); + + sprintf(tempbuf, "%8i %s", t, desc); + length = strlen(tempbuf); + while (length < 20) + tempbuf[length++] = ' '; + tempbuf[length] = 0; + if (speedstringcount + length > (vid.conwidth / 8)) + { + strcat(r_speeds_string, "\n"); + speedstringcount = 0; + } + // skip the space at the beginning if it's the first on the line + if (speedstringcount == 0) + { + strcat(r_speeds_string, tempbuf + 1); + speedstringcount = length - 1; + } + else + { + strcat(r_speeds_string, tempbuf); + speedstringcount += length; + } +} + +void R_TimeReport_Start(void) +{ + r_timereport_active = r_speeds.integer && cl.worldmodel && cls.state == ca_connected; + r_speeds_string[0] = 0; + if (r_timereport_active) + { + speedstringcount = 0; + AngleVectors (r_refdef.viewangles, vpn, NULL, NULL); + //sprintf(r_speeds_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i meshtris\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", + // r_refdef.vieworg[0] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[0]), r_refdef.vieworg[1] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[1]), r_refdef.vieworg[2] < 0 ? '-' : ' ', fabs(r_refdef.vieworg[2]), + // r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), + // vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]), + 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 walls%6i dlitwalls\n" + "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n" + "%6i modeltris%6i transmeshs%6i transtris%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_brush_polys, c_light_polys, + c_models, c_bmodels, c_sprites, c_particles, c_dlights, + c_alias_polys, c_transmeshs, c_transtris, c_meshs, c_meshtris); + + c_brush_polys = 0; + c_alias_polys = 0; + c_light_polys = 0; + c_faces = 0; + c_nodes = 0; + c_leafs = 0; + c_models = 0; + c_bmodels = 0; + c_sprites = 0; + c_particles = 0; + // c_dlights = 0; + + r_timereport_start = Sys_DoubleTime(); + } +} + +void R_TimeReport_End(void) +{ + r_timereport_current = r_timereport_start; + R_TimeReport("total"); + + if (r_timereport_active) + { + int i, j, lines, y; + lines = 1; + for (i = 0;r_speeds_string[i];i++) + if (r_speeds_string[i] == '\n') + lines++; + y = vid.conheight - sb_lines - lines * 8/* - 8*/; + i = j = 0; + DrawQ_Fill(0, y, vid.conwidth, lines * 8, 0, 0, 0, 0.5, 0); + while (r_speeds_string[i]) + { + j = i; + while (r_speeds_string[i] && r_speeds_string[i] != '\n') + i++; + if (i - j > 0) + DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0); + if (r_speeds_string[i] == '\n') + i++; + y += 8; + } + } +} + +/* +================= +SCR_SizeUp_f + +Keybinding command +================= +*/ +void SCR_SizeUp_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value+10); +} + + +/* +================= +SCR_SizeDown_f + +Keybinding command +================= +*/ +void SCR_SizeDown_f (void) +{ + Cvar_SetValue ("viewsize",scr_viewsize.value-10); +} void CL_Screen_Init(void) { qpic_t *dat; + Cvar_RegisterVariable (&scr_fov); + Cvar_RegisterVariable (&scr_viewsize); + Cvar_RegisterVariable (&scr_conspeed); + Cvar_RegisterVariable (&scr_showram); + Cvar_RegisterVariable (&scr_showturtle); + Cvar_RegisterVariable (&scr_showpause); + Cvar_RegisterVariable (&scr_centertime); + Cvar_RegisterVariable (&scr_printspeed); + Cvar_RegisterVariable(&scr_2dresolution); + + Cmd_AddCommand ("sizeup",SCR_SizeUp_f); + Cmd_AddCommand ("sizedown",SCR_SizeDown_f); + + scr_initialized = true; + // HACK HACK HACK // load the image data for the player image in the config menu dat = (qpic_t *)COM_LoadFile ("gfx/menuplyr.lmp", false); @@ -120,7 +634,7 @@ void DrawQ_Fill (float x, float y, float w, float h, float red, float green, flo } //only used for the player color selection menu -void DrawQ_PicTranslate (int x, int y, char *picname, byte *translation) +void DrawQ_PicTranslate (int x, int y, char *picname, qbyte *translation) { int i, c; unsigned int trans[4096]; @@ -141,29 +655,106 @@ void DrawQ_PicTranslate (int x, int y, char *picname, byte *translation) trans[i] = d_8to24table[translation[menuplyr_pixels[i]]]; // FIXME: this is renderer stuff? - R_UpdateTexture (pic->tex, (byte *)trans); + R_UpdateTexture (pic->tex, (qbyte *)trans); DrawQ_Pic(x, y, picname, 0, 0, 1, 1, 1, 1, 0); } -void V_CalcRefdef (void); -void CL_UpdateScreen(void) + +/* +==================== +CalcFov +==================== +*/ +float CalcFov (float fov_x, float width, float height) { - DrawQ_Clear(); + // 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; +} - SHOWLMP_drawall(); +/* +================= +SCR_CalcRefdef - V_UpdateBlends(); - V_CalcRefdef (); +Must be called whenever vid changes +Internal use only +================= +*/ +static void SCR_CalcRefdef (void) +{ + float size; + int contents; - SCR_UpdateScreen(); -} +//======================================== -void CL_Screen_NewMap(void) -{ - SHOWLMP_clear(); +// 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 < 10) + Cvar_Set ("fov","10"); + if (scr_fov.value > 170) + Cvar_Set ("fov","170"); + +// intermission is always full screen + if (cl.intermission) + { + size = 1; + sb_lines = 0; + } + else + { + 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); + } + + if (size >= 1) + { + r_refdef.width = vid.realwidth; + r_refdef.height = vid.realheight; + r_refdef.x = 0; + r_refdef.y = 0; + } + 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; + } + + 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; + + // 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 = Mod_PointInLeaf(r_refdef.vieworg, cl.worldmodel)->contents; + 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); + } + } } + +void V_CalcRefdef (void); + //============================================================================= // LordHavoc: SHOWLMP stuff @@ -183,7 +774,7 @@ showlmp_t showlmp[SHOWLMP_MAXLABELS]; void SHOWLMP_decodehide(void) { int i; - byte *lmplabel; + qbyte *lmplabel; lmplabel = MSG_ReadString(); for (i = 0;i < SHOWLMP_MAXLABELS;i++) if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0) @@ -196,7 +787,7 @@ void SHOWLMP_decodehide(void) void SHOWLMP_decodeshow(void) { int i, k; - byte lmplabel[256], picname[256]; + qbyte lmplabel[256], picname[256]; float x, y; strcpy(lmplabel,MSG_ReadString()); strcpy(picname, MSG_ReadString()); @@ -247,3 +838,84 @@ void SHOWLMP_clear(void) for (i = 0;i < SHOWLMP_MAXLABELS;i++) showlmp[i].isactive = false; } + +void CL_UpdateScreen(void) +{ + static float old2dresolution = -1; + + if (scr_disabled_for_loading) + return; + + if (!scr_initialized || !con_initialized) + return; // not initialized yet + + R_TimeReport("other"); + + 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; + } + + 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; + + 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; + + SCR_SetUpToDrawConsole(); + + // determine size of refresh window + SCR_CalcRefdef(); + + DrawQ_Clear(); + + V_UpdateBlends(); + V_CalcRefdef (); + + R_TimeReport("setup"); + + SCR_DrawRam(); + SCR_DrawNet(); + SCR_DrawTurtle(); + SCR_DrawPause(); + SCR_CheckDrawCenterString(); + Sbar_Draw(); + SHOWLMP_drawall(); + + SCR_DrawConsole(); + + ui_draw(); + + R_TimeReport("2d"); + + // add r_speeds text to queue + R_TimeReport_End(); + + // start a new timing run + R_TimeReport_Start(); + + // make menu fade everything else on the screen + M_Draw(); + + SCR_UpdateScreen(); +} + +void CL_Screen_NewMap(void) +{ + SHOWLMP_clear(); +}