2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 //#define GL_COLOR_INDEX8_EXT 0x80E5
25 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
27 rtexture_t *char_texture;
34 rtexture_t *conbacktex;
36 //=============================================================================
37 /* Support Routines */
39 typedef struct cachepic_s
42 // FIXME: qpic is evil
44 byte padding[32]; // for appended glpic
48 #define MAX_CACHED_PICS 256
49 cachepic_t menu_cachepics[MAX_CACHED_PICS];
50 int menu_numcachepics;
52 byte menuplyr_pixels[4096];
57 rtexturepool_t *drawtexturepool;
64 // FIXME: qpic is evil
65 qpic_t *Draw_CachePic (char *path)
73 for (pic = menu_cachepics, i = 0;i < menu_numcachepics;pic++, i++)
74 if (!strcmp (path, pic->name))
77 if (menu_numcachepics == MAX_CACHED_PICS)
78 Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
80 strcpy (pic->name, path);
82 // FIXME: move this to menu code
83 // HACK HACK HACK --- we need to keep the bytes for
84 // the translatable player picture just for the menu
85 // configuration dialog
86 if (!strcmp (path, "gfx/menuplyr.lmp"))
88 dat = (qpic_t *)COM_LoadFile (path, false);
90 Sys_Error("unable to load gfx/menuplyr.lmp");
93 memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
96 // load the pic from disk
97 if ((tex = loadtextureimage(drawtexturepool, path, 0, 0, false, false, true)))
99 // load the pic from an image file
100 pic->pic.width = image_width;
101 pic->pic.height = image_height;
102 gl = (glpic_t *)pic->pic.data;
109 // load the pic from gfx.wad
110 p = W_GetLumpName (path);
112 Sys_Error ("Draw_CachePic: failed to load %s", path);
113 pic->pic.width = p->width;
114 pic->pic.height = p->height;
115 gl = (glpic_t *)pic->pic.data;
116 gl->tex = R_LoadTexture (drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
126 static void gl_draw_start(void)
131 menu_numcachepics = 0;
133 drawtexturepool = R_AllocTexturePool();
134 char_texture = loadtextureimage (drawtexturepool, "conchars", 0, 0, false, false, true);
137 draw_chars = W_GetLumpName ("conchars");
138 // convert font to proper transparent color
139 for (i = 0;i < 128 * 128;i++)
140 if (draw_chars[i] == 0)
143 // now turn into texture
144 char_texture = R_LoadTexture (drawtexturepool, "charset", 128, 128, draw_chars, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
147 conbacktex = loadtextureimage(drawtexturepool, "gfx/conback", 0, 0, false, false, true);
150 static void gl_draw_shutdown(void)
152 R_FreeTexturePool(&drawtexturepool);
154 menu_numcachepics = 0;
157 void SHOWLMP_clear(void);
158 static void gl_draw_newmap(void)
163 extern char engineversion[40];
164 int engineversionx, engineversiony;
166 void GL_Draw_Init (void)
169 Cvar_RegisterVariable (&scr_conalpha);
171 for (i = 0;i < 40 && engineversion[i];i++)
172 engineversion[i] |= 0x80; // shift to orange
173 engineversionx = vid.conwidth - strlen(engineversion) * 8 - 8;
174 engineversiony = vid.conheight - 8;
176 menu_numcachepics = 0;
178 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
185 Draws one 8*8 graphics character with 0 being transparent.
186 It can be clipped to the top of the screen to allow the console to be
187 smoothly scrolled off.
190 void Draw_Character (int x, int y, int num)
193 float frow, fcol, size;
201 return; // totally off screen
210 if (!r_render.integer)
212 glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
214 // LordHavoc: NEAREST mode on text if not scaling up
215 if (vid.realwidth <= (int) vid.conwidth)
217 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
219 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
224 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
226 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
231 glColor3f(0.5f,0.5f,0.5f);
233 glColor3f(1.0f,1.0f,1.0f);
236 glTexCoord2f (fcol, frow);
238 glTexCoord2f (fcol + size, frow);
240 glTexCoord2f (fcol + size, frow + size);
241 glVertex2f (x+8, y+8);
242 glTexCoord2f (fcol, frow + size);
247 // LordHavoc: revert to LINEAR mode
248 // if (vid.realwidth <= (int) vid.conwidth)
250 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
251 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
260 // LordHavoc: sped this up a lot, and added maxlen
261 void Draw_String (int x, int y, char *str, int maxlen)
265 if (!r_render.integer)
267 if (y <= -8 || y >= (int) vid.conheight || x >= (int) vid.conwidth || *str == 0) // completely offscreen or no text to print
270 maxlen = strlen(str);
271 else if (maxlen > (int) strlen(str))
272 maxlen = strlen(str);
273 glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
275 // LordHavoc: NEAREST mode on text if not scaling up
276 if (vid.realwidth <= (int) vid.conwidth)
278 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
280 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
287 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
292 glColor3f(0.5f,0.5f,0.5f);
294 glColor3f(1.0f,1.0f,1.0f);
297 while (maxlen-- && x < (int) vid.conwidth) // stop rendering when out of characters or room
299 if ((num = *str++) != 32) // skip spaces
301 frow = (float) ((int) num >> 4)*0.0625;
302 fcol = (float) ((int) num & 15)*0.0625;
303 glTexCoord2f (fcol , frow );glVertex2f (x, y);
304 glTexCoord2f (fcol + 0.0625, frow );glVertex2f (x+8, y);
305 glTexCoord2f (fcol + 0.0625, frow + 0.0625);glVertex2f (x+8, y+8);
306 glTexCoord2f (fcol , frow + 0.0625);glVertex2f (x, y+8);
313 // LordHavoc: revert to LINEAR mode
314 // if (vid.realwidth < (int) vid.conwidth)
316 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
317 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
321 void Draw_AdditiveString (int x, int y, char *str, int maxlen)
323 if (!r_render.integer)
325 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
327 Draw_String(x, y, str, maxlen);
328 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
332 void Draw_GenericPic (rtexture_t *tex, float red, float green, float blue, float alpha, int x, int y, int width, int height)
334 if (!r_render.integer)
337 glColor4f(red * 0.5f, green * 0.5f, blue * 0.5f, alpha);
339 glColor4f(red, green, blue, alpha);
341 glBindTexture(GL_TEXTURE_2D, R_GetTexture(tex));
344 glTexCoord2f (0, 0);glVertex2f (x, y);
345 glTexCoord2f (1, 0);glVertex2f (x+width, y);
346 glTexCoord2f (1, 1);glVertex2f (x+width, y+height);
347 glTexCoord2f (0, 1);glVertex2f (x, y+height);
357 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
360 Draw_GenericPic(((glpic_t *)pic->data)->tex, 1,1,1,alpha, x,y,pic->width, pic->height);
369 void Draw_Pic (int x, int y, qpic_t *pic)
372 Draw_GenericPic(((glpic_t *)pic->data)->tex, 1,1,1,1, x,y,pic->width, pic->height);
376 void Draw_AdditivePic (int x, int y, qpic_t *pic)
380 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
382 Draw_GenericPic(((glpic_t *)pic->data)->tex, 1,1,1,1, x,y,pic->width, pic->height);
383 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
393 Only used for the player color selection menu
396 void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation)
399 byte *trans, *src, *dest;
405 c = pic->width * pic->height;
406 src = menuplyr_pixels;
407 dest = trans = Mem_Alloc(tempmempool, c);
408 for (i = 0;i < c;i++)
409 *dest++ = translation[*src++];
411 rt = R_LoadTexture (drawtexturepool, "translatedplayerpic", pic->width, pic->height, trans, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
414 if (!r_render.integer)
416 Draw_GenericPic (rt, 1,1,1,1, x, y, pic->width, pic->height);
422 Draw_ConsoleBackground
426 void Draw_ConsoleBackground (int lines)
428 Draw_GenericPic (conbacktex, 1,1,1,scr_conalpha.value * lines / vid.conheight, 0, lines - vid.conheight, vid.conwidth, vid.conheight);
429 // LordHavoc: draw version
430 Draw_String(engineversionx, lines - vid.conheight + engineversiony, engineversion, 9999);
437 Fills a box of pixels with a single color
440 void Draw_Fill (int x, int y, int w, int h, int c)
442 if (!r_render.integer)
444 glDisable (GL_TEXTURE_2D);
448 byte *tempcolor = (byte *)&d_8to24table[c];
449 glColor4ub ((byte) (tempcolor[0] >> 1), (byte) (tempcolor[1] >> 1), (byte) (tempcolor[2] >> 1), tempcolor[3]);
452 glColor4ubv ((byte *)&d_8to24table[c]);
459 glVertex2f (x+w, y+h);
466 glEnable (GL_TEXTURE_2D);
469 //=============================================================================
471 //=============================================================================
477 Setup as if the screen was 320*200
482 if (!r_render.integer)
484 glViewport (vid.realx, vid.realy, vid.realwidth, vid.realheight);
487 glMatrixMode(GL_PROJECTION);
491 glOrtho (0, vid.conwidth, vid.conheight, 0, -99999, 99999);
494 glMatrixMode(GL_MODELVIEW);
499 glDisable (GL_DEPTH_TEST);
501 glDisable (GL_CULL_FACE);
505 glEnable(GL_TEXTURE_2D);
508 // LordHavoc: added this
509 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
511 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
518 // LordHavoc: SHOWLMP stuff
519 #define SHOWLMP_MAXLABELS 256
520 typedef struct showlmp_s
529 showlmp_t showlmp[SHOWLMP_MAXLABELS];
531 void SHOWLMP_decodehide(void)
535 lmplabel = MSG_ReadString();
536 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
537 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
539 showlmp[i].isactive = false;
544 void SHOWLMP_decodeshow(void)
547 byte lmplabel[256], picname[256];
549 strcpy(lmplabel,MSG_ReadString());
550 strcpy(picname, MSG_ReadString());
551 if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
562 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
563 if (showlmp[i].isactive)
565 if (strcmp(showlmp[i].label, lmplabel) == 0)
568 break; // drop out to replace it
571 else if (k < 0) // find first empty one to replace
574 return; // none found to replace
575 // change existing one
576 showlmp[k].isactive = true;
577 strcpy(showlmp[k].label, lmplabel);
578 strcpy(showlmp[k].pic, picname);
583 void SHOWLMP_drawall(void)
586 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
587 if (showlmp[i].isactive)
588 Draw_Pic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic));
591 void SHOWLMP_clear(void)
594 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
595 showlmp[i].isactive = false;