From e13119a0c2d45c917d429dda262803208fee95a9 Mon Sep 17 00:00:00 2001 From: molivier Date: Thu, 3 Apr 2003 08:02:14 +0000 Subject: [PATCH] Added support for JPEG screenshots. You can toggle that with the cvar "scr_screenshot_jpeg" or the option menu. Note that you'll need the libjpeg library DLL. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2897 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_screen.c | 25 +++-- cl_screen.h | 1 + gl_backend.c | 8 +- gl_backend.h | 4 +- gl_textures.c | 4 +- jpeg.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++--- jpeg.h | 1 + menu.c | 44 ++++---- 8 files changed, 322 insertions(+), 45 deletions(-) diff --git a/cl_screen.c b/cl_screen.c index 5e7ce092..eca31c2e 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -1,6 +1,7 @@ #include "quakedef.h" #include "cl_video.h" +#include "jpeg.h" cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"}; cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 10 - 170 @@ -11,6 +12,7 @@ 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 scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","0"}; cvar_t cl_avidemo = {0, "cl_avidemo", "0"}; qboolean scr_initialized; // ready to draw @@ -465,6 +467,7 @@ void CL_Screen_Init(void) Cvar_RegisterVariable (&scr_centertime); Cvar_RegisterVariable (&scr_printspeed); Cvar_RegisterVariable (&scr_2dresolution); + Cvar_RegisterVariable (&scr_screenshot_jpeg); Cvar_RegisterVariable (&cl_avidemo); Cmd_AddCommand ("sizeup",SCR_SizeUp_f); @@ -815,23 +818,29 @@ void SCR_ScreenShot_f (void) static int i = 0; char filename[16]; char checkname[MAX_OSPATH]; -// -// find a file name to save it to -// + const char* extens; + qboolean jpeg = (scr_screenshot_jpeg.integer != 0); + + if (jpeg) + extens = "jpg"; + else + extens = "tga"; + + // find a file name to save it to for (; i<=9999 ; i++) { - sprintf (filename, "dp%04i.tga", i); + sprintf (filename, "dp%04i.%s", i, extens); sprintf (checkname, "%s/%s", fs_gamedir, filename); if (!FS_SysFileExists(checkname)) break; } if (i==10000) { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); + Con_Printf ("SCR_ScreenShot_f: Couldn't create the image file\n"); return; } - if (SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight)) + 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); @@ -843,7 +852,7 @@ void SCR_CaptureAVIDemo(void) { char filename[32]; sprintf(filename, "dpavi%06d.tga", cl_avidemo_frame); - if (SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight)) + if (SCR_ScreenShot(filename, vid.realx, vid.realy, vid.realwidth, vid.realheight, false)) cl_avidemo_frame++; else { @@ -915,7 +924,7 @@ static void R_Envmap_f (void) VectorCopy(envmapinfo[j].angles, r_refdef.viewangles); R_ClearScreen(); R_RenderView (); - SCR_ScreenShot(filename, vid.realx, vid.realy, size, size); + SCR_ScreenShot(filename, vid.realx, vid.realy, size, size, false); } envmap = false; diff --git a/cl_screen.h b/cl_screen.h index ec41eace..7f1ddb97 100644 --- a/cl_screen.h +++ b/cl_screen.h @@ -53,6 +53,7 @@ void SHOWLMP_drawall(void); void SHOWLMP_clear(void); extern cvar_t scr_2dresolution; +extern cvar_t scr_screenshot_jpeg; void CL_Screen_NewMap(void); void CL_Screen_Init(void); diff --git a/gl_backend.c b/gl_backend.c index a4549527..e21c1c8c 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -1,6 +1,7 @@ #include "quakedef.h" #include "image.h" +#include "jpeg.h" cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "21760"}; cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"}; @@ -1060,7 +1061,7 @@ void R_Mesh_State(const rmeshstate_t *m) ============================================================================== */ -qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height) +qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height, qboolean jpeg) { qboolean ret; int i, j; @@ -1083,7 +1084,10 @@ qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height) } } - ret = Image_WriteTGARGB_preflipped(filename, width, height, buffer); + if (jpeg) + ret = JPEG_SaveImage_preflipped (filename, width, height, buffer); + else + ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer); Mem_Free(buffer); return ret; diff --git a/gl_backend.h b/gl_backend.h index 89f0a886..24431800 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -83,8 +83,8 @@ void R_Mesh_CopyTexCoord2f(int tmu, const float *texcoord2f, int numverts); // copies a color4f array into varray_color4f void R_Mesh_CopyColor4f(const float *color4f, int numverts); -// saves a section of the rendered frame to a .tga file -qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height); +// saves a section of the rendered frame to a .tga or .jpg file +qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height, qboolean jpeg); // used by R_Envmap_f and internally in backend, clears the frame void R_ClearScreen(void); // invoke refresh of frame diff --git a/gl_textures.c b/gl_textures.c index cab9f636..6bcd55a8 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -478,7 +478,9 @@ static void r_textures_start(void) texturedatamempool = Mem_AllocPool("Texture Storage (not yet uploaded)"); textureprocessingmempool = Mem_AllocPool("Texture Processing Buffers"); - JPEG_OpenLibrary (); + // Disable JPEG screenshots if the DLL isn't loaded + if (! JPEG_OpenLibrary ()) + Cvar_SetValueQuick (&scr_screenshot_jpeg, 0); } static void r_textures_shutdown(void) diff --git a/jpeg.c b/jpeg.c index 3519ab19..063a86f4 100644 --- a/jpeg.c +++ b/jpeg.c @@ -25,6 +25,7 @@ #include "quakedef.h" #include "jpeg.h" + /* ================================================================= @@ -46,13 +47,23 @@ typedef int jboolean; #define JPEG_LIB_VERSION 62 // Version 6b typedef void *j_common_ptr; +typedef struct jpeg_compress_struct *j_compress_ptr; typedef struct jpeg_decompress_struct *j_decompress_ptr; -typedef enum {JPEG_DUMMY1} J_COLOR_SPACE; -typedef enum {JPEG_DUMMY2} J_DCT_METHOD; -typedef enum {JPEG_DUMMY3} J_DITHER_MODE; +typedef enum +{ + JCS_UNKNOWN, + JCS_GRAYSCALE, + JCS_RGB, + JCS_YCbCr, + JCS_CMYK, + JCS_YCCK +} J_COLOR_SPACE; +typedef enum {JPEG_DUMMY1} J_DCT_METHOD; +typedef enum {JPEG_DUMMY2} J_DITHER_MODE; typedef unsigned int JDIMENSION; -#define JPOOL_PERMANENT 0 +#define JPOOL_PERMANENT 0 // lasts until master record is destroyed +#define JPOOL_IMAGE 1 // lasts until done with image/datastream #define JPEG_EOI 0xD9 // EOI marker code @@ -63,6 +74,7 @@ typedef unsigned int JDIMENSION; #define NUM_HUFF_TBLS 4 #define NUM_ARITH_TBLS 16 #define MAX_COMPS_IN_SCAN 4 +#define C_MAX_BLOCKS_IN_MCU 10 #define D_MAX_BLOCKS_IN_MCU 10 struct jpeg_memory_mgr @@ -214,6 +226,90 @@ struct jpeg_decompress_struct }; +struct jpeg_compress_struct +{ + struct jpeg_error_mgr *err; + struct jpeg_memory_mgr *mem; + void *progress; + void *client_data; + jboolean is_decompressor; + int global_state; + + void *dest; + JDIMENSION image_width; + JDIMENSION image_height; + int input_components; + J_COLOR_SPACE in_color_space; + double input_gamma; + int data_precision; + + int num_components; + J_COLOR_SPACE jpeg_color_space; + void *comp_info; + void *quant_tbl_ptrs[NUM_QUANT_TBLS]; + void *dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + void *ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + qbyte arith_dc_L[NUM_ARITH_TBLS]; + qbyte arith_dc_U[NUM_ARITH_TBLS]; + qbyte arith_ac_K[NUM_ARITH_TBLS]; + + int num_scans; + const void *scan_info; + jboolean raw_data_in; + jboolean arith_code; + jboolean optimize_coding; + jboolean CCIR601_sampling; + int smoothing_factor; + J_DCT_METHOD dct_method; + + unsigned int restart_interval; + int restart_in_rows; + + jboolean write_JFIF_header; + qbyte JFIF_major_version; + qbyte JFIF_minor_version; + qbyte density_unit; + unsigned short X_density; + unsigned short Y_density; + jboolean write_Adobe_marker; + JDIMENSION next_scanline; + + jboolean progressive_mode; + int max_h_samp_factor; + int max_v_samp_factor; + JDIMENSION total_iMCU_rows; + int comps_in_scan; + void *cur_comp_info[MAX_COMPS_IN_SCAN]; + JDIMENSION MCUs_per_row; + JDIMENSION MCU_rows_in_scan; + int blocks_in_MCU; + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + int Ss, Se, Ah, Al; + + void *master; + void *main; + void *prep; + void *coef; + void *marker; + void *cconvert; + void *downsample; + void *fdct; + void *entropy; + void *script_space; + int script_space_size; +}; + +struct jpeg_destination_mgr +{ + qbyte* next_output_byte; + size_t free_in_buffer; + + void (*init_destination) (j_compress_ptr cinfo); + jboolean (*empty_output_buffer) (j_compress_ptr cinfo); + void (*term_destination) (j_compress_ptr cinfo); +}; + + /* ================================================================= @@ -223,30 +319,62 @@ struct jpeg_decompress_struct */ // Functions exported from libjpeg +#define qjpeg_create_compress(cinfo) \ + qjpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_compress_struct)) +#define qjpeg_create_decompress(cinfo) \ + qjpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct)) + +static void (*qjpeg_CreateCompress) (j_compress_ptr cinfo, int version, size_t structsize); static void (*qjpeg_CreateDecompress) (j_decompress_ptr cinfo, int version, size_t structsize); +static void (*qjpeg_destroy_compress) (j_compress_ptr cinfo); static void (*qjpeg_destroy_decompress) (j_decompress_ptr cinfo); +static void (*qjpeg_finish_compress) (j_compress_ptr cinfo); static jboolean (*qjpeg_finish_decompress) (j_decompress_ptr cinfo); static jboolean (*qjpeg_resync_to_restart) (j_decompress_ptr cinfo, int desired); static int (*qjpeg_read_header) (j_decompress_ptr cinfo, jboolean require_image); static JDIMENSION (*qjpeg_read_scanlines) (j_decompress_ptr cinfo, qbyte** scanlines, JDIMENSION max_lines); +static void (*qjpeg_set_defaults) (j_compress_ptr cinfo); +static void (*qjpeg_set_quality) (j_compress_ptr cinfo, int quality, jboolean force_baseline); +static jboolean (*qjpeg_start_compress) (j_compress_ptr cinfo, jboolean write_all_tables); static jboolean (*qjpeg_start_decompress) (j_decompress_ptr cinfo); static struct jpeg_error_mgr* (*qjpeg_std_error) (struct jpeg_error_mgr *err); +static JDIMENSION (*qjpeg_write_scanlines) (j_compress_ptr cinfo, qbyte** scanlines, JDIMENSION num_lines); static dllfunction_t jpegfuncs[] = { + {"jpeg_CreateCompress", (void **) &qjpeg_CreateCompress}, {"jpeg_CreateDecompress", (void **) &qjpeg_CreateDecompress}, + {"jpeg_destroy_compress", (void **) &qjpeg_destroy_compress}, {"jpeg_destroy_decompress", (void **) &qjpeg_destroy_decompress}, + {"jpeg_finish_compress", (void **) &qjpeg_finish_compress}, {"jpeg_finish_decompress", (void **) &qjpeg_finish_decompress}, {"jpeg_resync_to_restart", (void **) &qjpeg_resync_to_restart}, {"jpeg_read_header", (void **) &qjpeg_read_header}, {"jpeg_read_scanlines", (void **) &qjpeg_read_scanlines}, + {"jpeg_set_defaults", (void **) &qjpeg_set_defaults}, + {"jpeg_set_quality", (void **) &qjpeg_set_quality}, + {"jpeg_start_compress", (void **) &qjpeg_start_compress}, {"jpeg_start_decompress", (void **) &qjpeg_start_decompress}, {"jpeg_std_error", (void **) &qjpeg_std_error}, + {"jpeg_write_scanlines", (void **) &qjpeg_write_scanlines}, {NULL, NULL} }; // Handle for JPEG DLL -static dllhandle_t jpeg_dll = NULL; +dllhandle_t jpeg_dll = NULL; + +static qbyte jpeg_eoi_marker [2] = {0xFF, JPEG_EOI}; +static qboolean error_in_jpeg; + +// Our own output manager for JPEG compression +typedef struct +{ + struct jpeg_destination_mgr pub; + + qfile_t* outfile; + qbyte* buffer; +} my_destination_mgr; +typedef my_destination_mgr* my_dest_ptr; /* @@ -286,7 +414,7 @@ qboolean JPEG_OpenLibrary (void) // Load the DLL if (! (jpeg_dll = Sys_LoadLibrary (dllname))) { - Con_Printf("Can't find %s. JPEG support disabled\n", dllname); + Con_Printf ("Can't find %s. JPEG support disabled\n", dllname); return false; } @@ -294,12 +422,12 @@ qboolean JPEG_OpenLibrary (void) for (func = jpegfuncs; func && func->name != NULL; func++) if (!(*func->funcvariable = (void *) Sys_GetProcAddress (jpeg_dll, func->name))) { - Con_Printf("missing function \"%s\" - broken JPEG library!\n", func->name); + Con_Printf ("missing function \"%s\" - broken JPEG library!\n", func->name); JPEG_CloseLibrary (); return false; } - Con_Printf("%s loaded. JPEG support enabled\n", dllname); + Con_Printf ("%s loaded. JPEG support enabled\n", dllname); return true; } @@ -324,13 +452,11 @@ void JPEG_CloseLibrary (void) /* ================================================================= - Functions for handling JPEG images + JPEG decompression ================================================================= */ -static qbyte jpeg_eoi_marker [2] = {0xFF, JPEG_EOI}; - static void JPEG_Noop (j_decompress_ptr cinfo) {} static jboolean JPEG_FillInputBuffer (j_decompress_ptr cinfo) @@ -356,7 +482,7 @@ static void JPEG_SkipInputData (j_decompress_ptr cinfo, long num_bytes) static void JPEG_MemSrc (j_decompress_ptr cinfo, qbyte *buffer) { - cinfo->src = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr)); + cinfo->src = cinfo->mem->alloc_small ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr)); cinfo->src->next_input_byte = buffer; cinfo->src->bytes_in_buffer = fs_filesize; @@ -368,6 +494,12 @@ static void JPEG_MemSrc (j_decompress_ptr cinfo, qbyte *buffer) cinfo->src->term_source = JPEG_Noop; } +static void JPEG_ErrorExit (j_common_ptr cinfo) +{ + ((struct jpeg_decompress_struct*)cinfo)->err->output_message (cinfo); + error_in_jpeg = true; +} + /* ==================== @@ -388,7 +520,7 @@ qbyte* JPEG_LoadImage (qbyte *f, int matchwidth, int matchheight) return NULL; cinfo.err = qjpeg_std_error (&jerr); - qjpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct)); + qjpeg_create_decompress (&cinfo); JPEG_MemSrc (&cinfo, f); qjpeg_read_header (&cinfo, TRUE); qjpeg_start_decompress (&cinfo); @@ -462,3 +594,125 @@ qbyte* JPEG_LoadImage (qbyte *f, int matchwidth, int matchheight) return image_rgba; } + + +/* +================================================================= + + JPEG compression + +================================================================= +*/ + +#define JPEG_OUTPUT_BUF_SIZE 4096 +static void JPEG_InitDestination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr)cinfo->dest; + dest->buffer = (qbyte*)cinfo->mem->alloc_small ((j_common_ptr) cinfo, JPOOL_IMAGE, JPEG_OUTPUT_BUF_SIZE * sizeof(qbyte)); + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE; +} + +static jboolean JPEG_EmptyOutputBuffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr)cinfo->dest; + + if (FS_Write (dest->outfile, dest->buffer, JPEG_OUTPUT_BUF_SIZE) != (size_t) JPEG_OUTPUT_BUF_SIZE) + { + error_in_jpeg = true; + return false; + } + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = JPEG_OUTPUT_BUF_SIZE; + return true; +} + +static void JPEG_TermDestination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr)cinfo->dest; + size_t datacount = JPEG_OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + // Write any data remaining in the buffer + if (datacount > 0) + if (FS_Write (dest->outfile, dest->buffer, datacount) != datacount) + error_in_jpeg = true; +} + +static void JPEG_MemDest (j_compress_ptr cinfo, qfile_t* outfile) +{ + my_dest_ptr dest; + + // First time for this JPEG object? + if (cinfo->dest == NULL) + cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_destination_mgr)); + + dest = (my_dest_ptr)cinfo->dest; + dest->pub.init_destination = JPEG_InitDestination; + dest->pub.empty_output_buffer = JPEG_EmptyOutputBuffer; + dest->pub.term_destination = JPEG_TermDestination; + dest->outfile = outfile; +} + + +/* +==================== +JPEG_SaveImage_preflipped + +Save a preflipped JPEG image to a file +==================== +*/ +qboolean JPEG_SaveImage_preflipped (const char *filename, int width, int height, qbyte *data) +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + qbyte *scanline; + unsigned int offset, linesize; + qfile_t* file; + + // No DLL = no JPEGs + if (!jpeg_dll) + { + Con_Printf ("You need the libjpeg library to save JPEG images\n"); + return false; + } + + // Open the file + file = FS_Open (filename, "wb", true); + if (!file) + return false; + + cinfo.err = qjpeg_std_error (&jerr); + cinfo.err->error_exit = JPEG_ErrorExit; + error_in_jpeg = false; + + qjpeg_create_compress (&cinfo); + JPEG_MemDest (&cinfo, file); + + // Set the parameters for compression + cinfo.image_width = width; + cinfo.image_height = height; + cinfo.in_color_space = JCS_RGB; + cinfo.input_components = 3; + qjpeg_set_defaults (&cinfo); + qjpeg_set_quality (&cinfo, 90, TRUE); // 90% quality; FIXME: use a cvar + qjpeg_start_compress (&cinfo, true); + + // Compress each scanline + linesize = cinfo.image_width * 3; + offset = linesize * (cinfo.image_height - 1); + while (cinfo.next_scanline < cinfo.image_height) + { + scanline = &data[offset - cinfo.next_scanline * linesize]; + + qjpeg_write_scanlines (&cinfo, &scanline, 1); + if (error_in_jpeg) + break; + } + + qjpeg_finish_compress (&cinfo); + qjpeg_destroy_compress (&cinfo); + + FS_Close (file); + return true; +} diff --git a/jpeg.h b/jpeg.h index d9de27c5..787f9c88 100644 --- a/jpeg.h +++ b/jpeg.h @@ -28,6 +28,7 @@ qboolean JPEG_OpenLibrary (void); void JPEG_CloseLibrary (void); qbyte* JPEG_LoadImage (qbyte *f, int matchwidth, int matchheight); +qboolean JPEG_SaveImage_preflipped (const char *filename, int width, int height, qbyte *data); #endif diff --git a/menu.c b/menu.c index f4bda352..0d905a57 100644 --- a/menu.c +++ b/menu.c @@ -1274,7 +1274,7 @@ void M_DrawCheckbox (int x, int y, int on) } -#define OPTIONS_ITEMS 27 +#define OPTIONS_ITEMS 28 int options_cursor; @@ -1287,6 +1287,7 @@ void M_Menu_Options_f (void) extern cvar_t gl_delayfinish; extern cvar_t slowmo; +extern dllhandle_t jpeg_dll; void M_Menu_Options_AdjustSliders (int dir) { @@ -1301,46 +1302,50 @@ void M_Menu_Options_AdjustSliders (int dir) Cvar_SetValueQuick (&scr_viewsize, bound(30, scr_viewsize.value + dir * 10, 120)); break; case 8: - Cvar_SetValueQuick (&r_sky, !r_sky.integer); + if (jpeg_dll != NULL) + Cvar_SetValueQuick (&scr_screenshot_jpeg, !scr_screenshot_jpeg.integer); break; case 9: - Cvar_SetValueQuick (&v_overbrightbits, bound(0, v_overbrightbits.integer + dir, 4)); + Cvar_SetValueQuick (&r_sky, !r_sky.integer); break; case 10: - Cvar_SetValueQuick (&gl_combine, !gl_combine.integer); + Cvar_SetValueQuick (&v_overbrightbits, bound(0, v_overbrightbits.integer + dir, 4)); break; case 11: - Cvar_SetValueQuick (&gl_dither, !gl_dither.integer); + Cvar_SetValueQuick (&gl_combine, !gl_combine.integer); break; case 12: - Cvar_SetValueQuick (&gl_delayfinish, !gl_delayfinish.integer); + Cvar_SetValueQuick (&gl_dither, !gl_dither.integer); break; case 13: + Cvar_SetValueQuick (&gl_delayfinish, !gl_delayfinish.integer); + break; + case 14: Cvar_SetValueQuick (&slowmo, bound(0, slowmo.value + dir * 0.25, 5)); break; - case 14: // music volume + case 15: // music volume #ifdef _WIN32 Cvar_SetValueQuick (&bgmvolume, bound(0, bgmvolume.value + dir * 1.0, 1)); #else Cvar_SetValueQuick (&bgmvolume, bound(0, bgmvolume.value + dir * 0.1, 1)); #endif break; - case 15: // sfx volume + case 16: // sfx volume Cvar_SetValueQuick (&volume, bound(0, volume.value + dir * 0.1, 1)); break; - case 16: + case 17: Cvar_SetValueQuick (&crosshair, bound(0, crosshair.integer + dir, 5)); break; - case 17: + case 18: Cvar_SetValueQuick (&crosshair_size, bound(1, crosshair_size.value + dir, 5)); break; - case 18: // static crosshair + case 19: // static crosshair Cvar_SetValueQuick (&crosshair_static, !crosshair_static.integer); break; - case 19: // show framerate + case 20: // show framerate Cvar_SetValueQuick (&showfps, !showfps.integer); break; - case 20: // always run + case 21: // always run if (cl_forwardspeed.value > 200) { Cvar_SetValueQuick (&cl_forwardspeed, 200); @@ -1352,22 +1357,22 @@ void M_Menu_Options_AdjustSliders (int dir) Cvar_SetValueQuick (&cl_backspeed, 400); } break; - case 21: // lookspring + case 22: // lookspring Cvar_SetValueQuick (&lookspring, !lookspring.integer); break; - case 22: // lookstrafe + case 23: // lookstrafe Cvar_SetValueQuick (&lookstrafe, !lookstrafe.integer); break; - case 23: // mouse speed + case 24: // mouse speed Cvar_SetValueQuick (&sensitivity, bound(1, sensitivity.value + dir * 0.5, 50)); break; - case 24: // mouse look + case 25: // mouse look Cvar_SetValueQuick (&freelook, !freelook.integer); break; - case 25: // invert mouse + case 26: // invert mouse Cvar_SetValueQuick (&m_pitch, -m_pitch.value); break; - case 26: // windowed mouse + case 27: // windowed mouse Cvar_SetValueQuick (&vid_mouse, !vid_mouse.integer); break; } @@ -1391,6 +1396,7 @@ void M_Options_Draw (void) M_Print(16, y, " Color Control Options");y += 8; M_Print(16, y, " 2D Resolution");M_DrawSlider(220, y, scr_2dresolution.value, 0, 1);y += 8; M_Print(16, y, " Screen size");M_DrawSlider(220, y, scr_viewsize.value, 30, 120);y += 8; + M_ItemPrint(16, y, " JPEG screenshots", jpeg_dll != NULL);M_DrawCheckbox(220, y, scr_screenshot_jpeg.integer);y += 8; M_Print(16, y, " Sky");M_DrawCheckbox(220, y, r_sky.integer);y += 8; M_Print(16, y, " Overbright Bits");M_DrawSlider(220, y, v_overbrightbits.value, 0, 4);y += 8; M_Print(16, y, " Texture Combine");M_DrawCheckbox(220, y, gl_combine.integer);y += 8; -- 2.39.2