📄 screen.c
字号:
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// screen.c -- master for refresh, status bar, console, chat, notify, etc
#include "quakedef.h"
#include "r_local.h"
// only the refresh window will be updated unless these variables are flagged
int scr_copytop;
int scr_copyeverything;
float scr_con_current;
float scr_conlines; // lines of console to display
float oldscreensize, oldfov;
cvar_t *scr_viewsize;
cvar_t *scr_fov; // 10 - 170
cvar_t *scr_conspeed;
cvar_t *scr_centertime;
cvar_t *scr_showram;
cvar_t *scr_showturtle;
cvar_t *scr_showpause;
cvar_t *scr_printspeed;
cvar_t *scr_conheight; // 2000-01-12 Variable console height by Fett
qboolean scr_initialized; // ready to draw
qpic_t *scr_ram;
qpic_t *scr_net;
qpic_t *scr_turtle;
int scr_fullupdate;
int clearconsole;
int clearnotify;
viddef_t vid; // global video state
vrect_t *pconupdate;
vrect_t scr_vrect;
qboolean scr_disabled_for_loading;
qboolean scr_drawloading;
float scr_disabled_time;
qboolean scr_skipupdate;
qboolean block_drawing;
void SCR_ScreenShot_f (void);
/*
===============================================================================
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_EraseCenterString (void)
{
int y;
if (scr_erase_center++ > vid.numpages)
{
scr_erase_lines = 0;
return;
}
if (scr_center_lines <= 4)
y = vid.height*0.35;
else
y = 48;
scr_copytop = 1;
Draw_TileClear (0, y,vid.width, 8*scr_erase_lines);
}
void SCR_DrawCenterString (void)
{
char *start;
int l;
int j;
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.height*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.width - l*8)/2;
for (j=0 ; j<l ; j++, x+=8)
{
Draw_Character (x, y, start[j]);
if (!remaining--)
return;
}
y += 8;
while (*start && *start != '\n')
start++;
if (!*start)
break;
start++; // skip the \n
} while (1);
}
void SCR_CheckDrawCenterString (void)
{
scr_copytop = 1;
if (scr_center_lines > scr_erase_lines)
scr_erase_lines = scr_center_lines;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
// scr_centertime_off -= host_frametime;
scr_centertime_off -= host_cpu_frametime;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
if (scr_centertime_off <= 0 && !cl.intermission)
return;
if (key_dest != key_game)
return;
SCR_DrawCenterString ();
}
//=============================================================================
/*
====================
CalcFov
====================
*/
float CalcFov (float fov_x, float width, float height)
{
float a;
float x;
if (fov_x < 1 || fov_x > 179)
Sys_Error ("Bad fov: %f", fov_x);
x = width/tan(fov_x/360*M_PI);
a = atan (height/x);
a = a*360/M_PI;
return a;
}
/*
=================
SCR_CalcRefdef
Must be called whenever vid changes
Internal use only
=================
*/
static void SCR_CalcRefdef (void)
{
vrect_t vrect;
float size;
scr_fullupdate = 0; // force a background redraw
vid.recalc_refdef = 0;
// force the status bar to redraw
Sbar_Changed ();
//========================================
// bound viewsize
if (scr_viewsize->value < 30)
Cvar_Set (scr_viewsize, "30");
if (scr_viewsize->value > 120)
Cvar_Set (scr_viewsize, "120");
// bound field of view
if (scr_fov->value < 10)
Cvar_Set (scr_fov,"10");
if (scr_fov->value > 170)
Cvar_Set (scr_fov,"170");
r_refdef.fov_x = scr_fov->value;
r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
// intermission is always full screen
if (cl.intermission)
size = 120;
else
size = scr_viewsize->value;
if (size >= 120)
sb_lines = 0; // no status bar at all
else if (size >= 110)
sb_lines = 24; // no inventory
else
sb_lines = 24+16+8;
// these calculations mirror those in R_Init() for r_refdef, but take no
// account of water warping
vrect.x = 0;
vrect.y = 0;
vrect.width = vid.width;
vrect.height = vid.height;
R_SetVrect (&vrect, &scr_vrect, sb_lines);
// guard against going from one mode to another that's less than half the
// vertical resolution
if (scr_con_current > vid.height)
scr_con_current = vid.height;
// notify the refresh of the change
R_ViewChanged (&vrect, sb_lines, vid.aspect);
}
/*
=================
SCR_SizeUp_f
Keybinding command
=================
*/
void SCR_SizeUp_f (void)
{
Cvar_SetValue (scr_viewsize, scr_viewsize->value+10);
vid.recalc_refdef = 1;
}
/*
=================
SCR_SizeDown_f
Keybinding command
=================
*/
void SCR_SizeDown_f (void)
{
Cvar_SetValue (scr_viewsize, scr_viewsize->value-10);
vid.recalc_refdef = 1;
}
//============================================================================
// 2001-09-18 New cvar system by Maddes (Init) start
/*
==================
SCR_Init_Cvars
==================
*/
void SCR_Init_Cvars (void)
{
scr_fov = Cvar_Get ("fov", "90", CVAR_ORIGINAL);
scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE|CVAR_ORIGINAL);
scr_conspeed = Cvar_Get ("scr_conspeed", "300", CVAR_ORIGINAL);
scr_showram = Cvar_Get ("showram", "1", CVAR_ORIGINAL);
scr_showturtle = Cvar_Get ("showturtle", "0", CVAR_ORIGINAL);
scr_showpause = Cvar_Get ("showpause", "1", CVAR_ORIGINAL);
scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_ORIGINAL);
scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_ORIGINAL);
// 2000-01-12 Variable console height by Fett start
scr_conheight = Cvar_Get ("scr_conheight", "0.5", CVAR_ARCHIVE);
Cvar_SetRangecheck (scr_conheight, Cvar_RangecheckFloat, 0, 1);
Cvar_Set(scr_conheight, scr_conheight->string); // do rangecheck
// 2000-01-12 Variable console height by Fett end
}
// 2001-09-18 New cvar system by Maddes (Init) end
/*
==================
SCR_Init
==================
*/
void SCR_Init (void)
{
// 2001-09-18 New cvar system by Maddes (Init) start
/*
scr_fov = Cvar_Get ("fov", "90", CVAR_ORIGINAL);
scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE|CVAR_ORIGINAL);
scr_conspeed = Cvar_Get ("scr_conspeed", "300", CVAR_ORIGINAL);
scr_showram = Cvar_Get ("showram", "1", CVAR_ORIGINAL);
scr_showturtle = Cvar_Get ("showturtle", "0", CVAR_ORIGINAL);
scr_showpause = Cvar_Get ("showpause", "1", CVAR_ORIGINAL);
scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_ORIGINAL);
scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_ORIGINAL);
// 2000-01-12 Variable console height by Fett start
scr_conheight = Cvar_Get ("scr_conheight", "0.5", CVAR_ARCHIVE);
Cvar_SetRangecheck (scr_conheight, Cvar_RangecheckFloat, 0, 1);
Cvar_Set(scr_conheight, scr_conheight->string); // do rangecheck
// 2000-01-12 Variable console height by Fett end
*/
// 2001-09-18 New cvar system by Maddes (Init) end
//
// register our commands
//
Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
scr_ram = Draw_PicFromWad ("ram");
scr_net = Draw_PicFromWad ("net");
scr_turtle = Draw_PicFromWad ("turtle");
scr_initialized = true;
}
/*
==============
SCR_DrawRam
==============
*/
void SCR_DrawRam (void)
{
if (!scr_showram->value)
return;
if (!r_cache_thrash)
return;
Draw_Pic (scr_vrect.x+32, scr_vrect.y, scr_ram);
}
/*
==============
SCR_DrawTurtle
==============
*/
void SCR_DrawTurtle (void)
{
static int count;
if (!scr_showturtle->value)
return;
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes start
// if (host_frametime < 0.1)
if (host_cpu_frametime < 0.1)
// 2001-10-20 TIMESCALE extension by Tomaz/Maddes end
{
count = 0;
return;
}
count++;
if (count < 3)
return;
Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle);
}
/*
==============
SCR_DrawNet
==============
*/
void SCR_DrawNet (void)
{
if (realtime - cl.last_received_message < 0.3)
return;
if (cls.demoplayback)
return;
Draw_Pic (scr_vrect.x+64, scr_vrect.y, scr_net);
}
// 2001-11-31 FPS display by QuakeForge/Muff start
/*
==============
SCR_DrawFPS
==============
*/
//muff - hacked out of SourceForge implementation + modified
void SCR_DrawFPS (void)
{
static double lastframetime;
double t;
static int lastfps;
int x, y;
char st[80];
if (!cl_showfps->value)
return;
t = Sys_FloatTime ();
if ((t - lastframetime) >= 1.0) {
lastfps = fps_count;
fps_count = 0;
lastframetime = t;
}
sprintf(st, "%3d FPS", lastfps);
x = vid.width - strlen(st) * 16 - 16;
y = 0 ; //vid.height - (sb_lines * (vid.height/240) )- 16;
// Draw_TileClear(x, y, strlen(st)*16, 16);
Draw_String(x, y, st);
}
// 2001-11-31 FPS display by QuakeForge/Muff end
/*
==============
DrawPause
==============
*/
void SCR_DrawPause (void)
{
qpic_t *pic;
if (!scr_showpause->value) // turn off for screenshots
return;
if (!cl.paused)
return;
pic = Draw_CachePic ("gfx/pause.lmp");
Draw_Pic ( (vid.width - pic->width)/2,
(vid.height - 48 - pic->height)/2, pic);
}
/*
==============
SCR_DrawLoading
==============
*/
void SCR_DrawLoading (void)
{
qpic_t *pic;
if (!scr_drawloading)
return;
pic = Draw_CachePic ("gfx/loading.lmp");
Draw_Pic ( (vid.width - pic->width)/2,
(vid.height - 48 - pic->height)/2, pic);
}
//=============================================================================
/*
==================
SCR_SetUpToDrawConsole
==================
*/
extern cvar_t *con_alpha; // 2000-08-04 "Transparent" console background for software renderer by Norberto Alfredo Bensa/Maddes
void SCR_SetUpToDrawConsole (void)
{
Con_CheckResize ();
if (scr_drawloading)
return; // never a console with loading plaque
// decide on the height of the console
con_forcedup = !cl.worldmodel || cls.signon != SIGNONS;
if (con_forcedup)
{
scr_conlines = vid.height; // full screen
scr_con_current = scr_conlines;
}
else if (key_dest == key_console)
// 2000-01-12 Variable console height by Fett/Maddes start
{
// scr_conlines = vid.height/2; // half screen
scr_conlines = vid.height*scr_conheight->value; // in-game console
if (scr_conlines < (3*8+8+8)) // always leave three lines visible (plus command line and border)
{
scr_conlines = (3*8+8+8);
}
if (scr_conlines >= vid.height)
{
scr_conlines = vid.height - 1; // maximum is full screen
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -