/* Copyright (C) 1996-2001 Id Software, Inc. Copyright (C) 2002-2009 John Fitzgibbons and others Copyright (C) 2007-2008 Kristian Duske Copyright (C) 2010-2014 QuakeSpasm developers 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. */ // draw.c -- 2d drawing #include "quakedef.h" //extern unsigned char d_15to8table[65536]; //johnfitz -- never used cvar_t scr_conalpha = {"scr_conalpha", "0.5", CVAR_ARCHIVE}; //johnfitz cvar_t gl_nobind = {"gl_nobind", "0"}; cvar_t gl_max_size = {"gl_max_size", "4096"}; cvar_t gl_picmip = {"gl_picmip", "0"}; qpic_t *draw_disc; qpic_t *draw_backtile; gltexture_t *char_texture; //johnfitz qpic_t *pic_ovr, *pic_ins; //johnfitz -- new cursor handling qpic_t *pic_nul; //johnfitz -- for missing gfx, don't crash qpic_t *sniper_scope; int zombie_skins[2][2]; //Loading Fill by Crow_bar float loading_cur_step; char loading_name[32]; float loading_num_step; int loading_step; float loading_cur_step_bk; //johnfitz -- new pics byte pic_ovr_data[8][8] = { {255,255,255,255,255,255,255,255}, {255, 15, 15, 15, 15, 15, 15,255}, {255, 15, 15, 15, 15, 15, 15, 2}, {255, 15, 15, 15, 15, 15, 15, 2}, {255, 15, 15, 15, 15, 15, 15, 2}, {255, 15, 15, 15, 15, 15, 15, 2}, {255, 15, 15, 15, 15, 15, 15, 2}, {255,255, 2, 2, 2, 2, 2, 2}, }; byte pic_ins_data[9][8] = { { 15, 15,255,255,255,255,255,255}, { 15, 15, 2,255,255,255,255,255}, { 15, 15, 2,255,255,255,255,255}, { 15, 15, 2,255,255,255,255,255}, { 15, 15, 2,255,255,255,255,255}, { 15, 15, 2,255,255,255,255,255}, { 15, 15, 2,255,255,255,255,255}, { 15, 15, 2,255,255,255,255,255}, {255, 2, 2,255,255,255,255,255}, }; byte pic_nul_data[8][8] = { {252,252,252,252, 0, 0, 0, 0}, {252,252,252,252, 0, 0, 0, 0}, {252,252,252,252, 0, 0, 0, 0}, {252,252,252,252, 0, 0, 0, 0}, { 0, 0, 0, 0,252,252,252,252}, { 0, 0, 0, 0,252,252,252,252}, { 0, 0, 0, 0,252,252,252,252}, { 0, 0, 0, 0,252,252,252,252}, }; byte pic_stipple_data[8][8] = { {255, 0, 0, 0,255, 0, 0, 0}, { 0, 0,255, 0, 0, 0,255, 0}, {255, 0, 0, 0,255, 0, 0, 0}, { 0, 0,255, 0, 0, 0,255, 0}, {255, 0, 0, 0,255, 0, 0, 0}, { 0, 0,255, 0, 0, 0,255, 0}, {255, 0, 0, 0,255, 0, 0, 0}, { 0, 0,255, 0, 0, 0,255, 0}, }; byte pic_crosshair_data[8][8] = { {255,255,255,255,255,255,255,255}, {255,255,255, 8, 9,255,255,255}, {255,255,255, 6, 8, 2,255,255}, {255, 6, 8, 8, 6, 8, 8,255}, {255,255, 2, 8, 8, 2, 2, 2}, {255,255,255, 7, 8, 2,255,255}, {255,255,255,255, 2, 2,255,255}, {255,255,255,255,255,255,255,255}, }; //johnfitz typedef struct { gltexture_t *gltexture; float sl, tl, sh, th; } glpic_t; int gl_lightmap_format = GL_RGBA; int gl_solid_format = 3; int gl_alpha_format = 4; int gl_filter_min = GL_LINEAR; int gl_filter_max = GL_LINEAR; int texels; extern int texture_extension_number; canvastype currentcanvas = CANVAS_NONE; //johnfitz -- for GL_SetCanvas //============================================================================== // // PIC CACHING // //============================================================================== typedef struct cachepic_s { char name[MAX_QPATH]; qpic_t pic; byte padding[32]; // for appended glpic } cachepic_t; #define MAX_CACHED_PICS 128 cachepic_t menu_cachepics[MAX_CACHED_PICS]; int menu_numcachepics; byte menuplyr_pixels[4096]; // scrap allocation // Allocate all the little status bar obejcts into a single texture // to crutch up stupid hardware / drivers #define MAX_SCRAPS 2 #define BLOCK_WIDTH 256 #define BLOCK_HEIGHT 256 int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH]; byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT]; //johnfitz -- removed *4 after BLOCK_HEIGHT qboolean scrap_dirty; gltexture_t *scrap_textures[MAX_SCRAPS]; //johnfitz /* ================ Scrap_AllocBlock returns an index into scrap_texnums[] and the position inside it ================ */ int Scrap_AllocBlock (int w, int h, int *x, int *y) { int i, j; int best, best2; int texnum; for (texnum=0 ; texnum= best) break; if (scrap_allocated[texnum][i+j] > best2) best2 = scrap_allocated[texnum][i+j]; } if (j == w) { // this is a valid spot *x = i; *y = best = best2; } } if (best + h > BLOCK_HEIGHT) continue; for (i=0 ; iwidth < 64 && p->height < 64) { int x, y; int i, j, k; int texnum; x = 0; y = 0; texnum = Scrap_AllocBlock (p->width, p->height, &x, &y); scrap_dirty = true; k = 0; for (i=0 ; iheight ; i++) { for (j=0 ; jwidth ; j++, k++) scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k]; } gl.gltexture = scrap_textures[texnum]; //johnfitz -- changed to an array //johnfitz -- no longer go from 0.01 to 0.99 gl.sl = x/(float)BLOCK_WIDTH; gl.sh = (x+p->width)/(float)BLOCK_WIDTH; gl.tl = y/(float)BLOCK_WIDTH; gl.th = (y+p->height)/(float)BLOCK_WIDTH; } else { char texturename[64]; //johnfitz q_snprintf (texturename, sizeof(texturename), "%s:%s", WADFILENAME, name); //johnfitz offset = (src_offset_t)p - (src_offset_t)wad_base + sizeof(int)*2; //johnfitz gl.gltexture = TexMgr_LoadImage (NULL, texturename, p->width, p->height, SRC_INDEXED, p->data, WADFILENAME, offset, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr gl.sl = 0; gl.sh = (float)p->width/(float)TexMgr_PadConditional(p->width); //johnfitz gl.tl = 0; gl.th = (float)p->height/(float)TexMgr_PadConditional(p->height); //johnfitz } memcpy (p->data, &gl, sizeof(glpic_t)); return p; } /* ================ Draw_CachePic ================ */ extern char cwd[MAX_OSPATH]; qpic_t *Draw_CachePic (const char *path) { cachepic_t *pic; int i; qpic_t *dat; glpic_t gl; if (!COM_FileExists(path, NULL)) return NULL; for (pic=menu_cachepics, i=0 ; iname)) return &pic->pic; } if (menu_numcachepics == MAX_CACHED_PICS) Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); menu_numcachepics++; strcpy (pic->name, path); // Determine whether or not we need to have a source by index or by something else // char extension[16]; char path_noext[2*MAX_OSPATH]; COM_StripExtension(path, path_noext, 2*MAX_OSPATH); strcpy(extension, COM_FileGetExtension(path)); int src_type; if (!strcmp("tga", extension)) { src_type = SRC_TGA; dat = (qpic_t *)LoadTGAPic(path_noext); if (!dat) Host_Error ("Draw_CachePic: failed to load %s", path); } else { src_type = SRC_INDEXED; dat = (qpic_t *)COM_LoadTempFile (path, NULL); if (!dat) Host_Error ("Draw_CachePic: failed to load %s", path); SwapPic (dat); } // HACK HACK HACK --- we need to keep the bytes for // the translatable player picture just for the menu // configuration dialog if (!strcmp (path, "gfx/menuplyr.lmp")) memcpy (menuplyr_pixels, dat->data, dat->width*dat->height); pic->pic.width = dat->width; pic->pic.height = dat->height; // naievil -- modified to change extension gl.gltexture = TexMgr_LoadImage (NULL, path, dat->width, dat->height, src_type, dat->data, path, sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr gl.sl = 0; gl.sh = (float)dat->width/(float)TexMgr_PadConditional(dat->width); //johnfitz gl.tl = 0; gl.th = (float)dat->height/(float)TexMgr_PadConditional(dat->height); //johnfitz memcpy (pic->pic.data, &gl, sizeof(glpic_t)); return &pic->pic; } /* ================ Draw_MakePic -- johnfitz -- generate pics from internal data ================ */ qpic_t *Draw_MakePic (const char *name, int width, int height, byte *data) { int flags = TEXPREF_NEAREST | TEXPREF_ALPHA | TEXPREF_PERSIST | TEXPREF_NOPICMIP | TEXPREF_PAD; qpic_t *pic; glpic_t gl; pic = (qpic_t *) Hunk_Alloc (sizeof(qpic_t) - 4 + sizeof (glpic_t)); pic->width = width; pic->height = height; gl.gltexture = TexMgr_LoadImage (NULL, name, width, height, SRC_INDEXED, data, "", (src_offset_t)data, flags); gl.sl = 0; gl.sh = (float)width/(float)TexMgr_PadConditional(width); gl.tl = 0; gl.th = (float)height/(float)TexMgr_PadConditional(height); memcpy (pic->data, &gl, sizeof(glpic_t)); return pic; } //============================================================================== // // INIT // //============================================================================== /* =============== Draw_LoadPics -- johnfitz =============== */ void Draw_LoadPics (void) { qpic_t *dat; dat = (qpic_t *)LoadTGAPic("gfx/charset"); char_texture = TexMgr_LoadImage (NULL, "gfx/charset", dat->width, dat->height, SRC_TGA, dat->data, "gfx/charset", sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_NEAREST | TEXPREF_NOPICMIP | TEXPREF_CONCHARS); draw_disc = Draw_PicFromWad ("disc"); draw_backtile = Draw_PicFromWad ("backtile"); } /* =============== Draw_NewGame -- johnfitz =============== */ void Draw_NewGame (void) { cachepic_t *pic; int i; // empty scrap and reallocate gltextures memset(scrap_allocated, 0, sizeof(scrap_allocated)); memset(scrap_texels, 255, sizeof(scrap_texels)); Scrap_Upload (); //creates 2 empty gltextures // reload wad pics W_LoadWadFile (); //johnfitz -- filename is now hard-coded for honesty Draw_LoadPics (); SCR_LoadPics (); Sbar_LoadPics (); // empty lmp cache for (pic = menu_cachepics, i = 0; i < menu_numcachepics; pic++, i++) pic->name[0] = 0; menu_numcachepics = 0; } /* =============== Draw_Init -- johnfitz -- rewritten =============== */ void Draw_Init (void) { Cvar_RegisterVariable (&scr_conalpha); // clear scrap and allocate gltextures memset(scrap_allocated, 0, sizeof(scrap_allocated)); memset(scrap_texels, 255, sizeof(scrap_texels)); Scrap_Upload (); //creates 2 empty textures // create internal pics pic_ins = Draw_MakePic ("ins", 8, 9, &pic_ins_data[0][0]); pic_ovr = Draw_MakePic ("ovr", 8, 8, &pic_ovr_data[0][0]); pic_nul = Draw_MakePic ("nul", 8, 8, &pic_nul_data[0][0]); sniper_scope = Draw_CachePic ("gfx/hud/scope.tga"); //zombie_skins[0][0] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR); //zombie_skins[0][1] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR); //zombie_skins[1][0] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR); //zombie_skins[1][1] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR); // load game pics Draw_LoadPics (); Clear_LoadingFill (); } //============================================================================== // // 2D DRAWING // //============================================================================== /* ================ Draw_CharacterQuadScale Draw_CharacterQuad with scale parm ================ */ void Draw_CharacterQuadScale (int x, int y, char num, float s) { int row, col; float frow, fcol, size; row = num>>4; col = num&15; frow = row*0.0625; fcol = col*0.0625; size = 0.0625*s; glTexCoord2f (fcol, frow); glVertex2f (x, y); glTexCoord2f (fcol + (float)(size/s), frow); glVertex2f (x+(8*(s)), y); glTexCoord2f (fcol + (float)(size/s), frow + (float)(size/s)); glVertex2f (x+(8*(s)), y+(8*(s))); glTexCoord2f (fcol, frow + (float)(size/s)); glVertex2f (x, y+(8*(s))); } /* ================ Draw_CharacterQuad -- johnfitz -- seperate function to spit out verts ================ */ void Draw_CharacterQuad (int x, int y, char num) { int row, col; float frow, fcol, size; row = num>>4; col = num&15; frow = row*0.0625; fcol = col*0.0625; size = 0.0625; glTexCoord2f (fcol, frow); glVertex2f (x, y); glTexCoord2f (fcol + size, frow); glVertex2f (x+8, y); glTexCoord2f (fcol + size, frow + size); glVertex2f (x+8, y+8); glTexCoord2f (fcol, frow + size); glVertex2f (x, y+8); } /* ================ Draw_Character -- johnfitz -- modified to call Draw_CharacterQuad ================ */ void Draw_Character (int x, int y, int num) { if (y <= -8) return; // totally off screen num &= 255; if (num == 32) return; //don't waste verts on spaces GL_Bind (char_texture); glBegin (GL_QUADS); Draw_CharacterQuad (x, y, (char) num); glEnd (); } /* ================ Draw_CharacterRGBA This is the same as Draw_Character, but with RGBA color codes. - MotoLegacy and ported to Quakespasm by sB :) ================ */ void Draw_CharacterRGBA(int x, int y, int num, float r, float g, float b, float a) { int row, col; float frow, fcol, size; if (y <= -8) return; // totally off screen num &= 255; if (num == 32) return; //don't waste verts on spaces glEnable (GL_BLEND); glColor4f(r, g, b, a); glDisable (GL_ALPHA_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_Bind (char_texture); glBegin (GL_QUADS); row = num>>4; col = num&15; frow = row*0.0625; fcol = col*0.0625; size = 0.0625; glTexCoord2f (fcol, frow); glVertex2f (x, y); glTexCoord2f (fcol + size, frow); glVertex2f (x+8, y); glTexCoord2f (fcol + size, frow + size); glVertex2f (x+8, y+8); glTexCoord2f (fcol, frow + size); glVertex2f (x, y+8); glEnd (); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); glColor4f (1,1,1,1); } /* ================ Draw_String -- johnfitz -- modified to call Draw_CharacterQuad ================ */ void Draw_String (int x, int y, const char *str) { if (y <= -8) return; // totally off screen GL_Bind (char_texture); glBegin (GL_QUADS); while (*str) { if (*str != 32) //don't waste verts on spaces Draw_CharacterQuad (x, y, *str); str++; x += 8; } glEnd (); } /* ================ Draw_ColoredStringScale Draw_ColoredString with scale parm ================ */ void Draw_ColoredStringScale (int x, int y, const char *str, float r, float g, float b, float a, float s) { if (y <= -8) return; // totally off screen glEnable (GL_BLEND); glColor4f(r, g, b, a); glDisable (GL_ALPHA_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_Bind (char_texture); glBegin (GL_QUADS); while (*str) { if (*str != 32) //don't waste verts on spaces Draw_CharacterQuadScale (x, y, *str, s); str++; x += 8*s; } glEnd (); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); glColor4f (1,1,1,1); } /* ================ Draw_ColoredString Assume that all rgba values are divided by 255 already ================ */ void Draw_ColoredString (int x, int y, const char *str, float r, float g, float b, float a) { if (y <= -8) return; // totally off screen glEnable (GL_BLEND); glColor4f(r, g, b, a); glDisable (GL_ALPHA_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_Bind (char_texture); glBegin (GL_QUADS); while (*str) { if (*str != 32) //don't waste verts on spaces Draw_CharacterQuad (x, y, *str); str++; x += 8; } glEnd (); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); glColor4f (1,1,1,1); } /* ============= Draw_ColorPic ============= */ void Draw_ColorPic (int x, int y, qpic_t *pic, float r, float g, float b, float alpha) { glpic_t *gl; if (alpha <= 1.0) { glEnable (GL_BLEND); glColor4f (r,g,b,alpha); glDisable (GL_ALPHA_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } if (scrap_dirty) Scrap_Upload (); gl = (glpic_t *)pic->data; GL_Bind (gl->gltexture); glBegin (GL_QUADS); glTexCoord2f (gl->sl, gl->tl); glVertex2f (x, y); glTexCoord2f (gl->sh, gl->tl); glVertex2f (x+pic->width, y); glTexCoord2f (gl->sh, gl->th); glVertex2f (x+pic->width, y+pic->height); glTexCoord2f (gl->sl, gl->th); glVertex2f (x, y+pic->height); glEnd (); if (alpha <= 1.0) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); glColor4f (1,1,1,1); } } //sB needed a way to stretch round pics void Draw_ColorStretchPic (int x, int y, int width, int height, qpic_t *pic, float r, float g, float b, float alpha) { glpic_t *gl; if (alpha <= 1.0) { glEnable (GL_BLEND); glColor4f (r,g,b,alpha); glDisable (GL_ALPHA_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } if (scrap_dirty) Scrap_Upload (); gl = (glpic_t *)pic->data; GL_Bind (gl->gltexture); glBegin (GL_QUADS); #ifdef VITA glTexCoord2f (0, 0); glVertex2f (x, y); glTexCoord2f (1, 0); glVertex2f (x+width, y); glTexCoord2f (1, 1); glVertex2f (x+width, y+height); glTexCoord2f (0, 1); glVertex2f (x, y+height); #else glTexCoord2f (gl->sl, gl->tl); glVertex2f (x, y); glTexCoord2f (gl->sh, gl->tl); glVertex2f (x+width, y); glTexCoord2f (gl->sh, gl->th); glVertex2f (x+width, y+height); glTexCoord2f (gl->sl, gl->th); glVertex2f (x, y+height); #endif glEnd (); if (alpha <= 1.0) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); glColor4f (1,1,1,1); } } /* ============= Draw_StretchPic ============= */ void Draw_StretchPic (int x, int y, qpic_t *pic, int x_value, int y_value) { glpic_t *gl; if (scrap_dirty) Scrap_Upload (); gl = (glpic_t *)pic->data; GL_Bind (gl->gltexture); glBegin (GL_QUADS); #ifdef VITA glTexCoord2f (0, 0); glVertex2f (x, y); glTexCoord2f (1, 0); glVertex2f (x+x_value, y); glTexCoord2f (1, 1); glVertex2f (x+x_value, y+y_value); glTexCoord2f (0, 1); glVertex2f (x, y+y_value); #else glTexCoord2f (gl->sl, gl->tl); glVertex2f (x, y); glTexCoord2f (gl->sh, gl->tl); glVertex2f (x+x_value, y); glTexCoord2f (gl->sh, gl->th); glVertex2f (x+x_value, y+y_value); glTexCoord2f (gl->sl, gl->th); glVertex2f (x, y+y_value); #endif glEnd (); } /* ============= Draw_Pic -- johnfitz -- modified ============= */ void Draw_Pic (int x, int y, qpic_t *pic) { glpic_t *gl; if (scrap_dirty) Scrap_Upload (); gl = (glpic_t *)pic->data; GL_Bind (gl->gltexture); glBegin (GL_QUADS); glTexCoord2f (gl->sl, gl->tl); glVertex2f (x, y); glTexCoord2f (gl->sh, gl->tl); glVertex2f (x+pic->width, y); glTexCoord2f (gl->sh, gl->th); glVertex2f (x+pic->width, y+pic->height); glTexCoord2f (gl->sl, gl->th); glVertex2f (x, y+pic->height); glEnd (); } /* ============= Draw_Pic -- johnfitz -- modified ============= */ // motolegacy -- ultimate draw function!! probably annihilates gl calls so use wisely lol // TODO: color shifting? void Draw_AlphaStretchPic (int x, int y, int width, int height, float alpha, qpic_t *pic) { glpic_t *gl; if (alpha <= 1.0) { glEnable (GL_BLEND); glColor4f (1,1,1,alpha); glDisable (GL_ALPHA_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } if (scrap_dirty) Scrap_Upload (); gl = (glpic_t *)pic->data; GL_Bind (gl->gltexture); glBegin (GL_QUADS); #ifdef VITA glTexCoord2f (0, 0); glVertex2f (x, y); glTexCoord2f (1, 0); glVertex2f (x+width, y); glTexCoord2f (1, 1); glVertex2f (x+width, y+height); glTexCoord2f (0, 1); glVertex2f (x, y+height); #else glTexCoord2f (gl->sl, gl->tl); glVertex2f (x, y); glTexCoord2f (gl->sh, gl->tl); glVertex2f (x+width, y); glTexCoord2f (gl->sh, gl->th); glVertex2f (x+width, y+height); glTexCoord2f (gl->sl, gl->th); glVertex2f (x, y+height); #endif glEnd (); if (alpha <= 1.0) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); glColor4f (1,1,1,1); } } void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha) { glpic_t *gl; if (alpha <= 1.0) { glEnable (GL_BLEND); glColor4f (1,1,1,alpha); glDisable (GL_ALPHA_TEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } if (scrap_dirty) Scrap_Upload (); gl = (glpic_t *)pic->data; GL_Bind (gl->gltexture); glBegin (GL_QUADS); glTexCoord2f (gl->sl, gl->tl); glVertex2f (x, y); glTexCoord2f (gl->sh, gl->tl); glVertex2f (x+pic->width, y); glTexCoord2f (gl->sh, gl->th); glVertex2f (x+pic->width, y+pic->height); glTexCoord2f (gl->sl, gl->th); glVertex2f (x, y+pic->height); glEnd (); if (alpha <= 1.0) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); glColor4f (1,1,1,1); } } /* ============= Draw_TransPicTranslate -- johnfitz -- rewritten to use texmgr to do translation Only used for the player color selection menu ============= */ void Draw_TransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom) { static int oldtop = -2; static int oldbottom = -2; if (top != oldtop || bottom != oldbottom) { glpic_t *p = (glpic_t *)pic->data; gltexture_t *glt = p->gltexture; oldtop = top; oldbottom = bottom; TexMgr_ReloadImage (glt, top, bottom); } Draw_Pic (x, y, pic); } /* ================ Draw_ConsoleBackground -- johnfitz -- rewritten ================ */ void Draw_ConsoleBackground (void) { GL_SetCanvas (CANVAS_CONSOLE); //in case this is called from weird places Draw_FillByColor (0, 0, vid.conwidth, vid.conheight, 1, 1, 1, 200); } /* ================ Draw_LoadingFill By Crow_bar ================ */ void Draw_LoadingFill(void) { if(!loading_num_step) return; int size = 8; int max_step = 350; int x = (vid.width / 2) - (max_step / 2); int y = vid.height - (size/ 2) - 25; int l; char str[64]; char* text; if(loading_cur_step > loading_num_step) loading_cur_step = loading_num_step; if (loading_cur_step < loading_cur_step_bk) loading_cur_step = loading_cur_step_bk; if (loading_cur_step == loading_num_step && loading_cur_step_bk != loading_num_step) loading_cur_step = loading_cur_step_bk; float loadsize = loading_cur_step * (max_step / loading_num_step); Draw_FillByColor (x - 2, y - 2, max_step + 4, size + 4, 69, 69, 69, 255); Draw_FillByColor (x, y, loadsize, size, 0, 0, 0, 200); switch(loading_step) { case 1: text = "Loading Models.."; break; case 2: text = "Loading World.."; break; case 3: text = "Running Test Frame.."; break; case 4: text = "Loading Sounds.."; break; default: text = "Initializing.."; break; } l = strlen (text); Draw_String((vid.width - l*8)/2, y, text); loading_cur_step_bk = loading_cur_step; } void Clear_LoadingFill (void) { //it is end loading loading_cur_step = 0; loading_cur_step_bk = 0; loading_num_step = 0; loading_step = -1; memset(loading_name, 0, sizeof(loading_name)); } /* ============= Draw_TileClear This repeats a 64*64 tile graphic to fill the screen around a sized down refresh window. ============= */ void Draw_TileClear (int x, int y, int w, int h) { glpic_t *gl; gl = (glpic_t *)draw_backtile->data; glColor3f (1,1,1); GL_Bind (gl->gltexture); glBegin (GL_QUADS); glTexCoord2f (x/64.0, y/64.0); glVertex2f (x, y); glTexCoord2f ( (x+w)/64.0, y/64.0); glVertex2f (x+w, y); glTexCoord2f ( (x+w)/64.0, (y+h)/64.0); glVertex2f (x+w, y+h); glTexCoord2f ( x/64.0, (y+h)/64.0 ); glVertex2f (x, y+h); glEnd (); } /* ============= Draw_Fill Fills a box of pixels with a single color ============= */ void Draw_Fill (int x, int y, int w, int h, int c, float alpha) //johnfitz -- added alpha { byte *pal = (byte *)d_8to24table; //johnfitz -- use d_8to24table instead of host_basepal glDisable (GL_TEXTURE_2D); glEnable (GL_BLEND); //johnfitz -- for alpha glDisable (GL_ALPHA_TEST); //johnfitz -- for alpha glColor4f (pal[c*4]/255.0, pal[c*4+1]/255.0, pal[c*4+2]/255.0, alpha); //johnfitz -- added alpha glBegin (GL_QUADS); glVertex2f (x,y); glVertex2f (x+w, y); glVertex2f (x+w, y+h); glVertex2f (x, y+h); glEnd (); glColor3f (1,1,1); glDisable (GL_BLEND); //johnfitz -- for alpha glEnable(GL_ALPHA_TEST); //johnfitz -- for alpha glEnable (GL_TEXTURE_2D); } /* ============= Draw_FillByColor Fills a box of pixels with a single color not in basepal ============= */ void Draw_FillByColor (int x, int y, int w, int h, float r, float g, float b, float a) { glDisable (GL_TEXTURE_2D); glEnable (GL_BLEND); glDisable (GL_ALPHA_TEST); glColor4f (r/255, g/255, b/255, a/255); glBegin (GL_QUADS); glVertex2f (x,y); glVertex2f (x+w, y); glVertex2f (x+w, y+h); glVertex2f (x, y+h); glEnd (); glColor4f (1,1,1,1); glDisable (GL_BLEND); glEnable(GL_ALPHA_TEST); glEnable (GL_TEXTURE_2D); } /* ================ Draw_FadeScreen -- johnfitz -- revised ================ */ void Draw_FadeScreen (void) { GL_SetCanvas (CANVAS_DEFAULT); glEnable (GL_BLEND); glDisable (GL_ALPHA_TEST); glDisable (GL_TEXTURE_2D); glColor4f (0, 0, 0, 0.5); glBegin (GL_QUADS); glVertex2f (0,0); glVertex2f (glwidth, 0); glVertex2f (glwidth, glheight); glVertex2f (0, glheight); glEnd (); glColor4f (1,1,1,1); glEnable (GL_TEXTURE_2D); glEnable(GL_ALPHA_TEST); glDisable (GL_BLEND); Sbar_Changed(); } /* ================ GL_SetCanvas -- johnfitz -- support various canvas types ================ */ void GL_SetCanvas (canvastype newcanvas) { extern vrect_t scr_vrect; float s; int lines; if (newcanvas == currentcanvas) return; currentcanvas = newcanvas; glMatrixMode(GL_PROJECTION); glLoadIdentity (); switch(newcanvas) { case CANVAS_DEFAULT: glOrtho (0, glwidth, glheight, 0, -99999, 99999); glViewport (glx, gly, glwidth, glheight); break; case CANVAS_CONSOLE: lines = vid.conheight - (scr_con_current * vid.conheight / glheight); glOrtho (0, vid.conwidth, vid.conheight + lines, lines, -99999, 99999); glViewport (glx, gly, glwidth, glheight); break; case CANVAS_MENU: s = q_min((float)glwidth / 320.0, (float)glheight / 200.0); s = CLAMP (1.0, scr_menuscale.value, s); // ericw -- doubled width to 640 to accommodate long keybindings glOrtho (0, 640, 200, 0, -99999, 99999); glViewport (glx + (glwidth - 320*s) / 2, gly + (glheight - 200*s) / 2, 640*s, 200*s); break; case CANVAS_SBAR: s = CLAMP (1.0, scr_sbarscale.value, (float)glwidth / 320.0); if (cl.gametype == GAME_DEATHMATCH) { glOrtho (0, glwidth / s, 48, 0, -99999, 99999); glViewport (glx, gly, glwidth, 48*s); } else { glOrtho (0, 320, 48, 0, -99999, 99999); glViewport (glx + (glwidth - 320*s) / 2, gly, 320*s, 48*s); } break; case CANVAS_WARPIMAGE: glOrtho (0, 128, 0, 128, -99999, 99999); glViewport (glx, gly+glheight-gl_warpimagesize, gl_warpimagesize, gl_warpimagesize); break; case CANVAS_CROSSHAIR: //0,0 is center of viewport s = CLAMP (1.0, scr_crosshairscale.value, 10.0); glOrtho (scr_vrect.width/-2/s, scr_vrect.width/2/s, scr_vrect.height/2/s, scr_vrect.height/-2/s, -99999, 99999); glViewport (scr_vrect.x, glheight - scr_vrect.y - scr_vrect.height, scr_vrect.width & ~1, scr_vrect.height & ~1); break; case CANVAS_BOTTOMLEFT: //used by devstats s = (float)glwidth/vid.conwidth; //use console scale glOrtho (0, 320, 200, 0, -99999, 99999); glViewport (glx, gly, 320*s, 200*s); break; case CANVAS_BOTTOMRIGHT: //used by fps/clock s = (float)glwidth/vid.conwidth; //use console scale glOrtho (0, 320, 200, 0, -99999, 99999); glViewport (glx+glwidth-320*s, gly, 320*s, 200*s); break; case CANVAS_TOPRIGHT: //used by disc s = 1; glOrtho (0, 320, 200, 0, -99999, 99999); glViewport (glx+glwidth-320*s, gly+glheight-200*s, 320*s, 200*s); break; case CANVAS_USEPRINT: s = (float)glwidth/vid.conwidth; //use console scale glOrtho (0, glwidth, glheight, 0, -99999, 99999); glViewport (glx, gly, glwidth*s, glheight*s); break; case CANVAS_HUD: // FIXME: Workaround for Vita build, would be better to rework completely gl_hud.c code. s = (float)glwidth/vid.conwidth; //use console scale s *= 2; glOrtho (0, glwidth, glheight, 0, -99999, 99999); glViewport (glx, gly, glwidth*s, glheight*s); break; default: Sys_Error ("GL_SetCanvas: bad canvas type"); } glMatrixMode(GL_MODELVIEW); glLoadIdentity (); } /* ================ GL_Set2D -- johnfitz -- rewritten ================ */ void GL_Set2D (void) { currentcanvas = CANVAS_INVALID; GL_SetCanvas (CANVAS_DEFAULT); glDisable (GL_DEPTH_TEST); glDisable (GL_CULL_FACE); glDisable (GL_BLEND); glEnable(GL_ALPHA_TEST); glColor4f (1,1,1,1); } /* ================ GL_ResampleTexture ================ */ void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight) { int i, j; unsigned *inrow; unsigned frac, fracstep; fracstep = inwidth*0x10000/outwidth; for (i=0 ; i> 1; for (j=0 ; j>16]; frac += fracstep; out[j+1] = inrow[frac>>16]; frac += fracstep; out[j+2] = inrow[frac>>16]; frac += fracstep; out[j+3] = inrow[frac>>16]; frac += fracstep; } } } /* int loading_cur_step; int loading_num_step; void Clear_LoadingFill (void) { //it is end loading loading_cur_step = 0; loading_num_step = 0; } */ /* ============= loadtextureimage ============= */ gltexture_t *loadtextureimage (char* filename) { byte *data; glpic_t gl; int w, h; data = Image_LoadImage (filename, &w, &h); if(!data) { Sys_Error("loadtextureimage: Cannot load the image %s\n", filename); //return 0; } gl.gltexture = TexMgr_LoadImage (NULL, filename, w, h, SRC_RGBA, data, filename, sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_NEAREST | TEXPREF_NOPICMIP); return gl.gltexture; }