dp_fonts_t dp_fonts;
static mempool_t *fonts_mempool = NULL;
-cvar_t r_textshadow = {CVAR_SAVE, "r_textshadow", "0", "draws a shadow on all text to improve readability (note: value controls offset, 1 = 1 pixel, 1.5 = 1.5 pixels, etc)"};
-cvar_t r_textbrightness = {CVAR_SAVE, "r_textbrightness", "0", "additional brightness for text color codes (0 keeps colors as is, 1 makes them all white)"};
-cvar_t r_textcontrast = {CVAR_SAVE, "r_textcontrast", "1", "additional contrast for text color codes (1 keeps colors as is, 0 makes them all black)"};
-
-cvar_t r_font_postprocess_blur = {CVAR_SAVE, "r_font_postprocess_blur", "0", "font blur amount"};
-cvar_t r_font_postprocess_outline = {CVAR_SAVE, "r_font_postprocess_outline", "0", "font outline amount"};
-cvar_t r_font_postprocess_shadow_x = {CVAR_SAVE, "r_font_postprocess_shadow_x", "0", "font shadow X shift amount, applied during outlining"};
-cvar_t r_font_postprocess_shadow_y = {CVAR_SAVE, "r_font_postprocess_shadow_y", "0", "font shadow Y shift amount, applied during outlining"};
-cvar_t r_font_postprocess_shadow_z = {CVAR_SAVE, "r_font_postprocess_shadow_z", "0", "font shadow Z shift amount, applied during blurring"};
-cvar_t r_font_hinting = {CVAR_SAVE, "r_font_hinting", "3", "0 = no hinting, 1 = light autohinting, 2 = full autohinting, 3 = full hinting"};
-cvar_t r_font_antialias = {CVAR_SAVE, "r_font_antialias", "1", "0 = monochrome, 1 = grey" /* , 2 = rgb, 3 = bgr" */};
-cvar_t r_nearest_2d = {CVAR_SAVE, "r_nearest_2d", "0", "use nearest filtering on all 2d textures (including conchars)"};
-cvar_t r_nearest_conchars = {CVAR_SAVE, "r_nearest_conchars", "0", "use nearest filtering on conchars texture"};
+cvar_t r_textshadow = {CVAR_CLIENT | CVAR_SAVE, "r_textshadow", "0", "draws a shadow on all text to improve readability (note: value controls offset, 1 = 1 pixel, 1.5 = 1.5 pixels, etc)"};
+cvar_t r_textbrightness = {CVAR_CLIENT | CVAR_SAVE, "r_textbrightness", "0", "additional brightness for text color codes (0 keeps colors as is, 1 makes them all white)"};
+cvar_t r_textcontrast = {CVAR_CLIENT | CVAR_SAVE, "r_textcontrast", "1", "additional contrast for text color codes (1 keeps colors as is, 0 makes them all black)"};
+
+cvar_t r_font_postprocess_blur = {CVAR_CLIENT | CVAR_SAVE, "r_font_postprocess_blur", "0", "font blur amount"};
+cvar_t r_font_postprocess_outline = {CVAR_CLIENT | CVAR_SAVE, "r_font_postprocess_outline", "0", "font outline amount"};
+cvar_t r_font_postprocess_shadow_x = {CVAR_CLIENT | CVAR_SAVE, "r_font_postprocess_shadow_x", "0", "font shadow X shift amount, applied during outlining"};
+cvar_t r_font_postprocess_shadow_y = {CVAR_CLIENT | CVAR_SAVE, "r_font_postprocess_shadow_y", "0", "font shadow Y shift amount, applied during outlining"};
+cvar_t r_font_postprocess_shadow_z = {CVAR_CLIENT | CVAR_SAVE, "r_font_postprocess_shadow_z", "0", "font shadow Z shift amount, applied during blurring"};
+cvar_t r_font_hinting = {CVAR_CLIENT | CVAR_SAVE, "r_font_hinting", "3", "0 = no hinting, 1 = light autohinting, 2 = full autohinting, 3 = full hinting"};
+cvar_t r_font_antialias = {CVAR_CLIENT | CVAR_SAVE, "r_font_antialias", "1", "0 = monochrome, 1 = grey" /* , 2 = rgb, 3 = bgr" */};
+cvar_t r_nearest_2d = {CVAR_CLIENT | CVAR_SAVE, "r_nearest_2d", "0", "use nearest filtering on all 2d textures (including conchars)"};
+cvar_t r_nearest_conchars = {CVAR_CLIENT | CVAR_SAVE, "r_nearest_conchars", "0", "use nearest filtering on conchars texture"};
//=============================================================================
/* Support Routines */
texflags |= TEXF_MIPMAP;
if (!(cachepicflags & CACHEPICFLAG_NOCOMPRESSION) && gl_texturecompression_2d.integer && gl_texturecompression.integer)
texflags |= TEXF_COMPRESS;
- if ((cachepicflags & CACHEPICFLAG_NEAREST) || r_nearest_2d.integer)
+ if (cachepicflags & CACHEPICFLAG_LINEAR)
+ texflags |= TEXF_FORCELINEAR;
+ else if ((cachepicflags & CACHEPICFLAG_NEAREST) || r_nearest_2d.integer)
texflags |= TEXF_FORCENEAREST;
// check whether the picture has already been cached
if (!strcmp(path, pic->name))
{
// if it was created (or replaced) by Draw_NewPic, just return it
- if (pic->flags & CACHEPICFLAG_NEWPIC)
- {
- if (pic->skinframe)
- R_SkinFrame_MarkUsed(pic->skinframe);
- pic->lastusedframe = draw_frame;
- return pic;
- }
- if (!((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))) // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that
+ if (!(pic->flags & CACHEPICFLAG_NEWPIC))
{
+ // reload the pic if texflags changed in important ways
+ // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that
+ if ((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))
+ {
+ Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic due to mismatch on flags\n", path, draw_frame);
+ goto reload;
+ }
if (!pic->skinframe || !pic->skinframe->base)
+ {
+ if (pic->flags & CACHEPICFLAG_FAILONMISSING)
+ return NULL;
+ Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic\n", path, draw_frame);
goto reload;
+ }
if (!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT))
pic->autoload = false; // caller is making this pic persistent
- R_SkinFrame_MarkUsed(pic->skinframe);
- pic->lastusedframe = draw_frame;
- return pic;
}
+ if (pic->skinframe)
+ R_SkinFrame_MarkUsed(pic->skinframe);
+ pic->lastusedframe = draw_frame;
+ return pic;
}
}
if (numcachepics == MAX_CACHED_PICS)
{
- Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
+ Con_DPrintf ("Draw_CachePic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", path, draw_frame);
// FIXME: support NULL in callers?
return cachepics; // return the first one
}
+ Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: loading pic%s\n", path, draw_frame, (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) ? " notpersist" : "");
pic = cachepics + (numcachepics++);
memset(pic, 0, sizeof(*pic));
strlcpy (pic->name, path, sizeof(pic->name));
pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) != 0;
pic->lastusedframe = draw_frame;
- // load high quality image (this falls back to low quality too)
- pic->skinframe = R_SkinFrame_LoadExternal(pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0);
+ if (pic->skinframe)
+ {
+ // reload image after it was unloaded or texflags changed significantly
+ R_SkinFrame_LoadExternal_SkinFrame(pic->skinframe, pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0);
+ }
+ else
+ {
+ // load high quality image (this falls back to low quality too)
+ pic->skinframe = R_SkinFrame_LoadExternal(pic->name, texflags | TEXF_FORCE_RELOAD, (cachepicflags & CACHEPICFLAG_QUIET) == 0, (cachepicflags & CACHEPICFLAG_FAILONMISSING) == 0);
+ }
// get the dimensions of the image we loaded (if it was successful)
if (pic->skinframe && pic->skinframe->base)
if (pic == NULL)
return false;
if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+ {
+ Con_DPrintf("Draw_IsPicLoaded(\"%s\"): Loading external skin\n", pic->name);
pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+ }
// skinframe will only be NULL if the pic was created with CACHEPICFLAG_FAILONMISSING and not found
return pic->skinframe != NULL && pic->skinframe->base != NULL;
}
if (pic == NULL)
return NULL;
if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+ {
+ Con_DPrintf("Draw_GetPicTexture(\"%s\"): Loading external skin\n", pic->name);
pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+ }
pic->lastusedframe = draw_frame;
return pic->skinframe ? pic->skinframe->base : NULL;
}
int i;
cachepic_t *pic;
static double nextpurgetime;
- if (nextpurgetime > realtime)
+ if (nextpurgetime > host.realtime)
return;
- nextpurgetime = realtime + 0.05;
+ nextpurgetime = host.realtime + 0.05;
for (i = 0, pic = cachepics;i < numcachepics;i++, pic++)
- if (pic->autoload && pic->skinframe && pic->skinframe->base && pic->lastusedframe < draw_frame)
+ {
+ if (pic->autoload && pic->skinframe && pic->skinframe->base && pic->lastusedframe < draw_frame - 3)
+ {
+ Con_DPrintf("Draw_Frame(%i): Unloading \"%s\"\n", draw_frame, pic->name);
R_SkinFrame_PurgeSkinFrame(pic->skinframe);
+ }
+ }
draw_frame++;
}
{
if (pic->flags & CACHEPICFLAG_NEWPIC && pic->skinframe && pic->skinframe->base && pic->width == width && pic->height == height)
{
+ Con_DPrintf("Draw_NewPic(\"%s\"): frame %i: updating texture\n", picname, draw_frame);
R_UpdateTexture(pic->skinframe->base, pixels_bgra, 0, 0, 0, width, height, 1);
R_SkinFrame_MarkUsed(pic->skinframe);
pic->lastusedframe = draw_frame;
return pic;
}
+ Con_DPrintf("Draw_NewPic(\"%s\"): frame %i: reloading pic because flags/size changed\n", picname, draw_frame);
}
else
{
if (numcachepics == MAX_CACHED_PICS)
{
- Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
+ Con_DPrintf ("Draw_NewPic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", picname, draw_frame);
// FIXME: support NULL in callers?
return cachepics; // return the first one
}
+ Con_DPrintf("Draw_NewPic(\"%s\"): frame %i: creating new cachepic\n", picname, draw_frame);
pic = cachepics + (numcachepics++);
memset(pic, 0, sizeof(*pic));
strlcpy (pic->name, picname, sizeof(pic->name));
R_SkinFrame_PurgeSkinFrame(pic->skinframe);
+ pic->autoload = false;
pic->flags = CACHEPICFLAG_NEWPIC; // disable texflags checks in Draw_CachePic
pic->flags |= (texflags & TEXF_CLAMP) ? 0 : CACHEPICFLAG_NOCLAMP;
pic->flags |= (texflags & TEXF_FORCENEAREST) ? CACHEPICFLAG_NEAREST : 0;
pic->width = width;
pic->height = height;
- pic->skinframe = R_SkinFrame_LoadInternalBGRA(picname, texflags | TEXF_FORCE_RELOAD, pixels_bgra, width, height, vid.sRGB2D);
+ pic->skinframe = R_SkinFrame_LoadInternalBGRA(picname, texflags | TEXF_FORCE_RELOAD, pixels_bgra, width, height, 0, 0, 0, vid.sRGB2D);
pic->lastusedframe = draw_frame;
return pic;
}
{
if (!strcmp (picname, pic->name) && pic->skinframe)
{
+ Con_DPrintf("Draw_FreePic(\"%s\"): frame %i: freeing pic\n", picname, draw_frame);
R_SkinFrame_PurgeSkinFrame(pic->skinframe);
- pic->width = 0;
- pic->height = 0;
return;
}
}
}
else
{
- Con_Printf("Warning: skipped unknown font property %s\n", com_token);
+ Con_DPrintf("Warning: skipped unknown font property %s\n", com_token);
if(!COM_ParseToken_Simple(&p, false, false, true))
return;
}
*/
}
-static void LoadFont_f(void)
+static void LoadFont_f(cmd_state_t *cmd)
{
dp_font_t *f;
int i, sizes;
float sz, scale, voffset;
char mainfont[MAX_QPATH];
- if(Cmd_Argc() < 2)
+ if(Cmd_Argc(cmd) < 2)
{
Con_Printf("Available font commands:\n");
for(i = 0; i < dp_fonts.maxsize; ++i)
);
return;
}
- f = FindFont(Cmd_Argv(1), true);
+ f = FindFont(Cmd_Argv(cmd, 1), true);
if(f == NULL)
{
Con_Printf("font function not found\n");
return;
}
- if(Cmd_Argc() < 3)
+ if(Cmd_Argc(cmd) < 3)
filelist = "gfx/conchars";
else
- filelist = Cmd_Argv(2);
+ filelist = Cmd_Argv(cmd, 2);
memset(f->fallbacks, 0, sizeof(f->fallbacks));
memset(f->fallback_faces, 0, sizeof(f->fallback_faces));
scale = 1;
voffset = 0;
- if(Cmd_Argc() >= 4)
+ if(Cmd_Argc(cmd) >= 4)
{
- for(sizes = 0, i = 3; i < Cmd_Argc(); ++i)
+ for(sizes = 0, i = 3; i < Cmd_Argc(cmd); ++i)
{
// special switches
- if (!strcmp(Cmd_Argv(i), "scale"))
+ if (!strcmp(Cmd_Argv(cmd, i), "scale"))
{
i++;
- if (i < Cmd_Argc())
- scale = atof(Cmd_Argv(i));
+ if (i < Cmd_Argc(cmd))
+ scale = atof(Cmd_Argv(cmd, i));
continue;
}
- if (!strcmp(Cmd_Argv(i), "voffset"))
+ if (!strcmp(Cmd_Argv(cmd, i), "voffset"))
{
i++;
- if (i < Cmd_Argc())
- voffset = atof(Cmd_Argv(i));
+ if (i < Cmd_Argc(cmd))
+ voffset = atof(Cmd_Argv(cmd, i));
continue;
}
continue; // no slot for other sizes
// parse one of sizes
- sz = atof(Cmd_Argv(i));
+ sz = atof(Cmd_Argv(cmd, i));
if (sz > 0.001f && sz < 1000.0f) // do not use crap sizes
{
// search for duplicated sizes
if (sizes == MAX_FONT_SIZES)
{
- Con_Printf("Warning: specified more than %i different font sizes, exceding ones are ignored\n", MAX_FONT_SIZES);
+ Con_Printf(CON_WARN "Warning: specified more than %i different font sizes, exceding ones are ignored\n", MAX_FONT_SIZES);
sizes = -1;
continue;
}
for(i = 0; i < dp_fonts.maxsize; ++i)
if (dp_fonts.f[i].title[0])
LoadFont(false, va(vabuf, sizeof(vabuf), "gfx/font_%s", dp_fonts.f[i].title), &dp_fonts.f[i], 1, 0);
-
- // draw the loading screen so people have something to see in the newly opened window
- SCR_UpdateLoadingScreen(true, true);
}
static void gl_draw_shutdown(void)
if(!FONT_USER(i)->title[0])
dpsnprintf(FONT_USER(i)->title, sizeof(FONT_USER(i)->title), "user%d", j++);
- Cmd_AddCommand ("loadfont",LoadFont_f, "loadfont function tganame loads a font; example: loadfont console gfx/veramono; loadfont without arguments lists the available functions");
+ Cmd_AddCommand(CMD_CLIENT, "loadfont", LoadFont_f, "loadfont function tganame loads a font; example: loadfont console gfx/veramono; loadfont without arguments lists the available functions");
R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap, NULL, NULL);
}
int e0, e1, e2, e3;
if (!pic)
pic = Draw_CachePic("white");
+ // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name
+ Draw_GetPicTexture(pic);
if (width == 0)
width = pic->width;
if (height == 0)
height = pic->height;
- surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_VERTEXCOLOR), true);
+ surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW), true);
e0 = Mod_Mesh_IndexForVertex(mod, surf, x , y , 0, 0, 0, -1, 0, 0, 0, 0, red, green, blue, alpha);
e1 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y , 0, 0, 0, -1, 1, 0, 0, 0, red, green, blue, alpha);
e2 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y + height, 0, 0, 0, -1, 1, 1, 0, 0, red, green, blue, alpha);
int e0, e1, e2, e3;
if (!pic)
pic = Draw_CachePic("white");
+ // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name
+ Draw_GetPicTexture(pic);
if (width == 0)
width = pic->width;
if (height == 0)
height = pic->height;
- surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_VERTEXCOLOR), true);
- e0 = Mod_Mesh_IndexForVertex(mod, surf, x - cosaf * org_x - cosar * org_y, y - sinaf * org_x - sinar * org_y, 0, 0, 0, -1, 0, 0, 0, 0, red, green, blue, alpha);
- e1 = Mod_Mesh_IndexForVertex(mod, surf, x + cosaf * (width - org_x) - cosar * org_y, y + sinaf * (width - org_x) - sinar * org_y, 0, 0, 0, -1, 1, 0, 0, 0, red, green, blue, alpha);
- e2 = Mod_Mesh_IndexForVertex(mod, surf, x + cosaf * (width - org_x) + cosar * (height - org_y), sinaf*(width - org_x) + sinar * (height - org_y), 0, 0, 0, -1, 1, 1, 0, 0, red, green, blue, alpha);
- e3 = Mod_Mesh_IndexForVertex(mod, surf, x - cosaf * org_x + cosar * (height - org_y), y - sinaf * org_x + sinar * (height - org_y), 0, 0, 0, -1, 0, 1, 0, 0, red, green, blue, alpha);
+ surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW), true);
+ e0 = Mod_Mesh_IndexForVertex(mod, surf, x - cosaf * org_x - cosar * org_y , y - sinaf * org_x - sinar * org_y , 0, 0, 0, -1, 0, 0, 0, 0, red, green, blue, alpha);
+ e1 = Mod_Mesh_IndexForVertex(mod, surf, x + cosaf * (width - org_x) - cosar * org_y , y + sinaf * (width - org_x) - sinar * org_y , 0, 0, 0, -1, 1, 0, 0, 0, red, green, blue, alpha);
+ e2 = Mod_Mesh_IndexForVertex(mod, surf, x + cosaf * (width - org_x) + cosar * (height - org_y), y + sinaf * (width - org_x) + sinar * (height - org_y), 0, 0, 0, -1, 1, 1, 0, 0, red, green, blue, alpha);
+ e3 = Mod_Mesh_IndexForVertex(mod, surf, x - cosaf * org_x + cosar * (height - org_y), y - sinaf * org_x + sinar * (height - org_y), 0, 0, 0, -1, 0, 1, 0, 0, red, green, blue, alpha);
Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3);
}
static const vec4_t string_colors[] =
{
// Quake3 colors
- // LordHavoc: why on earth is cyan before magenta in Quake3?
- // LordHavoc: note: Doom3 uses white for [0] and [7]
+ // LadyHavoc: why on earth is cyan before magenta in Quake3?
+ // LadyHavoc: note: Doom3 uses white for [0] and [7]
{0.0, 0.0, 0.0, 1.0}, // black
{1.0, 0.0, 0.0, 1.0}, // red
{0.0, 1.0, 0.0, 1.0}, // green
}
}
+// returns a colorindex (format 0x1RGBA) if str is a valid RGB string
+// returns 0 otherwise
+static int RGBstring_to_colorindex(const char *str)
+{
+ Uchar ch;
+ int ind = 0x0001 << 4;
+ do {
+ if (*str <= '9' && *str >= '0')
+ ind |= (*str - '0');
+ else
+ {
+ ch = tolower(*str);
+ if (ch >= 'a' && ch <= 'f')
+ ind |= (ch - 87);
+ else
+ return 0;
+ }
+ ++str;
+ ind <<= 4;
+ } while(!(ind & 0x10000));
+ return ind | 0xf; // add costant alpha value
+}
+
// NOTE: this function always draws exactly one character if maxwidth <= 0
float DrawQ_TextWidth_UntilWidth_TrackColors_Scale(const char *text, size_t *maxlen, float w, float h, float sw, float sh, int *outcolor, qboolean ignorecolorcodes, const dp_font_t *fnt, float maxwidth)
{
const char *text_start = text;
- int colorindex = STRING_COLOR_DEFAULT;
+ int colorindex;
size_t i;
float x = 0;
Uchar ch, mapch, nextch;
Uchar prevch = 0; // used for kerning
- int tempcolorindex;
float kx;
int map_index = 0;
size_t bytes_left;
// maxwidth /= fnt->scale; // w and h are multiplied by it already
// ftbase_x = snap_to_pixel_x(0);
-
+
if(maxwidth <= 0)
{
least_one = true;
x += width_of[(int) ' '] * dw;
continue;
}
- // i points to the char after ^
if (ch == STRING_COLOR_TAG && !ignorecolorcodes && i < *maxlen)
{
ch = *text; // colors are ascii, so no u8_ needed
++i;
continue;
}
- // i points to the char after ^...
- // i+3 points to 3 in ^x123
- // i+3 == *maxlen would mean that char is missing
else if (ch == STRING_COLOR_RGB_TAG_CHAR && i + 3 < *maxlen ) // ^x found
{
- // building colorindex...
- ch = tolower(text[1]);
- tempcolorindex = 0x10000; // binary: 1,0000,0000,0000,0000
- if (ch <= '9' && ch >= '0') tempcolorindex |= (ch - '0') << 12;
- else if (ch >= 'a' && ch <= 'f') tempcolorindex |= (ch - 87) << 12;
- else tempcolorindex = 0;
+ const char *text_p = &text[1];
+ int tempcolorindex = RGBstring_to_colorindex(text_p);
if (tempcolorindex)
{
- ch = tolower(text[2]);
- if (ch <= '9' && ch >= '0') tempcolorindex |= (ch - '0') << 8;
- else if (ch >= 'a' && ch <= 'f') tempcolorindex |= (ch - 87) << 8;
- else tempcolorindex = 0;
- if (tempcolorindex)
- {
- ch = tolower(text[3]);
- if (ch <= '9' && ch >= '0') tempcolorindex |= (ch - '0') << 4;
- else if (ch >= 'a' && ch <= 'f') tempcolorindex |= (ch - 87) << 4;
- else tempcolorindex = 0;
- if (tempcolorindex)
- {
- colorindex = tempcolorindex | 0xf;
- // ...done! now colorindex has rgba codes (1,rrrr,gggg,bbbb,aaaa)
- i+=4;
- text += 4;
- continue;
- }
- }
+ colorindex = tempcolorindex;
+ i+=4;
+ text += 4;
+ continue;
}
}
- else if (ch == STRING_COLOR_TAG) // ^^ found, ignore the first ^ and go to print the second
+ else if (ch == STRING_COLOR_TAG) // ^^ found
{
i++;
text++;
float x = startx, y, s, t, u, v, thisw;
Uchar ch, mapch, nextch;
Uchar prevch = 0; // used for kerning
- int tempcolorindex;
int map_index = 0;
//ft2_font_map_t *prevmap = NULL; // the previous map
ft2_font_map_t *map = NULL; // the currently used map
}
else if (ch == STRING_COLOR_RGB_TAG_CHAR && i+3 < maxlen ) // ^x found
{
- // building colorindex...
- ch = tolower(text[1]);
- tempcolorindex = 0x10000; // binary: 1,0000,0000,0000,0000
- if (ch <= '9' && ch >= '0') tempcolorindex |= (ch - '0') << 12;
- else if (ch >= 'a' && ch <= 'f') tempcolorindex |= (ch - 87) << 12;
- else tempcolorindex = 0;
- if (tempcolorindex)
+ const char *text_p = &text[1];
+ int tempcolorindex = RGBstring_to_colorindex(text_p);
+ if(tempcolorindex)
{
- ch = tolower(text[2]);
- if (ch <= '9' && ch >= '0') tempcolorindex |= (ch - '0') << 8;
- else if (ch >= 'a' && ch <= 'f') tempcolorindex |= (ch - 87) << 8;
- else tempcolorindex = 0;
- if (tempcolorindex)
- {
- ch = tolower(text[3]);
- if (ch <= '9' && ch >= '0') tempcolorindex |= (ch - '0') << 4;
- else if (ch >= 'a' && ch <= 'f') tempcolorindex |= (ch - 87) << 4;
- else tempcolorindex = 0;
- if (tempcolorindex)
- {
- colorindex = tempcolorindex | 0xf;
- // ...done! now colorindex has rgba codes (1,rrrr,gggg,bbbb,aaaa)
- //Con_Printf("^1colorindex:^7 %x\n", colorindex);
- DrawQ_GetTextColor(DrawQ_Color, colorindex, basered, basegreen, baseblue, basealpha, shadow != 0);
- i+=4;
- text+=4;
- continue;
- }
- }
+ colorindex = tempcolorindex;
+ DrawQ_GetTextColor(DrawQ_Color, colorindex, basered, basegreen, baseblue, basealpha, shadow != 0);
+ i+=4;
+ text+=4;
+ continue;
}
}
else if (ch == STRING_COLOR_TAG)
u = 0.0625f * thisw - (1.0f / tw);
v = 0.0625f - (1.0f / th);
}
- surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, fnt->pic->name, flags, TEXF_ALPHA | TEXF_CLAMP, MATERIALFLAG_VERTEXCOLOR), true);
+ surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, fnt->pic->name, flags, TEXF_ALPHA | TEXF_CLAMP, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW), true);
e0 = Mod_Mesh_IndexForVertex(mod, surf, x , y , 10, 0, 0, -1, s , t , 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]);
e1 = Mod_Mesh_IndexForVertex(mod, surf, x+dw*thisw, y , 10, 0, 0, -1, s+u, t , 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]);
e2 = Mod_Mesh_IndexForVertex(mod, surf, x+dw*thisw, y+dh, 10, 0, 0, -1, s+u, t+v, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]);
}
else
kx = ky = 0;
- surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, map->pic->name, flags, TEXF_ALPHA | TEXF_CLAMP, MATERIALFLAG_VERTEXCOLOR), true);
+ surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, map->pic->name, flags, TEXF_ALPHA | TEXF_CLAMP, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW), true);
e0 = Mod_Mesh_IndexForVertex(mod, surf, x + dw * map->glyphs[mapch].vxmin, y + dh * map->glyphs[mapch].vymin, 10, 0, 0, -1, map->glyphs[mapch].txmin, map->glyphs[mapch].tymin, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]);
e1 = Mod_Mesh_IndexForVertex(mod, surf, x + dw * map->glyphs[mapch].vxmax, y + dh * map->glyphs[mapch].vymin, 10, 0, 0, -1, map->glyphs[mapch].txmax, map->glyphs[mapch].tymin, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]);
e2 = Mod_Mesh_IndexForVertex(mod, surf, x + dw * map->glyphs[mapch].vxmax, y + dh * map->glyphs[mapch].vymax, 10, 0, 0, -1, map->glyphs[mapch].txmax, map->glyphs[mapch].tymax, 0, 0, DrawQ_Color[0], DrawQ_Color[1], DrawQ_Color[2], DrawQ_Color[3]);
if (outcolor)
*outcolor = colorindex;
-
+
// note: this relies on the proper text (not shadow) being drawn last
return x;
}
int e0, e1, e2, e3;
if (!pic)
pic = Draw_CachePic("white");
+ // make sure pic is loaded - we don't use the texture here, Mod_Mesh_GetTexture looks up the skinframe by name
+ Draw_GetPicTexture(pic);
if (width == 0)
width = pic->width;
if (height == 0)
height = pic->height;
- surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_VERTEXCOLOR), true);
+ surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, pic->name, flags, pic->texflags, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW), true);
e0 = Mod_Mesh_IndexForVertex(mod, surf, x , y , 0, 0, 0, -1, s1, t1, 0, 0, r1, g1, b1, a1);
e1 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y , 0, 0, 0, -1, s2, t2, 0, 0, r2, g2, b2, a2);
e2 = Mod_Mesh_IndexForVertex(mod, surf, x + width, y + height, 0, 0, 0, -1, s4, t4, 0, 0, r4, g4, b4, a4);
offsetx = 0.5f * width * vid_conwidth.value / vid.width;
offsety = 0;
}
- surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_VERTEXCOLOR), true);
+ surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_WALL | MATERIALFLAG_VERTEXCOLOR | MATERIALFLAG_ALPHAGEN_VERTEX | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW), true);
e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha);
e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha);
e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r, g, b, alpha);
ih = (int)(0.5 + height * ((float)r_refdef.view.height / vid_conheight.integer));
switch(vid.renderpath)
{
- case RENDERPATH_GL20:
+ case RENDERPATH_GL32:
case RENDERPATH_GLES2:
GL_Scissor(ix, vid.height - iy - ih, iw, ih);
break;
void DrawQ_FlushUI(void)
{
- int i;
dp_model_t *mod = CL_Mesh_UI();
if (mod->num_surfaces == 0)
return;
return;
}
- // TODO: render the mesh using R_Q1BSP_Draw or similar, for full material support.
+ // this is roughly equivalent to R_Mod_Draw, so the UI can use full material feature set
+ r_refdef.view.colorscale = 1;
+ r_textureframe++; // used only by R_GetCurrentTexture
GL_DepthMask(false);
- R_Mesh_PrepareVertices_Generic_Arrays(mod->surfmesh.num_vertices, mod->surfmesh.data_vertex3f, mod->surfmesh.data_lightmapcolor4f, mod->surfmesh.data_texcoordtexture2f);
- for (i = 0; i < mod->num_surfaces; i++)
- {
- msurface_t *surf = mod->data_surfaces + i;
- texture_t *tex = surf->texture;
- if (tex->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
- GL_BlendFunc(tex->customblendfunc[0], tex->customblendfunc[1]);
- else if (tex->currentmaterialflags & MATERIALFLAG_ADD)
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- else if (tex->currentmaterialflags & MATERIALFLAG_ALPHA)
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- else
- GL_BlendFunc(GL_ONE, GL_ZERO);
- R_SetupShader_Generic(tex->currentskinframe->base, NULL, GL_MODULATE, 1, (tex->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND) ? false : true, true, false);
- R_Mesh_Draw(surf->num_firstvertex, surf->num_vertices, surf->num_firsttriangle, surf->num_triangles, mod->surfmesh.data_element3i, NULL, 0, mod->surfmesh.data_element3s, NULL, 0);
- }
+
+ Mod_Mesh_Finalize(mod);
+ R_DrawModelSurfaces(&cl_meshentities[MESH_UI].render, false, false, false, false, false, true);
Mod_Mesh_Reset(mod);
}