fix glsl not being used for skeletal animations (10->50 fps jump)

fix vbos not being used for skeletal animations (50->770 fps jump, yes, really. OOPS!)
so yeah, 7700% speedup there. lol... *sigh*
fixed update notification prompt not appearing by splitting menu key dest into emenu+gmenu. thus the prompt is no longer killed by menu.dat starting up.
fog command now displays a the extra params.
rewrote console char handling to support 32bit unicode chars. font code does not support more than 16bit codepoints still, however.
rewrote beam code in order to restore models on vid_restart. this solves a crash where they were invalid pointers afterwards.
revived old menu_media, because jogi wanted shuffle.
music now fades out for a sec when changing fake-cd-tracks.
music no longer abruptly stops when changing maps.
added fxaa support.
reworked bloom a bit. can now bloom further.
added r_renderscale cvar, for people that want supersampling (max 2), or subsampling for more speed or whatever.
$timer now favours cvars with that name, rather than the $time macro.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4942 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-07-14 14:47:00 +00:00
parent 9b058ce95b
commit 869e544ad4
54 changed files with 1357 additions and 725 deletions

View file

@ -484,7 +484,8 @@ qboolean CL_GetDemoMessage (void)
//force the console up, we're done loading. //force the console up, we're done loading.
Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_console);
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_gmenu);
Key_Dest_Remove(kdm_emenu);
scr_con_current = 0; scr_con_current = 0;
} }
@ -2031,7 +2032,7 @@ void CL_QTVPoll (void)
if (!sourcesmenu) if (!sourcesmenu)
{ {
m_state = m_complex; m_state = m_complex;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
sourcesmenu = M_CreateMenu(0); sourcesmenu = M_CreateMenu(0);
MC_AddPicture(sourcesmenu, 16, 4, 32, 144, "gfx/qplaque.lmp"); MC_AddPicture(sourcesmenu, 16, 4, 32, 144, "gfx/qplaque.lmp");

View file

@ -3549,7 +3549,7 @@ void CL_FTP_f(void)
void CL_Fog_f(void) void CL_Fog_f(void)
{ {
if ((cl.fog_locked && !Cmd_FromGamecode()) || Cmd_Argc() <= 1) if ((cl.fog_locked && !Cmd_FromGamecode()) || Cmd_Argc() <= 1)
Con_Printf("Current fog %f (r:%f g:%f b:%f)\n", cl.fog.density, cl.fog.colour[0], cl.fog.colour[1], cl.fog.colour[2]); Con_Printf("Current fog %f (r:%f g:%f b:%f, a:%f bias:%f)\n", cl.fog.density, cl.fog.colour[0], cl.fog.colour[1], cl.fog.colour[2], cl.fog.alpha, cl.fog.depthbias);
else else
{ {
CL_ResetFog(); CL_ResetFog();
@ -3923,7 +3923,7 @@ void CL_Init (void)
Cmd_AddCommand ("topten", NULL); Cmd_AddCommand ("topten", NULL);
Cmd_AddCommand ("fog", CL_Fog_f); Cmd_AddCommandD ("fog", CL_Fog_f, "fog <density> <red> <green> <blue> <alpha> <depthbias>");
Cmd_AddCommand ("kill", NULL); Cmd_AddCommand ("kill", NULL);
Cmd_AddCommand ("pause", NULL); Cmd_AddCommand ("pause", NULL);
Cmd_AddCommand ("say", CL_Say_f); Cmd_AddCommand ("say", CL_Say_f);
@ -4729,7 +4729,8 @@ double Host_Frame (double time)
#ifdef VM_UI #ifdef VM_UI
UI_MenuState() != 0 || UI_MenuState() != 0 ||
#endif #endif
Key_Dest_Has(kdm_menu) || Key_Dest_Has(kdm_gmenu) ||
Key_Dest_Has(kdm_emenu) ||
Key_Dest_Has(kdm_editor) || Key_Dest_Has(kdm_editor) ||
#ifdef _WIN32 #ifdef _WIN32
!ActiveApp || !ActiveApp ||
@ -5052,7 +5053,9 @@ void CL_StartCinematicOrMenu(void)
UI_Start(); UI_Start();
#endif #endif
#ifdef MENU_DAT
Cbuf_AddText("menu_restart\n", RESTRICT_LOCAL); Cbuf_AddText("menu_restart\n", RESTRICT_LOCAL);
#endif
Con_TPrintf ("^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081 %s %sInitialized ^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082\n", *fs_gamename.string?fs_gamename.string:"Nothing", com_installer?"Installer ":""); Con_TPrintf ("^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081 %s %sInitialized ^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082\n", *fs_gamename.string?fs_gamename.string:"Nothing", com_installer?"Installer ":"");

View file

@ -27,19 +27,19 @@ static qintptr_t VARGS Plug_Menu_Control(void *offset, quintptr_t mask, const qi
Plug_Menu_Event(3, 0); Plug_Menu_Event(3, 0);
menuplug = NULL; menuplug = NULL;
currentplug = oldplug; currentplug = oldplug;
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
} }
if (VM_LONG(arg[0]) != 1) if (VM_LONG(arg[0]) != 1)
return 1; return 1;
//give us menu control //give us menu control
menuplug = currentplug; menuplug = currentplug;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_plugin; m_state = m_plugin;
return 1; return 1;
case 2: //weather it's us or not. case 2: //weather it's us or not.
return currentplug == menuplug && m_state == m_plugin; return currentplug == menuplug && m_state == m_plugin;
case 3: //weather a menu is active case 3: //weather a menu is active
return !!Key_Dest_Has(kdm_menu); return !!Key_Dest_Has(kdm_emenu|kdm_gmenu);
default: default:
return 0; return 0;
} }
@ -288,7 +288,7 @@ static qintptr_t VARGS Plug_Draw_Character(void *offset, quintptr_t mask, const
if (qrenderer == QR_NONE) if (qrenderer == QR_NONE)
return 0; return 0;
Font_BeginString(font_default, arg[0], arg[1], &x, &y); Font_BeginString(font_default, arg[0], arg[1], &x, &y);
Font_DrawChar(x, y, CON_WHITEMASK | 0xe000 | (unsigned int)arg[2]); Font_DrawChar(x, y, CON_WHITEMASK, 0xe000 | (unsigned int)arg[2]);
Font_EndString(font_default); Font_EndString(font_default);
return 0; return 0;
} }
@ -307,7 +307,7 @@ static qintptr_t VARGS Plug_Draw_CharacterH(void *offset, quintptr_t mask, const
if (!(flags & 2)) if (!(flags & 2))
cmask |= 0xe000; cmask |= 0xe000;
Font_BeginScaledString(font_default, x, y, h, h, &x, &y); Font_BeginScaledString(font_default, x, y, h, h, &x, &y);
Font_DrawScaleChar(x, y, cmask | charc); Font_DrawScaleChar(x, y, cmask, charc);
Font_EndString(font_default); Font_EndString(font_default);
return 0; return 0;
} }
@ -315,6 +315,7 @@ static qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qin
{ {
int ipx, px, py; int ipx, px, py;
conchar_t buffer[2048], *str; conchar_t buffer[2048], *str;
unsigned int codeflags, codepoint;
if (qrenderer == QR_NONE) if (qrenderer == QR_NONE)
return 0; return 0;
COM_ParseFunString(CON_WHITEMASK, VM_POINTER(arg[2]), buffer, sizeof(buffer), false); COM_ParseFunString(CON_WHITEMASK, VM_POINTER(arg[2]), buffer, sizeof(buffer), false);
@ -323,13 +324,13 @@ static qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qin
ipx = px; ipx = px;
while(*str) while(*str)
{ {
if ((*str & CON_CHARMASK) == '\n') str = Font_Decode(str, &codeflags, &codepoint);
if (codepoint == '\n')
py += Font_CharHeight(); py += Font_CharHeight();
else if ((*str & CON_CHARMASK) == '\r') else if (codepoint == '\r')
px = ipx; px = ipx;
else else
px = Font_DrawChar(px, py, *str); px = Font_DrawChar(px, py, codeflags, codepoint);
str++;
} }
Font_EndString(font_default); Font_EndString(font_default);
return 0; return 0;
@ -343,6 +344,7 @@ static qintptr_t VARGS Plug_Draw_StringH(void *offset, quintptr_t mask, const qi
char *instr = VM_POINTER(arg[4]); char *instr = VM_POINTER(arg[4]);
float ipx; float ipx;
conchar_t buffer[2048], *str, cmask = CON_WHITEMASK; conchar_t buffer[2048], *str, cmask = CON_WHITEMASK;
unsigned int codeflags, codepoint;
unsigned int parseflags = 0; unsigned int parseflags = 0;
if (qrenderer == QR_NONE) if (qrenderer == QR_NONE)
return 0; return 0;
@ -356,13 +358,13 @@ static qintptr_t VARGS Plug_Draw_StringH(void *offset, quintptr_t mask, const qi
ipx = x; ipx = x;
while(*str) while(*str)
{ {
if ((*str & CON_CHARMASK) == '\n') str = Font_Decode(str, &codeflags, &codepoint);
if (codepoint == '\n')
y += Font_CharScaleHeight(); y += Font_CharScaleHeight();
else if ((*str & CON_CHARMASK) == '\r') else if (codepoint == '\r')
x = ipx; x = ipx;
else else
x = Font_DrawScaleChar(x, y, *str); x = Font_DrawScaleChar(x, y, codeflags, codepoint);
str++;
} }
Font_EndString(font_default); Font_EndString(font_default);
return 0; return 0;
@ -1171,7 +1173,7 @@ void Plug_Client_Close(plugin_t *plug)
if (menuplug == plug) if (menuplug == plug)
{ {
menuplug = NULL; menuplug = NULL;
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
} }
if (protocolclientplugin == plug) if (protocolclientplugin == plug)
{ {

View file

@ -703,13 +703,10 @@ void SCR_DrawCursor(void)
//choose the cursor based upon the module that has primary focus //choose the cursor based upon the module that has primary focus
if (key_dest_mask & key_dest_absolutemouse & (kdm_console|kdm_cwindows|kdm_editor)) if (key_dest_mask & key_dest_absolutemouse & (kdm_console|kdm_cwindows|kdm_editor))
cmod = kc_console; cmod = kc_console;
else if ((key_dest_mask & key_dest_absolutemouse & kdm_menu)) else if ((key_dest_mask & key_dest_absolutemouse & kdm_emenu))
{ cmod = kc_console;
if (m_state == m_menu_dat) else if ((key_dest_mask & key_dest_absolutemouse & kdm_gmenu))
cmod = kc_menu; cmod = kc_menu;
else
cmod = kc_console;
}
else// if (key_dest_mask & key_dest_absolutemouse) else// if (key_dest_mask & key_dest_absolutemouse)
cmod = prydoncursornum?kc_console:kc_game; cmod = prydoncursornum?kc_console:kc_game;
@ -778,9 +775,9 @@ void SCR_DrawCursor(void)
{ {
float x, y; float x, y;
Font_BeginScaledString(font_default, mousecursor_x, mousecursor_y, 8, 8, &x, &y); Font_BeginScaledString(font_default, mousecursor_x, mousecursor_y, 8, 8, &x, &y);
x -= Font_CharWidth('+' | 0xe000 | CON_WHITEMASK)/2; x -= Font_CharScaleWidth(CON_WHITEMASK, '+' | 0xe000)/2;
y -= Font_CharHeight()/2; y -= Font_CharHeight()/2;
Font_DrawScaleChar(x, y, '+' | 0xe000 | CON_WHITEMASK); Font_DrawScaleChar(x, y, CON_WHITEMASK, '+' | 0xe000);
Font_EndString(font_default); Font_EndString(font_default);
} }
} }
@ -793,9 +790,9 @@ static void SCR_DrawSimMTouchCursor(void)
if (multicursor_active[i]) if (multicursor_active[i])
{ {
Font_BeginScaledString(font_default, multicursor_x[i], multicursor_y[i], 8, 8, &x, &y); Font_BeginScaledString(font_default, multicursor_x[i], multicursor_y[i], 8, 8, &x, &y);
x -= Font_CharWidth('+' | 0xe000 | CON_WHITEMASK)/2; x -= Font_CharScaleWidth(CON_WHITEMASK, '+' | 0xe000)/2;
y -= Font_CharHeight()/2; y -= Font_CharHeight()/2;
Font_DrawScaleChar(x, y, '+' | 0xe000 | CON_WHITEMASK); Font_DrawScaleChar(x, y, CON_WHITEMASK, '+' | 0xe000);
Font_EndString(font_default); Font_EndString(font_default);
} }
} }
@ -1382,6 +1379,7 @@ void SCR_DrawNet (void)
R2D_ScalePic (scr_vrect.x+64, scr_vrect.y, 64, 64, scr_net); R2D_ScalePic (scr_vrect.x+64, scr_vrect.y, 64, 64, scr_net);
} }
//FIXME: no support for UTF-8 input
void SCR_StringXY(char *str, float x, float y) void SCR_StringXY(char *str, float x, float y)
{ {
char *s2; char *s2;
@ -1392,14 +1390,14 @@ void SCR_StringXY(char *str, float x, float y)
if (x < 0) if (x < 0)
{ {
for (s2 = str; *s2; s2++) for (s2 = str; *s2; s2++)
px -= Font_CharWidth(*s2); px -= Font_CharWidth(CON_WHITEMASK, *s2);
} }
if (y < 0) if (y < 0)
py += y*Font_CharHeight(); py += y*Font_CharHeight();
while (*str) while (*str)
px = Font_DrawChar(px, py, CON_WHITEMASK|*str++); px = Font_DrawChar(px, py, CON_WHITEMASK, *str++);
Font_EndString(font_default); Font_EndString(font_default);
} }
@ -1568,7 +1566,7 @@ void SCR_DrawPause (void)
if (!cl.paused) if (!cl.paused)
return; return;
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_emenu) || Key_Dest_Has(kdm_gmenu))
return; return;
pic = R2D_SafeCachePic ("gfx/pause.lmp"); pic = R2D_SafeCachePic ("gfx/pause.lmp");
@ -1911,7 +1909,7 @@ void SCR_SetUpToDrawConsole (void)
// Key_Dest_Add(kdm_console); // Key_Dest_Add(kdm_console);
scr_conlines = scr_con_current = vid.height * fullscreenpercent; scr_conlines = scr_con_current = vid.height * fullscreenpercent;
} }
else if (!startuppending && !Key_Dest_Has(kdm_menu) && (!Key_Dest_Has(~((!con_stayhidden.ival?kdm_console:0)|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false)) else if (!startuppending && !Key_Dest_Has(kdm_emenu|kdm_gmenu) && (!Key_Dest_Has(~((!con_stayhidden.ival?kdm_console:0)|kdm_game))) && SCR_GetLoadingStage() == LS_NONE && cls.state < ca_active && !Media_PlayingFullScreen() && !CSQC_UnconnectedOkay(false))
{ {
//go fullscreen if we're not doing anything //go fullscreen if we're not doing anything
if (con_curwindow && !cls.state) if (con_curwindow && !cls.state)
@ -1996,7 +1994,7 @@ void SCR_DrawConsole (qboolean noback)
{ {
if (!scr_con_current) if (!scr_con_current)
{ {
if (!Key_Dest_Has(kdm_console|kdm_menu)) if (!Key_Dest_Has(kdm_console|kdm_gmenu|kdm_emenu))
Con_DrawNotify (); // only draw notify in game Con_DrawNotify (); // only draw notify in game
} }
if (scr_con_current || Key_Dest_Has(kdm_cwindows)) if (scr_con_current || Key_Dest_Has(kdm_cwindows))
@ -2574,10 +2572,10 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
if (!consolefocused) if (!consolefocused)
SCR_DrawConsole (false); SCR_DrawConsole (false);
M_Draw (uimenu);
#ifdef MENU_DAT #ifdef MENU_DAT
MP_Draw(); MP_Draw();
#endif #endif
M_Draw (uimenu);
//but if the console IS focused, then always show it infront. //but if the console IS focused, then always show it infront.
if (consolefocused) if (consolefocused)

View file

@ -244,30 +244,39 @@ int
rtq2_grenade=P_INVALID, rtq2_grenade=P_INVALID,
rtqw_railtrail=P_INVALID, rtqw_railtrail=P_INVALID,
rtfte_lightning1=P_INVALID,
ptfte_lightning1_end=P_INVALID,
rtfte_lightning2=P_INVALID,
ptfte_lightning2_end=P_INVALID,
rtfte_lightning3=P_INVALID,
ptfte_lightning3_end=P_INVALID,
ptfte_bullet=P_INVALID, ptfte_bullet=P_INVALID,
ptfte_superbullet=P_INVALID; ptfte_superbullet=P_INVALID;
typedef struct {
/*static stuff*/
char *modelname;
char *beamparticles;
char *beamimpactparticle;
int bflags;
/*cached stuff*/
model_t *model;
int ef_beam;
int ef_impact;
} tentmodels_t;
typedef struct typedef struct
{ {
tentmodels_t *info;
int entity; int entity;
short tag; short tag;
qbyte active; // short pad;
// qbyte pad;
qbyte bflags; qbyte bflags;
qbyte type; qbyte type;
qbyte skin; qbyte skin;
unsigned int rflags; unsigned int rflags;
struct model_s *model;
float endtime; float endtime;
float alpha; float alpha;
vec3_t start, end; vec3_t start, end;
vec3_t offset; //when attached, this is the offset from the owning entity. probably only z is meaningful. vec3_t offset; //when attached, this is the offset from the owning entity. probably only z is meaningful.
int particleeffect; // int particlecolour; //some effects have specific colours. which is weird.
trailstate_t *trailstate; trailstate_t *trailstate;
trailstate_t *emitstate; trailstate_t *emitstate;
} beam_t; } beam_t;
@ -305,6 +314,30 @@ int cl_explosions_max;
static int explosions_running; static int explosions_running;
static int beams_running; static int beams_running;
static tentmodels_t beamtypes[] =
{
{"progs/bolt.mdl", "TE_LIGHTNING1", "TE_LIGHTNING1_END"},
{"progs/bolt2.mdl", "TE_LIGHTNING2", "TE_LIGHTNING2_END"},
{"progs/bolt3.mdl", "TE_LIGHTNING3", "TE_LIGHTNING3_END"},
{"progs/beam.mdl", "te_beam", "te_beam_end"}, //a CTF addition, but has other potential uses, sadly.
{"q2cl_mod_parasite_segment", "te_parasite_attack", "te_parasite_attack_end"},
{"q2cl_mod_grapple_cable", "te_grapple_cable", "te_grapple_cable_end"},
{"models/proj/beam/tris.md2", "te_heatbeam", "te_heatbeam_end"},
{"models/stltng2.mdl", "te_stream_lightning_small", NULL},
{"models/stchain.mdl", "te_stream_chain", NULL},
{"models/stsunsf1.mdl", "te_stream_sunstaff1", NULL},
{"models/stsunsf2.mdl", NULL, NULL},
{"models/stsunsf1.mdl", "te_stream_sunstaff2", NULL},
{"models/stlghtng.mdl", "te_stream_lightning", NULL},
{"models/stclrbm.mdl", "te_stream_colorbeam", NULL},
{"models/stice.mdl", "te_stream_icechunks", NULL},
{"models/stmedgaz.mdl", "te_stream_gaze", NULL},
{"models/fambeam.mdl", "te_stream_famine", NULL},
};
sfx_t *cl_sfx_wizhit; sfx_t *cl_sfx_wizhit;
sfx_t *cl_sfx_knighthit; sfx_t *cl_sfx_knighthit;
sfx_t *cl_sfx_tink1; sfx_t *cl_sfx_tink1;
@ -578,16 +611,22 @@ void CL_RegisterParticles(void)
#endif #endif
rtqw_railtrail = P_FindParticleType("TE_RAILTRAIL"); rtqw_railtrail = P_FindParticleType("TE_RAILTRAIL");
rtfte_lightning1 = P_FindParticleType("TE_LIGHTNING1");
ptfte_lightning1_end = P_FindParticleType("TE_LIGHTNING1_END");
rtfte_lightning2 = P_FindParticleType("TE_LIGHTNING2");
ptfte_lightning2_end = P_FindParticleType("TE_LIGHTNING2_END");
rtfte_lightning3 = P_FindParticleType("TE_LIGHTNING3");
ptfte_lightning3_end = P_FindParticleType("TE_LIGHTNING3_END");
ptfte_bullet = P_FindParticleType("TE_BULLET"); ptfte_bullet = P_FindParticleType("TE_BULLET");
ptfte_superbullet = P_FindParticleType("TE_SUPERBULLET"); ptfte_superbullet = P_FindParticleType("TE_SUPERBULLET");
CL_RefreshCustomTEnts(); CL_RefreshCustomTEnts();
for (i = 0; i < countof(beamtypes); i++)
{
//we can normally expect the server to have precache_modeled these models, so any lookups should be just a lookup, and thus relatively cheap.
beamtypes[i].model = NULL;
beamtypes[i].ef_beam = beamtypes[i].beamparticles?P_FindParticleType(beamtypes[i].beamparticles):P_INVALID;
beamtypes[i].ef_impact = beamtypes[i].beamimpactparticle?P_FindParticleType(beamtypes[i].beamimpactparticle):P_INVALID;
}
//FIXME
for (i = 0; i < cl_explosions_max; i++)
cl_explosions[i].model = NULL;
} }
#ifdef Q2CLIENT #ifdef Q2CLIENT
@ -595,24 +634,16 @@ enum {
q2cl_mod_explode, q2cl_mod_explode,
q2cl_mod_smoke, q2cl_mod_smoke,
q2cl_mod_flash, q2cl_mod_flash,
q2cl_mod_parasite_segment,
q2cl_mod_grapple_cable,
q2cl_mod_parasite_tip, q2cl_mod_parasite_tip,
q2cl_mod_explo4, q2cl_mod_explo4,
q2cl_mod_bfg_explo, q2cl_mod_bfg_explo,
q2cl_mod_powerscreen, q2cl_mod_powerscreen,
q2cl_mod_max q2cl_mod_max
}; };
typedef struct {
char *modelname;
} tentmodels_t;
tentmodels_t q2tentmodels[q2cl_mod_max] = { tentmodels_t q2tentmodels[q2cl_mod_max] = {
{"models/objects/explode/tris.md2"}, {"models/objects/explode/tris.md2"},
{"models/objects/smoke/tris.md2"}, {"models/objects/smoke/tris.md2"},
{"models/objects/flash/tris.md2"}, {"models/objects/flash/tris.md2"},
{"models/monsters/parasite/segment/tris.md2"},
{"models/ctf/segment/tris.md2"},
{"models/monsters/parasite/tip/tris.md2"}, {"models/monsters/parasite/tip/tris.md2"},
{"models/objects/r_explode/tris.md2"}, {"models/objects/r_explode/tris.md2"},
{"sprites/s_bfg2.sp2"}, {"sprites/s_bfg2.sp2"},
@ -726,7 +757,7 @@ explosion_t *CL_AllocExplosion (vec3_t org)
CL_ParseBeam CL_ParseBeam
================= =================
*/ */
beam_t *CL_NewBeam (int entity, int tag) beam_t *CL_NewBeam (int entity, int tag, tentmodels_t *btype)
{ {
beam_t *b; beam_t *b;
int i; int i;
@ -737,7 +768,7 @@ beam_t *CL_NewBeam (int entity, int tag)
for (i=0, b=cl_beams; i < beams_running; i++, b++) for (i=0, b=cl_beams; i < beams_running; i++, b++)
if (b->entity == entity && b->tag == tag) if (b->entity == entity && b->tag == tag)
{ {
b->active = true; b->info = btype;
return b; return b;
} }
} }
@ -745,9 +776,9 @@ beam_t *CL_NewBeam (int entity, int tag)
// find a free beam // find a free beam
for (i=0, b=cl_beams; i < beams_running; i++, b++) for (i=0, b=cl_beams; i < beams_running; i++, b++)
{ {
if (!b->active) if (!b->info)
{ {
b->active = true; b->info = btype;
return b; return b;
} }
} }
@ -765,7 +796,7 @@ beam_t *CL_NewBeam (int entity, int tag)
} }
beams_running++; beams_running++;
cl_beams[i].active = true; cl_beams[i].info = btype;
return &cl_beams[i]; return &cl_beams[i];
} }
@ -773,7 +804,7 @@ beam_t *CL_NewBeam (int entity, int tag)
} }
#define STREAM_ATTACHED 16 #define STREAM_ATTACHED 16
#define STREAM_TRANSLUCENT 32 #define STREAM_TRANSLUCENT 32
void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ numbers instead of 0 - 5 void CL_AddBeam (enum beamtype_e tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ numbers instead of 0 - 5
{ {
beam_t *b; beam_t *b;
@ -782,11 +813,11 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
int i; int i;
vec3_t impact, normal; vec3_t impact, normal;
vec3_t extra; vec3_t extra;
char *mname;
//zquake compat requires some parsing weirdness.
switch(tent) switch(tent)
{ {
case 0: case BT_Q1LIGHTNING1:
if (ent < 0 && ent >= -512) //a zquake concept. ent between -1 and -maxplayers is to be taken to be a railtrail from a particular player instead of a beam. if (ent < 0 && ent >= -512) //a zquake concept. ent between -1 and -maxplayers is to be taken to be a railtrail from a particular player instead of a beam.
{ {
// TODO: add support for those finnicky colored railtrails... // TODO: add support for those finnicky colored railtrails...
@ -794,55 +825,27 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
P_ParticleTrailIndex(start, end, 208, 8, NULL); P_ParticleTrailIndex(start, end, 208, 8, NULL);
return; return;
} }
default:
mname = "progs/bolt.mdl";
btype = rtfte_lightning1;
etype = ptfte_lightning1_end;
break; break;
case 1: case BT_Q1LIGHTNING2:
if (ent < 0 && ent >= -MAX_CLIENTS) //based on the railgun concept - this adds a rogue style TE_BEAM effect. if (ent < 0 && ent >= -MAX_CLIENTS) //based on the railgun concept - this adds a rogue style TE_BEAM effect.
{ tent = BT_Q1BEAM;
case 5:
mname = "progs/beam.mdl"; //remember to precache!
btype = P_FindParticleType("te_beam");
etype = P_FindParticleType("te_beam_end");
}
else
{
mname = "progs/bolt2.mdl";
btype = rtfte_lightning2;
etype = ptfte_lightning2_end;
}
break; break;
case 2: default:
mname = "progs/bolt3.mdl";
btype = rtfte_lightning3;
etype = ptfte_lightning3_end;
break; break;
#ifdef Q2CLIENT
case 3:
mname = q2tentmodels[q2cl_mod_parasite_segment].modelname;
btype = P_FindParticleType("te_parasite_attack");
etype = P_FindParticleType("te_parasite_attack_end");
break;
case 4:
mname = q2tentmodels[q2cl_mod_grapple_cable].modelname;
btype = P_FindParticleType("te_grapple_cable");
etype = P_FindParticleType("te_grapple_cable_end");
break;
case 6:
mname = "models/proj/beam/tris.md2";
btype = P_FindParticleType("te_heatbeam");
etype = P_FindParticleType("te_heatbeam_end");
break;
#endif
} }
btype = beamtypes[tent].ef_beam;
etype = beamtypes[tent].ef_impact;
/*don't bother loading the model if we have a particle effect for it instead*/ /*don't bother loading the model if we have a particle effect for it instead*/
if (ruleset_allow_particle_lightning.ival && btype >= 0) if (ruleset_allow_particle_lightning.ival && btype >= 0)
m = NULL; m = NULL;
else else
m = Mod_ForName(mname, MLV_WARN); {
m = beamtypes[tent].model;
if (!m)
m = beamtypes[tent].model = Mod_ForName(beamtypes[tent].modelname, MLV_WARN);
}
if (m && m->loadstate != MLS_LOADED) if (m && m->loadstate != MLS_LOADED)
CL_CheckOrEnqueDownloadFile(m->name, NULL, 0); CL_CheckOrEnqueDownloadFile(m->name, NULL, 0);
@ -878,7 +881,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
} }
} }
b = CL_NewBeam(ent, -1); b = CL_NewBeam(ent, -1, &beamtypes[tent]);
if (!b) if (!b)
{ {
Con_Printf ("beam list overflow!\n"); Con_Printf ("beam list overflow!\n");
@ -887,8 +890,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
b->rflags = RF_NOSHADOW; b->rflags = RF_NOSHADOW;
b->entity = ent; b->entity = ent;
b->model = m; b->info = &beamtypes[tent];
b->particleeffect = btype;
b->tag = -1; b->tag = -1;
b->bflags |= /*STREAM_ATTACHED|*/1; b->bflags |= /*STREAM_ATTACHED|*/1;
b->endtime = cl.time + 0.2; b->endtime = cl.time + 0.2;
@ -902,7 +904,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, -10, 20); if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, -10, 20);
} }
} }
void CL_ParseBeam (int tent) void CL_ParseBeam (enum beamtype_e tent)
{ {
int ent; int ent;
vec3_t start, end; vec3_t start, end;
@ -950,6 +952,7 @@ void CL_ParseStream (int type)
int tag; int tag;
float duration; float duration;
int skin; int skin;
tentmodels_t *info;
ent = MSGCL_ReadEntity(); ent = MSGCL_ReadEntity();
flags = MSG_ReadByte(); flags = MSG_ReadByte();
@ -968,7 +971,47 @@ void CL_ParseStream (int type)
end[1] = MSG_ReadCoord(); end[1] = MSG_ReadCoord();
end[2] = MSG_ReadCoord(); end[2] = MSG_ReadCoord();
b = CL_NewBeam(ent, tag); switch(type)
{
case TEH2_STREAM_LIGHTNING_SMALL:
info = &beamtypes[BT_H2LIGHTNING_SMALL];
flags |= 2;
break;
case TEH2_STREAM_LIGHTNING:
info = &beamtypes[BT_H2LIGHTNING];
flags |= 2;
break;
case TEH2_STREAM_ICECHUNKS:
info = &beamtypes[BT_H2ICECHUNKS];
flags |= 2;
if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, 0, 20);
break;
case TEH2_STREAM_SUNSTAFF1:
info = &beamtypes[BT_H2SUNSTAFF1];
break;
case TEH2_STREAM_SUNSTAFF2:
info = &beamtypes[BT_H2SUNSTAFF2];
if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, -10, 20);
break;
case TEH2_STREAM_COLORBEAM:
info = &beamtypes[BT_H2COLORBEAM];
break;
case TEH2_STREAM_GAZE:
info = &beamtypes[BT_H2GAZE];
break;
case TEH2_STREAM_FAMINE:
info = &beamtypes[BT_H2FAMINE];
break;
case TEH2_STREAM_CHAIN:
info = &beamtypes[BT_H2CHAIN];
break;
default:
Con_Printf("CL_ParseStream: type %i\n", type);
info = &beamtypes[BT_H2LIGHTNING];
break;
}
b = CL_NewBeam(ent, tag, info);
if (!b) if (!b)
{ {
Con_Printf ("beam list overflow!\n"); Con_Printf ("beam list overflow!\n");
@ -979,8 +1022,6 @@ void CL_ParseStream (int type)
b->entity = ent; b->entity = ent;
b->tag = tag; b->tag = tag;
b->bflags = flags; b->bflags = flags;
b->model = NULL;
b->particleeffect = -1;
b->endtime = cl.time + duration; b->endtime = cl.time + duration;
b->alpha = 1; b->alpha = 1;
b->skin = skin; b->skin = skin;
@ -998,30 +1039,13 @@ void CL_ParseStream (int type)
} }
} }
//special handling...
switch(type) switch(type)
{ {
case TEH2_STREAM_LIGHTNING_SMALL:
b->model = Mod_ForName("models/stltng2.mdl", MLV_WARN);
b->bflags |= 2;
b->particleeffect = P_FindParticleType("te_stream_lightning_small");
break;
case TEH2_STREAM_LIGHTNING:
b->model = Mod_ForName("models/stlghtng.mdl", MLV_WARN);
b->bflags |= 2;
b->particleeffect = P_FindParticleType("te_stream_lightning");
break;
case TEH2_STREAM_ICECHUNKS:
b->model = Mod_ForName("models/stice.mdl", MLV_WARN);
b->bflags |= 2;
b->particleeffect = P_FindParticleType("te_stream_icechunks");
if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, 0, 20);
break;
case TEH2_STREAM_SUNSTAFF1: case TEH2_STREAM_SUNSTAFF1:
b->model = Mod_ForName("models/stsunsf1.mdl", MLV_WARN); if (info->ef_beam == P_INVALID)
b->particleeffect = P_FindParticleType("te_stream_sunstaff1");
if (b->particleeffect < 0)
{ {
b2 = CL_NewBeam(ent, tag+128); b2 = CL_NewBeam(ent, tag+128, &beamtypes[BT_H2SUNSTAFF1_SUB]);
if (b2) if (b2)
{ {
P_DelinkTrailstate(&b2->trailstate); P_DelinkTrailstate(&b2->trailstate);
@ -1029,37 +1053,12 @@ void CL_ParseStream (int type)
memcpy(b2, b, sizeof(*b2)); memcpy(b2, b, sizeof(*b2));
b2->trailstate = NULL; b2->trailstate = NULL;
b2->emitstate = NULL; b2->emitstate = NULL;
b2->model = Mod_ForName("models/stsunsf2.mdl", MLV_WARN);
b2->alpha = 0.5; b2->alpha = 0.5;
b2->rflags = RF_TRANSLUCENT|RF_NOSHADOW; b2->rflags = RF_TRANSLUCENT|RF_NOSHADOW;
} }
} }
//FIXME: we don't add the blob corners+smoke //FIXME: we don't add the blob corners+smoke
break; break;
case TEH2_STREAM_SUNSTAFF2:
b->model = Mod_ForName("models/stsunsf1.mdl", MLV_WARN);
b->particleeffect = P_FindParticleType("te_stream_sunstaff2");
if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, -10, 20);
break;
case TEH2_STREAM_COLORBEAM:
b->model = Mod_ForName("models/stclrbm.mdl", MLV_WARN);
b->particleeffect = P_FindParticleType("te_stream_colorbeam");
break;
case TEH2_STREAM_GAZE:
b->model = Mod_ForName("models/stmedgaz.mdl", MLV_WARN);
b->particleeffect = P_FindParticleType("te_stream_gaze");
break;
case TEH2_STREAM_FAMINE:
b->model = Mod_ForName("models/fambeam.mdl", MLV_WARN);
b->particleeffect = P_FindParticleType("te_stream_famine");
break;
case TEH2_STREAM_CHAIN:
b->model = Mod_ForName("models/stchain.mdl", MLV_WARN);
b->particleeffect = P_FindParticleType("te_stream_chain");
break;
default:
Con_Printf("CL_ParseStream: type %i\n", type);
break;
} }
} }
@ -1470,11 +1469,13 @@ void CL_ParseTEnt (void)
break; break;
case TE_LIGHTNING1: // lightning bolts case TE_LIGHTNING1: // lightning bolts
CL_ParseBeam (BT_Q1LIGHTNING1);
break;
case TE_LIGHTNING2: // lightning bolts case TE_LIGHTNING2: // lightning bolts
CL_ParseBeam (type - TE_LIGHTNING1); CL_ParseBeam (BT_Q1LIGHTNING2);
break; break;
case TE_LIGHTNING3: // lightning bolts case TE_LIGHTNING3: // lightning bolts
CL_ParseBeam (2); CL_ParseBeam (BT_Q1LIGHTNING3);
break; break;
case TE_LAVASPLASH: case TE_LAVASPLASH:
@ -1546,7 +1547,7 @@ void CL_ParseTEnt (void)
break; break;
case TEQW_BEAM: case TEQW_BEAM:
CL_ParseBeam (5); CL_ParseBeam (BT_Q1BEAM);
break; break;
case TE_RAILTRAIL: case TE_RAILTRAIL:
@ -2524,14 +2525,14 @@ void CLQ2_ParseTEnt (void)
case Q2TE_PARASITE_ATTACK: case Q2TE_PARASITE_ATTACK:
case Q2TE_MEDIC_CABLE_ATTACK: case Q2TE_MEDIC_CABLE_ATTACK:
CL_ParseBeam (3); CL_ParseBeam (BT_Q2PARASITE);
break; break;
case Q2TE_HEATBEAM: case Q2TE_HEATBEAM:
case Q2TE_MONSTER_HEATBEAM: case Q2TE_MONSTER_HEATBEAM:
CL_ParseBeam (6); CL_ParseBeam (BT_Q2HEATBEAM);
break; break;
case Q2TE_GRAPPLE_CABLE: case Q2TE_GRAPPLE_CABLE:
CL_ParseBeam (4); CL_ParseBeam (BT_Q2GRAPPLE);
MSG_ReadPos (pos); MSG_ReadPos (pos);
break; break;
@ -2544,7 +2545,7 @@ void CLQ2_ParseTEnt (void)
pos2[0] = MSG_ReadCoord (); pos2[0] = MSG_ReadCoord ();
pos2[1] = MSG_ReadCoord (); pos2[1] = MSG_ReadCoord ();
pos2[2] = MSG_ReadCoord (); pos2[2] = MSG_ReadCoord ();
CL_AddBeam(0, ent, pos, pos2); CL_AddBeam(BT_Q1LIGHTNING1, ent, pos, pos2);
break; break;
@ -3407,13 +3408,15 @@ void CL_UpdateBeams (void)
float yaw, pitch; float yaw, pitch;
float forward, offset; float forward, offset;
int lastrunningbeam = -1; int lastrunningbeam = -1;
tentmodels_t *type;
extern cvar_t cl_truelightning, v_viewheight; extern cvar_t cl_truelightning, v_viewheight;
// update lightning // update lightning
for (bnum=0, b=cl_beams; bnum < beams_running; bnum++, b++) for (bnum=0, b=cl_beams; bnum < beams_running; bnum++, b++)
{ {
if (!b->active) type = b->info;
if (!type)
continue; continue;
if (b->endtime < cl.time) if (b->endtime < cl.time)
@ -3422,7 +3425,7 @@ void CL_UpdateBeams (void)
{ /*don't let lightning decay while paused*/ { /*don't let lightning decay while paused*/
P_DelinkTrailstate(&b->trailstate); P_DelinkTrailstate(&b->trailstate);
P_DelinkTrailstate(&b->emitstate); P_DelinkTrailstate(&b->emitstate);
b->active = false; b->info = NULL;
continue; continue;
} }
} }
@ -3554,11 +3557,15 @@ void CL_UpdateBeams (void)
pitch += 360; pitch += 360;
} }
if (ruleset_allow_particle_lightning.ival || !b->model) if (ruleset_allow_particle_lightning.ival || !type->modelname)
if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, b->entity, NULL, &b->trailstate)) if (type->ef_beam >= 0 && !P_ParticleTrail(b->start, b->end, type->ef_beam, b->entity, NULL, &b->trailstate))
continue; continue;
if (!b->model) if (!type->model)
continue; {
type->model = type->modelname?Mod_ForName(type->modelname, MLV_WARN):NULL;
if (!type->model)
continue;
}
// add new entities for the lightning // add new entities for the lightning
VectorCopy (b->start, org); VectorCopy (b->start, org);
@ -3579,7 +3586,7 @@ void CL_UpdateBeams (void)
if (!ent) if (!ent)
return; return;
VectorCopy (org, ent->origin); VectorCopy (org, ent->origin);
ent->model = b->model; ent->model = type->model;
ent->drawflags |= MLS_ABSLIGHT; ent->drawflags |= MLS_ABSLIGHT;
ent->abslight = 64 + 128 * bound(0, cl_shaftlight.value, 1); ent->abslight = 64 + 128 * bound(0, cl_shaftlight.value, 1);
ent->shaderRGBAf[3] = b->alpha; ent->shaderRGBAf[3] = b->alpha;

View file

@ -1519,8 +1519,8 @@ void UI_Reset(void)
int UI_MenuState(void) int UI_MenuState(void)
{ {
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_gmenu) || Key_Dest_Has(kdm_emenu))
{ { //engine's menus take precedence over q3's ui
return false; return false;
} }
if (!uivm) if (!uivm)

View file

@ -1033,7 +1033,30 @@ void CL_ParseTEnt (qboolean nqprot);
void CL_ParseTEnt (void); void CL_ParseTEnt (void);
#endif #endif
void CL_UpdateTEnts (void); void CL_UpdateTEnts (void);
void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end);
enum beamtype_e
{ //these are internal ids, matching the beam table
BT_Q1LIGHTNING1,
BT_Q1LIGHTNING2,
BT_Q1LIGHTNING3,
BT_Q1BEAM,
BT_Q2PARASITE,
BT_Q2GRAPPLE,
BT_Q2HEATBEAM,
BT_H2LIGHTNING_SMALL,
BT_H2CHAIN,
BT_H2SUNSTAFF1,
BT_H2SUNSTAFF1_SUB, //inner beam hack
BT_H2SUNSTAFF2, //same model as 1, but different particle effect
BT_H2LIGHTNING,
BT_H2COLORBEAM,
BT_H2ICECHUNKS,
BT_H2GAZE,
BT_H2FAMINE,
};
void CL_AddBeam (enum beamtype_e tent, int ent, vec3_t start, vec3_t end);
void CL_ClearState (void); void CL_ClearState (void);
void CLQ2_ClearState(void); void CLQ2_ClearState(void);

View file

@ -1077,6 +1077,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
conchar_t *cursor; conchar_t *cursor;
conchar_t *cchar; conchar_t *cchar;
qboolean cursorframe; qboolean cursorframe;
unsigned int codeflags, codepoint;
int x; int x;
@ -1152,44 +1153,52 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
#endif #endif
cursorframe = ((int)(realtime*con_cursorspeed)&1); cursorframe = ((int)(realtime*con_cursorspeed)&1);
for (lhs = 0, i = cursor - maskedtext-1; i >= 0; i--) //FIXME: support tab somehow
for (lhs = 0, cchar = maskedtext-1; cchar < cursor; )
{ {
lhs += Font_CharWidth(maskedtext[i]); cchar = Font_Decode(cchar, &codeflags, &codepoint);
lhs += Font_CharWidth(codeflags, codepoint);
} }
for (rhs = 0, i = cursor - maskedtext; maskedtext[i]; i++) for (rhs = 0, cchar = cursor; *cchar; )
{ {
rhs += Font_CharWidth(maskedtext[i]); cchar = Font_Decode(cchar, &codeflags, &codepoint);
rhs += Font_CharWidth(codeflags, codepoint);
} }
//put the cursor in the middle //put the cursor in the middle
x = (right-left)/2 + left; x = (right-left)/2 + left;
//move the line to the right if there's not enough text to touch the right hand side //move the line to the right if there's not enough text to touch the right hand side
if (x < right-rhs - Font_CharWidth(0xe000|11|CON_WHITEMASK)) if (x < right-rhs - Font_CharWidth(CON_WHITEMASK, 0xe000|11))
x = right - rhs - Font_CharWidth(0xe000|11|CON_WHITEMASK); x = right - rhs - Font_CharWidth(CON_WHITEMASK, 0xe000|11);
//if the left hand side is on the right of the left point (overrides right alignment) //if the left hand side is on the right of the left point (overrides right alignment)
if (x > lhs + left) if (x > lhs + left)
x = lhs + left; x = lhs + left;
lhs = x - lhs; lhs = x - lhs;
for (cchar = maskedtext; cchar < cursor; cchar++) for (cchar = maskedtext; cchar < cursor; )
{ {
lhs = Font_DrawChar(lhs, y, *cchar); cchar = Font_Decode(cchar, &codeflags, &codepoint);
lhs = Font_DrawChar(lhs, y, codeflags, codepoint);
} }
rhs = x; rhs = x;
Font_Decode(cursor, &codeflags, &codepoint);
if (cursorframe) if (cursorframe)
{ {
// extern cvar_t com_parseutf8; // extern cvar_t com_parseutf8;
// if (com_parseutf8.ival) // if (com_parseutf8.ival)
// Font_DrawChar(rhs, y, (*cursor&~(CON_BGMASK|CON_FGMASK)) | (COLOR_BLUE<<CON_BGSHIFT) | CON_NONCLEARBG | CON_WHITEMASK); // Font_DrawChar(rhs, y, (*cursor&~(CON_BGMASK|CON_FGMASK)) | (COLOR_BLUE<<CON_BGSHIFT) | CON_NONCLEARBG | CON_WHITEMASK);
// else // else
Font_DrawChar(rhs, y, 0xe000|11|CON_WHITEMASK); Font_DrawChar(rhs, y, CON_WHITEMASK, 0xe000|11);
} }
else if (*cursor) else if (*cursor)
Font_DrawChar(rhs, y, *cursor);
rhs += Font_CharWidth(*cursor);
for (cchar = cursor+1; *cchar; cchar++)
{ {
rhs = Font_DrawChar(rhs, y, *cchar); Font_DrawChar(rhs, y, codeflags, codepoint);
}
rhs += Font_CharWidth(codeflags, codepoint);
for (cchar = cursor+1; *cchar; )
{
cchar = Font_Decode(cchar, &codeflags, &codepoint);
rhs = Font_DrawChar(rhs, y, codeflags, codepoint);
} }
/*if its getting completed to something, show some help about the command that is going to be used*/ /*if its getting completed to something, show some help about the command that is going to be used*/
@ -1261,6 +1270,7 @@ void Con_DrawNotifyOne (console_t *con)
int nx, y; int nx, y;
int nw; int nw;
int x; int x;
unsigned int codeflags, codepoint;
int maxlines; int maxlines;
float t; float t;
@ -1330,17 +1340,19 @@ void Con_DrawNotifyOne (console_t *con)
Font_ForceColour(1, 1, 1, alphas[lines]); Font_ForceColour(1, 1, 1, alphas[lines]);
if (con->flags & CONF_NOTIFY_RIGHT) if (con->flags & CONF_NOTIFY_RIGHT)
{ {
for (c = starts[lines]; c < ends[lines]; c++) for (c = starts[lines]; c < ends[lines]; )
{ {
x += Font_CharWidth(*c); c = Font_Decode(c, &codeflags, &codepoint);
x += Font_CharWidth(codeflags, codepoint);
} }
x = (nw - x); x = (nw - x);
} }
else if (con_centernotify.value) else if (con_centernotify.value)
{ {
for (c = starts[lines]; c < ends[lines]; c++) for (c = starts[lines]; c < ends[lines]; )
{ {
x += Font_CharWidth(*c); c = Font_Decode(c, &codeflags, &codepoint);
x += Font_CharWidth(codeflags, codepoint);
} }
x = (nw - x) / 2; x = (nw - x) / 2;
} }
@ -1487,7 +1499,7 @@ static int Con_DrawProgress(int left, int right, int y)
extern int relitsurface; extern int relitsurface;
#endif #endif
conchar_t dlbar[1024]; conchar_t dlbar[1024], *chr;
unsigned char progresspercenttext[128]; unsigned char progresspercenttext[128];
char *progresstext = NULL; char *progresstext = NULL;
char *txt; char *txt;
@ -1495,6 +1507,7 @@ static int Con_DrawProgress(int left, int right, int y)
int i, j; int i, j;
int barwidth, barleft; int barwidth, barleft;
float progresspercent = 0; float progresspercent = 0;
unsigned int codeflags, codepoint;
*progresspercenttext = 0; *progresspercenttext = 0;
// draw the download bar // draw the download bar
@ -1564,9 +1577,10 @@ static int Con_DrawProgress(int left, int right, int y)
x = 0; x = 0;
COM_ParseFunString(CON_WHITEMASK, txt, dlbar, sizeof(dlbar), false); COM_ParseFunString(CON_WHITEMASK, txt, dlbar, sizeof(dlbar), false);
for (i = 0; dlbar[i]; ) for (i=0,chr = dlbar; *chr; )
{ {
x += Font_CharWidth(dlbar[i]); chr = Font_Decode(chr, &codeflags, &codepoint);
x += Font_CharWidth(codeflags, codepoint);
i++; i++;
} }
@ -1574,11 +1588,11 @@ static int Con_DrawProgress(int left, int right, int y)
if (x > (right - left)/3) if (x > (right - left)/3)
{ {
//truncate the file name and add ... //truncate the file name and add ...
x += 3*Font_CharWidth('.'|CON_WHITEMASK); x += 3*Font_CharWidth(CON_WHITEMASK, '.');
while (x > (right - left)/3 && i > 0) while (x > (right - left)/3)
{ {
i--; chr = Font_DecodeReverse(chr, dlbar, &codeflags, &codepoint);
x -= Font_CharWidth(dlbar[i]); x -= Font_CharWidth(codeflags, codepoint);
} }
dlbar[i++] = '.'|CON_WHITEMASK; dlbar[i++] = '.'|CON_WHITEMASK;
@ -1591,46 +1605,52 @@ static int Con_DrawProgress(int left, int right, int y)
//add a couple chars //add a couple chars
dlbar[i] = ':'|CON_WHITEMASK; dlbar[i] = ':'|CON_WHITEMASK;
x += Font_CharWidth(dlbar[i]); x += Font_CharWidth(CON_WHITEMASK, ':');
i++; i++;
dlbar[i] = ' '|CON_WHITEMASK; dlbar[i] = ' '|CON_WHITEMASK;
x += Font_CharWidth(dlbar[i]); x += Font_CharWidth(CON_WHITEMASK, ' ');
i++; i++;
COM_ParseFunString(CON_WHITEMASK, progresspercenttext, dlbar+i, sizeof(dlbar)-i*sizeof(conchar_t), false); COM_ParseFunString(CON_WHITEMASK, progresspercenttext, dlbar+i, sizeof(dlbar)-i*sizeof(conchar_t), false);
for (j = i, tw = 0; dlbar[j]; ) for (chr = &dlbar[i], tw = 0; *chr; )
{ {
tw += Font_CharWidth(dlbar[j]); chr = Font_Decode(chr, &codeflags, &codepoint);
j++; tw += Font_CharWidth(codeflags, codepoint);
} }
barwidth = (right-left) - (x + tw); barwidth = (right-left) - (x + tw);
//draw the right hand side //draw the right hand side
x = right - tw; x = right - tw;
for (j = i; dlbar[j]; j++) for (chr = &dlbar[i]; *chr; )
x = Font_DrawChar(x, y, dlbar[j]); {
chr = Font_Decode(chr, &codeflags, &codepoint);
x = Font_DrawChar(x, y, codeflags, codepoint);
}
//draw the left hand side //draw the left hand side
x = left; x = left;
for (j = 0; j < i; j++) for (chr = dlbar; chr < &dlbar[i]; )
x = Font_DrawChar(x, y, dlbar[j]); {
chr = Font_Decode(chr, &codeflags, &codepoint);
x = Font_DrawChar(x, y, codeflags, codepoint);
}
//and in the middle we have lots of stuff //and in the middle we have lots of stuff
barwidth -= (Font_CharWidth(0xe080|CON_WHITEMASK) + Font_CharWidth(0xe082|CON_WHITEMASK)); barwidth -= (Font_CharWidth(CON_WHITEMASK, 0xe080) + Font_CharWidth(CON_WHITEMASK, 0xe082));
x = Font_DrawChar(x, y, 0xe080|CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe080);
barleft = x; barleft = x;
for(;;) for(;;)
{ {
if (x + Font_CharWidth(0xe081|CON_WHITEMASK) > barleft+barwidth) if (x + Font_CharWidth(CON_WHITEMASK, 0xe081) > barleft+barwidth)
break; break;
x = Font_DrawChar(x, y, 0xe081|CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe081);
} }
x = Font_DrawChar(x, y, 0xe082|CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe082);
if (progresspercent >= 0) if (progresspercent >= 0)
Font_DrawChar(barleft+(barwidth*progresspercent)/100 - Font_CharWidth(0xe083|CON_WHITEMASK)/2, y, 0xe083|CON_WHITEMASK); Font_DrawChar(barleft+(barwidth*progresspercent)/100 - Font_CharWidth(CON_WHITEMASK, 0xe083)/2, y, CON_WHITEMASK, 0xe083);
y += Font_CharHeight(); y += Font_CharHeight();
} }
@ -1646,6 +1666,7 @@ int Con_DrawAlternateConsoles(int lines)
int consshown = 0; int consshown = 0;
console_t *con = &con_main, *om = con_mouseover; console_t *con = &con_main, *om = con_mouseover;
conchar_t buffer[512], *end, *start; conchar_t buffer[512], *end, *start;
unsigned int codeflags, codepoint;
for (con = &con_main; con; con = con->next) for (con = &con_main; con; con = con->next)
{ {
@ -1669,19 +1690,20 @@ int Con_DrawAlternateConsoles(int lines)
end = COM_ParseFunString(CON_WHITEMASK, va("^&%c%i%s", ((con!=om)?'F':'B'), (con==con_current)+con->unseentext*4, txt), buffer, sizeof(buffer), false); end = COM_ParseFunString(CON_WHITEMASK, va("^&%c%i%s", ((con!=om)?'F':'B'), (con==con_current)+con->unseentext*4, txt), buffer, sizeof(buffer), false);
lx = 0; lx = 0;
for (lx = x, start = buffer; start < end; start++) for (lx = x, start = buffer; start < end; )
{ {
lx = Font_CharEndCoord(font_console, lx, *start); start = Font_Decode(start, &codeflags, &codepoint);
lx = Font_CharEndCoord(font_console, lx, codeflags, codepoint);
} }
if (lx > Font_ScreenWidth()) if (lx > Font_ScreenWidth())
{ {
x = 0; x = 0;
y += h; y += h;
} }
for (lx = x, start = buffer; start < end; start++) for (lx = x, start = buffer; start < end; )
{ {
Font_DrawChar(lx, y, *start); start = Font_Decode(start, &codeflags, &codepoint);
lx = Font_CharEndCoord(font_console, lx, *start); lx = Font_DrawChar(lx, y, codeflags, codepoint);
} }
lx += 8; lx += 8;
if (mx >= x && mx < lx && my >= y && my < y+h) if (mx >= x && mx < lx && my >= y && my < y+h)
@ -1701,12 +1723,12 @@ int Con_DrawAlternateConsoles(int lines)
static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, int y, int top, qboolean selactive, int selsx, int selex, int selsy, int seley) static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, int y, int top, qboolean selactive, int selsx, int selex, int selsy, int seley)
{ {
int linecount; int linecount;
int linelength;
conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])]; conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])];
conchar_t *s; conchar_t *s, *e, *c;
int i; int i;
int x; int x;
int charh = Font_CharHeight(); int charh = Font_CharHeight();
unsigned int codeflags, codepoint;
if (l != con->completionline) if (l != con->completionline)
if (l != con->footerline) if (l != con->footerline)
@ -1715,7 +1737,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
y -= 8; y -= 8;
// draw arrows to show the buffer is backscrolled // draw arrows to show the buffer is backscrolled
for (x = sx ; x<ex; ) for (x = sx ; x<ex; )
x = (Font_DrawChar (x, y, '^'|CON_WHITEMASK)-x)*4+x; x = (Font_DrawChar (x, y, CON_WHITEMASK, '^')-x)*4+x;
} }
if (!selactive) if (!selactive)
@ -1860,7 +1882,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
while(linecount-- > 0) while(linecount-- > 0)
{ {
s = starts[linecount]; s = starts[linecount];
linelength = ends[linecount] - s; e = ends[linecount];
y -= Font_CharHeight(); y -= Font_CharHeight();
@ -1877,12 +1899,15 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
int send; int send;
sstart = sx+picw; sstart = sx+picw;
send = sstart; send = sstart;
for (i = 0; i < linelength; i++) for (c = s; c < e; )
send = Font_CharEndCoord(font_console, send, s[i]); {
c = Font_Decode(c, &codeflags, &codepoint);
send = Font_CharEndCoord(font_console, send, codeflags, codepoint);
}
//show something on blank lines //show something on blank lines
if (send == sstart) if (send == sstart)
send = Font_CharEndCoord(font_console, send, ' '); send = Font_CharEndCoord(font_console, send, CON_WHITEMASK, ' ');
if (y+charh >= seley && y < selsy) if (y+charh >= seley && y < selsy)
{ //if they're both on the same line, make sure sx is to the left of ex, so our stuff makes sense { //if they're both on the same line, make sure sx is to the left of ex, so our stuff makes sense
@ -1897,9 +1922,10 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
if (y+charh >= seley) if (y+charh >= seley)
{ {
send = sstart; send = sstart;
for (i = 0; i < linelength; ) for (c = s; c < e; )
{ {
send = Font_CharEndCoord(font_console, send, s[i++]); c = Font_Decode(c, &codeflags, &codepoint);
send = Font_CharEndCoord(font_console, send, codeflags, codepoint);
if (send > selex) if (send > selex)
break; break;
@ -1907,23 +1933,25 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
con->selendline = l; con->selendline = l;
if (s) if (s)
con->selendoffset = (s+i) - (conchar_t*)(l+1); con->selendoffset = c - (conchar_t*)(l+1);
else else
con->selendoffset = 0; con->selendoffset = 0;
} }
if (y < selsy) if (y < selsy)
{ {
for (i = 0; i < linelength; i++) for (c = s; c < e; )
{ {
x = Font_CharEndCoord(font_console, sstart, s[i]); Font_Decode(c, &codeflags, &codepoint);
x = Font_CharEndCoord(font_console, sstart, codeflags, codepoint);
if (x > selsx) if (x > selsx)
break; break;
c = Font_Decode(c, &codeflags, &codepoint);
sstart = x; sstart = x;
} }
con->selstartline = l; con->selstartline = l;
if (s) if (s)
con->selstartoffset = (s+i) - (conchar_t*)(l+1); con->selstartoffset = c - (conchar_t*)(l+1);
else else
con->selstartoffset = 0; con->selstartoffset = 0;
} }
@ -1942,7 +1970,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
R2D_ImageColours(1.0, 1.0, 1.0, 1.0); R2D_ImageColours(1.0, 1.0, 1.0, 1.0);
x = sx + picw; x = sx + picw;
Font_LineDraw(x, y, s, s+linelength); Font_LineDraw(x, y, s, e);
if (y < top) if (y < top)
break; break;
@ -2092,10 +2120,11 @@ void Con_DrawConsole (int lines, qboolean noback)
int i; int i;
Font_BeginString(font_console, vid.width, lines, &x, &y); Font_BeginString(font_console, vid.width, lines, &x, &y);
y -= Font_CharHeight(); y -= Font_CharHeight();
//assumption: version == ascii
for (i = 0; version[i]; i++) for (i = 0; version[i]; i++)
x -= Font_CharWidth(version[i] | CON_WHITEMASK|CON_HALFALPHA); x -= Font_CharWidth(CON_WHITEMASK|CON_HALFALPHA, version[i]);
for (i = 0; version[i]; i++) for (i = 0; version[i]; i++)
x = Font_DrawChar(x, y, version[i] | CON_WHITEMASK|CON_HALFALPHA); x = Font_DrawChar(x, y, CON_WHITEMASK|CON_HALFALPHA, version[i]);
} }
Font_EndString(font_console); Font_EndString(font_console);

View file

@ -2036,7 +2036,7 @@ qboolean Key_MouseShouldBeFree(void)
// if (!ActiveApp) // if (!ActiveApp)
// return true; // return true;
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_emenu))
{ {
if (m_state == m_complex || m_state == m_plugin /*|| m_state == m_menu_dat*/) if (m_state == m_complex || m_state == m_plugin /*|| m_state == m_menu_dat*/)
return true; return true;
@ -2178,8 +2178,12 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
else if (Key_Dest_Has(kdm_editor)) else if (Key_Dest_Has(kdm_editor))
Editor_Key (key, unicode); Editor_Key (key, unicode);
#endif #endif
else if (Key_Dest_Has(kdm_menu)) else if (Key_Dest_Has(kdm_emenu))
M_Keydown (key, unicode); M_Keydown (key, unicode);
#ifdef MENU_DAT
else if (Key_Dest_Has(kdm_gmenu))
MP_Keydown (key, unicode);
#endif
else if (Key_Dest_Has(kdm_message)) else if (Key_Dest_Has(kdm_message))
Key_Dest_Remove(kdm_message); Key_Dest_Remove(kdm_message);
else else
@ -2219,8 +2223,12 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
Key_ConsoleRelease(con, key, unicode); Key_ConsoleRelease(con, key, unicode);
} }
} }
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_emenu))
M_Keyup (key, unicode); M_Keyup (key, unicode);
#ifdef MENU_DAT
if (Key_Dest_Has(kdm_gmenu))
MP_Keyup (key, unicode);
#endif
#ifndef NOMEDIA #ifndef NOMEDIA
if (Media_PlayingFullScreen()) if (Media_PlayingFullScreen())
Media_Send_KeyEvent(NULL, key, unicode, down?0:1); Media_Send_KeyEvent(NULL, key, unicode, down?0:1);
@ -2297,11 +2305,18 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
return; return;
} }
#endif #endif
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_emenu))
{ {
M_Keydown (key, unicode); M_Keydown (key, unicode);
return; return;
} }
#ifdef MENU_DAT
if (Key_Dest_Has(kdm_gmenu))
{
MP_Keydown (key, unicode);
return;
}
#endif
if (Key_Dest_Has(kdm_message)) if (Key_Dest_Has(kdm_message))
{ {
Key_Message (key, unicode); Key_Message (key, unicode);

View file

@ -179,10 +179,11 @@ typedef enum //highest has priority
{ {
kdm_game = 1u<<0, //should always be set kdm_game = 1u<<0, //should always be set
kdm_message = 1u<<1, kdm_message = 1u<<1,
kdm_menu = 1u<<2, kdm_gmenu = 1u<<2, //menu.dat
kdm_editor = 1u<<3, kdm_emenu = 1u<<3, //engine's menus
kdm_console = 1u<<4, kdm_editor = 1u<<4,
kdm_cwindows = 1u<<5, kdm_console = 1u<<5,
kdm_cwindows = 1u<<6,
} keydestmask_t; } keydestmask_t;
//unsigned int Key_Dest_Get(void); //returns highest priority destination //unsigned int Key_Dest_Get(void); //returns highest priority destination

View file

@ -763,7 +763,7 @@ void Menu_DownloadStuff_f (void)
menu_t *menu; menu_t *menu;
dlmenu_t *info; dlmenu_t *info;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(dlmenu_t)); menu = M_CreateMenu(sizeof(dlmenu_t));

View file

@ -567,12 +567,12 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
option->slider.vx = x; option->slider.vx = x;
x -= 8; x -= 8;
Font_BeginString(font_default, x, y, &x, &y); Font_BeginString(font_default, x, y, &x, &y);
x = Font_DrawChar(x, y, 0xe080 | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe080);
s = x; s = x;
for (i=0 ; i<SLIDER_RANGE ; i++) for (i=0 ; i<SLIDER_RANGE ; i++)
x = Font_DrawChar(x, y, 0xe081 | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe081);
Font_DrawChar(x, y, 0xe082 | CON_WHITEMASK); Font_DrawChar(x, y, CON_WHITEMASK, 0xe082);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(0xe083 | CON_WHITEMASK)/2, y, 0xe083 | CON_WHITEMASK); Font_DrawChar(s + (x-s) * range - Font_CharWidth(CON_WHITEMASK, 0xe083)/2, y, CON_WHITEMASK, 0xe083);
Font_EndString(font_default); Font_EndString(font_default);
} }
break; break;
@ -1678,13 +1678,24 @@ void M_RemoveMenu (menu_t *menu)
currentmenu = firstmenu; currentmenu = firstmenu;
} }
void M_RemoveAllMenus (void) void M_RemoveAllMenus (qboolean leaveprompts)
{ {
if (!firstmenu) menu_t **link, *m;
return;
while(firstmenu) for (link = &firstmenu; *link; )
M_RemoveMenu(firstmenu); {
m = *link;
if (!m->exclusive && leaveprompts)
{
//this is WEIRD.
if (m == firstmenu)
link = &m->parent;
else
link = &m->child;
}
else
M_RemoveMenu(m);
}
} }
void M_MenuPop_f (void) void M_MenuPop_f (void)
@ -1701,7 +1712,7 @@ void M_Complex_Draw(void)
if (!firstmenu) if (!firstmenu)
{ {
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
m_state = m_none; m_state = m_none;
return; return;
} }
@ -2045,7 +2056,7 @@ qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos.
if (!CL_TryingToConnect()) if (!CL_TryingToConnect())
return true; return true;
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
m_state = m_none; m_state = m_none;
/* if (m_save_demonum != -1) /* if (m_save_demonum != -1)
{ {
@ -2118,7 +2129,7 @@ void M_Menu_Main_f (void)
if (R_GetShaderSizes(R2D_SafeCachePic("pics/m_main_quit"), NULL, NULL, true) > 0) if (R_GetShaderSizes(R2D_SafeCachePic("pics/m_main_quit"), NULL, NULL, true) > 0)
{ {
m_state = m_complex; m_state = m_complex;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0); mainm = M_CreateMenu(0);
mainm->key = MC_Main_Key; mainm->key = MC_Main_Key;
@ -2176,7 +2187,7 @@ void M_Menu_Main_f (void)
return; return;
m_state = m_complex; m_state = m_complex;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0); mainm = M_CreateMenu(0);
mainm->key = MC_Main_Key; mainm->key = MC_Main_Key;
@ -2216,7 +2227,7 @@ void M_Menu_Main_f (void)
{ {
int y; int y;
m_state = m_complex; m_state = m_complex;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0); mainm = M_CreateMenu(0);
p = R2D_SafeCachePic("gfx/ttl_main.lmp"); p = R2D_SafeCachePic("gfx/ttl_main.lmp");
@ -2271,7 +2282,7 @@ void M_Menu_Main_f (void)
else else
{ {
m_state = m_complex; m_state = m_complex;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0); mainm = M_CreateMenu(0);
p = R2D_SafeCachePic("gfx/ttl_main.lmp"); p = R2D_SafeCachePic("gfx/ttl_main.lmp");

View file

@ -721,7 +721,7 @@ doconnect:
Cbuf_AddText("\n", RESTRICT_LOCAL); Cbuf_AddText("\n", RESTRICT_LOCAL);
M_RemoveAllMenus(); M_RemoveAllMenus(true);
return true; return true;
} }
else if (server && key == 'c' && ctrldown) //copy to clip else if (server && key == 'c' && ctrldown) //copy to clip
@ -1031,7 +1031,7 @@ void M_Menu_ServerList2_f(void)
serverpreview = false; //in case it was lingering. serverpreview = false; //in case it was lingering.
Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_console);
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(serverlist_t)); menu = M_CreateMenu(sizeof(serverlist_t));
@ -1229,7 +1229,7 @@ void M_QuickConnect_f(void)
menucustom_t *cust; menucustom_t *cust;
menu_t *menu; menu_t *menu;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
MasterInfo_Refresh(); MasterInfo_Refresh();

View file

@ -8,8 +8,8 @@
#include "shader.h" #include "shader.h"
#if !defined(NOMEDIA) #if !defined(NOMEDIA)
#if defined(_WIN32) && !defined(WINRT) #if defined(_WIN32) && !defined(WINRT) && !defined(NOMEDIAMENU)
#define WINAMP //#define WINAMP
#endif #endif
#if defined(_WIN32) && !defined(WINRT) #if defined(_WIN32) && !defined(WINRT)
#define WINAVI #define WINAVI
@ -22,6 +22,8 @@ typedef struct mediatrack_s{
int length; int length;
struct mediatrack_s *next; struct mediatrack_s *next;
} mediatrack_t; } mediatrack_t;
qboolean media_fadeout;
float media_fadeouttime;
static mediatrack_t currenttrack; static mediatrack_t currenttrack;
int media_playing=true;//try to continue from the standard playlist int media_playing=true;//try to continue from the standard playlist
@ -56,9 +58,10 @@ void Media_Clear (void)
Q_strncpyz(currenttrack.filename, "", sizeof(currenttrack.filename)); Q_strncpyz(currenttrack.filename, "", sizeof(currenttrack.filename));
fakecdactive = false; fakecdactive = false;
media_playing = false; media_playing = false;
#endif
S_Music_Clear(NULL); media_fadeout = true;
media_fadeouttime = realtime;
#endif
} }
//fake cd tracks. //fake cd tracks.
@ -579,20 +582,67 @@ void Media_Next_f (void)
void Media_AddTrack(const char *fname)
{
mediatrack_t *newtrack;
if (!*fname)
return;
for (newtrack = tracks; newtrack; newtrack = newtrack->next)
{
if (!strcmp(newtrack->filename, fname))
return; //already added. ho hum
}
newtrack = Z_Malloc(sizeof(mediatrack_t));
Q_strncpyz(newtrack->filename, fname, sizeof(newtrack->filename));
Q_strncpyz(newtrack->nicename, COM_SkipPath(fname), sizeof(newtrack->nicename));
newtrack->length = 0;
newtrack->next = tracks;
tracks = newtrack;
numtracks++;
}
void Media_RemoveTrack(const char *fname)
{
mediatrack_t **link, *newtrack;
if (!*fname)
return;
for (link = &tracks; *link; link = &(*link)->next)
{
newtrack = *link;
if (!strcmp(newtrack->filename, fname))
{
*link = newtrack->next;
Z_Free(newtrack);
numtracks--;
return;
}
}
}
void M_Media_Add_f (void)
{
char *fname = Cmd_Argv(1);
if (Cmd_Argc() == 1)
Con_Printf("%s <track>\n", Cmd_Argv(0));
else
Media_AddTrack(fname);
}
void M_Media_Remove_f (void)
{
char *fname = Cmd_Argv(1);
if (Cmd_Argc() == 1)
Con_Printf("%s <track>\n", Cmd_Argv(0));
else
Media_RemoveTrack(fname);
}
#ifndef NOMEDIAMENU #ifndef NOMEDIAMENU
void M_Menu_Media_f (void)
{
Key_Dest_Add(kdm_menu);
m_state = m_media;
}
void Media_LoadTrackNames (char *listname); void Media_LoadTrackNames (char *listname);
#define MEDIA_MIN -8 #define MEDIA_MIN -7
#define MEDIA_VOLUME -8 #define MEDIA_VOLUME -7
#define MEDIA_REWIND -7
#define MEDIA_FASTFORWARD -6 #define MEDIA_FASTFORWARD -6
#define MEDIA_CLEARLIST -5 #define MEDIA_CLEARLIST -5
#define MEDIA_ADDTRACK -4 #define MEDIA_ADDTRACK -4
@ -600,7 +650,7 @@ void Media_LoadTrackNames (char *listname);
#define MEDIA_SHUFFLE -2 #define MEDIA_SHUFFLE -2
#define MEDIA_REPEAT -1 #define MEDIA_REPEAT -1
void M_Media_Draw (void) void M_Media_Draw (menu_t *menu)
{ {
mpic_t *p; mpic_t *p;
mediatrack_t *track; mediatrack_t *track;
@ -609,9 +659,6 @@ void M_Media_Draw (void)
#define MP_Hightlight(x,y,text,hl) (hl?M_PrintWhite(x, y, text):M_Print(x, y, text)) #define MP_Hightlight(x,y,text,hl) (hl?M_PrintWhite(x, y, text):M_Print(x, y, text))
p = R2D_SafeCachePic ("gfx/p_option.lmp");
if (p)
M_DrawScalePic ( (320-p->width)/2, 4, 144, 24, p);
if (!bgmvolume.value) if (!bgmvolume.value)
M_Print (12, 32, "Not playing - no volume"); M_Print (12, 32, "Not playing - no volume");
else if (!*currenttrack.nicename) else if (!*currenttrack.nicename)
@ -634,18 +681,18 @@ void M_Media_Draw (void)
M_Print (12, 40, currenttrack.nicename); M_Print (12, 40, currenttrack.nicename);
} }
op = selectedoption - (vid.height-52)/16; y=52;
if (op + (vid.height-52)/8>numtracks) op = selectedoption - (vid.height-y)/16;
op = numtracks - (vid.height-52)/8; if (op + (vid.height-y)/8>numtracks)
op = numtracks - (vid.height-y)/8;
if (op < MEDIA_MIN) if (op < MEDIA_MIN)
op = MEDIA_MIN; op = MEDIA_MIN;
y=52;
while(op < 0) while(op < 0)
{ {
switch(op) switch(op)
{ {
case MEDIA_VOLUME: case MEDIA_VOLUME:
MP_Hightlight (12, y, "Volume", op == selectedoption); MP_Hightlight (12, y, va("<< Volume %2i%% >>", (int)(100*bgmvolume.value)), op == selectedoption);
y+=8; y+=8;
break; break;
case MEDIA_CLEARLIST: case MEDIA_CLEARLIST:
@ -653,11 +700,13 @@ void M_Media_Draw (void)
y+=8; y+=8;
break; break;
case MEDIA_FASTFORWARD: case MEDIA_FASTFORWARD:
MP_Hightlight (12, y, ">> Fast Forward", op == selectedoption); {
y+=8; float time, duration;
break; if (S_GetMusicInfo(0, &time, &duration))
case MEDIA_REWIND: MP_Hightlight (12, y, va("<< %i:%02i / %i:%02i - %i%% >>", (int)time/60, (int)time%60, (int)duration/60, (int)duration%60, (int)(100*time/duration)), op == selectedoption);
MP_Hightlight (12, y, "<< Rewind", op == selectedoption); else
MP_Hightlight (12, y, "<< skip >>", op == selectedoption);
}
y+=8; y+=8;
break; break;
case MEDIA_ADDTRACK: case MEDIA_ADDTRACK:
@ -713,7 +762,7 @@ void M_Media_Draw (void)
char compleatenamepath[MAX_OSPATH]; char compleatenamepath[MAX_OSPATH];
char compleatenamename[MAX_OSPATH]; char compleatenamename[MAX_OSPATH];
qboolean compleatenamemultiple; qboolean compleatenamemultiple;
int QDECL Com_CompleatenameCallback(const char *name, qofs_t size, void *data, searchpathfuncs_t *spath) int QDECL Com_CompleatenameCallback(const char *name, qofs_t size, time_t mtime, void *data, searchpathfuncs_t *spath)
{ {
if (*compleatenamename) if (*compleatenamename)
compleatenamemultiple = true; compleatenamemultiple = true;
@ -739,17 +788,12 @@ void Com_CompleateOSFileName(char *name)
strcpy(name, compleatenamename); strcpy(name, compleatenamename);
} }
void M_Media_Key (int key) qboolean M_Media_Key (int key, menu_t *menu)
{ {
int dir; int dir;
if (key == K_ESCAPE) if (key == K_ESCAPE)
{ {
#ifndef NOBUILTINMENUS return false;
M_Menu_Main_f();
#else
m_state = m_none;
Key_Dest_Remove(kdm_menu);
#endif
} }
else if (key == K_RIGHTARROW || key == K_LEFTARROW) else if (key == K_RIGHTARROW || key == K_LEFTARROW)
{ {
@ -766,6 +810,9 @@ void M_Media_Key (int key)
bgmvolume.value = 1; bgmvolume.value = 1;
Cvar_SetValue (&bgmvolume, bgmvolume.value); Cvar_SetValue (&bgmvolume, bgmvolume.value);
break; break;
case MEDIA_FASTFORWARD:
Media_Seek(15*dir);
break;
default: default:
if (selectedoption >= 0) if (selectedoption >= 0)
Media_Next_f(); Media_Next_f();
@ -829,9 +876,6 @@ void M_Media_Key (int key)
case MEDIA_FASTFORWARD: case MEDIA_FASTFORWARD:
Media_Seek(15); Media_Seek(15);
break; break;
case MEDIA_REWIND:
Media_Seek(-15);
break;
case MEDIA_CLEARLIST: case MEDIA_CLEARLIST:
{ {
mediatrack_t *prevtrack; mediatrack_t *prevtrack;
@ -851,16 +895,9 @@ void M_Media_Key (int key)
break; break;
case MEDIA_ADDTRACK: case MEDIA_ADDTRACK:
if (*media_iofilename) if (*media_iofilename)
{ Media_AddTrack(media_iofilename);
mediatrack_t *newtrack; else
newtrack = Z_Malloc(sizeof(mediatrack_t)); Cmd_ExecuteString("menu_mediafiles", RESTRICT_LOCAL);
Q_strncpyz(newtrack->filename, media_iofilename, sizeof(newtrack->filename));
Q_strncpyz(newtrack->nicename, COM_SkipPath(media_iofilename), sizeof(newtrack->nicename));
newtrack->length = 0;
newtrack->next = tracks;
tracks = newtrack;
numtracks++;
}
break; break;
case MEDIA_ADDLIST: case MEDIA_ADDLIST:
if (*media_iofilename) if (*media_iofilename)
@ -878,27 +915,34 @@ void M_Media_Key (int key)
media_playing = true; media_playing = true;
nexttrack = selectedoption; nexttrack = selectedoption;
Media_Next_f(); Media_Next_f();
return true;
} }
break; return false;
} }
return true;
} }
else else
{ {
if (selectedoption == MEDIA_ADDLIST || selectedoption == MEDIA_ADDTRACK) if (selectedoption == MEDIA_ADDLIST || selectedoption == MEDIA_ADDTRACK)
{ {
if (key == K_TAB) if (key == K_TAB)
{
Com_CompleateOSFileName(media_iofilename); Com_CompleateOSFileName(media_iofilename);
return true;
}
else if (key == K_BACKSPACE) else if (key == K_BACKSPACE)
{ {
dir = strlen(media_iofilename); dir = strlen(media_iofilename);
if (dir) if (dir)
media_iofilename[dir-1] = '\0'; media_iofilename[dir-1] = '\0';
return true;
} }
else if ((key >= 'a' && key <= 'z') || (key >= '0' && key <= '9') || key == '/' || key == '_' || key == '.' || key == ':') else if ((key >= 'a' && key <= 'z') || (key >= '0' && key <= '9') || key == '/' || key == '_' || key == '.' || key == ':')
{ {
dir = strlen(media_iofilename); dir = strlen(media_iofilename);
media_iofilename[dir] = key; media_iofilename[dir] = key;
media_iofilename[dir+1] = '\0'; media_iofilename[dir+1] = '\0';
return true;
} }
} }
else if (selectedoption>=0) else if (selectedoption>=0)
@ -915,25 +959,40 @@ void M_Media_Key (int key)
num++; num++;
} }
if (!tr) if (!tr)
return; return false;
if (key == K_BACKSPACE) if (key == K_BACKSPACE)
{ {
dir = strlen(tr->nicename); dir = strlen(tr->nicename);
if (dir) if (dir)
tr->nicename[dir-1] = '\0'; tr->nicename[dir-1] = '\0';
return true;
} }
else if ((key >= 'a' && key <= 'z') || (key >= '0' && key <= '9') || key == '/' || key == '_' || key == '.' || key == ':' || key == '&' || key == '|' || key == '#' || key == '\'' || key == '\"' || key == '\\' || key == '*' || key == '@' || key == '!' || key == '(' || key == ')' || key == '%' || key == '^' || key == '?' || key == '[' || key == ']' || key == ';' || key == ':' || key == '+' || key == '-' || key == '=') else if ((key >= 'a' && key <= 'z') || (key >= '0' && key <= '9') || key == '/' || key == '_' || key == '.' || key == ':' || key == '&' || key == '|' || key == '#' || key == '\'' || key == '\"' || key == '\\' || key == '*' || key == '@' || key == '!' || key == '(' || key == ')' || key == '%' || key == '^' || key == '?' || key == '[' || key == ']' || key == ';' || key == ':' || key == '+' || key == '-' || key == '=')
{ {
dir = strlen(tr->nicename); dir = strlen(tr->nicename);
tr->nicename[dir] = key; tr->nicename[dir] = key;
tr->nicename[dir+1] = '\0'; tr->nicename[dir+1] = '\0';
return true;
} }
} }
} }
return false;
} }
void M_Menu_Media_f (void)
{
menu_t *menu;
m_state = m_complex;
Key_Dest_Add(kdm_emenu);
menu = M_CreateMenu(0);
// MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp");
MC_AddCenterPicture(menu, 4, 24, "gfx/p_option.lmp");
menu->key = M_Media_Key;
menu->postdraw = M_Media_Draw;
}
@ -945,7 +1004,8 @@ void Media_LoadTrackNames (char *listname)
char *filename; char *filename;
char *trackname; char *trackname;
mediatrack_t *newtrack; mediatrack_t *newtrack;
char *data = COM_LoadTempFile(listname); size_t fsize;
char *data = COM_LoadTempFile(listname, &fsize);
loadedtracknames=true; loadedtracknames=true;
@ -1032,21 +1092,33 @@ void Media_LoadTrackNames (char *listname)
} }
#endif #endif
//safeprints only. //mixer is locked, its safe to do stuff, but try not to block
float Media_CrossFade(int musicchanel, float vol)
{
if (media_fadeout)
{
float fadetime = 1;
float frac = (fadetime + media_fadeouttime - realtime)/fadetime;
vol *= frac;
}
return vol;
}
//mixer is locked, its safe to do stuff, but try not to block
char *Media_NextTrack(int musicchannelnum) char *Media_NextTrack(int musicchannelnum)
{ {
#ifdef WINAMP
if (media_hijackwinamp.value)
{
WinAmp_Think();
return NULL;
}
#endif
if (bgmvolume.value <= 0 || !media_playing) if (bgmvolume.value <= 0 || !media_playing)
return NULL; return NULL;
if (media_fadeout)
{
if (S_Music_Playing(musicchannelnum))
return NULL; //can't pick a new track until they've all stopped.
}
if (!fakecdactive) if (!fakecdactive)
Media_EndedTrack(); Media_EndedTrack();
media_fadeout = false;
#ifndef NOMEDIAMENU #ifndef NOMEDIAMENU
if (!loadedtracknames) if (!loadedtracknames)
@ -2274,11 +2346,13 @@ qboolean Media_PlayFilm(char *name, qboolean enqueue)
CDAudio_Stop(); CDAudio_Stop();
SCR_EndLoadingPlaque(); SCR_EndLoadingPlaque();
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_emenu))
{ {
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
m_state = m_none; m_state = m_none;
} }
if (Key_Dest_Has(kdm_gmenu))
Key_Dest_Remove(kdm_gmenu); //FIXME
if (!Key_Dest_Has(kdm_console)) if (!Key_Dest_Has(kdm_console))
scr_con_current=0; scr_con_current=0;
return true; return true;
@ -3228,7 +3302,7 @@ void Media_RecordDemo_f(void)
Cmd_ShiftArgs(1, false); Cmd_ShiftArgs(1, false);
Media_RecordFilm_f(); Media_RecordFilm_f();
scr_con_current=0; scr_con_current=0;
Key_Dest_Remove(kdm_console|kdm_menu); Key_Dest_Remove(kdm_console|kdm_emenu|kdm_gmenu);
if (currentcapture_funcs) if (currentcapture_funcs)
recordingdemo = true; recordingdemo = true;
@ -3981,6 +4055,9 @@ void Media_Init(void)
#endif #endif
Cvar_Register(&media_shuffle, "Media player things"); Cvar_Register(&media_shuffle, "Media player things");
Cvar_Register(&media_repeat, "Media player things"); Cvar_Register(&media_repeat, "Media player things");
Cmd_AddCommand ("media_add", M_Media_Add_f);
Cmd_AddCommand ("media_rmeove", M_Media_Remove_f);
Cmd_AddCommand ("menu_media", M_Menu_Media_f);
} }
@ -4209,6 +4286,7 @@ void Media_RecordAudioFrame (short *sample_buffer, int samples) {}
void Media_StopRecordFilm_f (void) {} void Media_StopRecordFilm_f (void) {}
void Media_RecordFilm_f (void){} void Media_RecordFilm_f (void){}
void M_Menu_Media_f (void) {} void M_Menu_Media_f (void) {}
float Media_CrossFade(int ch, float vol) {return vol;}
char *Media_NextTrack(int musicchannelnum) {return NULL;} char *Media_NextTrack(int musicchannelnum) {return NULL;}
qboolean Media_PausedDemo(qboolean fortiming) {return false;} qboolean Media_PausedDemo(qboolean fortiming) {return false;}

View file

@ -18,7 +18,7 @@ void M_Menu_MultiPlayer_f (void)
static menuresel_t resel; static menuresel_t resel;
p = NULL; p = NULL;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
mgt = M_GameType(); mgt = M_GameType();
@ -442,7 +442,7 @@ void M_Menu_Setup_f (void)
mpic_t *p; mpic_t *p;
menucustom_t *cu; menucustom_t *cu;
m_state = m_complex; m_state = m_complex;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
menu = M_CreateMenu(sizeof(setupmenu_t)); menu = M_CreateMenu(sizeof(setupmenu_t));
info = menu->data; info = menu->data;
@ -468,7 +468,7 @@ void M_Menu_Setup_f (void)
} }
#endif #endif
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(setupmenu_t)); menu = M_CreateMenu(sizeof(setupmenu_t));
@ -591,7 +591,7 @@ qboolean MultiBeginGame (union menuoption_s *option,struct menu_s *menu, int key
Cbuf_AddText("echo You can use the setrenderer command to return to a graphical interface at any time\n", RESTRICT_LOCAL); Cbuf_AddText("echo You can use the setrenderer command to return to a graphical interface at any time\n", RESTRICT_LOCAL);
} }
M_RemoveAllMenus(); M_RemoveAllMenus(true);
return true; return true;
} }
@ -656,7 +656,7 @@ void M_Menu_GameOptions_f (void)
int mgt; int mgt;
int players; int players;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(newmultimenu_t)); menu = M_CreateMenu(sizeof(newmultimenu_t));

View file

@ -103,7 +103,7 @@ menu_t *M_Options_Title(int *y, int infosize)
struct menu_s *menu; struct menu_s *menu;
*y = 32; *y = 32;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(infosize); menu = M_CreateMenu(infosize);
@ -365,7 +365,7 @@ void M_Menu_Audio_Speakers_f (void)
audiomenuinfo_t *info; audiomenuinfo_t *info;
menu_t *menu; menu_t *menu;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(audiomenuinfo_t)); menu = M_CreateMenu(sizeof(audiomenuinfo_t));
@ -2651,7 +2651,7 @@ static void M_BoneDisplay(entity_t *e, galiasbone_t *b, int *y, int depth, int p
{ {
float result[12]; float result[12];
memset(result, 0, sizeof(result)); memset(result, 0, sizeof(result));
if (Mod_GetTag(e->model, i, &e->framestate, result)) if (Mod_GetTag(e->model, i+1, &e->framestate, result))
Draw_FunString(depth*16, *y, va("%i: %s (%g %g %g)", i, b[i].name, result[3], result[7], result[11])); Draw_FunString(depth*16, *y, va("%i: %s (%g %g %g)", i, b[i].name, result[3], result[7], result[11]));
else else
Draw_FunString(depth*16, *y, va("%i: %s", i, b[i].name)); Draw_FunString(depth*16, *y, va("%i: %s", i, b[i].name));
@ -2882,7 +2882,7 @@ void M_Menu_ModelViewer_f(void)
menucustom_t *c; menucustom_t *c;
menu_t *menu; menu_t *menu;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
menu = M_CreateMenu(sizeof(*mv)); menu = M_CreateMenu(sizeof(*mv));
mv = menu->data; mv = menu->data;
@ -2996,7 +2996,7 @@ void M_Menu_Mods_f (void)
} }
else else
{ {
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
menu = M_CreateMenu(sizeof(modmenu_t)); menu = M_CreateMenu(sizeof(modmenu_t));
*(modmenu_t*)menu->data = mods; *(modmenu_t*)menu->data = mods;

View file

@ -79,7 +79,7 @@ void M_MenuS_Script_f (void) //create a menu.
extern menu_t *currentmenu; extern menu_t *currentmenu;
menu_t *oldmenu; menu_t *oldmenu;
char *alias = Cmd_Argv(1); char *alias = Cmd_Argv(1);
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
selectitem = 0; selectitem = 0;

View file

@ -137,7 +137,7 @@ void M_Menu_Save_f (void)
if (cl.intermission) if (cl.intermission)
return; return;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t)); menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
@ -164,7 +164,7 @@ void M_Menu_Load_f (void)
menu_t *menu; menu_t *menu;
int i; int i;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t)); menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
@ -201,7 +201,7 @@ void M_Menu_SinglePlayer_f (void)
#endif #endif
static menuresel_t resel; static menuresel_t resel;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
#ifdef CLIENTONLY #ifdef CLIENTONLY
@ -565,6 +565,7 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key, unsigned
ShowDemoMenu(menu, info->selected->name); ShowDemoMenu(menu, info->selected->name);
else else
{ {
extern int shift_down;
int extnum; int extnum;
for (extnum = 0; extnum < info->numext; extnum++) for (extnum = 0; extnum < info->numext; extnum++)
if (!stricmp(info->selected->name + strlen(info->selected->name)-4, info->ext[extnum])) if (!stricmp(info->selected->name + strlen(info->selected->name)-4, info->ext[extnum]))
@ -574,7 +575,8 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key, unsigned
extnum = 0; extnum = 0;
Cbuf_AddText(va("%s \"%s%s\"\n", info->command[extnum], (info->fs->fsroot==FS_SYSTEM)?"#":"", info->selected->name), RESTRICT_LOCAL); Cbuf_AddText(va("%s \"%s%s\"\n", info->command[extnum], (info->fs->fsroot==FS_SYSTEM)?"#":"", info->selected->name), RESTRICT_LOCAL);
M_RemoveMenu(menu); if (!shift_down)
M_RemoveMenu(menu);
return true; return true;
} }
} }
@ -832,7 +834,7 @@ void M_Menu_Demos_f (void)
menu_t *menu; menu_t *menu;
static demoloc_t mediareenterloc = {FS_GAME}; static demoloc_t mediareenterloc = {FS_GAME};
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_console);
m_state = m_complex; m_state = m_complex;
@ -885,7 +887,7 @@ void M_Menu_MediaFiles_f (void)
menu_t *menu; menu_t *menu;
static demoloc_t mediareenterloc = {FS_GAME}; static demoloc_t mediareenterloc = {FS_GAME};
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(sizeof(demomenu_t)); menu = M_CreateMenu(sizeof(demomenu_t));
@ -893,19 +895,28 @@ void M_Menu_MediaFiles_f (void)
info = menu->data; info = menu->data;
info->fs = &mediareenterloc; info->fs = &mediareenterloc;
info->numext = 0;
info->ext[0] = ".m3u"; info->ext[info->numext] = ".m3u";
info->command[0] = "mediaplaylist"; info->command[info->numext] = "mediaplaylist";
info->ext[1] = ".mp3"; info->numext++;
info->command[1] = "mediaadd"; #if defined(_WIN32) || defined(FTE_TARGET_WEB)
info->ext[2] = ".wav"; info->ext[info->numext] = ".mp3";
info->command[2] = "mediaadd"; info->command[info->numext] = "media_add";
info->ext[3] = ".ogg"; //will this ever be added properly? info->numext++;
info->command[3] = "mediaadd"; #endif
info->ext[4] = ".roq"; info->ext[info->numext] = ".wav";
info->command[4] = "playfilm"; info->command[info->numext] = "media_add";
info->numext = 5; info->numext++;
#if defined(AVAIL_OGGVORBIS) || defined(FTE_TARGET_WEB)
info->ext[info->numext] = ".ogg"; //will this ever be added properly?
info->command[info->numext] = "media_add";
info->numext++;
#endif
info->ext[info->numext] = ".roq";
info->command[info->numext] = "playfilm";
info->numext++;
#ifdef _WIN32 //avis are only playable on windows due to a windows dll being used to decode them. #ifdef _WIN32 //avis are only playable on windows due to a windows dll being used to decode them.
info->ext[info->numext] = ".avi"; info->ext[info->numext] = ".avi";
info->command[info->numext] = "playfilm"; info->command[info->numext] = "playfilm";

View file

@ -300,10 +300,10 @@ int m_save_demonum;
void M_CloseMenu_f (void) void M_CloseMenu_f (void)
{ {
if (!Key_Dest_Has(kdm_menu)) if (!Key_Dest_Has(kdm_emenu))
return; return;
M_RemoveAllMenus(); M_RemoveAllMenus(false);
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
m_state = m_none; m_state = m_none;
} }
/* /*
@ -315,7 +315,7 @@ void M_ToggleMenu_f (void)
{ {
if (m_state) if (m_state)
{ {
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
return; return;
} }
@ -339,9 +339,9 @@ void M_ToggleMenu_f (void)
#endif #endif
//it IS a toggle, so close the menu if its already active //it IS a toggle, so close the menu if its already active
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_emenu))
{ {
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
m_state = m_none; m_state = m_none;
return; return;
} }
@ -494,7 +494,7 @@ void M_Menu_Keys_f (void)
menu_t *menu; menu_t *menu;
vfsfile_t *bindslist; vfsfile_t *bindslist;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
menu = M_CreateMenu(0); menu = M_CreateMenu(0);
@ -618,7 +618,7 @@ struct
void M_Menu_Help_f (void) void M_Menu_Help_f (void)
{ {
int i; int i;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_help; m_state = m_help;
help_page = 0; help_page = 0;
@ -734,7 +734,7 @@ void M_Menu_Prompt (void (*callback)(void *, int), void *ctx, char *m1, char *m2
promptmenu_t *m; promptmenu_t *m;
char *t; char *t;
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
m_state = m_complex; m_state = m_complex;
m = (promptmenu_t*)M_CreateMenuInfront(sizeof(*m) - sizeof(m->m) + strlen(m1)+strlen(m2)+strlen(m3)+strlen(optionyes)+strlen(optionyes)+strlen(optioncancel)+6); m = (promptmenu_t*)M_CreateMenuInfront(sizeof(*m) - sizeof(m->m) + strlen(m1)+strlen(m2)+strlen(m3)+strlen(optionyes)+strlen(optionyes)+strlen(optioncancel)+6);
@ -1035,7 +1035,7 @@ void M_Menu_Quit_f (void)
#endif #endif
break; break;
case 2: case 2:
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_console);
m_state = m_complex; m_state = m_complex;
@ -1059,7 +1059,7 @@ void M_Menu_Quit_f (void)
MC_AddBox (quitmenu, 56, 76, 25, 5); MC_AddBox (quitmenu, 56, 76, 25, 5);
break; break;
case 1: case 1:
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_emenu);
Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_console);
m_state = m_complex; m_state = m_complex;
@ -1139,10 +1139,6 @@ void M_Init_Internal (void)
Cmd_AddCommand ("menu_keys", M_Menu_Keys_f); Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
Cmd_AddCommand ("help", M_Menu_Help_f); Cmd_AddCommand ("help", M_Menu_Help_f);
Cmd_AddCommand ("menu_quit", M_Menu_Quit_f); Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
#ifndef NOMEDIAMENU
Cmd_AddCommand ("menu_media", M_Menu_Media_f);
#endif
Cmd_AddCommand ("menu_mediafiles", M_Menu_MediaFiles_f);
Cmd_AddCommand ("menu_mods", M_Menu_Mods_f); Cmd_AddCommand ("menu_mods", M_Menu_Mods_f);
Cmd_AddCommand ("modelviewer", M_Menu_ModelViewer_f); Cmd_AddCommand ("modelviewer", M_Menu_ModelViewer_f);
@ -1191,7 +1187,7 @@ void M_Init_Internal (void)
void M_DeInit_Internal (void) void M_DeInit_Internal (void)
{ {
M_RemoveAllMenus(); M_RemoveAllMenus(true);
if (!internalmenusregistered) if (!internalmenusregistered)
return; return;
@ -1208,10 +1204,6 @@ void M_DeInit_Internal (void)
Cmd_RemoveCommand ("menu_keys"); Cmd_RemoveCommand ("menu_keys");
Cmd_RemoveCommand ("help"); Cmd_RemoveCommand ("help");
Cmd_RemoveCommand ("menu_quit"); Cmd_RemoveCommand ("menu_quit");
#ifndef NOMEDIAMENU
Cmd_RemoveCommand ("menu_media");
#endif
Cmd_RemoveCommand ("menu_mediafiles");
#ifdef CL_MASTER #ifdef CL_MASTER
Cmd_RemoveCommand ("menu_slist"); Cmd_RemoveCommand ("menu_slist");
@ -1286,6 +1278,7 @@ void M_Init (void)
#endif #endif
//demo menu is allowed to see outside of the quakedir. you can't replicate that in qc's sandbox. //demo menu is allowed to see outside of the quakedir. you can't replicate that in qc's sandbox.
Cmd_AddCommand ("menu_demo", M_Menu_Demos_f); Cmd_AddCommand ("menu_demo", M_Menu_Demos_f);
Cmd_AddCommand ("menu_mediafiles", M_Menu_MediaFiles_f);
@ -1341,18 +1334,18 @@ void M_Draw (int uimenu)
#ifndef NOBUILTINMENUS #ifndef NOBUILTINMENUS
if (m_state != m_complex) if (m_state != m_complex)
{ {
M_RemoveAllMenus(); M_RemoveAllMenus(false);
menu_mousedown = false; menu_mousedown = false;
} }
#endif #endif
if (!Key_Dest_Has(kdm_menu)) if (!Key_Dest_Has(kdm_emenu))
{ {
m_state = m_none; m_state = m_none;
return; return;
} }
if (m_state == m_none || m_state == m_menu_dat) if (m_state == m_none)
return; return;
#ifndef NOBUILTINMENUS #ifndef NOBUILTINMENUS
@ -1388,21 +1381,10 @@ void M_Draw (int uimenu)
break; break;
#endif #endif
#ifndef NOMEDIAMENU
case m_media:
M_Media_Draw ();
break;
#endif
#ifdef PLUGINS #ifdef PLUGINS
case m_plugin: case m_plugin:
Plug_Menu_Event (0, (int)(realtime*1000)); Plug_Menu_Event (0, (int)(realtime*1000));
break; break;
#endif
#ifdef MENU_DAT
case m_menu_dat:
// MP_Draw();
return;
#endif #endif
} }
} }
@ -1414,7 +1396,7 @@ void M_Keydown (int key, int unicode)
{ {
default: default:
case m_none: case m_none:
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_emenu);
return; return;
#ifndef NOBUILTINMENUS #ifndef NOBUILTINMENUS
case m_help: case m_help:
@ -1429,21 +1411,10 @@ void M_Keydown (int key, int unicode)
return; return;
#endif #endif
#ifndef NOMEDIAMENU
case m_media:
M_Media_Key (key);
return;
#endif
#ifdef PLUGINS #ifdef PLUGINS
case m_plugin: case m_plugin:
Plug_Menu_Event (1, key); Plug_Menu_Event (1, key);
return; return;
#endif
#ifdef MENU_DAT
case m_menu_dat:
MP_Keydown(key, unicode);
return;
#endif #endif
} }
} }
@ -1464,11 +1435,6 @@ void M_Keyup (int key, int unicode)
case m_plugin: case m_plugin:
Plug_Menu_Event (2, key); Plug_Menu_Event (2, key);
return; return;
#endif
#ifdef MENU_DAT
case m_menu_dat:
MP_Keyup(key, unicode);
return;
#endif #endif
default: default:
break; break;

View file

@ -24,12 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//m_none - menu is disabled //m_none - menu is disabled
//m_complex - hirachy of item types //m_complex - hirachy of item types
//m_help - old q1 style help menu (fixme: make m_complex) //m_help - old q1 style help menu (fixme: make m_complex)
//m_keys - old q1 style key menu (fixme: make m_complex)
//m_slist - serverbrowser. Takes full control of screen.
//m_media - an mp3 player type thing. It was never really compleate.
// It should perhaps either be fixed or removed.
//m_plugin - A QVM based or DLL based plugin. //m_plugin - A QVM based or DLL based plugin.
//m_menu_dat- A QC based version of m_plugin. This should be compatible with DP's menu.dat stuff.
//the m_complex menu state is the most advanced, and drives the bulk of FTE's menus in an event driven way. //the m_complex menu state is the most advanced, and drives the bulk of FTE's menus in an event driven way.
@ -96,12 +91,10 @@ void M_SomeInitialisationFunctionCalledAtStartup(void)
} }
*/ */
typedef enum {m_none, m_complex, m_help, m_media, m_plugin, m_menu_dat} m_state_t; typedef enum {m_none, m_complex, m_help, m_plugin} m_state_t;
extern m_state_t m_state; extern m_state_t m_state;
void M_DrawTextBox (int x, int y, int width, int lines); void M_DrawTextBox (int x, int y, int width, int lines);
#define NOMEDIAMENU
#ifndef NOBUILTINMENUS #ifndef NOBUILTINMENUS
// //
@ -380,7 +373,7 @@ void M_AddMenu (menu_t *menu);
void M_AddMenuFront (menu_t *menu); void M_AddMenuFront (menu_t *menu);
void M_HideMenu (menu_t *menu); void M_HideMenu (menu_t *menu);
void M_RemoveMenu (menu_t *menu); void M_RemoveMenu (menu_t *menu);
void M_RemoveAllMenus (void); void M_RemoveAllMenus (qboolean leaveprompts);
void M_Complex_Key(int key, int unicode); void M_Complex_Key(int key, int unicode);
void M_Complex_Draw(void); void M_Complex_Draw(void);
@ -404,7 +397,6 @@ void M_Menu_LanConfig_f (void);
void M_Menu_GameOptions_f (void); void M_Menu_GameOptions_f (void);
void M_Menu_Search_f (void); void M_Menu_Search_f (void);
void M_Menu_ServerList_f (void); void M_Menu_ServerList_f (void);
void M_Menu_Media_f (void);
/* /*
void M_Main_Draw (void); void M_Main_Draw (void);
@ -440,10 +432,6 @@ void M_Search_Key (int key);
void M_ServerList_Key (int key); void M_ServerList_Key (int key);
*/ */
void MasterInfo_Refresh(void);
void M_DrawServers(void);
void M_SListKey(int key);
//drawing funcs //drawing funcs
void M_BuildTranslationTable(unsigned int pc, unsigned int top, unsigned int bottom, unsigned int *translationTable); void M_BuildTranslationTable(unsigned int pc, unsigned int top, unsigned int bottom, unsigned int *translationTable);
void M_DrawCharacter (int cx, int line, unsigned int num); void M_DrawCharacter (int cx, int line, unsigned int num);
@ -471,9 +459,7 @@ void M_Draw (int uimenu);
void M_FindKeysForCommand (int pnum, const char *command, int *twokeys); void M_FindKeysForCommand (int pnum, const char *command, int *twokeys);
int M_FindKeysForBind (const char *command, int *keylist, int *keymods, int total); int M_FindKeysForBind (const char *command, int *keylist, int *keymods, int total);
void M_Media_Draw (void); #ifdef MENU_DAT
void M_Media_Key (int key);
void MP_CvarChanged(cvar_t *var); void MP_CvarChanged(cvar_t *var);
qboolean MP_Init (void); qboolean MP_Init (void);
void MP_Shutdown (void); void MP_Shutdown (void);
@ -483,6 +469,7 @@ void MP_RegisterCvarsAndCmds(void);
void MP_Keydown(int key, int unicode); void MP_Keydown(int key, int unicode);
void MP_Keyup(int key, int unicode); void MP_Keyup(int key, int unicode);
int MP_BuiltinValid(char *name, int num); int MP_BuiltinValid(char *name, int num);
#endif
#define MGT_BAD ~0 #define MGT_BAD ~0
#define MGT_QUAKE1 0 #define MGT_QUAKE1 0

View file

@ -3667,7 +3667,7 @@ static void QCBUILTIN PF_cl_te_lightning1 (pubprogfuncs_t *prinst, struct global
float *start = G_VECTOR(OFS_PARM1); float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM2); float *end = G_VECTOR(OFS_PARM2);
CL_AddBeam(0, ent->entnum+MAX_EDICTS, start, end); CL_AddBeam(BT_Q1LIGHTNING1, ent->entnum+MAX_EDICTS, start, end);
} }
static void QCBUILTIN PF_cl_te_lightning2 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_cl_te_lightning2 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -3675,7 +3675,7 @@ static void QCBUILTIN PF_cl_te_lightning2 (pubprogfuncs_t *prinst, struct global
float *start = G_VECTOR(OFS_PARM1); float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM2); float *end = G_VECTOR(OFS_PARM2);
CL_AddBeam(1, ent->entnum+MAX_EDICTS, start, end); CL_AddBeam(BT_Q1LIGHTNING2, ent->entnum+MAX_EDICTS, start, end);
} }
static void QCBUILTIN PF_cl_te_lightning3 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_cl_te_lightning3 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -3683,7 +3683,7 @@ static void QCBUILTIN PF_cl_te_lightning3 (pubprogfuncs_t *prinst, struct global
float *start = G_VECTOR(OFS_PARM1); float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM2); float *end = G_VECTOR(OFS_PARM2);
CL_AddBeam(2, ent->entnum+MAX_EDICTS, start, end); CL_AddBeam(BT_Q1LIGHTNING3, ent->entnum+MAX_EDICTS, start, end);
} }
static void QCBUILTIN PF_cl_te_beam (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_cl_te_beam (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -3691,7 +3691,7 @@ static void QCBUILTIN PF_cl_te_beam (pubprogfuncs_t *prinst, struct globalvars_s
float *start = G_VECTOR(OFS_PARM1); float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM2); float *end = G_VECTOR(OFS_PARM2);
CL_AddBeam(5, ent->entnum+MAX_EDICTS, start, end); CL_AddBeam(BT_Q1BEAM, ent->entnum+MAX_EDICTS, start, end);
} }
static void QCBUILTIN PF_cl_te_plasmaburn (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_cl_te_plasmaburn (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {

View file

@ -10,6 +10,8 @@
#if defined(MENU_DAT) || defined(CSQC_DAT) #if defined(MENU_DAT) || defined(CSQC_DAT)
#include "cl_master.h" #include "cl_master.h"
qbyte mpkeysdown[K_MAX/8];
extern unsigned int r2d_be_flags; extern unsigned int r2d_be_flags;
#define DRAWFLAG_NORMAL 0 #define DRAWFLAG_NORMAL 0
#define DRAWFLAG_ADD 1 #define DRAWFLAG_ADD 1
@ -391,6 +393,7 @@ void QCBUILTIN PF_CL_drawcolouredstring (pubprogfuncs_t *prinst, struct globalva
float flag = 0; float flag = 0;
float r, g, b; float r, g, b;
float px, py, ipx; float px, py, ipx;
unsigned int codeflags, codepoint;
conchar_t buffer[2048], *str; conchar_t buffer[2048], *str;
@ -426,13 +429,13 @@ void QCBUILTIN PF_CL_drawcolouredstring (pubprogfuncs_t *prinst, struct globalva
Font_ForceColour(r, g, b, alpha); Font_ForceColour(r, g, b, alpha);
while(*str) while(*str)
{ {
if ((*str & CON_CHARMASK) == '\n') str = Font_Decode(str, &codeflags, &codepoint);
if (codepoint == '\n')
py += Font_CharHeight(); py += Font_CharHeight();
else if ((*str & CON_CHARMASK) == '\r') else if (codepoint == '\r')
px = ipx; px = ipx;
else else
px = Font_DrawScaleChar(px, py, *str); px = Font_DrawScaleChar(px, py, codeflags, codepoint);
str++;
} }
Font_InvalidateColour(); Font_InvalidateColour();
Font_EndString(NULL); Font_EndString(NULL);
@ -682,7 +685,7 @@ void QCBUILTIN PF_CL_drawcharacter (pubprogfuncs_t *prinst, struct globalvars_s
r2d_be_flags = PF_SelectDPDrawFlag(flag); r2d_be_flags = PF_SelectDPDrawFlag(flag);
PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y); PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y);
Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha); Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha);
Font_DrawScaleChar(x, y, CON_WHITEMASK | chara); Font_DrawScaleChar(x, y, CON_WHITEMASK, chara);
Font_InvalidateColour(); Font_InvalidateColour();
Font_EndString(NULL); Font_EndString(NULL);
r2d_be_flags = 0; r2d_be_flags = 0;
@ -727,7 +730,7 @@ void QCBUILTIN PF_CL_drawrawstring (pubprogfuncs_t *prinst, struct globalvars_s
else if (c & 0x80) else if (c & 0x80)
c |= 0xe000; //if its a high char, just use the quake range instead. we could colour it, but why bother c |= 0xe000; //if its a high char, just use the quake range instead. we could colour it, but why bother
} }
x = Font_DrawScaleChar(x, y, CON_WHITEMASK|c); x = Font_DrawScaleChar(x, y, CON_WHITEMASK, c);
} }
Font_InvalidateColour(); Font_InvalidateColour();
Font_EndString(NULL); Font_EndString(NULL);
@ -1236,25 +1239,25 @@ void QCBUILTIN PF_CL_precache_sound (pubprogfuncs_t *prinst, struct globalvars_s
//void setkeydest(float dest) = #601; //void setkeydest(float dest) = #601;
void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
//these arguments are stupid
switch((int)G_FLOAT(OFS_PARM0)) switch((int)G_FLOAT(OFS_PARM0))
{ {
case 0: case 0:
// key_game // key_game
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_gmenu))
{ {
Key_Dest_Remove(kdm_menu); Key_Dest_Remove(kdm_gmenu);
// Key_Dest_Remove(kdm_message); // Key_Dest_Remove(kdm_message);
if (cls.state == ca_disconnected) // if (cls.state == ca_disconnected)
Key_Dest_Add(kdm_console); // Key_Dest_Add(kdm_console);
} }
break; break;
case 2: case 2:
// key_menu // key_menu
m_state = m_menu_dat;
Key_Dest_Remove(kdm_message); Key_Dest_Remove(kdm_message);
if (!Key_Dest_Has(kdm_menu)) if (!Key_Dest_Has(kdm_gmenu))
Key_Dest_Remove(kdm_console); Key_Dest_Remove(kdm_console);
Key_Dest_Add(kdm_menu); Key_Dest_Add(kdm_gmenu);
break; break;
case 1: case 1:
// key_message // key_message
@ -1268,13 +1271,10 @@ void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr
//float getkeydest(void) = #602; //float getkeydest(void) = #602;
void QCBUILTIN PF_cl_getkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_cl_getkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
if (Key_Dest_Has(kdm_menu)) if (Key_Dest_Has(kdm_emenu))
{ G_FLOAT(OFS_RETURN) = 3;
if (m_state == m_menu_dat) else if (Key_Dest_Has(kdm_gmenu))
G_FLOAT(OFS_RETURN) = 2; G_FLOAT(OFS_RETURN) = 2;
else
G_FLOAT(OFS_RETURN) = 3;
}
// else if (Key_Dest_Has(kdm_message)) // else if (Key_Dest_Has(kdm_message))
// G_FLOAT(OFS_RETURN) = 1; // G_FLOAT(OFS_RETURN) = 1;
else else
@ -2241,19 +2241,14 @@ void MP_Shutdown (void)
PR_Common_Shutdown(menu_world.progs, false); PR_Common_Shutdown(menu_world.progs, false);
menu_world.progs->CloseProgs(menu_world.progs); menu_world.progs->CloseProgs(menu_world.progs);
memset(&menu_world, 0, sizeof(menu_world)); memset(&menu_world, 0, sizeof(menu_world));
PR_ReleaseFonts(kdm_menu); PR_ReleaseFonts(kdm_gmenu);
#ifdef CL_MASTER #ifdef CL_MASTER
Master_ClearMasks(); Master_ClearMasks();
#endif #endif
if (m_state == m_menu_dat) Key_Dest_Remove(kdm_gmenu);
{ key_dest_absolutemouse &= ~kdm_gmenu;
Key_Dest_Remove(kdm_menu);
m_state = 0;
}
key_dest_absolutemouse &= ~kdm_menu;
} }
void *VARGS PR_CB_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves. void *VARGS PR_CB_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves.
@ -2358,7 +2353,7 @@ qboolean MP_Init (void)
menuprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); menuprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
menuprogparms.user = &menu_world; menuprogparms.user = &menu_world;
menu_world.keydestmask = kdm_menu; menu_world.keydestmask = kdm_gmenu;
menutime = Sys_DoubleTime(); menutime = Sys_DoubleTime();
if (!menu_world.progs) if (!menu_world.progs)
@ -2537,6 +2532,7 @@ void MP_Draw(void)
inmenuprogs--; inmenuprogs--;
} }
void MP_Keydown(int key, int unicode) void MP_Keydown(int key, int unicode)
{ {
extern qboolean keydown[K_MAX]; extern qboolean keydown[K_MAX];
@ -2559,6 +2555,8 @@ void MP_Keydown(int key, int unicode)
} }
} }
mpkeysdown[key>>3] |= (1<<(key&7));
menutime = Sys_DoubleTime(); menutime = Sys_DoubleTime();
if (menu_world.g.time) if (menu_world.g.time)
*menu_world.g.time = menutime; *menu_world.g.time = menutime;
@ -2584,6 +2582,10 @@ void MP_Keyup(int key, int unicode)
if (setjmp(mp_abort)) if (setjmp(mp_abort))
return; return;
if (key && !(mpkeysdown[key>>3] & (1<<(key&7))))
return;
mpkeysdown[key>>3] &= ~(1<<(key&7));
menutime = Sys_DoubleTime(); menutime = Sys_DoubleTime();
if (menu_world.g.time) if (menu_world.g.time)
*menu_world.g.time = menutime; *menu_world.g.time = menutime;

View file

@ -157,6 +157,7 @@ extern "C" {
#include "protocol.h" #include "protocol.h"
#include "cmd.h" #include "cmd.h"
#include "wad.h" #include "wad.h"
#include "console.h"
#include "screen.h" #include "screen.h"
#include "sbar.h" #include "sbar.h"
#include "sound.h" #include "sound.h"
@ -169,7 +170,6 @@ extern "C" {
#include "input.h" #include "input.h"
#include "keys.h" #include "keys.h"
#include "console.h"
#include "view.h" #include "view.h"
#include "menu.h" #include "menu.h"
#include "crc.h" #include "crc.h"

View file

@ -1315,10 +1315,10 @@ void R2D_DrawCrosshair(void)
{ {
SCR_CrosshairPosition(&cl.playerview[sc], &sx, &sy); SCR_CrosshairPosition(&cl.playerview[sc], &sx, &sy);
Font_BeginScaledString(font_default, sx, sy, size, size, &sx, &sy); Font_BeginScaledString(font_default, sx, sy, size, size, &sx, &sy);
sx -= Font_CharScaleWidth('+' | 0xe000 | CON_WHITEMASK)/2; sx -= Font_CharScaleWidth(CON_WHITEMASK, '+' | 0xe000)/2;
sy -= Font_CharScaleHeight()/2; sy -= Font_CharScaleHeight()/2;
Font_ForceColour(ch_color[0], ch_color[1], ch_color[2], crosshairalpha.value); Font_ForceColour(ch_color[0], ch_color[1], ch_color[2], crosshairalpha.value);
Font_DrawScaleChar(sx, sy, '+' | 0xe000 | CON_WHITEMASK); Font_DrawScaleChar(sx, sy, CON_WHITEMASK, '+' | 0xe000);
Font_InvalidateColour(); Font_InvalidateColour();
Font_EndString(font_default); Font_EndString(font_default);
} }

View file

@ -582,6 +582,7 @@ extern cvar_t gl_maxdist;
extern cvar_t r_clear; extern cvar_t r_clear;
extern cvar_t gl_poly; extern cvar_t gl_poly;
extern cvar_t gl_affinemodels; extern cvar_t gl_affinemodels;
extern cvar_t r_renderscale;
extern cvar_t gl_nohwblend; extern cvar_t gl_nohwblend;
extern cvar_t r_coronas, r_flashblend, r_flashblendscale; extern cvar_t r_coronas, r_flashblend, r_flashblendscale;
extern cvar_t r_lightstylesmooth; extern cvar_t r_lightstylesmooth;

View file

@ -142,6 +142,7 @@ cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1");
cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"), cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"),
CVAR_ARCHIVE, CVAR_ARCHIVE,
Cvar_Limiter_ZeroToOne_Callback); Cvar_Limiter_ZeroToOne_Callback);
cvar_t r_fxaa = CVARD("r_fxaa", "0", "Runs a post-procesing pass to strip the jaggies.");
cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a custom shader to use as a post-processing shader"); cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a custom shader to use as a post-processing shader");
cvar_t r_wallcolour = CVARAF ("r_wallcolour", "128 128 128", cvar_t r_wallcolour = CVARAF ("r_wallcolour", "128 128 128",
"r_wallcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken "r_wallcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken
@ -430,6 +431,8 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS); Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS);
Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS); Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS);
Cvar_Register (&r_postprocshader, GLRENDEREROPTIONS); Cvar_Register (&r_postprocshader, GLRENDEREROPTIONS);
Cvar_Register (&r_fxaa, GLRENDEREROPTIONS);
Cvar_Register (&r_renderscale, GLRENDEREROPTIONS);
Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS); Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS);
Cvar_Register (&r_lerpmuzzlehack, GLRENDEREROPTIONS); Cvar_Register (&r_lerpmuzzlehack, GLRENDEREROPTIONS);

View file

@ -176,10 +176,12 @@ int Sbar_BottomColour(player_info_t *p)
void Draw_ExpandedString(float x, float y, conchar_t *str) void Draw_ExpandedString(float x, float y, conchar_t *str)
{ {
int px, py; int px, py;
unsigned int codeflags, codepoint;
Font_BeginString(font_default, x, y, &px, &py); Font_BeginString(font_default, x, y, &px, &py);
while(*str) while(*str)
{ {
px = Font_DrawChar(px, py, *str++); str = Font_Decode(str, &codeflags, &codepoint);
px = Font_DrawChar(px, py, codeflags, codepoint);
} }
Font_EndString(font_default); Font_EndString(font_default);
} }
@ -208,6 +210,7 @@ void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean
conchar_t *w; conchar_t *w;
int px, py; int px, py;
int fw = 0; int fw = 0;
unsigned int codeflags, codepoint;
width = (width*vid.rotpixelwidth)/vid.width; width = (width*vid.rotpixelwidth)/vid.width;
@ -216,9 +219,10 @@ void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean
Font_BeginString(font_default, x, y, &px, &py); Font_BeginString(font_default, x, y, &px, &py);
if (rightalign) if (rightalign)
{ {
for (w = buffer; *w; w++) for (w = buffer; *w; )
{ {
fw += Font_CharWidth(*w); w = Font_Decode(w, &codeflags, &codepoint);
fw += Font_CharWidth(codeflags, codepoint);
} }
if (rightalign == 2) if (rightalign == 2)
{ {
@ -237,12 +241,14 @@ void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean
} }
} }
for (w = buffer; *w; w++) for (w = buffer; *w; )
{ {
width -= Font_CharWidth(*w); w = Font_Decode(w, &codeflags, &codepoint);
width -= Font_CharWidth(codeflags, codepoint);
if (width < 0) if (width < 0)
return; return;
px = Font_DrawChar(px, py, *w); px = Font_DrawChar(px, py, codeflags, codepoint);
} }
Font_EndString(font_default); Font_EndString(font_default);
} }
@ -1115,7 +1121,7 @@ void Sbar_DrawCharacter (float x, float y, int num)
{ {
int px, py; int px, py;
Font_BeginString(font_default, sbar_rect.x + x + 4, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &px, &py); Font_BeginString(font_default, sbar_rect.x + x + 4, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &px, &py);
Font_DrawChar(px, py, num | 0xe000 | CON_WHITEMASK); Font_DrawChar(px, py, CON_WHITEMASK, num | 0xe000);
Font_EndString(font_default); Font_EndString(font_default);
} }
@ -1158,7 +1164,8 @@ void Draw_TinyString (float x, float y, const qbyte *str)
str++; str++;
continue; continue;
} }
px = Font_DrawChar(px, py, CON_WHITEMASK|*str++); //fixme: utf-8 encoding.
px = Font_DrawChar(px, py, CON_WHITEMASK, *str++);
} }
Font_EndString(font_tiny); Font_EndString(font_tiny);
} }
@ -2593,24 +2600,24 @@ static void Sbar_Voice(int y)
float range = loudness/100.0f; float range = loudness/100.0f;
w = 0; w = 0;
Font_BeginString(font_default, sbar_rect.x + sbar_rect.width/2, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &x, &y); Font_BeginString(font_default, sbar_rect.x + sbar_rect.width/2, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &x, &y);
w += Font_CharWidth(0xe080 | CON_WHITEMASK); w += Font_CharWidth(CON_WHITEMASK, 0xe080);
w += Font_CharWidth(0xe081 | CON_WHITEMASK)*16; w += Font_CharWidth(CON_WHITEMASK, 0xe081)*16;
w += Font_CharWidth(0xe082 | CON_WHITEMASK); w += Font_CharWidth(CON_WHITEMASK, 0xe082);
w += Font_CharWidth('M' | CON_WHITEMASK); w += Font_CharWidth(CON_WHITEMASK, 'M');
w += Font_CharWidth('i' | CON_WHITEMASK); w += Font_CharWidth(CON_WHITEMASK, 'i');
w += Font_CharWidth('c' | CON_WHITEMASK); w += Font_CharWidth(CON_WHITEMASK, 'c');
w += Font_CharWidth(' ' | CON_WHITEMASK); w += Font_CharWidth(CON_WHITEMASK, ' ');
x -= w/2; x -= w/2;
x = Font_DrawChar(x, y, 'M' | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 'M');
x = Font_DrawChar(x, y, 'i' | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 'i');
x = Font_DrawChar(x, y, 'c' | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 'c');
x = Font_DrawChar(x, y, ' ' | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, ' ');
x = Font_DrawChar(x, y, 0xe080 | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe080);
s = x; s = x;
for (i=0 ; i<16 ; i++) for (i=0 ; i<16 ; i++)
x = Font_DrawChar(x, y, 0xe081 | CON_WHITEMASK); x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe081);
Font_DrawChar(x, y, 0xe082 | CON_WHITEMASK); Font_DrawChar(x, y, CON_WHITEMASK, 0xe082);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(0xe083 | CON_WHITEMASK)/2, y, 0xe083 | CON_WHITEMASK); Font_DrawChar(s + (x-s) * range - Font_CharWidth(CON_WHITEMASK, 0xe083)/2, y, CON_WHITEMASK, 0xe083);
Font_EndString(font_default); Font_EndString(font_default);
} }
#endif #endif
@ -3137,19 +3144,19 @@ ping time frags name
sprintf(num, "%3i",f); \ sprintf(num, "%3i",f); \
\ \
Font_BeginString(font_default, x+8, y, &cx, &cy); \ Font_BeginString(font_default, x+8, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[0] | 0xe000 | CON_WHITEMASK); \ Font_DrawChar(cx, cy, CON_WHITEMASK, num[0] | 0xe000); \
Font_BeginString(font_default, x+16, y, &cx, &cy); \ Font_BeginString(font_default, x+16, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[1] | 0xe000 | CON_WHITEMASK); \ Font_DrawChar(cx, cy, CON_WHITEMASK, num[1] | 0xe000); \
Font_BeginString(font_default, x+24, y, &cx, &cy); \ Font_BeginString(font_default, x+24, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[2] | 0xe000 | CON_WHITEMASK); \ Font_DrawChar(cx, cy, CON_WHITEMASK, num[2] | 0xe000); \
\ \
if ((pv->cam_state == CAM_FREECAM && k == pv->playernum) || \ if ((pv->cam_state == CAM_FREECAM && k == pv->playernum) || \
(pv->cam_state != CAM_FREECAM && k == pv->cam_spec_track)) \ (pv->cam_state != CAM_FREECAM && k == pv->cam_spec_track)) \
{ \ { \
Font_BeginString(font_default, x, y, &cx, &cy); \ Font_BeginString(font_default, x, y, &cx, &cy); \
Font_DrawChar(cx, cy, 16 | 0xe000 | CON_WHITEMASK); \ Font_DrawChar(cx, cy, CON_WHITEMASK, 16 | 0xe000); \
Font_BeginString(font_default, x+32, y, &cx, &cy); \ Font_BeginString(font_default, x+32, y, &cx, &cy); \
Font_DrawChar(cx, cy, 17 | 0xe000 | CON_WHITEMASK); \ Font_DrawChar(cx, cy, CON_WHITEMASK, 17 | 0xe000); \
} \ } \
Font_EndString(font_default); \ Font_EndString(font_default); \
} \ } \
@ -3588,19 +3595,19 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
sprintf (num, "%3i",f); sprintf (num, "%3i",f);
Font_BeginString(font_default, x+8, y, &px, &py); Font_BeginString(font_default, x+8, y, &px, &py);
Font_DrawChar ( px, py, num[0] | 0xe000 | CON_WHITEMASK); Font_DrawChar ( px, py, CON_WHITEMASK, num[0] | 0xe000);
Font_BeginString(font_default, x+16, y, &px, &py); Font_BeginString(font_default, x+16, y, &px, &py);
Font_DrawChar ( px, py, num[1] | 0xe000 | CON_WHITEMASK); Font_DrawChar ( px, py, CON_WHITEMASK, num[1] | 0xe000);
Font_BeginString(font_default, x+24, y, &px, &py); Font_BeginString(font_default, x+24, y, &px, &py);
Font_DrawChar ( px, py, num[2] | 0xe000 | CON_WHITEMASK); Font_DrawChar ( px, py, CON_WHITEMASK, num[2] | 0xe000);
if ((cl.spectator && k == pv->cam_spec_track && pv->cam_state != CAM_FREECAM) || if ((cl.spectator && k == pv->cam_spec_track && pv->cam_state != CAM_FREECAM) ||
(!cl.spectator && k == pv->playernum)) (!cl.spectator && k == pv->playernum))
{ {
Font_BeginString(font_default, x, y, &px, &py); Font_BeginString(font_default, x, y, &px, &py);
Font_DrawChar ( px, py, 16 | 0xe000 | CON_WHITEMASK); Font_DrawChar ( px, py, CON_WHITEMASK, 16 | 0xe000);
Font_BeginString(font_default, x+32, y, &px, &py); Font_BeginString(font_default, x+32, y, &px, &py);
Font_DrawChar ( px, py, 17 | 0xe000 | CON_WHITEMASK); Font_DrawChar ( px, py, CON_WHITEMASK, 17 | 0xe000);
} }
Q_strncpyz(name, s->name, sizeof(name)); Q_strncpyz(name, s->name, sizeof(name));
@ -3642,9 +3649,9 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
if (!strncmp(cl.players[pv->playernum].team, tm->team, 16)) if (!strncmp(cl.players[pv->playernum].team, tm->team, 16))
{ {
Font_BeginString(font_default, x-8, y, &px, &py); Font_BeginString(font_default, x-8, y, &px, &py);
Font_DrawChar(px, py, 16|0xe000|CON_WHITEMASK); Font_DrawChar(px, py, CON_WHITEMASK, 16|0xe000);
Font_BeginString(font_default, x+32, y, &px, &py); Font_BeginString(font_default, x+32, y, &px, &py);
Font_DrawChar(px, py, 17|0xe000|CON_WHITEMASK); Font_DrawChar(px, py, CON_WHITEMASK, 17|0xe000);
Font_EndString(font_default); Font_EndString(font_default);
} }

View file

@ -108,15 +108,30 @@ void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx,
void Font_Transform(float vx, float vy, int *px, int *py); void Font_Transform(float vx, float vy, int *px, int *py);
int Font_CharHeight(void); int Font_CharHeight(void);
float Font_CharScaleHeight(void); float Font_CharScaleHeight(void);
int Font_CharWidth(unsigned int charcode); int Font_CharWidth(unsigned int charflags, unsigned int codepoint);
float Font_CharScaleWidth(unsigned int charcode); float Font_CharScaleWidth(unsigned int charflags, unsigned int codepoint);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode); int Font_CharEndCoord(struct font_s *font, int x, unsigned int charflags, unsigned int codepoint);
int Font_DrawChar(int px, int py, unsigned int charcode); int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint);
float Font_DrawScaleChar(float px, float py, unsigned int charcode); /*avoid using*/ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned int codepoint); /*avoid using*/
void Font_EndString(struct font_s *font); void Font_EndString(struct font_s *font);
void Font_ForceColour(float r, float g, float b, float a); //This colour will be applied while the char mask remains WHITE. If you print char by char, make sure to include the mask. void Font_ForceColour(float r, float g, float b, float a); //This colour will be applied while the char mask remains WHITE. If you print char by char, make sure to include the mask.
void Font_InvalidateColour(void); void Font_InvalidateColour(void);
/*these three functions deal with formatted blocks of text (including tabs and new lines)*/ /*these three functions deal with formatted blocks of text (including tabs and new lines)*/
fte_inline conchar_t *Font_Decode(conchar_t *start, unsigned int *codeflags, unsigned int *codepoint)
{
if (*start & CON_LONGCHAR)
if (!(*start & CON_RICHFORECOLOUR))
{
*codeflags = start[1];
*codepoint = ((start[0] & CON_CHARMASK)<<16) | (start[1] & CON_CHARMASK);
return start+2;
}
*codeflags = start[0] & CON_FLAGSMASK;
*codepoint = start[0] & CON_CHARMASK;
return start+1;
}
conchar_t *Font_DecodeReverse(conchar_t *start, conchar_t *stop, unsigned int *codeflags, unsigned int *codepoint);
int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends); int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends);
int Font_LineWidth(conchar_t *start, conchar_t *end); int Font_LineWidth(conchar_t *start, conchar_t *end);
float Font_LineScaleWidth(conchar_t *start, conchar_t *end); float Font_LineScaleWidth(conchar_t *start, conchar_t *end);

View file

@ -2098,6 +2098,9 @@ void S_Purge(qboolean retaintouched)
if (retaintouched && sfx->touched) if (retaintouched && sfx->touched)
continue; continue;
if (S_IsPlayingSomewhere(sfx))
continue; //eep?!?
sfx->loadstate = SLS_NOTLOADED; sfx->loadstate = SLS_NOTLOADED;
/*nothing to do if there's no data within*/ /*nothing to do if there's no data within*/
if (!sfx->decoder.buf) if (!sfx->decoder.buf)
@ -2380,6 +2383,48 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
S_UnlockMixer(); S_UnlockMixer();
} }
qboolean S_GetMusicInfo(int musicchannel, float *time, float *duration)
{
qboolean result = false;
soundcardinfo_t *sc;
sfxcache_t scachebuf, *c;
sfx_t *sfx;
*time = 0;
*duration = 0;
musicchannel += MUSIC_FIRST;
S_LockMixer();
for (sc = sndcardinfo; sc; sc = sc->next)
{
sfx = sc->channel[musicchannel].sfx;
if (sfx)
{
if (sfx->loadstate != SLS_LOADED)
c = NULL;
else if (sfx->decoder.decodedata)
{
if (sfx->decoder.querydata)
c = sfx->decoder.querydata(sfx, &scachebuf);
else
c = NULL; //don't bother trying to actually decode anything here.
}
else
c = sfx->decoder.buf;
if (c)
{
*duration = c->length / c->speed;
*time = (sc->channel[musicchannel].pos>>PITCHSHIFT) / (float)snd_speed; //the time into the sound, ignoring play rate.
result = true;
}
}
}
S_UnlockMixer();
return result;
}
float S_GetSoundTime(int entnum, int entchannel) float S_GetSoundTime(int entnum, int entchannel)
{ {
int i; int i;
@ -2448,6 +2493,7 @@ void S_StopAllSounds(qboolean clear)
{ {
int i; int i;
sfx_t *s; sfx_t *s;
channel_t musics[NUM_MUSICS];
soundcardinfo_t *sc; soundcardinfo_t *sc;
@ -2458,12 +2504,15 @@ void S_StopAllSounds(qboolean clear)
for (sc = sndcardinfo; sc; sc = sc->next) for (sc = sndcardinfo; sc; sc = sc->next)
{ {
for (i=0 ; i<sc->total_chans ; i++) for (i=0 ; i<sc->total_chans ; i++)
{
if (i >= MUSIC_FIRST && i < MUSIC_FIRST+NUM_MUSICS && sc->selfpainting)
continue; //don't reset music if is safe to continue playing it without stuttering
if (sc->channel[i].sfx) if (sc->channel[i].sfx)
{ {
s = sc->channel[i].sfx; s = sc->channel[i].sfx;
if (s->loadstate == SLS_LOADING) if (s->loadstate == SLS_LOADING)
;//COM_WorkerPartialSync(s, &s->loadstate, SLS_LOADING); COM_WorkerPartialSync(s, &s->loadstate, SLS_LOADING);
else // else
{ {
sc->channel[i].sfx = NULL; sc->channel[i].sfx = NULL;
if (s->decoder.ended) if (s->decoder.ended)
@ -2475,12 +2524,15 @@ void S_StopAllSounds(qboolean clear)
sc->ChannelUpdate(sc, &sc->channel[i], true); sc->ChannelUpdate(sc, &sc->channel[i], true);
} }
} }
}
sc->total_chans = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS + NUM_MUSICS; // no statics sc->total_chans = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS + NUM_MUSICS; // no statics
memcpy(musics, &sc->channel[MUSIC_FIRST], sizeof(musics));
Q_memset(sc->channel, 0, MAX_CHANNELS * sizeof(channel_t)); Q_memset(sc->channel, 0, MAX_CHANNELS * sizeof(channel_t));
memcpy(&sc->channel[MUSIC_FIRST], musics, sizeof(musics));
if (clear) if (clear && !sc->selfpainting) //if its self-painting, then the mixer will continue painting anyway (which is important if its still painting music, but otherwise don't stutter at all when loading)
S_ClearBuffer (sc); S_ClearBuffer (sc);
} }
@ -2613,12 +2665,24 @@ void S_Music_Seek(float time)
} }
} }
//mixer must be locked
qboolean S_Music_Playing(int musicchannel)
{
soundcardinfo_t *sc;
musicchannel += MUSIC_FIRST;
for (sc = sndcardinfo; sc; sc=sc->next)
{
if (sc->channel[musicchannel].sfx)
return true;
}
return false;
}
/* /*
=================== ===================
S_UpdateAmbientSounds S_UpdateAmbientSounds
=================== ===================
*/ */
char *Media_NextTrack(int musicchannelnum);
mleaf_t *Q1BSP_LeafForPoint (model_t *model, vec3_t p); mleaf_t *Q1BSP_LeafForPoint (model_t *model, vec3_t p);
void S_UpdateAmbientSounds (soundcardinfo_t *sc) void S_UpdateAmbientSounds (soundcardinfo_t *sc)
{ {
@ -2656,7 +2720,27 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc)
if (chan->sfx) if (chan->sfx)
{ {
chan->flags = CF_ABSVOLUME; //bypasses volume cvar completely. chan->flags = CF_ABSVOLUME; //bypasses volume cvar completely.
chan->master_vol = bound(0, 255*bgmvolume.value*voicevolumemod, 255); vol = 255*bgmvolume.value*voicevolumemod;
vol = bound(0, vol, 255);
vol = Media_CrossFade(i-MUSIC_FIRST, vol);
if (vol < 0)
{ //cross fading wants to KILL this track now, apparently.
sfx_t *s = chan->sfx;
if (s->loadstate != SLS_LOADING)
{
chan->pos = 0;
chan->sfx = NULL;
if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, chan, true);
if (s && s->decoder.ended && !S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly.
s->decoder.ended(s);
}
continue;
}
chan->master_vol = bound(0, vol, 255);
chan->vol[0] = chan->vol[1] = chan->vol[2] = chan->vol[3] = chan->vol[4] = chan->vol[5] = chan->master_vol; chan->vol[0] = chan->vol[1] = chan->vol[2] = chan->vol[3] = chan->vol[4] = chan->vol[5] = chan->master_vol;
if (sc->ChannelUpdate) if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, chan, changed); sc->ChannelUpdate(sc, chan, changed);
@ -3059,9 +3143,14 @@ void S_SoundList_f(void)
total = 0; total = 0;
for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++) for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
{ {
if (sfx->decoder.decodedata) if (sfx->loadstate != SLS_LOADED)
sc = NULL;
else if (sfx->decoder.decodedata)
{ {
sc = sfx->decoder.decodedata(sfx, &scachebuf, 0, 0x0fffffff); if (sfx->decoder.querydata)
sc = sfx->decoder.querydata(sfx, &scachebuf);
else
sc = NULL; //don't bother trying to actually decode anything here.
if (!sc) if (!sc)
{ {
Con_Printf("S( ) : %s\n", sfx->name); Con_Printf("S( ) : %s\n", sfx->name);

View file

@ -779,8 +779,10 @@ qboolean S_RegisterSoundInputPlugin(S_LoadSound_t loadfnc)
return false; return false;
} }
void S_Wakeup (void *ctx, void *ctxdata, size_t a, size_t b) void S_LoadedOrFailed (void *ctx, void *ctxdata, size_t a, size_t b)
{ {
sfx_t *s = ctx;
s->loadstate = a;
} }
/* /*
============== ==============
@ -829,7 +831,7 @@ void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
else else
{ {
Con_SafePrintf ("Couldn't load %s\n", namebuffer); Con_SafePrintf ("Couldn't load %s\n", namebuffer);
s->loadstate = SLS_FAILED; COM_AddWork(0, S_LoadedOrFailed, s, NULL, SLS_FAILED, 0);
return; return;
} }
} }
@ -878,7 +880,7 @@ void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
{ {
//FIXME: check to see if queued for download. //FIXME: check to see if queued for download.
Con_DPrintf ("Couldn't load %s\n", namebuffer); Con_DPrintf ("Couldn't load %s\n", namebuffer);
s->loadstate = SLS_FAILED; COM_AddWork(0, S_LoadedOrFailed, s, NULL, SLS_FAILED, 0);
return; return;
} }
@ -890,7 +892,7 @@ void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
{ {
s->loadstate = SLS_LOADED; s->loadstate = SLS_LOADED;
//wake up the main thread in case it decided to wait for us. //wake up the main thread in case it decided to wait for us.
COM_AddWork(0, S_Wakeup, s, NULL, 0, 0); COM_AddWork(0, S_LoadedOrFailed, s, NULL, SLS_LOADED, 0);
BZ_Free(data); BZ_Free(data);
return; return;
} }
@ -900,7 +902,7 @@ void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
if (s->loadstate != SLS_FAILED) if (s->loadstate != SLS_FAILED)
Con_Printf ("Format not recognised: %s\n", namebuffer); Con_Printf ("Format not recognised: %s\n", namebuffer);
s->loadstate = SLS_FAILED; COM_AddWork(0, S_LoadedOrFailed, s, NULL, SLS_FAILED, 0);
BZ_Free(data); BZ_Free(data);
return; return;
} }

View file

@ -75,9 +75,10 @@ typedef struct {
sfx_t *s; sfx_t *s;
} ovdecoderbuffer_t; } ovdecoderbuffer_t;
sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length); static sfxcache_t *OV_Query(struct sfx_s *sfx, struct sfxcache_s *buf);
void OV_CancelDecoder(sfx_t *s); static sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length);
qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer); static void OV_CancelDecoder(sfx_t *s);
static qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer);
qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed) qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
{ {
@ -93,6 +94,7 @@ qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
buffer->s = s; buffer->s = s;
s->decoder.buf = buffer; s->decoder.buf = buffer;
s->decoder.decodedata = OV_DecodeSome; s->decoder.decodedata = OV_DecodeSome;
s->decoder.querydata = OV_Query;
s->decoder.purge = OV_CancelDecoder; s->decoder.purge = OV_CancelDecoder;
s->decoder.ended = OV_CancelDecoder; s->decoder.ended = OV_CancelDecoder;
@ -117,7 +119,25 @@ qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
return true; return true;
} }
sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length) static sfxcache_t *OV_Query(struct sfx_s *sfx, struct sfxcache_s *buf)
{
ovdecoderbuffer_t *dec = sfx->decoder.buf;
if (!dec)
buf = NULL;
if (buf)
{
buf->data = NULL; //you're not meant to actually be using the data here
buf->soundoffset = 0;
buf->length = p_ov_pcm_total(&dec->vf, -1);
buf->loopstart = -1;
buf->numchannels = dec->srcchannels;
buf->speed = dec->srcspeed;
buf->width = 2;
}
return buf;
}
static sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length)
{ {
extern int snd_speed; extern int snd_speed;
extern cvar_t snd_linearresample_stream; extern cvar_t snd_linearresample_stream;
@ -141,9 +161,16 @@ sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start,
dec->decodedbytestart = start; dec->decodedbytestart = start;
//check pos //check pos
//fixme: seeking might not be supported
p_ov_pcm_seek(&dec->vf, dec->decodedbytestart); p_ov_pcm_seek(&dec->vf, dec->decodedbytestart);
} }
/* if (start > dec->decodedbytestart + dec->decodedbytecount)
{
dec->decodedbytestart = start;
p_ov_pcm_seek(&dec->vf, dec->decodedbytestart);
}
*/
if (dec->decodedbytecount > snd_speed*8) if (dec->decodedbytecount > snd_speed*8)
{ {
/*everything is okay, but our buffer is getting needlessly large. /*everything is okay, but our buffer is getting needlessly large.
@ -243,14 +270,22 @@ sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start,
} }
return buf; return buf;
} }
void OV_CancelDecoder(sfx_t *s) static void OV_CanceledDecoder(void *ctx, void *data, size_t a, size_t b)
{
sfx_t *s = ctx;
if (s->loadstate != SLS_LOADING)
s->loadstate = SLS_NOTLOADED;
}
static void OV_CancelDecoder(sfx_t *s)
{ {
ovdecoderbuffer_t *dec; ovdecoderbuffer_t *dec;
s->loadstate = SLS_FAILED;
dec = s->decoder.buf; dec = s->decoder.buf;
s->decoder.buf = NULL; s->decoder.buf = NULL;
s->decoder.purge = NULL; s->decoder.purge = NULL;
s->decoder.ended = NULL; s->decoder.ended = NULL;
s->decoder.querydata = NULL;
s->decoder.decodedata = NULL; s->decoder.decodedata = NULL;
p_ov_clear (&dec->vf); //close the decoder p_ov_clear (&dec->vf); //close the decoder
@ -264,6 +299,11 @@ void OV_CancelDecoder(sfx_t *s)
dec->decodedbuffer = NULL; dec->decodedbuffer = NULL;
BZ_Free(dec); BZ_Free(dec);
//due to the nature of message passing, we can get into a state where the main thread is going to flag us as loaded when we have already failed.
//that is bad.
//so post a message to the main thread to override it, just in case.
// COM_AddWork(0, OV_CanceledDecoder, s, NULL, SLS_NOTLOADED, 0);
s->loadstate = SLS_NOTLOADED; s->loadstate = SLS_NOTLOADED;
} }
@ -316,7 +356,7 @@ static ov_callbacks callbacks = {
close_func, close_func,
tell_func, tell_func,
}; };
qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer) static qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer)
{ {
#ifndef LIBVORBISFILE_STATIC #ifndef LIBVORBISFILE_STATIC
static qboolean tried; static qboolean tried;

View file

@ -40,6 +40,7 @@ typedef struct
typedef struct { typedef struct {
struct sfxcache_s *(*decodedata) (struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length); //retrurn true when done. struct sfxcache_s *(*decodedata) (struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length); //retrurn true when done.
struct sfxcache_s *(*querydata) (struct sfx_s *sfx, struct sfxcache_s *buf); //reports length + format info without actually decoding anything.
void (*ended) (struct sfx_s *sfx); //sound stopped playing and is now silent (allow rewinding or something). void (*ended) (struct sfx_s *sfx); //sound stopped playing and is now silent (allow rewinding or something).
void (*purge) (struct sfx_s *sfx); //sound is being purged from memory. destroy everything. void (*purge) (struct sfx_s *sfx); //sound is being purged from memory. destroy everything.
void *buf; void *buf;
@ -141,6 +142,10 @@ qboolean S_HaveOutput(void);
void S_Music_Clear(sfx_t *onlyifsample); void S_Music_Clear(sfx_t *onlyifsample);
void S_Music_Seek(float time); void S_Music_Seek(float time);
qboolean S_GetMusicInfo(int musicchannel, float *time, float *duration);
qboolean S_Music_Playing(int musicchannel);
float Media_CrossFade(int musicchanel, float vol); //queries the volume we're meant to be playing (checks for fade out). -1 for no more, otherwise returns vol.
char *Media_NextTrack(int musicchanel); //queries the track we're meant to be playing now.
sfx_t *S_FindName (const char *name, qboolean create); sfx_t *S_FindName (const char *name, qboolean create);
sfx_t *S_PrecacheSound (const char *sample); sfx_t *S_PrecacheSound (const char *sample);

View file

@ -1540,11 +1540,13 @@ void VARGS Sys_Printf (char *fmt, ...)
out = wide; out = wide;
in = msg; in = msg;
wlen = 0; wlen = 0;
for (in = msg; in < end; in++) for (in = msg; in < end; )
{ {
if (!(*in & CON_HIDDEN)) unsigned int flags, cp;
in = Font_Decode(in, &flags, &cp);
if (!(flags & CON_HIDDEN))
{ {
*out++ = COM_DeQuake(*in & CON_CHARMASK); *out++ = COM_DeQuake(cp);
wlen++; wlen++;
} }
} }
@ -1686,9 +1688,21 @@ char *Sys_GetClipboard(void)
utf8 = cliputf8 = malloc(l); utf8 = cliputf8 = malloc(l);
while(*clipWText) while(*clipWText)
{ {
if (clipWText[0] == '\r' && clipWText[1] == '\n') //bloomin microsoft. unsigned int cp = *clipWText++;
clipWText++; if (cp == '\r' && *clipWText == '\n') //bloomin microsoft.
c = utf8_encode(utf8, *clipWText++, l); cp = *clipWText++;
if (cp >= 0xD800u && cp <= 0xDBFFu)
{ //handle utf-16 surrogates
if (*clipWText >= 0xDC00u && *clipWText <= 0xDFFFu)
{
cp = (cp&0x3ff)<<10;
cp |= *clipWText++ & 0x3ff;
}
else
cp = 0xFFFDu;
}
c = utf8_encode(utf8, cp, l);
if (!c) if (!c)
break; break;
l -= c; l -= c;
@ -1756,13 +1770,14 @@ void Sys_SaveClipboard(char *text)
HANDLE glob; HANDLE glob;
char *temp; char *temp;
unsigned short *tempw; unsigned short *tempw;
unsigned int codepoint;
if (!OpenClipboard(NULL)) if (!OpenClipboard(NULL))
return; return;
EmptyClipboard(); EmptyClipboard();
if (com_parseutf8.ival > 0) if (com_parseutf8.ival > 0)
{ {
glob = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1)*2); glob = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1)*4);
if (glob) if (glob)
{ {
tempw = GlobalLock(glob); tempw = GlobalLock(glob);
@ -1771,8 +1786,20 @@ void Sys_SaveClipboard(char *text)
int error; int error;
while(*text) while(*text)
{ {
//NOTE: should be \r\n and not just \n codepoint = utf8_decode(&error, text, &text);
*tempw++ = utf8_decode(&error, text, &text); if (codepoint == '\n')
{ //windows is stupid and annoying.
*tempw++ = '\r';
*tempw++ = '\n';
}
else if (codepoint > 0xffff)
{ //and badly designed, too.
codepoint -= 0x10000;
*tempw++ = 0xD800 | ((codepoint>>10)&0x3ff);
*tempw++ = 0xDC00 | (codepoint&0x3ff);
}
else
*tempw++ = codepoint;
} }
*tempw = 0; *tempw = 0;
GlobalUnlock(glob); GlobalUnlock(glob);
@ -2818,9 +2845,10 @@ BOOL MoveFileU(const char *src, const char *dst)
qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize) qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
{ {
wchar_t wide1[2048];
int ffe = COM_CheckParm("--fromfrontend"); int ffe = COM_CheckParm("--fromfrontend");
PROCESS_INFORMATION childinfo; PROCESS_INFORMATION childinfo;
STARTUPINFO startinfo = {sizeof(startinfo)}; STARTUPINFOW startinfo = {sizeof(startinfo)};
char *e; char *e;
strtoul(SVNREVISIONSTR, &e, 10); strtoul(SVNREVISIONSTR, &e, 10);
@ -2847,7 +2875,6 @@ qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
else if (!ffe) else if (!ffe)
{ {
//if we're not from the frontend (ie: we ARE the frontend), we should run the updated build instead //if we're not from the frontend (ie: we ARE the frontend), we should run the updated build instead
char frontendpath[MAX_OSPATH];
char pendingpath[MAX_OSPATH]; char pendingpath[MAX_OSPATH];
char updatedpath[MAX_OSPATH]; char updatedpath[MAX_OSPATH];
@ -2881,9 +2908,10 @@ qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
if (*updatedpath) if (*updatedpath)
{ {
//fixme: unicode paths/commandline. wchar_t widefe[MAX_OSPATH], wargs[2048];
GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1); GetModuleFileNameW(NULL, widefe, countof(widefe)-1);
if (CreateProcess(updatedpath, va("%s --fromfrontend \"%s\" \"%s\"", GetCommandLineA(), SVNREVISIONSTR, frontendpath), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) _snwprintf(wargs, countof(wargs), L"%s --fromfrontend \"%s\" \"%s\"", GetCommandLineW(), widen(wide1, sizeof(wide1), SVNREVISIONSTR), widefe);
if (CreateProcessW(widen(wide1, sizeof(wide1), updatedpath), wargs, NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo))
return true; return true;
} }
} }
@ -2894,7 +2922,6 @@ qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
//com_argv[ffe+2] is frontend location //com_argv[ffe+2] is frontend location
if (atoi(com_argv[ffe+1]) > atoi(SVNREVISIONSTR)) if (atoi(com_argv[ffe+1]) > atoi(SVNREVISIONSTR))
{ {
wchar_t wide1[2048];
//ping-pong it back, to make sure we're running the most recent version. //ping-pong it back, to make sure we're running the most recent version.
// GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1); // GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1);
if (CreateProcessW(widen(wide1, sizeof(wide1), com_argv[ffe+2]), GetCommandLineW(), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo)) if (CreateProcessW(widen(wide1, sizeof(wide1), com_argv[ffe+2]), GetCommandLineW(), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo))

View file

@ -956,7 +956,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
nnx-=(nnx - -viewportx)%ts; nnx-=(nnx - -viewportx)%ts;
} }
else else
nnx = Font_CharEndCoord(font_default, nx, (int)d[i] | (colour)); nnx = Font_CharEndCoord(font_default, nx, colour, (int)d[i]);
if (smx >= nx && smx <= nnx) if (smx >= nx && smx <= nnx)
{ {
@ -999,7 +999,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
{ {
if (d == c) if (d == c)
{ {
int e = Font_DrawChar(nx, y, (int)0xe00b | (CON_WHITEMASK|CON_BLINKTEXT)); int e = Font_DrawChar(nx, y, CON_WHITEMASK|CON_BLINKTEXT, (int)0xe00b);
if (e >= vid.pixelwidth) if (e >= vid.pixelwidth)
viewportx += e - vid.pixelwidth; viewportx += e - vid.pixelwidth;
if (nx < 0) if (nx < 0)
@ -1015,12 +1015,12 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
continue; continue;
} }
if (nx <= (int)vid.pixelwidth || cursorx>=0) if (nx <= (int)vid.pixelwidth || cursorx>=0)
nnx = Font_DrawChar(nx, y, (int)*d | (colour)); nnx = Font_DrawChar(nx, y, colour, (int)*d);
else nnx = vid.pixelwidth; else nnx = vid.pixelwidth;
if (d == c) if (d == c)
{ {
int e = Font_DrawChar(nx, y, (int)0xe00b | (CON_WHITEMASK|CON_BLINKTEXT)); int e = Font_DrawChar(nx, y, CON_WHITEMASK|CON_BLINKTEXT, (int)0xe00b);
if (e >= vid.pixelwidth) if (e >= vid.pixelwidth)
viewportx += e - vid.pixelwidth; viewportx += e - vid.pixelwidth;
if (nx < 0) if (nx < 0)
@ -1038,7 +1038,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
/*we didn't do the cursor! stick it at the end*/ /*we didn't do the cursor! stick it at the end*/
if (c && c >= d) if (c && c >= d)
{ {
int e = Font_DrawChar(nx, y, (int)0xe00b | (CON_WHITEMASK|CON_BLINKTEXT)); int e = Font_DrawChar(nx, y, CON_WHITEMASK|CON_BLINKTEXT, (int)0xe00b);
if (e >= vid.pixelwidth) if (e >= vid.pixelwidth)
viewportx += e - vid.pixelwidth; viewportx += e - vid.pixelwidth;
if (nx < 0) if (nx < 0)
@ -1058,7 +1058,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
{ {
if (*tooltip == '\n') if (*tooltip == '\n')
break; break;
smx = Font_CharEndCoord(font_default, smx, *tooltip); smx = Font_CharEndCoord(font_default, smx, (COLOR_CYAN<<CON_FGSHIFT), *tooltip);
} }
y = Font_CharHeight(); y = Font_CharHeight();
Font_EndString(font_default); Font_EndString(font_default);
@ -1068,7 +1068,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
Font_BeginString(font_default, nx, vy, &y, &y); Font_BeginString(font_default, nx, vy, &y, &y);
for(smx = nx; t < tooltip; t++) for(smx = nx; t < tooltip; t++)
{ {
smx = Font_DrawChar(smx, smy, (COLOR_CYAN<<CON_FGSHIFT) | *t); smx = Font_DrawChar(smx, smy, (COLOR_CYAN<<CON_FGSHIFT), *t);
} }
if (*tooltip == '\n') if (*tooltip == '\n')
tooltip++; tooltip++;

View file

@ -601,6 +601,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif #endif
#if __STDC_VERSION__ >= 199901L
//C99 specifies that an inline function is used as a hint. there should be an actual body/copy somewhere (extern inline foo).
#define fte_inline inline //must have non-line 'int foo();' somewhere
#define fte_inlinebody extern inline
#elif defined(_MSC_VER)
//msvc will inline like C++. and that's fine.
#define fte_inline __inline //c++ style
#define fte_inlinebody
#elif (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
//gcc will generally inline where it can - so long as its static. but that doesn't stop it warning
#define fte_inline __attribute__((unused)) static
#define fte_inlinebody static
#else
//make it static so we at least don't get errors (might still get warnings. see above)
#define fte_inline static
#define fte_inlinebody static
#endif
#ifndef FTE_DEPRECATED #ifndef FTE_DEPRECATED
#define FTE_DEPRECATED #define FTE_DEPRECATED
#endif #endif

View file

@ -1318,8 +1318,8 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel,
int i, len; int i, len;
int quotes = 0; int quotes = 0;
char *str; char *str;
char *bestmacro, *bestvar; char *bestvar;
int name_length, macro_length, var_length; int name_length, var_length;
qboolean striptrailing; qboolean striptrailing;
len = 0; len = 0;
@ -1340,8 +1340,6 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel,
buf[0] = 0; buf[0] = 0;
buf[1] = 0; buf[1] = 0;
bestvar = NULL; bestvar = NULL;
bestmacro = NULL;
macro_length=0;
var_length = 0; var_length = 0;
while ((c = *data) > 32) while ((c = *data) > 32)
{ {
@ -1350,21 +1348,13 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel,
data++; data++;
buf[i++] = c; buf[i++] = c;
buf[i] = 0; buf[i] = 0;
if (!bestmacro) if (expandcvars && (str = Cmd_ExpandCvar(buf+striptrailing, maxaccesslevel, &var_length)))
{ bestvar = str;
if ((str = Cmd_ExpandCvar(buf+striptrailing, maxaccesslevel, &var_length))) if (expandmacros && (str = TP_MacroString (buf+striptrailing, &var_length)))
bestvar = str; bestvar = str;
}
if (expandmacros && (str = TP_MacroString (buf+striptrailing, &macro_length)))
bestmacro = str;
} }
if (bestmacro) if (bestvar)
{
str = bestmacro;
name_length = macro_length;
}
else if (bestvar)
{ {
str = bestvar; str = bestvar;
name_length = var_length; name_length = var_length;
@ -3253,6 +3243,12 @@ static char *Macro_Quote (void)
return "\""; return "\"";
} }
static char *Macro_Random(void)
{
Q_snprintfz(macro_buf, sizeof(macro_buf), "%u", rand());
return macro_buf;
}
/* /*
============ ============
Cmd_Init Cmd_Init
@ -3307,6 +3303,7 @@ void Cmd_Init (void)
Cmd_AddCommandD ("apropos", Cmd_Apropos_f, "Lists all cvars or commands with the specified substring somewhere in their name or descrition."); Cmd_AddCommandD ("apropos", Cmd_Apropos_f, "Lists all cvars or commands with the specified substring somewhere in their name or descrition.");
Cmd_AddMacro("random", Macro_Random, true);
Cmd_AddMacro("time", Macro_Time, true); Cmd_AddMacro("time", Macro_Time, true);
Cmd_AddMacro("ukdate", Macro_UKDate, false); Cmd_AddMacro("ukdate", Macro_UKDate, false);
Cmd_AddMacro("usdate", Macro_USDate, false); Cmd_AddMacro("usdate", Macro_USDate, false);

View file

@ -1768,8 +1768,10 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
meshcache.vbo.svector = inf->vbo_skel_svector; meshcache.vbo.svector = inf->vbo_skel_svector;
meshcache.vbo.tvector = inf->vbo_skel_tvector; meshcache.vbo.tvector = inf->vbo_skel_tvector;
meshcache.vbo.colours[0] = inf->vborgba; meshcache.vbo.colours[0] = inf->vborgba;
meshcache.vbo.bonenums = inf->vbo_skel_bonenum; memset(&meshcache.vbo.bonenums, 0, sizeof(meshcache.vbo.bonenums));
meshcache.vbo.boneweights = inf->vbo_skel_bweight; memset(&meshcache.vbo.boneweights, 0, sizeof(meshcache.vbo.boneweights));
meshcache.vbo.numbones = 0;
meshcache.vbo.bones = NULL;
if (meshcache.vbo.indicies.sysptr) if (meshcache.vbo.indicies.sysptr)
*vbop = meshcache.vbop = &meshcache.vbo; *vbop = meshcache.vbop = &meshcache.vbo;
} }
@ -1820,6 +1822,26 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
mesh->normals_array = inf->ofs_skel_norm; mesh->normals_array = inf->ofs_skel_norm;
mesh->snormals_array = inf->ofs_skel_svect; mesh->snormals_array = inf->ofs_skel_svect;
mesh->tnormals_array = inf->ofs_skel_tvect; mesh->tnormals_array = inf->ofs_skel_tvect;
if (vbop)
{
meshcache.vbo.indicies = inf->vboindicies;
meshcache.vbo.indexcount = inf->numindexes;
meshcache.vbo.vertcount = inf->numverts;
meshcache.vbo.texcoord = inf->vbotexcoords;
meshcache.vbo.coord = inf->vbo_skel_verts;
memset(&meshcache.vbo.coord2, 0, sizeof(meshcache.vbo.coord2));
meshcache.vbo.normals = inf->vbo_skel_normals;
meshcache.vbo.svector = inf->vbo_skel_svector;
meshcache.vbo.tvector = inf->vbo_skel_tvector;
meshcache.vbo.colours[0] = inf->vborgba;
meshcache.vbo.bonenums = inf->vbo_skel_bonenum;
meshcache.vbo.boneweights = inf->vbo_skel_bweight;
meshcache.vbo.numbones = inf->numbones;
meshcache.vbo.bones = meshcache.usebonepose;
if (meshcache.vbo.indicies.sysptr)
*vbop = meshcache.vbop = &meshcache.vbo;
}
} }
} }
else else
@ -1918,6 +1940,13 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
meshcache.vbo.vertcount = inf->numverts; meshcache.vbo.vertcount = inf->numverts;
meshcache.vbo.texcoord = inf->vbotexcoords; meshcache.vbo.texcoord = inf->vbotexcoords;
#ifdef SKELETALMODELS
memset(&meshcache.vbo.bonenums, 0, sizeof(meshcache.vbo.bonenums));
memset(&meshcache.vbo.boneweights, 0, sizeof(meshcache.vbo.boneweights));
meshcache.vbo.numbones = 0;
meshcache.vbo.bones = 0;
#endif
#ifdef SERVERONLY #ifdef SERVERONLY
mesh->xyz_array = p1->ofsverts; mesh->xyz_array = p1->ofsverts;
mesh->xyz2_array = NULL; mesh->xyz2_array = NULL;
@ -6228,7 +6257,7 @@ static qboolean IQM_ImportArray4B(qbyte *base, struct iqmvertexarray *src, byte_
unsigned int fmt = LittleLong(src->format); unsigned int fmt = LittleLong(src->format);
unsigned int offset = LittleLong(src->offset); unsigned int offset = LittleLong(src->offset);
qboolean invalid = false; qboolean invalid = false;
maxval = min(256,maxval); maxval = min(256,maxval); //output is bytes.
if (!offset) if (!offset)
{ {
sz = 0; sz = 0;
@ -6447,6 +6476,8 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
vec4_t defaultweight = {0,0,0,0}; vec4_t defaultweight = {0,0,0,0};
vec4_t defaultvert = {0,0,0,1}; vec4_t defaultvert = {0,0,0,1};
struct iqmbounds *inbounds;
int memsize; int memsize;
qbyte *obase=NULL; qbyte *obase=NULL;
vecV_t *opos=NULL; vecV_t *opos=NULL;
@ -6752,6 +6783,24 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
} }
free(framegroups); free(framegroups);
//determine the bounds
inbounds = (struct iqmbounds*)(buffer + h->ofs_bounds);
for (i = 0; i < h->num_frames; i++)
{
vec3_t mins, maxs;
mins[0] = LittleFloat(inbounds[i].bbmin[0]);
mins[1] = LittleFloat(inbounds[i].bbmin[1]);
mins[2] = LittleFloat(inbounds[i].bbmin[2]);
AddPointToBounds(mins, mod->mins, mod->maxs);
maxs[0] = LittleFloat(inbounds[i].bbmax[0]);
maxs[1] = LittleFloat(inbounds[i].bbmax[1]);
maxs[2] = LittleFloat(inbounds[i].bbmax[2]);
AddPointToBounds(maxs, mod->mins, mod->maxs);
}
//fixme: shouldn't really be needed for an animated model
for (i = 0; i < h->num_vertexes; i++)
AddPointToBounds(opos[i], mod->mins, mod->maxs);
for (i = 0; i < h->num_meshes; i++) for (i = 0; i < h->num_meshes; i++)
{ {
gai[i].nextsurf = (i == (h->num_meshes-1))?NULL:&gai[i+1]; gai[i].nextsurf = (i == (h->num_meshes-1))?NULL:&gai[i+1];
@ -6799,9 +6848,9 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
gai[i].ofs_indexes = idx; gai[i].ofs_indexes = idx;
for (t = 0; t < nt; t++) for (t = 0; t < nt; t++)
{ {
*idx++ = LittleShort(tris[t].vertex[0]) - offset; *idx++ = LittleLong(tris[t].vertex[0]) - offset;
*idx++ = LittleShort(tris[t].vertex[1]) - offset; *idx++ = LittleLong(tris[t].vertex[1]) - offset;
*idx++ = LittleShort(tris[t].vertex[2]) - offset; *idx++ = LittleLong(tris[t].vertex[2]) - offset;
} }
/*verts*/ /*verts*/
@ -6866,10 +6915,11 @@ qboolean Mod_ParseIQMAnim(char *buffer, galiasinfo_t *prototype, void**poseofs,
qboolean QDECL Mod_LoadInterQuakeModel(model_t *mod, void *buffer, size_t fsize) qboolean QDECL Mod_LoadInterQuakeModel(model_t *mod, void *buffer, size_t fsize)
{ {
int i;
galiasinfo_t *root; galiasinfo_t *root;
struct iqmheader *h = (struct iqmheader *)buffer; struct iqmheader *h = (struct iqmheader *)buffer;
ClearBounds(mod->mins, mod->maxs);
root = Mod_ParseIQMMeshModel(mod, buffer, fsize); root = Mod_ParseIQMMeshModel(mod, buffer, fsize);
if (!root) if (!root)
{ {
@ -6878,9 +6928,7 @@ qboolean QDECL Mod_LoadInterQuakeModel(model_t *mod, void *buffer, size_t fsize)
mod->flags = h->flags; mod->flags = h->flags;
ClearBounds(mod->mins, mod->maxs); mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
for (i = 0; i < root->numverts; i++)
AddPointToBounds(root->ofs_skel_xyz[i], mod->mins, mod->maxs);
Mod_ClampModelSize(mod); Mod_ClampModelSize(mod);

View file

@ -2545,6 +2545,7 @@ conchar_t q3codemasks[MAXQ3COLOURS] = {
//Converts a conchar_t string into a char string. returns the null terminator. pass NULL for stop to calc it //Converts a conchar_t string into a char string. returns the null terminator. pass NULL for stop to calc it
char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags) char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags)
{ {
unsigned int codeflags, codepoint;
if (!stop) if (!stop)
{ {
for (stop = str; *stop; stop++) for (stop = str; *stop; stop++)
@ -2575,12 +2576,13 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
fl = CON_WHITEMASK; fl = CON_WHITEMASK;
while(str < stop) while(str < stop)
{ {
if ((*str & CON_HIDDEN) && ignoreflags) str = Font_Decode(str, &codeflags, &codepoint);
if ((codeflags & CON_HIDDEN) && ignoreflags)
{ {
str++; str++;
continue; continue;
} }
if (*str == CON_LINKSTART) if (codeflags == (CON_LINKSPECIAL | CON_HIDDEN) && codepoint == '[')
{ {
if (!ignoreflags) if (!ignoreflags)
{ {
@ -2595,7 +2597,7 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
str++; str++;
continue; continue;
} }
else if (*str == CON_LINKEND) else if (codeflags == (CON_LINKSPECIAL | CON_HIDDEN) && codepoint == ']')
{ {
if (!ignoreflags) if (!ignoreflags)
{ {
@ -2609,9 +2611,9 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
str++; str++;
continue; continue;
} }
else if ((*str & CON_FLAGSMASK) != fl && !ignoreflags) else if (codeflags != fl && !ignoreflags)
{ {
d = fl^(*str & CON_FLAGSMASK); d = fl^codeflags;
// if (fl & CON_NONCLEARBG) //not represented. // if (fl & CON_NONCLEARBG) //not represented.
if (d & CON_BLINKTEXT) if (d & CON_BLINKTEXT)
{ {
@ -2644,15 +2646,15 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
0, 0, 0, 0, 0, 0, 0, 0,
0, '4', '2', '5', 0, '4', '2', '5',
'1', '6', '3', '7'}; '1', '6', '3', '7'};
if (!(d & (CON_BGMASK | CON_NONCLEARBG)) && q3[(*str & CON_FGMASK) >> CON_FGSHIFT] && !((d|fl) & CON_HALFALPHA)) if (!(d & (CON_BGMASK | CON_NONCLEARBG)) && q3[(codeflags & CON_FGMASK) >> CON_FGSHIFT] && !((d|fl) & CON_HALFALPHA))
{ {
if (outsize<=2) if (outsize<=2)
break; break;
outsize -= 2; outsize -= 2;
d = (*str & CON_FLAGSMASK); d = codeflags;
*out++ = '^'; *out++ = '^';
*out++ = q3[(*str & CON_FGMASK) >> CON_FGSHIFT]; *out++ = q3[(codeflags & CON_FGMASK) >> CON_FGSHIFT];
} }
else else
{ {
@ -2660,7 +2662,7 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
break; break;
outsize -= 4; outsize -= 4;
d = (*str & CON_FLAGSMASK); d = codeflags;
*out++ = '^'; *out++ = '^';
*out++ = '&'; *out++ = '&';
if ((d & CON_FGMASK) == CON_WHITEMASK) if ((d & CON_FGMASK) == CON_WHITEMASK)
@ -2676,14 +2678,14 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
} }
} }
fl = (*str & CON_FLAGSMASK); fl = codeflags;
} }
//don't magically show hidden text //don't magically show hidden text
if (ignoreflags && (*str & CON_HIDDEN)) if (ignoreflags && (codeflags & CON_HIDDEN))
continue; continue;
c = unicode_encode(out, (*str++ & CON_CHARMASK), outsize-1, !ignoreflags); c = unicode_encode(out, codepoint, outsize-1, !ignoreflags);
if (!c) if (!c)
break; break;
outsize -= c; outsize -= c;
@ -2979,10 +2981,18 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
} }
else else
{ {
if (uc > CON_CHARMASK) if (uc > 0x10ffff)
uc = 0xfffd; uc = 0xfffd;
if (!--outsize) if (!--outsize)
break; break;
if (uc > 0xffff)
{
if (!--outsize)
break;
*out++ = uc>>16 | CON_LONGCHAR | (ext & CON_HIDDEN);
uc &= 0xffff;
}
*out++ = uc | ext; *out++ = uc | ext;
str = end; str = end;
continue; continue;
@ -3156,11 +3166,18 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
if (str[len] == '}') if (str[len] == '}')
len++; len++;
if (uc > CON_CHARMASK) if (uc > 0x10ffff) //utf-16 imposes a limit on standard unicode codepoints (any encoding)
uc = 0xfffd; uc = 0xfffd;
if (!--outsize) if (!--outsize)
break; break;
if (uc > 0xffff) //utf-16 imposes a limit on standard unicode codepoints (any encoding)
{
if (!--outsize)
break;
*out++ = uc>>16 | CON_LONGCHAR | (ext & CON_HIDDEN);
uc &= 0xffff;
}
*out++ = uc | ext; *out++ = uc | ext;
str += len; str += len;

View file

@ -31,10 +31,12 @@ extern consolecolours_t consolecolours[MAXCONCOLOURS];
#define MAXQ3COLOURS 10 #define MAXQ3COLOURS 10
extern conchar_t q3codemasks[MAXQ3COLOURS]; extern conchar_t q3codemasks[MAXQ3COLOURS];
#define CON_LONGCHAR_MASK (CON_LONGCHAR|CON_RICHFORECOLOUR)
#define CON_NONCLEARBG 0x00800000 //disabled if CON_RICHFORECOLOUR #define CON_NONCLEARBG 0x00800000 //disabled if CON_RICHFORECOLOUR
#define CON_HALFALPHA 0x00400000 //disabled if CON_RICHFORECOLOUR #define CON_HALFALPHA 0x00400000 //disabled if CON_RICHFORECOLOUR
#define CON_LINKSPECIAL 0x00200000 //disabled if CON_RICHFORECOLOUR #define CON_LINKSPECIAL 0x00200000 //disabled if CON_RICHFORECOLOUR
#define CON_UNUSED1 0x00100000 //disabled if CON_RICHFORECOLOUR #define CON_LONGCHAR 0x00100000 //flags (other than hidden) are found in the following conchar. disabled if CON_RICHFORECOLOUR
#define CON_HIDDEN 0x00080000 #define CON_HIDDEN 0x00080000
#define CON_BLINKTEXT 0x00040000 #define CON_BLINKTEXT 0x00040000
#define CON_2NDCHARSETTEXT 0x00020000 #define CON_2NDCHARSETTEXT 0x00020000

View file

@ -1232,7 +1232,6 @@ qboolean Cvar_Command (int level)
char *str; char *str;
char buffer[65536]; char buffer[65536];
int olev; int olev;
int seat;
// check variables // check variables
v = Cvar_FindVar (Cmd_Argv(0)); v = Cvar_FindVar (Cmd_Argv(0));
@ -1301,9 +1300,9 @@ qboolean Cvar_Command (int level)
} }
#ifndef SERVERONLY #ifndef SERVERONLY
seat = CL_TargettedSplit(true);
if (v->flags & CVAR_USERINFO) if (v->flags & CVAR_USERINFO)
{ {
int seat = CL_TargettedSplit(true);
if (Cmd_FromGamecode() && cls.protocol == CP_QUAKEWORLD) if (Cmd_FromGamecode() && cls.protocol == CP_QUAKEWORLD)
{ //don't bother even changing the cvar locally, just update the server's version. { //don't bother even changing the cvar locally, just update the server's version.
//fixme: quake2/quake3 latching. //fixme: quake2/quake3 latching.

View file

@ -52,12 +52,6 @@ extern int
#endif #endif
rtqw_railtrail, //common to zquake/fuhquake/fte rtqw_railtrail, //common to zquake/fuhquake/fte
rtfte_lightning1,
ptfte_lightning1_end,
rtfte_lightning2,
ptfte_lightning2_end,
rtfte_lightning3,
ptfte_lightning3_end,
ptfte_bullet, ptfte_bullet,
ptfte_superbullet; ptfte_superbullet;

View file

@ -1207,12 +1207,14 @@ typedef struct q1usercmd_s
#define Q2RDF_IRGOGGLES (1u<<2) //ents with Q2RF_IR_VISIBLE show up pure red. #define Q2RDF_IRGOGGLES (1u<<2) //ents with Q2RF_IR_VISIBLE show up pure red.
#define Q2RDF_UVGOGGLES (1u<<3) //usused / reserved #define Q2RDF_UVGOGGLES (1u<<3) //usused / reserved
//ROGUE //ROGUE
#define RDF_BLOOM (1u<<16) #define RDF_BLOOM (1u<<16)
#define RDF_FISHEYE (1u<<17) #define RDF_FISHEYE (1u<<17)
#define RDF_WATERWARP (1u<<18) #define RDF_WATERWARP (1u<<18)
#define RDF_CUSTOMPOSTPROC (1u<<19) #define RDF_CUSTOMPOSTPROC (1u<<19)
#define RDF_ANTIALIAS (1u<<20) //fxaa, or possibly even just fsaa
#define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC) //these flags require rendering to an fbo for the various different post-processing shaders. #define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS) //these flags require rendering to an fbo for the various different post-processing shaders.

View file

@ -2859,6 +2859,7 @@ static void DrawPass(const shaderpass_t *pass)
//second pass should be an ADD //second pass should be an ADD
//this depends upon rgbgens for light levels, so each pass *must* be pushed to hardware individually //this depends upon rgbgens for light levels, so each pass *must* be pushed to hardware individually
#if MAXRLIGHTMAPS > 1
for (j = 1; j < MAXRLIGHTMAPS && shaderstate.curbatch->lightmap[j] >= 0; j++) for (j = 1; j < MAXRLIGHTMAPS && shaderstate.curbatch->lightmap[j] >= 0; j++)
{ {
if (j == 1) if (j == 1)
@ -2901,6 +2902,7 @@ static void DrawPass(const shaderpass_t *pass)
tmu++; tmu++;
} }
#endif
//might need to break the pass here //might need to break the pass here
if (j > 1 && i != lastpass) if (j > 1 && i != lastpass)
@ -3211,6 +3213,24 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
qglUniform3fvARB(ph, 1, param4); qglUniform3fvARB(ph, 1, param4);
break; break;
case SP_SOURCESIZE:
if (shaderstate.tex_sourcecol)
{
param4[0] = shaderstate.tex_sourcecol->width;
param4[1] = shaderstate.tex_sourcecol->height;
}
else if (shaderstate.tex_sourcedepth)
{
param4[0] = shaderstate.tex_sourcedepth->width;
param4[1] = shaderstate.tex_sourcedepth->height;
}
else
{
param4[0] = 1;
param4[1] = 1;
}
qglUniform2fvARB(ph, 1, param4);
break;
case SP_RENDERTEXTURESCALE: case SP_RENDERTEXTURESCALE:
if (sh_config.texture_non_power_of_two_pic) if (sh_config.texture_non_power_of_two_pic)
{ {

View file

@ -46,13 +46,16 @@ http://prideout.net/archive/bloom/ contains some sample code
#include "glquake.h" #include "glquake.h"
cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects). Fractional values reduce the amount shown."); cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects). Fractional values reduce the amount shown.");
cvar_t r_bloom_filter = CVARD("r_bloom_filter", "0.7 0.7 0.7", "Controls how bright the image must get before it will bloom (3 separate values, in RGB order)."); cvar_t r_bloom_filter = CVARD("r_bloom_filter", "0.7 0.7 0.7", "Controls how bright the image must get before it will bloom (3 separate values, in RGB order).");
cvar_t r_bloom_scale = CVARD("r_bloom_scale", "0.5", "Controls the initial downscale size. Smaller values will bloom further but be more random."); cvar_t r_bloom_size = CVARD("r_bloom_size", "4", "Target bloom kernel size (assuming a video width of 320).");
cvar_t r_bloom_downsize = CVARD("r_bloom_downsize", "0", "Technically more correct with a value of 1, but you probably won't notice.");
cvar_t r_bloom_initialscale = CVARD("r_bloom_initialscale", "1", "Initial scaling factor for bloom. should be either 1 or 0.5");
static shader_t *bloomfilter; static shader_t *bloomfilter;
static shader_t *bloomrescale; static shader_t *bloomrescale;
static shader_t *bloomblur; static shader_t *bloomblur;
static shader_t *bloomfinal; static shader_t *bloomfinal;
#define MAXLEVELS 3 //presumably this could be up to 16, but that will be too expensive. #define MAXLEVELS 16
texid_t pingtex[2][MAXLEVELS]; texid_t pingtex[2][MAXLEVELS];
fbostate_t fbo_bloom; fbostate_t fbo_bloom;
static int scrwidth, scrheight; static int scrwidth, scrheight;
@ -78,24 +81,23 @@ void R_BloomRegister(void)
{ {
Cvar_Register (&r_bloom, "bloom"); Cvar_Register (&r_bloom, "bloom");
Cvar_Register (&r_bloom_filter, "bloom"); Cvar_Register (&r_bloom_filter, "bloom");
Cvar_Register (&r_bloom_scale, "bloom"); Cvar_Register (&r_bloom_size, "bloom");
Cvar_Register (&r_bloom_downsize, "bloom");
Cvar_Register (&r_bloom_initialscale, "bloom");
} }
static void R_SetupBloomTextures(int w, int h) static void R_SetupBloomTextures(int w, int h)
{ {
int i, j; int i, j;
char name[64]; if (w == scrwidth && h == scrheight && !r_bloom_initialscale.modified)
if (w == scrwidth && h == scrheight && !r_bloom_scale.modified)
return; return;
r_bloom_scale.modified = false; r_bloom_initialscale.modified = false;
scrwidth = w; scrwidth = w;
scrheight = h; scrheight = h;
//I'm depending on npot here //I'm depending on npot here
w *= r_bloom_scale.value; w *= r_bloom_initialscale.value;
h *= r_bloom_scale.value; h *= r_bloom_initialscale.value;
for (i = 0; i < MAXLEVELS; i++) for (i = 0; i < MAXLEVELS; i++)
{ {
w /= 2;
h /= 2;
/*I'm paranoid*/ /*I'm paranoid*/
if (w < 4) if (w < 4)
w = 4; w = 4;
@ -104,19 +106,19 @@ static void R_SetupBloomTextures(int w, int h)
texwidth[i] = w; texwidth[i] = w;
texheight[i] = h; texheight[i] = h;
w /= 2;
h /= 2;
} }
/*now create textures for each level*/ /*destroy textures for each level, to ensure they're created fresh as needed*/
for (j = 0; j < MAXLEVELS; j++) for (j = 0; j < MAXLEVELS; j++)
{ {
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
if (!TEXVALID(pingtex[i][j])) if (TEXVALID(pingtex[i][j]))
{ Image_UnloadTexture(pingtex[i][j]);
sprintf(name, "***bloom*%c*%i***", 'a'+i, j); pingtex[i][j] = r_nulltex;
TEXASSIGN(pingtex[i][j], Image_CreateTexture(name, NULL, IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR));
}
Image_Upload(pingtex[i][j], TF_RGBA32, NULL, NULL, texwidth[j], texheight[j], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR);
} }
} }
@ -162,9 +164,6 @@ static void R_SetupBloomTextures(int w, int h)
"map $upperoverlay\n" "map $upperoverlay\n"
"}\n" "}\n"
"}\n"); "}\n");
bloomfinal->defaulttextures->base = pingtex[0][0];
bloomfinal->defaulttextures->loweroverlay = pingtex[0][1];
bloomfinal->defaulttextures->upperoverlay = pingtex[0][2];
} }
qboolean R_CanBloom(void) qboolean R_CanBloom(void)
{ {
@ -184,6 +183,12 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h)
{ {
int i; int i;
int oldfbo = 0; int oldfbo = 0;
texid_t intex;
int pixels = 1;
int targetpixels = r_bloom_size.value * vid.pixelwidth / 320;
char name[64];
targetpixels *= r_bloom_initialscale.value;
/*whu?*/ /*whu?*/
if (!w || !h) if (!w || !h)
@ -192,52 +197,76 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h)
/*update textures if we need to resize them*/ /*update textures if we need to resize them*/
R_SetupBloomTextures(w, h); R_SetupBloomTextures(w, h);
for (i = 0; i < MAXLEVELS; i++) /*filter the screen into a downscaled image*/
if (!TEXVALID(pingtex[0][0]))
{ {
if (i == 0) sprintf(name, "***bloom*%c*%i***", 'a'+0, 0);
TEXASSIGN(pingtex[0][0], Image_CreateTexture(name, NULL, IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR));
Image_Upload(pingtex[0][0], TF_RGBA32, NULL, NULL, texwidth[0], texheight[0], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR);
}
oldfbo = GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][0], 1, r_nulltex, 0, 0, 0);
GLBE_FBO_Sources(source, r_nulltex);
qglViewport (0, 0, texwidth[0], texheight[0]);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomfilter);
intex = pingtex[0][0];
for (pixels = 1, i = 0; pixels < targetpixels && i < MAXLEVELS; i++, pixels <<= 1)
{
/*create any textures if they're not valid yet*/
if (!TEXVALID(pingtex[0][i]))
{ {
/*filter the screen into a downscaled image*/ sprintf(name, "***bloom*%c*%i***", 'a'+0, i);
oldfbo = GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][0], 1, r_nulltex, 0, 0, 0); TEXASSIGN(pingtex[0][i], Image_CreateTexture(name, NULL, IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR));
GLBE_FBO_Sources(source, r_nulltex); Image_Upload(pingtex[0][i], TF_RGBA32, NULL, NULL, texwidth[i], texheight[i], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR);
qglViewport (0, 0, texwidth[0], texheight[0]);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomfilter);
} }
else if (!TEXVALID(pingtex[1][i]))
{
sprintf(name, "***bloom*%c*%i***", 'a'+1, i);
TEXASSIGN(pingtex[1][i], Image_CreateTexture(name, NULL, IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR));
Image_Upload(pingtex[1][i], TF_RGBA32, NULL, NULL, texwidth[i], texheight[i], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR);
}
//downsize the blur, for added accuracy
if (i > 0 && r_bloom_downsize.ival)
{ {
/*simple downscale that multiple times*/ /*simple downscale that multiple times*/
GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][i], 1, r_nulltex, 0, 0, 0); GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][i], 1, r_nulltex, 0, 0, 0);
GLBE_FBO_Sources(pingtex[0][i-1], r_nulltex); GLBE_FBO_Sources(pingtex[0][i-1], r_nulltex);
qglViewport (0, 0, texwidth[i], texheight[i]); qglViewport (0, 0, texwidth[i], texheight[i]);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale);
intex = pingtex[0][i];
r_worldentity.glowmod[0] = 1.0 / intex->width;
} }
// } else
// for (i = 0; i < MAXLEVELS; i++) r_worldentity.glowmod[0] = 2.0 / intex->width;
// {
/*gaussian filter the mips to bloom more smoothly
the blur is done with two passes. first samples horizontally then vertically.
the 1.2 pixels thing gives us a 5*5 filter by weighting the edge accordingly
*/
r_worldentity.glowmod[0] = 1.2 / texwidth[i];
r_worldentity.glowmod[1] = 0; r_worldentity.glowmod[1] = 0;
GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[1][i], 1, r_nulltex, 0, 0, 0); GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[1][i], 1, r_nulltex, 0, 0, 0);
GLBE_FBO_Sources(pingtex[0][i], r_nulltex); GLBE_FBO_Sources(intex, r_nulltex);
qglViewport (0, 0, texwidth[i], texheight[i]); qglViewport (0, 0, pingtex[1][i]->width, pingtex[1][i]->height);
BE_SelectEntity(&r_worldentity); BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur);
r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 1.2 / texheight[i]; r_worldentity.glowmod[1] = 1.0 / pingtex[1][i]->height;
GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][i], 1, r_nulltex, 0, 0, 0); GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][i], 1, r_nulltex, 0, 0, 0);
GLBE_FBO_Sources(pingtex[1][i], r_nulltex); GLBE_FBO_Sources(pingtex[1][i], r_nulltex);
qglViewport (0, 0, texwidth[i], texheight[i]); qglViewport (0, 0, pingtex[0][i]->width, pingtex[0][i]->height);
BE_SelectEntity(&r_worldentity); BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur);
intex = pingtex[0][i];
} }
r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 0; r_worldentity.glowmod[1] = 0;
GL_Set2D(false); GL_Set2D(false);
bloomfinal->defaulttextures->base = intex;
bloomfinal->defaulttextures->loweroverlay = (i >= 2)?pingtex[0][i-2]:0;
bloomfinal->defaulttextures->upperoverlay = (i >= 3)?pingtex[0][i-3]:0;
/*combine them onto the screen*/ /*combine them onto the screen*/
GLBE_FBO_Pop(oldfbo); GLBE_FBO_Pop(oldfbo);
GLBE_FBO_Sources(source, r_nulltex); GLBE_FBO_Sources(source, r_nulltex);

View file

@ -17,11 +17,11 @@ void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx,
void Font_Transform(float vx, float vy, int *px, int *py); void Font_Transform(float vx, float vy, int *px, int *py);
int Font_CharHeight(void); int Font_CharHeight(void);
float Font_CharScaleHeight(void); float Font_CharScaleHeight(void);
int Font_CharWidth(unsigned int charcode); int Font_CharWidth(unsigned int charflags, unsigned int codepoint);
float Font_CharScaleWidth(unsigned int charcode); float Font_CharScaleWidth(unsigned int charflags, unsigned int codepoint);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode); int Font_CharEndCoord(struct font_s *font, int x, unsigned int charflags, unsigned int codepoint);
int Font_DrawChar(int px, int py, unsigned int charcode); int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint);
float Font_DrawScaleChar(float px, float py, unsigned int charcode); /*avoid using*/ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned int codepoint); /*avoid using*/
void Font_EndString(struct font_s *font); void Font_EndString(struct font_s *font);
int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends); int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends);
struct font_s *font_default; struct font_s *font_default;
@ -29,6 +29,10 @@ struct font_s *font_console;
struct font_s *font_tiny; struct font_s *font_tiny;
extern unsigned int r2d_be_flags; extern unsigned int r2d_be_flags;
//by adding 'extern' to one definition of a function in a translation unit, then the definition in that TU is NOT considered an inline definition. meaning non-inlined references in other TUs can link to it instead of their own if needed.
fte_inlinebody conchar_t *Font_Decode(conchar_t *start, unsigned int *codeflags, unsigned int *codepoint);
#ifdef AVAIL_FREETYPE #ifdef AVAIL_FREETYPE
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
@ -718,9 +722,15 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx)
} }
//obtains a cached char, null if not cached //obtains a cached char, null if not cached
static struct charcache_s *Font_GetChar(font_t *f, CHARIDXTYPE charidx) static struct charcache_s *Font_GetChar(font_t *f, unsigned int codepoint)
{ {
struct charcache_s *c = &f->chars[charidx]; CHARIDXTYPE charidx;
struct charcache_s *c;
if (codepoint > CON_CHARMASK)
charidx = 0xfffd;
else
charidx = codepoint;
c = &f->chars[charidx];
if (c->texplane == INVALIDPLANE) if (c->texplane == INVALIDPLANE)
{ {
if (charidx >= TRACKERFIRST && charidx < TRACKERFIRST+100) if (charidx >= TRACKERFIRST && charidx < TRACKERFIRST+100)
@ -1575,19 +1585,20 @@ float Font_CharScaleHeight(void)
This is where the character ends. This is where the character ends.
Note: this function supports tabs - x must always be based off 0, with Font_LineDraw actually used to draw the line. Note: this function supports tabs - x must always be based off 0, with Font_LineDraw actually used to draw the line.
*/ */
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode) int Font_CharEndCoord(struct font_s *font, int x, unsigned int charflags, unsigned int codepoint)
{ {
struct charcache_s *c; struct charcache_s *c;
#define TABWIDTH (8*20) #define TABWIDTH (8*20)
if (charcode&CON_HIDDEN) if (charflags&CON_HIDDEN)
return x; return x;
if ((charcode&CON_CHARMASK) == '\t') if (codepoint == '\t')
return x + ((TABWIDTH - (x % TABWIDTH)) % TABWIDTH); return x + ((TABWIDTH - (x % TABWIDTH)) % TABWIDTH);
if ((charcode & CON_2NDCHARSETTEXT) && font->alt) if ((charflags & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt; font = font->alt;
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK)); c = Font_GetChar(font, codepoint);
if (!c) if (!c)
{ {
return x+0; return x+0;
@ -1598,16 +1609,18 @@ int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode)
//obtains the width of a character from a given font. This is how wide it is. The next char should be drawn at x + result. //obtains the width of a character from a given font. This is how wide it is. The next char should be drawn at x + result.
//FIXME: this function cannot cope with tab and should not be used. //FIXME: this function cannot cope with tab and should not be used.
int Font_CharWidth(unsigned int charcode) int Font_CharWidth(unsigned int charflags, unsigned int codepoint)
{ {
struct charcache_s *c; struct charcache_s *c;
struct font_s *font = curfont; struct font_s *font = curfont;
if (charcode&CON_HIDDEN)
if (charflags&CON_HIDDEN)
return 0; return 0;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if ((charflags & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt; font = font->alt;
c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK)); c = Font_GetChar(curfont, codepoint);
if (!c) if (!c)
{ {
return 0; return 0;
@ -1618,16 +1631,17 @@ int Font_CharWidth(unsigned int charcode)
//obtains the width of a character from a given font. This is how wide it is. The next char should be drawn at x + result. //obtains the width of a character from a given font. This is how wide it is. The next char should be drawn at x + result.
//FIXME: this function cannot cope with tab and should not be used. //FIXME: this function cannot cope with tab and should not be used.
float Font_CharScaleWidth(unsigned int charcode) float Font_CharScaleWidth(unsigned int charflags, unsigned int codepoint)
{ {
struct charcache_s *c; struct charcache_s *c;
struct font_s *font = curfont; struct font_s *font = curfont;
if (charcode&CON_HIDDEN)
if (charflags&CON_HIDDEN)
return 0; return 0;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt) if ((charflags & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt; font = font->alt;
c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK)); c = Font_GetChar(curfont, codepoint);
if (!c) if (!c)
{ {
return 0; return 0;
@ -1636,6 +1650,29 @@ float Font_CharScaleWidth(unsigned int charcode)
return c->advance * curfont_scale[0]; return c->advance * curfont_scale[0];
} }
conchar_t *Font_DecodeReverse(conchar_t *start, conchar_t *stop, unsigned int *codeflags, unsigned int *codepoint)
{
if (start <= stop)
{
*codeflags = 0;
*codepoint = 0;
return stop;
}
start--;
if (start > stop && start[-1] & CON_LONGCHAR)
if (!(start[-1] & CON_RICHFORECOLOUR))
{
start--;
*codeflags = start[1];
*codepoint = ((start[0] & CON_CHARMASK)<<16) | (start[1] & CON_CHARMASK);
return start;
}
*codeflags = start[0];
*codepoint = start[0] & CON_CHARMASK;
return start;
}
//for a given font, calculate the line breaks and word wrapping for a block of text //for a given font, calculate the line breaks and word wrapping for a block of text
//start+end are the input string //start+end are the input string
//starts+ends are an array of line start and end points, which have maxlines elements. //starts+ends are an array of line start and end points, which have maxlines elements.
@ -1643,41 +1680,49 @@ float Font_CharScaleWidth(unsigned int charcode)
//maxpixelwidth is the width of the display area in pixels //maxpixelwidth is the width of the display area in pixels
int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends) int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends)
{ {
int l, bt; conchar_t *l, *bt, *n;
int px; int px;
int foundlines = 0; int foundlines = 0;
struct font_s *font = curfont; struct font_s *font = curfont;
unsigned int codeflags, codepoint;
while (start < end) while (start < end)
{ {
// scan the width of the line // scan the width of the line
for (px=0, l=0 ; px <= maxpixelwidth; ) for (px=0, l=start ; px <= maxpixelwidth; )
{ {
if (start+l >= end || (start[l]&(CON_CHARMASK|CON_HIDDEN)) == '\n' || (start[l]&(CON_CHARMASK|CON_HIDDEN)) == '\v') if (l >= end)
break; break;
px = Font_CharEndCoord(font, px, start[l]); n = Font_Decode(l, &codeflags, &codepoint);
l++; if (!(codeflags & CON_HIDDEN) && (codepoint == '\n' || codepoint == '\v'))
break;
px = Font_CharEndCoord(font, px, codeflags, codepoint);
l = n;
} }
//if we did get to the end //if we did get to the end
if (px > maxpixelwidth) if (px > maxpixelwidth)
{ {
bt = l; bt = l;
//backtrack until we find a space //backtrack until we find a space
while(l > 0 && (start[l-1]&CON_CHARMASK)>' ') for(;;)
{ {
l--; n = Font_DecodeReverse(l, start, &codeflags, &codepoint);
if (codepoint > ' ')
l = n;
else
break;
} }
if (l == 0 && bt>0) if (l == start && bt>start)
l = bt-1; l = Font_DecodeReverse(bt, start, &codeflags, &codepoint);
} }
starts[foundlines] = start; starts[foundlines] = start;
ends[foundlines] = start+l; ends[foundlines] = l;
foundlines++; foundlines++;
if (foundlines == maxlines) if (foundlines == maxlines)
break; break;
start+=l; start=l;
if (start == end) if (start == end)
break; break;
@ -1693,9 +1738,11 @@ int Font_LineWidth(conchar_t *start, conchar_t *end)
//fixme: does this do the right thing with tabs? //fixme: does this do the right thing with tabs?
int x = 0; int x = 0;
struct font_s *font = curfont; struct font_s *font = curfont;
unsigned int codeflags, codepoint;
for (; start < end; start++) for (; start < end; start++)
{ {
x = Font_CharEndCoord(font, x, *start); start = Font_Decode(start, &codeflags, &codepoint);
x = Font_CharEndCoord(font, x, codeflags, codepoint);
} }
return x; return x;
} }
@ -1703,9 +1750,11 @@ float Font_LineScaleWidth(conchar_t *start, conchar_t *end)
{ {
int x = 0; int x = 0;
struct font_s *font = curfont; struct font_s *font = curfont;
for (; start < end; start++) unsigned int codeflags, codepoint;
for (; start < end; start)
{ {
x = Font_CharEndCoord(font, x, *start); start = Font_Decode(start, &codeflags, &codepoint);
x = Font_CharEndCoord(font, x, codeflags, codepoint);
} }
return x * curfont_scale[0]; return x * curfont_scale[0];
} }
@ -1713,10 +1762,12 @@ void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end)
{ {
int lx = 0; int lx = 0;
struct font_s *font = curfont; struct font_s *font = curfont;
for (; start < end; start++) unsigned int codeflags, codepoint;
for (; start < end; )
{ {
Font_DrawChar(x+lx, y, *start); start = Font_Decode(start, &codeflags, &codepoint);
lx = Font_CharEndCoord(font, lx, *start); Font_DrawChar(x+lx, y, codeflags, codepoint);
lx = Font_CharEndCoord(font, lx, codeflags, codepoint);
} }
} }
@ -1747,7 +1798,7 @@ void Font_InvalidateColour(void)
} }
//draw a character from the current font at a pixel location. //draw a character from the current font at a pixel location.
int Font_DrawChar(int px, int py, unsigned int charcode) int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint)
{ {
struct charcache_s *c; struct charcache_s *c;
float s0, s1; float s0, s1;
@ -1762,30 +1813,30 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
#else #else
#define dxbias 0 #define dxbias 0
#endif #endif
if (charcode & CON_HIDDEN) if (charflags & CON_HIDDEN)
return px; return px;
if (charcode & CON_2NDCHARSETTEXT) if (charflags & CON_2NDCHARSETTEXT)
{ {
if (font->alt) if (font->alt)
{ {
font = font->alt; font = font->alt;
// charcode &= ~CON_2NDCHARSETTEXT; // charflags &= ~CON_2NDCHARSETTEXT;
} }
else if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff) else if ((codepoint) >= 0xe000 && (codepoint) <= 0xe0ff)
charcode &= ~CON_2NDCHARSETTEXT; //don't double-dip charflags &= ~CON_2NDCHARSETTEXT; //don't double-dip
} }
//crash if there is no current font. //crash if there is no current font.
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK)); c = Font_GetChar(font, codepoint);
if (!c) if (!c)
return px; return px;
nextx = px + c->advance; nextx = px + c->advance;
if ((charcode & CON_CHARMASK) == '\t') if (codepoint == '\t')
return px + ((TABWIDTH - (px % TABWIDTH)) % TABWIDTH); return px + ((TABWIDTH - (px % TABWIDTH)) % TABWIDTH);
if ((charcode & CON_CHARMASK) == ' ') if (codepoint == ' ')
return nextx; return nextx;
/* if (charcode & CON_BLINKTEXT) /* if (charcode & CON_BLINKTEXT)
@ -1795,9 +1846,9 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
return nextx; return nextx;
} }
*/ */
if (charcode & CON_RICHFORECOLOUR) if (charflags & CON_RICHFORECOLOUR)
{ {
col = charcode & (CON_2NDCHARSETTEXT|CON_BLINKTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT)); col = charflags & (CON_2NDCHARSETTEXT|CON_BLINKTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
if (col != font_colourmask) if (col != font_colourmask)
{ {
vec4_t rgba; vec4_t rgba;
@ -1814,7 +1865,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
font_backcolour[1] = 0; font_backcolour[1] = 0;
font_backcolour[2] = 0; font_backcolour[2] = 0;
font_backcolour[3] = 0; font_backcolour[3] = 0;
if (charcode & CON_2NDCHARSETTEXT) if (charflags & CON_2NDCHARSETTEXT)
{ {
rgba[0] *= font->alttint[0]; rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1]; rgba[1] *= font->alttint[1];
@ -1830,7 +1881,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
rgba[1] *= font_foretint[1]; rgba[1] *= font_foretint[1];
rgba[2] *= font_foretint[2]; rgba[2] *= font_foretint[2];
rgba[3] *= font_foretint[3]; rgba[3] *= font_foretint[3];
if (charcode & CON_BLINKTEXT) if (charflags & CON_BLINKTEXT)
{ {
float a = (sin(realtime*3)+1)*0.4 + 0.2; float a = (sin(realtime*3)+1)*0.4 + 0.2;
rgba[3] *= a; rgba[3] *= a;
@ -1843,7 +1894,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
} }
else else
{ {
col = charcode & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA|CON_BLINKTEXT); col = charflags & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA|CON_BLINKTEXT);
if (col != font_colourmask) if (col != font_colourmask)
{ {
vec4_t rgba; vec4_t rgba;
@ -1851,19 +1902,19 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
Font_Flush(); Font_Flush();
font_colourmask = col; font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT; col = (charflags&CON_FGMASK)>>CON_FGSHIFT;
rgba[0] = consolecolours[col].fr*255; rgba[0] = consolecolours[col].fr*255;
rgba[1] = consolecolours[col].fg*255; rgba[1] = consolecolours[col].fg*255;
rgba[2] = consolecolours[col].fb*255; rgba[2] = consolecolours[col].fb*255;
rgba[3] = (charcode & CON_HALFALPHA)?127:255; rgba[3] = (charflags & CON_HALFALPHA)?127:255;
col = (charcode&CON_BGMASK)>>CON_BGSHIFT; col = (charflags&CON_BGMASK)>>CON_BGSHIFT;
font_backcolour[0] = consolecolours[col].fr*255; font_backcolour[0] = consolecolours[col].fr*255;
font_backcolour[1] = consolecolours[col].fg*255; font_backcolour[1] = consolecolours[col].fg*255;
font_backcolour[2] = consolecolours[col].fb*255; font_backcolour[2] = consolecolours[col].fb*255;
font_backcolour[3] = (charcode & CON_NONCLEARBG)?127:0; font_backcolour[3] = (charflags & CON_NONCLEARBG)?127:0;
if (charcode & CON_2NDCHARSETTEXT) if (charflags & CON_2NDCHARSETTEXT)
{ {
rgba[0] *= font->alttint[0]; rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1]; rgba[1] *= font->alttint[1];
@ -1879,7 +1930,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
rgba[1] *= font_foretint[1]; rgba[1] *= font_foretint[1];
rgba[2] *= font_foretint[2]; rgba[2] *= font_foretint[2];
rgba[3] *= font_foretint[3]; rgba[3] *= font_foretint[3];
if (charcode & CON_BLINKTEXT) if (charflags & CON_BLINKTEXT)
{ {
float a = (sin(realtime*3)+1)*0.4 + 0.2; float a = (sin(realtime*3)+1)*0.4 + 0.2;
rgba[3] *= a; rgba[3] *= a;
@ -1968,7 +2019,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
} }
/*there is no sane way to make this pixel-correct*/ /*there is no sane way to make this pixel-correct*/
float Font_DrawScaleChar(float px, float py, unsigned int charcode) float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned int codepoint)
{ {
struct charcache_s *c; struct charcache_s *c;
float s0, s1; float s0, s1;
@ -1988,40 +2039,40 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
// if (!curfont_scaled) // if (!curfont_scaled)
// return Font_DrawChar(px, py, charcode); // return Font_DrawChar(px, py, charcode);
if (charcode & CON_2NDCHARSETTEXT) if (charflags & CON_2NDCHARSETTEXT)
{ {
if (font->alt) if (font->alt)
{ {
font = font->alt; font = font->alt;
charcode &= ~CON_2NDCHARSETTEXT; charflags &= ~CON_2NDCHARSETTEXT;
} }
else if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff) else if (codepoint >= 0xe000 && codepoint <= 0xe0ff)
charcode &= ~CON_2NDCHARSETTEXT; //don't double-dip charflags &= ~CON_2NDCHARSETTEXT; //don't double-dip
} }
cw = curfont_scale[0]; cw = curfont_scale[0];
ch = curfont_scale[1]; ch = curfont_scale[1];
//crash if there is no current font. //crash if there is no current font.
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK)); c = Font_GetChar(font, codepoint);
if (!c) if (!c)
return px; return px;
nextx = px + c->advance*cw; nextx = px + c->advance*cw;
if ((charcode & CON_CHARMASK) == ' ') if (codepoint == ' ')
return nextx; return nextx;
if (charcode & CON_BLINKTEXT) if (charflags & CON_BLINKTEXT)
{ {
if (!cl_noblink.ival) if (!cl_noblink.ival)
if ((int)(realtime*3) & 1) if ((int)(realtime*3) & 1)
return nextx; return nextx;
} }
if (charcode & CON_RICHFORECOLOUR) if (charflags & CON_RICHFORECOLOUR)
{ {
col = charcode & (CON_2NDCHARSETTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT)); col = charflags & (CON_2NDCHARSETTEXT|CON_RICHFORECOLOUR|(0xfff<<CON_RICHBSHIFT));
if (col != font_colourmask) if (col != font_colourmask)
{ {
vec4_t rgba; vec4_t rgba;
@ -2039,7 +2090,7 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
font_backcolour[2] = 0; font_backcolour[2] = 0;
font_backcolour[3] = 0; font_backcolour[3] = 0;
if (charcode & CON_2NDCHARSETTEXT) if (charflags & CON_2NDCHARSETTEXT)
{ {
rgba[0] *= font->alttint[0]; rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1]; rgba[1] *= font->alttint[1];
@ -2063,27 +2114,27 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
} }
else else
{ {
col = charcode & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA); col = charflags & (CON_2NDCHARSETTEXT|CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA);
if (col != font_colourmask) if (col != font_colourmask)
{ {
vec4_t rgba; vec4_t rgba;
if (font_backcolour[3] != ((charcode & CON_NONCLEARBG)?127:0)) if (font_backcolour[3] != ((charflags & CON_NONCLEARBG)?127:0))
Font_Flush(); Font_Flush();
font_colourmask = col; font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT; col = (charflags&CON_FGMASK)>>CON_FGSHIFT;
rgba[0] = consolecolours[col].fr*255; rgba[0] = consolecolours[col].fr*255;
rgba[1] = consolecolours[col].fg*255; rgba[1] = consolecolours[col].fg*255;
rgba[2] = consolecolours[col].fb*255; rgba[2] = consolecolours[col].fb*255;
rgba[3] = (charcode & CON_HALFALPHA)?127:255; rgba[3] = (charflags & CON_HALFALPHA)?127:255;
col = (charcode&CON_BGMASK)>>CON_BGSHIFT; col = (charflags&CON_BGMASK)>>CON_BGSHIFT;
font_backcolour[0] = consolecolours[col].fr*255; font_backcolour[0] = consolecolours[col].fr*255;
font_backcolour[1] = consolecolours[col].fg*255; font_backcolour[1] = consolecolours[col].fg*255;
font_backcolour[2] = consolecolours[col].fb*255; font_backcolour[2] = consolecolours[col].fb*255;
font_backcolour[3] = (charcode & CON_NONCLEARBG)?127:0; font_backcolour[3] = (charflags & CON_NONCLEARBG)?127:0;
if (charcode & CON_2NDCHARSETTEXT) if (charflags & CON_2NDCHARSETTEXT)
{ {
rgba[0] *= font->alttint[0]; rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1]; rgba[1] *= font->alttint[1];

View file

@ -125,7 +125,7 @@ static void Mod_MemList_f(void)
#ifndef SERVERONLY #ifndef SERVERONLY
static void Mod_BatchList_f(void) static void Mod_BatchList_f(void)
{ {
int m, i, lm; int m, i;
model_t *mod; model_t *mod;
batch_t *batch; batch_t *batch;
unsigned int count; unsigned int count;
@ -2441,7 +2441,7 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t *
out->firstedge = LittleLong(inl->firstedge); out->firstedge = LittleLong(inl->firstedge);
out->numedges = LittleLong(inl->numedges); out->numedges = LittleLong(inl->numedges);
tn = LittleLong (inl->texinfo); tn = LittleLong (inl->texinfo);
for (i=0 ; i<MAXRLIGHTMAPS ; i++) for (i=0 ; i<MAXQ1LIGHTMAPS ; i++)
out->styles[i] = inl->styles[i]; out->styles[i] = inl->styles[i];
lofs = LittleLong(inl->lightofs); lofs = LittleLong(inl->lightofs);
inl++; inl++;
@ -2453,7 +2453,7 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t *
out->firstedge = LittleLong(ins->firstedge); out->firstedge = LittleLong(ins->firstedge);
out->numedges = LittleShort(ins->numedges); out->numedges = LittleShort(ins->numedges);
tn = LittleShort (ins->texinfo); tn = LittleShort (ins->texinfo);
for (i=0 ; i<MAXRLIGHTMAPS ; i++) for (i=0 ; i<MAXQ1LIGHTMAPS ; i++)
out->styles[i] = ins->styles[i]; out->styles[i] = ins->styles[i];
lofs = LittleLong(ins->lightofs); lofs = LittleLong(ins->lightofs);
ins++; ins++;

View file

@ -56,12 +56,13 @@ extern cvar_t gl_part_flame;
extern cvar_t r_bloom; extern cvar_t r_bloom;
extern cvar_t r_wireframe_smooth; extern cvar_t r_wireframe_smooth;
cvar_t r_renderscale = CVARD("r_renderscale", "1", "Provides a way to enable subsampling or super-sampling");
cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0"); cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0");
cvar_t gl_finish = SCVAR("gl_finish","0"); cvar_t gl_finish = SCVAR("gl_finish","0");
cvar_t gl_dither = SCVAR("gl_dither", "1"); cvar_t gl_dither = SCVAR("gl_dither", "1");
extern cvar_t r_stereo_separation; extern cvar_t r_stereo_separation;
extern cvar_t r_stereo_method; extern cvar_t r_stereo_method;
extern cvar_t r_postprocshader; extern cvar_t r_postprocshader, r_fxaa;
extern cvar_t gl_screenangle; extern cvar_t gl_screenangle;
@ -87,6 +88,8 @@ cvar_t r_xflip = SCVAR("leftisright", "0");
extern cvar_t scr_fov; extern cvar_t scr_fov;
shader_t *scenepp_rescaled;
shader_t *scenepp_antialias;
shader_t *scenepp_waterwarp; shader_t *scenepp_waterwarp;
// post processing stuff // post processing stuff
@ -141,6 +144,23 @@ void GL_InitSceneProcessingShaders (void)
GL_InitSceneProcessingShaders_WaterWarp(); GL_InitSceneProcessingShaders_WaterWarp();
} }
scenepp_rescaled = R_RegisterShader("fte_rescaler", 0,
"{\n"
"program default2d\n"
"{\n"
"map $sourcecolour\n"
"}\n"
"}\n"
);
scenepp_antialias = R_RegisterShader("fte_ppantialias", 0,
"{\n"
"program fxaa\n"
"{\n"
"map $sourcecolour\n"
"}\n"
"}\n"
);
r_wireframe_smooth.modified = true; r_wireframe_smooth.modified = true;
gl_dither.modified = true; //fixme: bad place for this, but hey gl_dither.modified = true; //fixme: bad place for this, but hey
vid_srgb.modified = true; vid_srgb.modified = true;
@ -1641,13 +1661,13 @@ texid_t R_RenderPostProcess (texid_t sourcetex, int type, shader_t *shader, char
int h = (r_refdef.vrect.height * vid.pixelheight) / vid.height; int h = (r_refdef.vrect.height * vid.pixelheight) / vid.height;
sourcetex = R2D_RT_Configure(restexname, w, h, TF_RGBA32); sourcetex = R2D_RT_Configure(restexname, w, h, TF_RGBA32);
GLBE_FBO_Update(&fbo_postproc, 0, &sourcetex, 1, r_nulltex, w, h, 0); GLBE_FBO_Update(&fbo_postproc, 0, &sourcetex, 1, r_nulltex, w, h, 0);
R2D_ScalePic(0, vid.pixelheight-r_refdef.vrect.height, r_refdef.vrect.width, r_refdef.vrect.height, scenepp_waterwarp); R2D_ScalePic(0, vid.pixelheight-r_refdef.vrect.height, r_refdef.vrect.width, r_refdef.vrect.height, shader);
GLBE_RenderToTextureUpdate2d(true); GLBE_RenderToTextureUpdate2d(true);
} }
else else
{ //yay, dump it to the screen { //yay, dump it to the screen
//update stuff now that we're not rendering the 3d scene //update stuff now that we're not rendering the 3d scene
R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, scenepp_waterwarp); R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, shader);
} }
} }
@ -1667,6 +1687,7 @@ void GLR_RenderView (void)
double time1 = 0, time2; double time1 = 0, time2;
texid_t sourcetex = r_nulltex; texid_t sourcetex = r_nulltex;
shader_t *custompostproc = NULL; shader_t *custompostproc = NULL;
float renderscale = r_renderscale.value; //extreme, but whatever
checkglerror(); checkglerror();
@ -1721,6 +1742,9 @@ void GLR_RenderView (void)
r_refdef.flags |= RDF_CUSTOMPOSTPROC; r_refdef.flags |= RDF_CUSTOMPOSTPROC;
} }
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && r_fxaa.ival) //overlays will have problems.
r_refdef.flags |= RDF_ANTIALIAS;
//disable stuff if its simply not supported. //disable stuff if its simply not supported.
if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !sh_config.texture_non_power_of_two_pic) if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !sh_config.texture_non_power_of_two_pic)
r_refdef.flags &= ~(RDF_ALLPOSTPROC); //block all of this stuff r_refdef.flags &= ~(RDF_ALLPOSTPROC); //block all of this stuff
@ -1773,11 +1797,21 @@ void GLR_RenderView (void)
flags |= FBO_RB_DEPTH; flags |= FBO_RB_DEPTH;
GLBE_FBO_Update(&fbo_gameview, flags, col, mrt, depth, vid.fbpwidth, vid.fbpheight, 0); GLBE_FBO_Update(&fbo_gameview, flags, col, mrt, depth, vid.fbpwidth, vid.fbpheight, 0);
} }
else if (r_refdef.flags & (RDF_ALLPOSTPROC)) else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || renderscale != 1)
{ {
//the game needs to be drawn to a texture for post processing //the game needs to be drawn to a texture for post processing
vid.fbvwidth = vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width; vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width;
vid.fbvheight = vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height; vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height;
vid.fbpwidth *= renderscale;
vid.fbpheight *= renderscale;
//well... err... meh.
vid.fbpwidth = bound(1, vid.fbpwidth, sh_config.texture_maxsize);
vid.fbpheight = bound(1, vid.fbpheight, sh_config.texture_maxsize);
vid.fbvwidth = vid.fbpwidth;
vid.fbvheight = vid.fbpheight;
sourcetex = R2D_RT_Configure("rt/$lastgameview", vid.fbpwidth, vid.fbpheight, /*(r_refdef.flags&RDF_BLOOM)?TF_RGBA16F:*/TF_RGBA32); sourcetex = R2D_RT_Configure("rt/$lastgameview", vid.fbpwidth, vid.fbpheight, /*(r_refdef.flags&RDF_BLOOM)?TF_RGBA16F:*/TF_RGBA32);
@ -1861,10 +1895,19 @@ void GLR_RenderView (void)
// SCENE POST PROCESSING // SCENE POST PROCESSING
sourcetex = R_RenderPostProcess (sourcetex, RDF_WATERWARP, scenepp_waterwarp, "rt/$waterwarped"); if (renderscale != 1 && !(r_refdef.flags & RDF_ALLPOSTPROC))
sourcetex = R_RenderPostProcess (sourcetex, RDF_CUSTOMPOSTPROC, custompostproc, "rt/$postproced"); {
if (r_refdef.flags & RDF_BLOOM) GLBE_FBO_Sources(sourcetex, r_nulltex);
R_BloomBlend(sourcetex, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height); R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 1, 1, 0, scenepp_rescaled);
}
else
{
sourcetex = R_RenderPostProcess (sourcetex, RDF_WATERWARP, scenepp_waterwarp, "rt/$waterwarped");
sourcetex = R_RenderPostProcess (sourcetex, RDF_CUSTOMPOSTPROC, custompostproc, "rt/$postproced");
sourcetex = R_RenderPostProcess (sourcetex, RDF_ANTIALIAS, scenepp_antialias, "rt/$antialiased");
if (r_refdef.flags & RDF_BLOOM)
R_BloomBlend(sourcetex, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
}
GLBE_FBO_Sources(r_nulltex, r_nulltex); GLBE_FBO_Sources(r_nulltex, r_nulltex);

View file

@ -970,7 +970,9 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
"#define SKELETAL\n", "#define SKELETAL\n",
"#define FOG\n", "#define FOG\n",
"#define FRAMEBLEND\n", "#define FRAMEBLEND\n",
#if MAXRLIGHTMAPS > 1
"#define LIGHTSTYLED\n", "#define LIGHTSTYLED\n",
#endif
NULL NULL
}; };
#define MAXMODIFIERS 64 #define MAXMODIFIERS 64
@ -1340,9 +1342,10 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
initoffset = VFS_GETLEN(blobfile); initoffset = VFS_GETLEN(blobfile);
VFS_SEEK(blobfile, initoffset); VFS_SEEK(blobfile, initoffset);
} }
if (!sh_config.pCreateProgram(prog, name, p, ver, permutationdefines, script, tess?script:NULL, tess?script:NULL, geom?script:NULL, script, (p & PERMUTATION_SKELETAL)?true:onefailed, sh_config.pValidateProgram?NULL:blobfile)) #define SILENTPERMUTATIONS (developer.ival?0:PERMUTATION_SKELETAL)
if (!sh_config.pCreateProgram(prog, name, p, ver, permutationdefines, script, tess?script:NULL, tess?script:NULL, geom?script:NULL, script, (p & SILENTPERMUTATIONS)?true:onefailed, sh_config.pValidateProgram?NULL:blobfile))
{ {
if (!(p & PERMUTATION_SKELETAL)) if (!(p & SILENTPERMUTATIONS))
onefailed = true; //don't flag it if skeletal failed. onefailed = true; //don't flag it if skeletal failed.
if (!p) //give up if permutation 0 failed. that one failing is fatal. if (!p) //give up if permutation 0 failed. that one failing is fatal.
break; break;
@ -1672,6 +1675,7 @@ struct shader_field_names_s shader_unif_names[] =
{"l_shadowmapproj", SP_LIGHTSHADOWMAPPROJ}, {"l_shadowmapproj", SP_LIGHTSHADOWMAPPROJ},
{"l_shadowmapscale", SP_LIGHTSHADOWMAPSCALE}, {"l_shadowmapscale", SP_LIGHTSHADOWMAPSCALE},
{"e_sourcesize", SP_SOURCESIZE},
{"e_rendertexturescale", SP_RENDERTEXTURESCALE}, {"e_rendertexturescale", SP_RENDERTEXTURESCALE},
{NULL} {NULL}
}; };

View file

@ -3421,6 +3421,9 @@ void Sh_CalcPointLight(vec3_t point, vec3_t light)
if (!(dl->flags & ignoreflags)) if (!(dl->flags & ignoreflags))
continue; continue;
if (dl->key == cl.playerview[0].viewentity) //ignore the light if its emitting from the player. generally the player can't *SEE* that light so it still counts.
continue; //disable this check if this function gets used for anything other than iris adaptation
colour[0] = dl->color[0]; colour[0] = dl->color[0];
colour[1] = dl->color[1]; colour[1] = dl->color[1];
colour[2] = dl->color[2]; colour[2] = dl->color[2];

View file

@ -1139,12 +1139,12 @@ static const char *glsl_hdrs[] =
"uniform sampler2D s_reflectmask;\n" "uniform sampler2D s_reflectmask;\n"
"uniform sampler2D s_lightmap;\n" "uniform sampler2D s_lightmap;\n"
"uniform sampler2D s_deluxmap;\n" "uniform sampler2D s_deluxmap;\n"
#if MAXRLIGHTMAPS > 1
"#define s_lightmap0 s_lightmap\n" "#define s_lightmap0 s_lightmap\n"
"#define s_deluxmap0 s_deluxmap\n"
#if MAXRLIGHTMAPS > 1
"uniform sampler2D s_lightmap1;\n" "uniform sampler2D s_lightmap1;\n"
"uniform sampler2D s_lightmap2;\n" "uniform sampler2D s_lightmap2;\n"
"uniform sampler2D s_lightmap3;\n" "uniform sampler2D s_lightmap3;\n"
"#define s_deluxmap0 s_deluxmap\n"
"uniform sampler2D s_deluxmap1;\n" "uniform sampler2D s_deluxmap1;\n"
"uniform sampler2D s_deluxmap2;\n" "uniform sampler2D s_deluxmap2;\n"
"uniform sampler2D s_deluxmap3;\n" "uniform sampler2D s_deluxmap3;\n"
@ -1205,11 +1205,13 @@ static const char *glsl_hdrs[] =
"uniform mat4 m_modelview;\n" "uniform mat4 m_modelview;\n"
"uniform mat4 m_projection;\n" "uniform mat4 m_projection;\n"
// "uniform mat4 m_modelviewprojection;\n" // "uniform mat4 m_modelviewprojection;\n"
"#ifdef SKELETAL\n" //skeletal permutation tends to require glsl 120
#ifdef GLESONLY #ifdef GLESONLY
"uniform vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n" "uniform vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n"
#else #else
"uniform mat4 m_bones["STRINGIFY(MAX_GPU_BONES)"];\n" "uniform mat3x4 m_bones["STRINGIFY(MAX_GPU_BONES)"];\n"
#endif #endif
"#endif\n"
"uniform mat4 m_invviewprojection;\n" "uniform mat4 m_invviewprojection;\n"
"uniform mat4 m_invmodelviewprojection;\n" "uniform mat4 m_invmodelviewprojection;\n"
@ -1920,6 +1922,7 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
char *typedesc; char *typedesc;
char str[8192]; char str[8192];
*str = 0;
qglGetShaderInfoLog_(shader, sizeof(str), NULL, str); qglGetShaderInfoLog_(shader, sizeof(str), NULL, str);
if (!silent) if (!silent)
{ {

View file

@ -324,8 +324,10 @@ enum{
PERMUTATION_FRAMEBLEND = 64, PERMUTATION_FRAMEBLEND = 64,
#if MAXRLIGHTMAPS > 1 #if MAXRLIGHTMAPS > 1
PERMUTATION_LIGHTSTYLES = 128, //FIXME: make argument PERMUTATION_LIGHTSTYLES = 128, //FIXME: make argument
#endif
PERMUTATIONS = 256 PERMUTATIONS = 256
#else
PERMUTATIONS = 128
#endif
}; };
enum shaderattribs_e enum shaderattribs_e
@ -399,6 +401,7 @@ typedef struct {
SP_M_INVMODELVIEWPROJECTION, SP_M_INVMODELVIEWPROJECTION,
SP_RENDERTEXTURESCALE, /*multiplier for currentrender->texcoord*/ SP_RENDERTEXTURESCALE, /*multiplier for currentrender->texcoord*/
SP_SOURCESIZE, /*size of $sourcecolour*/
SP_LIGHTRADIUS, /*these light values are realtime lighting*/ SP_LIGHTRADIUS, /*these light values are realtime lighting*/
SP_LIGHTCOLOUR, SP_LIGHTCOLOUR,

View file

@ -206,7 +206,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldentity(tag_entity,NULL)\ comfieldentity(tag_entity,NULL)\
comfieldfloat(tag_index,NULL)\ comfieldfloat(tag_index,NULL)\
comfieldfloat(skeletonindex,"This object serves as a container for the skeletal bone states used to override the animation data.") /*FTE_CSQC_SKELETONOBJECTS*/\ comfieldfloat(skeletonindex,"This object serves as a container for the skeletal bone states used to override the animation data.") /*FTE_CSQC_SKELETONOBJECTS*/\
comfieldvector(colormod,NULL)\ comfieldvector(colormod,"Provides a colour tint for the entity.")\
comfieldvector(glowmod,NULL)\ comfieldvector(glowmod,NULL)\
comfieldvector(gravitydir,"Specifies the direction in which gravity acts. Must be normalised. '0 0 0' also means down. Use '0 0 1' if you want the player to be able to run on ceilings.")\ comfieldvector(gravitydir,"Specifies the direction in which gravity acts. Must be normalised. '0 0 0' also means down. Use '0 0 1' if you want the player to be able to run on ceilings.")\
comfieldfunction(camera_transform,".vector(vector org, vector ang)", "Provides portal transform information for portal surfaces attached to this entity. Also used to open up pvs in ssqc.")\ comfieldfunction(camera_transform,".vector(vector org, vector ang)", "Provides portal transform information for portal surfaces attached to this entity. Also used to open up pvs in ssqc.")\

View file

@ -1,4 +1,5 @@
!!cvarf r_bloom !!cvarf r_bloom
!!cvarf r_bloom_retain=1.0
//add them together //add them together
//optionally apply tonemapping //optionally apply tonemapping
@ -18,10 +19,11 @@ uniform sampler2D s_t1;
uniform sampler2D s_t2; uniform sampler2D s_t2;
uniform sampler2D s_t3; uniform sampler2D s_t3;
uniform float cvar_r_bloom; uniform float cvar_r_bloom;
uniform float cvar_r_bloom_retain;
void main () void main ()
{ {
gl_FragColor = gl_FragColor =
texture2D(s_t0, tc) + cvar_r_bloom_retain * texture2D(s_t0, tc) +
cvar_r_bloom*( cvar_r_bloom*(
texture2D(s_t1, tc) + texture2D(s_t1, tc) +
texture2D(s_t2, tc) + texture2D(s_t2, tc) +

View file

@ -0,0 +1,73 @@
/*
This shader implements super-sampled anti-aliasing.
*/
varying vec2 texcoord;
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
void main()
{
texcoord = v_texcoord.xy;
texcoord.y = 1.0 - texcoord.y;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
uniform vec2 e_sourcesize;
void main( void )
{
//gl_FragColor.xyz = texture2D(buf0,texcoord).xyz;
//return;
float FXAA_SPAN_MAX = 8.0;
float FXAA_REDUCE_MUL = 1.0/8.0;
float FXAA_REDUCE_MIN = 1.0/128.0;
vec3 rgbNW=texture2D(s_t0,texcoord+(vec2(-1.0,-1.0)/e_sourcesize)).xyz;
vec3 rgbNE=texture2D(s_t0,texcoord+(vec2(1.0,-1.0)/e_sourcesize)).xyz;
vec3 rgbSW=texture2D(s_t0,texcoord+(vec2(-1.0,1.0)/e_sourcesize)).xyz;
vec3 rgbSE=texture2D(s_t0,texcoord+(vec2(1.0,1.0)/e_sourcesize)).xyz;
vec3 rgbM=texture2D(s_t0,texcoord).xyz;
vec3 luma=vec3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
float lumaNE = dot(rgbNE, luma);
float lumaSW = dot(rgbSW, luma);
float lumaSE = dot(rgbSE, luma);
float lumaM = dot(rgbM, luma);
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
vec2 dir;
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
float dirReduce = max(
(lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
FXAA_REDUCE_MIN);
float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
dir * rcpDirMin)) / e_sourcesize;
vec3 rgbA = (1.0/2.0) * (
texture2D(s_t0, texcoord.xy + dir * (1.0/3.0 - 0.5)).xyz +
texture2D(s_t0, texcoord.xy + dir * (2.0/3.0 - 0.5)).xyz);
vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
texture2D(s_t0, texcoord.xy + dir * (0.0/3.0 - 0.5)).xyz +
texture2D(s_t0, texcoord.xy + dir * (3.0/3.0 - 0.5)).xyz);
float lumaB = dot(rgbB, luma);
if((lumaB < lumaMin) || (lumaB > lumaMax)){
gl_FragColor.xyz=rgbA;
}else{
gl_FragColor.xyz=rgbB;
}
}
#endif