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.
Key_Dest_Remove(kdm_console);
Key_Dest_Remove(kdm_menu);
Key_Dest_Remove(kdm_gmenu);
Key_Dest_Remove(kdm_emenu);
scr_con_current = 0;
}
@ -2031,7 +2032,7 @@ void CL_QTVPoll (void)
if (!sourcesmenu)
{
m_state = m_complex;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
sourcesmenu = M_CreateMenu(0);
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)
{
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
{
CL_ResetFog();
@ -3923,7 +3923,7 @@ void CL_Init (void)
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 ("pause", NULL);
Cmd_AddCommand ("say", CL_Say_f);
@ -4729,7 +4729,8 @@ double Host_Frame (double time)
#ifdef VM_UI
UI_MenuState() != 0 ||
#endif
Key_Dest_Has(kdm_menu) ||
Key_Dest_Has(kdm_gmenu) ||
Key_Dest_Has(kdm_emenu) ||
Key_Dest_Has(kdm_editor) ||
#ifdef _WIN32
!ActiveApp ||
@ -5052,7 +5053,9 @@ void CL_StartCinematicOrMenu(void)
UI_Start();
#endif
#ifdef MENU_DAT
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 ":"");

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

View File

@ -703,13 +703,10 @@ void SCR_DrawCursor(void)
//choose the cursor based upon the module that has primary focus
if (key_dest_mask & key_dest_absolutemouse & (kdm_console|kdm_cwindows|kdm_editor))
cmod = kc_console;
else if ((key_dest_mask & key_dest_absolutemouse & kdm_menu))
{
if (m_state == m_menu_dat)
cmod = kc_menu;
else
cmod = kc_console;
}
else if ((key_dest_mask & key_dest_absolutemouse & kdm_emenu))
cmod = kc_console;
else if ((key_dest_mask & key_dest_absolutemouse & kdm_gmenu))
cmod = kc_menu;
else// if (key_dest_mask & key_dest_absolutemouse)
cmod = prydoncursornum?kc_console:kc_game;
@ -778,9 +775,9 @@ void SCR_DrawCursor(void)
{
float 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;
Font_DrawScaleChar(x, y, '+' | 0xe000 | CON_WHITEMASK);
Font_DrawScaleChar(x, y, CON_WHITEMASK, '+' | 0xe000);
Font_EndString(font_default);
}
}
@ -793,9 +790,9 @@ static void SCR_DrawSimMTouchCursor(void)
if (multicursor_active[i])
{
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;
Font_DrawScaleChar(x, y, '+' | 0xe000 | CON_WHITEMASK);
Font_DrawScaleChar(x, y, CON_WHITEMASK, '+' | 0xe000);
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);
}
//FIXME: no support for UTF-8 input
void SCR_StringXY(char *str, float x, float y)
{
char *s2;
@ -1392,14 +1390,14 @@ void SCR_StringXY(char *str, float x, float y)
if (x < 0)
{
for (s2 = str; *s2; s2++)
px -= Font_CharWidth(*s2);
px -= Font_CharWidth(CON_WHITEMASK, *s2);
}
if (y < 0)
py += y*Font_CharHeight();
while (*str)
px = Font_DrawChar(px, py, CON_WHITEMASK|*str++);
px = Font_DrawChar(px, py, CON_WHITEMASK, *str++);
Font_EndString(font_default);
}
@ -1568,7 +1566,7 @@ void SCR_DrawPause (void)
if (!cl.paused)
return;
if (Key_Dest_Has(kdm_menu))
if (Key_Dest_Has(kdm_emenu) || Key_Dest_Has(kdm_gmenu))
return;
pic = R2D_SafeCachePic ("gfx/pause.lmp");
@ -1911,7 +1909,7 @@ void SCR_SetUpToDrawConsole (void)
// Key_Dest_Add(kdm_console);
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
if (con_curwindow && !cls.state)
@ -1996,7 +1994,7 @@ void SCR_DrawConsole (qboolean noback)
{
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
}
if (scr_con_current || Key_Dest_Has(kdm_cwindows))
@ -2574,10 +2572,10 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
if (!consolefocused)
SCR_DrawConsole (false);
M_Draw (uimenu);
#ifdef MENU_DAT
MP_Draw();
#endif
M_Draw (uimenu);
//but if the console IS focused, then always show it infront.
if (consolefocused)

View File

@ -244,30 +244,39 @@ int
rtq2_grenade=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_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
{
tentmodels_t *info;
int entity;
short tag;
qbyte active;
// short pad;
// qbyte pad;
qbyte bflags;
qbyte type;
qbyte skin;
unsigned int rflags;
struct model_s *model;
float endtime;
float alpha;
vec3_t start, end;
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 *emitstate;
} beam_t;
@ -305,6 +314,30 @@ int cl_explosions_max;
static int explosions_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_knighthit;
sfx_t *cl_sfx_tink1;
@ -578,16 +611,22 @@ void CL_RegisterParticles(void)
#endif
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_superbullet = P_FindParticleType("TE_SUPERBULLET");
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
@ -595,24 +634,16 @@ enum {
q2cl_mod_explode,
q2cl_mod_smoke,
q2cl_mod_flash,
q2cl_mod_parasite_segment,
q2cl_mod_grapple_cable,
q2cl_mod_parasite_tip,
q2cl_mod_explo4,
q2cl_mod_bfg_explo,
q2cl_mod_powerscreen,
q2cl_mod_max
};
typedef struct {
char *modelname;
} tentmodels_t;
tentmodels_t q2tentmodels[q2cl_mod_max] = {
{"models/objects/explode/tris.md2"},
{"models/objects/smoke/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/objects/r_explode/tris.md2"},
{"sprites/s_bfg2.sp2"},
@ -726,7 +757,7 @@ explosion_t *CL_AllocExplosion (vec3_t org)
CL_ParseBeam
=================
*/
beam_t *CL_NewBeam (int entity, int tag)
beam_t *CL_NewBeam (int entity, int tag, tentmodels_t *btype)
{
beam_t *b;
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++)
if (b->entity == entity && b->tag == tag)
{
b->active = true;
b->info = btype;
return b;
}
}
@ -745,9 +776,9 @@ beam_t *CL_NewBeam (int entity, int tag)
// find a free beam
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;
}
}
@ -765,7 +796,7 @@ beam_t *CL_NewBeam (int entity, int tag)
}
beams_running++;
cl_beams[i].active = true;
cl_beams[i].info = btype;
return &cl_beams[i];
}
@ -773,7 +804,7 @@ beam_t *CL_NewBeam (int entity, int tag)
}
#define STREAM_ATTACHED 16
#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;
@ -782,11 +813,11 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
int i;
vec3_t impact, normal;
vec3_t extra;
char *mname;
//zquake compat requires some parsing weirdness.
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.
{
// 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);
return;
}
default:
mname = "progs/bolt.mdl";
btype = rtfte_lightning1;
etype = ptfte_lightning1_end;
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.
{
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;
}
tent = BT_Q1BEAM;
break;
case 2:
mname = "progs/bolt3.mdl";
btype = rtfte_lightning3;
etype = ptfte_lightning3_end;
default:
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*/
if (ruleset_allow_particle_lightning.ival && btype >= 0)
m = NULL;
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)
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)
{
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->entity = ent;
b->model = m;
b->particleeffect = btype;
b->info = &beamtypes[tent];
b->tag = -1;
b->bflags |= /*STREAM_ATTACHED|*/1;
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);
}
}
void CL_ParseBeam (int tent)
void CL_ParseBeam (enum beamtype_e tent)
{
int ent;
vec3_t start, end;
@ -950,6 +952,7 @@ void CL_ParseStream (int type)
int tag;
float duration;
int skin;
tentmodels_t *info;
ent = MSGCL_ReadEntity();
flags = MSG_ReadByte();
@ -968,7 +971,47 @@ void CL_ParseStream (int type)
end[1] = 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)
{
Con_Printf ("beam list overflow!\n");
@ -979,8 +1022,6 @@ void CL_ParseStream (int type)
b->entity = ent;
b->tag = tag;
b->bflags = flags;
b->model = NULL;
b->particleeffect = -1;
b->endtime = cl.time + duration;
b->alpha = 1;
b->skin = skin;
@ -998,30 +1039,13 @@ void CL_ParseStream (int type)
}
}
//special handling...
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:
b->model = Mod_ForName("models/stsunsf1.mdl", MLV_WARN);
b->particleeffect = P_FindParticleType("te_stream_sunstaff1");
if (b->particleeffect < 0)
if (info->ef_beam == P_INVALID)
{
b2 = CL_NewBeam(ent, tag+128);
b2 = CL_NewBeam(ent, tag+128, &beamtypes[BT_H2SUNSTAFF1_SUB]);
if (b2)
{
P_DelinkTrailstate(&b2->trailstate);
@ -1029,37 +1053,12 @@ void CL_ParseStream (int type)
memcpy(b2, b, sizeof(*b2));
b2->trailstate = NULL;
b2->emitstate = NULL;
b2->model = Mod_ForName("models/stsunsf2.mdl", MLV_WARN);
b2->alpha = 0.5;
b2->rflags = RF_TRANSLUCENT|RF_NOSHADOW;
}
}
//FIXME: we don't add the blob corners+smoke
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;
case TE_LIGHTNING1: // lightning bolts
CL_ParseBeam (BT_Q1LIGHTNING1);
break;
case TE_LIGHTNING2: // lightning bolts
CL_ParseBeam (type - TE_LIGHTNING1);
CL_ParseBeam (BT_Q1LIGHTNING2);
break;
case TE_LIGHTNING3: // lightning bolts
CL_ParseBeam (2);
CL_ParseBeam (BT_Q1LIGHTNING3);
break;
case TE_LAVASPLASH:
@ -1546,7 +1547,7 @@ void CL_ParseTEnt (void)
break;
case TEQW_BEAM:
CL_ParseBeam (5);
CL_ParseBeam (BT_Q1BEAM);
break;
case TE_RAILTRAIL:
@ -2524,14 +2525,14 @@ void CLQ2_ParseTEnt (void)
case Q2TE_PARASITE_ATTACK:
case Q2TE_MEDIC_CABLE_ATTACK:
CL_ParseBeam (3);
CL_ParseBeam (BT_Q2PARASITE);
break;
case Q2TE_HEATBEAM:
case Q2TE_MONSTER_HEATBEAM:
CL_ParseBeam (6);
CL_ParseBeam (BT_Q2HEATBEAM);
break;
case Q2TE_GRAPPLE_CABLE:
CL_ParseBeam (4);
CL_ParseBeam (BT_Q2GRAPPLE);
MSG_ReadPos (pos);
break;
@ -2544,7 +2545,7 @@ void CLQ2_ParseTEnt (void)
pos2[0] = MSG_ReadCoord ();
pos2[1] = MSG_ReadCoord ();
pos2[2] = MSG_ReadCoord ();
CL_AddBeam(0, ent, pos, pos2);
CL_AddBeam(BT_Q1LIGHTNING1, ent, pos, pos2);
break;
@ -3407,13 +3408,15 @@ void CL_UpdateBeams (void)
float yaw, pitch;
float forward, offset;
int lastrunningbeam = -1;
tentmodels_t *type;
extern cvar_t cl_truelightning, v_viewheight;
// update lightning
for (bnum=0, b=cl_beams; bnum < beams_running; bnum++, b++)
{
if (!b->active)
type = b->info;
if (!type)
continue;
if (b->endtime < cl.time)
@ -3422,7 +3425,7 @@ void CL_UpdateBeams (void)
{ /*don't let lightning decay while paused*/
P_DelinkTrailstate(&b->trailstate);
P_DelinkTrailstate(&b->emitstate);
b->active = false;
b->info = NULL;
continue;
}
}
@ -3554,11 +3557,15 @@ void CL_UpdateBeams (void)
pitch += 360;
}
if (ruleset_allow_particle_lightning.ival || !b->model)
if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, b->entity, NULL, &b->trailstate))
if (ruleset_allow_particle_lightning.ival || !type->modelname)
if (type->ef_beam >= 0 && !P_ParticleTrail(b->start, b->end, type->ef_beam, b->entity, NULL, &b->trailstate))
continue;
if (!b->model)
continue;
if (!type->model)
{
type->model = type->modelname?Mod_ForName(type->modelname, MLV_WARN):NULL;
if (!type->model)
continue;
}
// add new entities for the lightning
VectorCopy (b->start, org);
@ -3579,7 +3586,7 @@ void CL_UpdateBeams (void)
if (!ent)
return;
VectorCopy (org, ent->origin);
ent->model = b->model;
ent->model = type->model;
ent->drawflags |= MLS_ABSLIGHT;
ent->abslight = 64 + 128 * bound(0, cl_shaftlight.value, 1);
ent->shaderRGBAf[3] = b->alpha;

View File

@ -1519,8 +1519,8 @@ void UI_Reset(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;
}
if (!uivm)

View File

@ -1033,7 +1033,30 @@ void CL_ParseTEnt (qboolean nqprot);
void CL_ParseTEnt (void);
#endif
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 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 *cchar;
qboolean cursorframe;
unsigned int codeflags, codepoint;
int x;
@ -1152,44 +1153,52 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y,
#endif
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
x = (right-left)/2 + left;
//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))
x = right - rhs - Font_CharWidth(0xe000|11|CON_WHITEMASK);
if (x < right-rhs - Font_CharWidth(CON_WHITEMASK, 0xe000|11))
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 (x > lhs + left)
x = lhs + left;
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;
Font_Decode(cursor, &codeflags, &codepoint);
if (cursorframe)
{
// extern cvar_t com_parseutf8;
// if (com_parseutf8.ival)
// Font_DrawChar(rhs, y, (*cursor&~(CON_BGMASK|CON_FGMASK)) | (COLOR_BLUE<<CON_BGSHIFT) | CON_NONCLEARBG | CON_WHITEMASK);
// else
Font_DrawChar(rhs, y, 0xe000|11|CON_WHITEMASK);
Font_DrawChar(rhs, y, CON_WHITEMASK, 0xe000|11);
}
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*/
@ -1261,6 +1270,7 @@ void Con_DrawNotifyOne (console_t *con)
int nx, y;
int nw;
int x;
unsigned int codeflags, codepoint;
int maxlines;
float t;
@ -1330,17 +1340,19 @@ void Con_DrawNotifyOne (console_t *con)
Font_ForceColour(1, 1, 1, alphas[lines]);
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);
}
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;
}
@ -1487,7 +1499,7 @@ static int Con_DrawProgress(int left, int right, int y)
extern int relitsurface;
#endif
conchar_t dlbar[1024];
conchar_t dlbar[1024], *chr;
unsigned char progresspercenttext[128];
char *progresstext = NULL;
char *txt;
@ -1495,6 +1507,7 @@ static int Con_DrawProgress(int left, int right, int y)
int i, j;
int barwidth, barleft;
float progresspercent = 0;
unsigned int codeflags, codepoint;
*progresspercenttext = 0;
// draw the download bar
@ -1564,9 +1577,10 @@ static int Con_DrawProgress(int left, int right, int y)
x = 0;
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++;
}
@ -1574,11 +1588,11 @@ static int Con_DrawProgress(int left, int right, int y)
if (x > (right - left)/3)
{
//truncate the file name and add ...
x += 3*Font_CharWidth('.'|CON_WHITEMASK);
while (x > (right - left)/3 && i > 0)
x += 3*Font_CharWidth(CON_WHITEMASK, '.');
while (x > (right - left)/3)
{
i--;
x -= Font_CharWidth(dlbar[i]);
chr = Font_DecodeReverse(chr, dlbar, &codeflags, &codepoint);
x -= Font_CharWidth(codeflags, codepoint);
}
dlbar[i++] = '.'|CON_WHITEMASK;
@ -1591,46 +1605,52 @@ static int Con_DrawProgress(int left, int right, int y)
//add a couple chars
dlbar[i] = ':'|CON_WHITEMASK;
x += Font_CharWidth(dlbar[i]);
x += Font_CharWidth(CON_WHITEMASK, ':');
i++;
dlbar[i] = ' '|CON_WHITEMASK;
x += Font_CharWidth(dlbar[i]);
x += Font_CharWidth(CON_WHITEMASK, ' ');
i++;
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]);
j++;
chr = Font_Decode(chr, &codeflags, &codepoint);
tw += Font_CharWidth(codeflags, codepoint);
}
barwidth = (right-left) - (x + tw);
//draw the right hand side
x = right - tw;
for (j = i; dlbar[j]; j++)
x = Font_DrawChar(x, y, dlbar[j]);
for (chr = &dlbar[i]; *chr; )
{
chr = Font_Decode(chr, &codeflags, &codepoint);
x = Font_DrawChar(x, y, codeflags, codepoint);
}
//draw the left hand side
x = left;
for (j = 0; j < i; j++)
x = Font_DrawChar(x, y, dlbar[j]);
for (chr = dlbar; chr < &dlbar[i]; )
{
chr = Font_Decode(chr, &codeflags, &codepoint);
x = Font_DrawChar(x, y, codeflags, codepoint);
}
//and in the middle we have lots of stuff
barwidth -= (Font_CharWidth(0xe080|CON_WHITEMASK) + Font_CharWidth(0xe082|CON_WHITEMASK));
x = Font_DrawChar(x, y, 0xe080|CON_WHITEMASK);
barwidth -= (Font_CharWidth(CON_WHITEMASK, 0xe080) + Font_CharWidth(CON_WHITEMASK, 0xe082));
x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe080);
barleft = x;
for(;;)
{
if (x + Font_CharWidth(0xe081|CON_WHITEMASK) > barleft+barwidth)
if (x + Font_CharWidth(CON_WHITEMASK, 0xe081) > barleft+barwidth)
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)
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();
}
@ -1646,6 +1666,7 @@ int Con_DrawAlternateConsoles(int lines)
int consshown = 0;
console_t *con = &con_main, *om = con_mouseover;
conchar_t buffer[512], *end, *start;
unsigned int codeflags, codepoint;
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);
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())
{
x = 0;
y += h;
}
for (lx = x, start = buffer; start < end; start++)
for (lx = x, start = buffer; start < end; )
{
Font_DrawChar(lx, y, *start);
lx = Font_CharEndCoord(font_console, lx, *start);
start = Font_Decode(start, &codeflags, &codepoint);
lx = Font_DrawChar(lx, y, codeflags, codepoint);
}
lx += 8;
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)
{
int linecount;
int linelength;
conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])];
conchar_t *s;
conchar_t *s, *e, *c;
int i;
int x;
int charh = Font_CharHeight();
unsigned int codeflags, codepoint;
if (l != con->completionline)
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;
// draw arrows to show the buffer is backscrolled
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)
@ -1860,7 +1882,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
while(linecount-- > 0)
{
s = starts[linecount];
linelength = ends[linecount] - s;
e = ends[linecount];
y -= Font_CharHeight();
@ -1877,12 +1899,15 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
int send;
sstart = sx+picw;
send = sstart;
for (i = 0; i < linelength; i++)
send = Font_CharEndCoord(font_console, send, s[i]);
for (c = s; c < e; )
{
c = Font_Decode(c, &codeflags, &codepoint);
send = Font_CharEndCoord(font_console, send, codeflags, codepoint);
}
//show something on blank lines
if (send == sstart)
send = Font_CharEndCoord(font_console, send, ' ');
send = Font_CharEndCoord(font_console, send, CON_WHITEMASK, ' ');
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
@ -1897,9 +1922,10 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
if (y+charh >= seley)
{
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)
break;
@ -1907,23 +1933,25 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
con->selendline = l;
if (s)
con->selendoffset = (s+i) - (conchar_t*)(l+1);
con->selendoffset = c - (conchar_t*)(l+1);
else
con->selendoffset = 0;
}
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)
break;
c = Font_Decode(c, &codeflags, &codepoint);
sstart = x;
}
con->selstartline = l;
if (s)
con->selstartoffset = (s+i) - (conchar_t*)(l+1);
con->selstartoffset = c - (conchar_t*)(l+1);
else
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);
x = sx + picw;
Font_LineDraw(x, y, s, s+linelength);
Font_LineDraw(x, y, s, e);
if (y < top)
break;
@ -2092,10 +2120,11 @@ void Con_DrawConsole (int lines, qboolean noback)
int i;
Font_BeginString(font_console, vid.width, lines, &x, &y);
y -= Font_CharHeight();
//assumption: version == ascii
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++)
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);

View File

@ -2036,7 +2036,7 @@ qboolean Key_MouseShouldBeFree(void)
// if (!ActiveApp)
// 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*/)
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))
Editor_Key (key, unicode);
#endif
else if (Key_Dest_Has(kdm_menu))
else if (Key_Dest_Has(kdm_emenu))
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))
Key_Dest_Remove(kdm_message);
else
@ -2219,8 +2223,12 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
Key_ConsoleRelease(con, key, unicode);
}
}
if (Key_Dest_Has(kdm_menu))
if (Key_Dest_Has(kdm_emenu))
M_Keyup (key, unicode);
#ifdef MENU_DAT
if (Key_Dest_Has(kdm_gmenu))
MP_Keyup (key, unicode);
#endif
#ifndef NOMEDIA
if (Media_PlayingFullScreen())
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;
}
#endif
if (Key_Dest_Has(kdm_menu))
if (Key_Dest_Has(kdm_emenu))
{
M_Keydown (key, unicode);
return;
}
#ifdef MENU_DAT
if (Key_Dest_Has(kdm_gmenu))
{
MP_Keydown (key, unicode);
return;
}
#endif
if (Key_Dest_Has(kdm_message))
{
Key_Message (key, unicode);

View File

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

View File

@ -763,7 +763,7 @@ void Menu_DownloadStuff_f (void)
menu_t *menu;
dlmenu_t *info;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
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;
x -= 8;
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;
for (i=0 ; i<SLIDER_RANGE ; i++)
x = Font_DrawChar(x, y, 0xe081 | CON_WHITEMASK);
Font_DrawChar(x, y, 0xe082 | CON_WHITEMASK);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(0xe083 | CON_WHITEMASK)/2, y, 0xe083 | CON_WHITEMASK);
x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe081);
Font_DrawChar(x, y, CON_WHITEMASK, 0xe082);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(CON_WHITEMASK, 0xe083)/2, y, CON_WHITEMASK, 0xe083);
Font_EndString(font_default);
}
break;
@ -1678,13 +1678,24 @@ void M_RemoveMenu (menu_t *menu)
currentmenu = firstmenu;
}
void M_RemoveAllMenus (void)
void M_RemoveAllMenus (qboolean leaveprompts)
{
if (!firstmenu)
return;
menu_t **link, *m;
while(firstmenu)
M_RemoveMenu(firstmenu);
for (link = &firstmenu; *link; )
{
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)
@ -1701,7 +1712,7 @@ void M_Complex_Draw(void)
if (!firstmenu)
{
Key_Dest_Remove(kdm_menu);
Key_Dest_Remove(kdm_emenu);
m_state = m_none;
return;
}
@ -2045,7 +2056,7 @@ qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos.
if (!CL_TryingToConnect())
return true;
Key_Dest_Remove(kdm_menu);
Key_Dest_Remove(kdm_emenu);
m_state = m_none;
/* 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)
{
m_state = m_complex;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0);
mainm->key = MC_Main_Key;
@ -2176,7 +2187,7 @@ void M_Menu_Main_f (void)
return;
m_state = m_complex;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0);
mainm->key = MC_Main_Key;
@ -2216,7 +2227,7 @@ void M_Menu_Main_f (void)
{
int y;
m_state = m_complex;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0);
p = R2D_SafeCachePic("gfx/ttl_main.lmp");
@ -2271,7 +2282,7 @@ void M_Menu_Main_f (void)
else
{
m_state = m_complex;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
mainm = M_CreateMenu(0);
p = R2D_SafeCachePic("gfx/ttl_main.lmp");

View File

@ -721,7 +721,7 @@ doconnect:
Cbuf_AddText("\n", RESTRICT_LOCAL);
M_RemoveAllMenus();
M_RemoveAllMenus(true);
return true;
}
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.
Key_Dest_Remove(kdm_console);
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
menu = M_CreateMenu(sizeof(serverlist_t));
@ -1229,7 +1229,7 @@ void M_QuickConnect_f(void)
menucustom_t *cust;
menu_t *menu;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
MasterInfo_Refresh();

View File

@ -8,8 +8,8 @@
#include "shader.h"
#if !defined(NOMEDIA)
#if defined(_WIN32) && !defined(WINRT)
#define WINAMP
#if defined(_WIN32) && !defined(WINRT) && !defined(NOMEDIAMENU)
//#define WINAMP
#endif
#if defined(_WIN32) && !defined(WINRT)
#define WINAVI
@ -22,6 +22,8 @@ typedef struct mediatrack_s{
int length;
struct mediatrack_s *next;
} mediatrack_t;
qboolean media_fadeout;
float media_fadeouttime;
static mediatrack_t currenttrack;
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));
fakecdactive = false;
media_playing = false;
#endif
S_Music_Clear(NULL);
media_fadeout = true;
media_fadeouttime = realtime;
#endif
}
//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
void M_Menu_Media_f (void)
{
Key_Dest_Add(kdm_menu);
m_state = m_media;
}
void Media_LoadTrackNames (char *listname);
#define MEDIA_MIN -8
#define MEDIA_VOLUME -8
#define MEDIA_REWIND -7
#define MEDIA_MIN -7
#define MEDIA_VOLUME -7
#define MEDIA_FASTFORWARD -6
#define MEDIA_CLEARLIST -5
#define MEDIA_ADDTRACK -4
@ -600,7 +650,7 @@ void Media_LoadTrackNames (char *listname);
#define MEDIA_SHUFFLE -2
#define MEDIA_REPEAT -1
void M_Media_Draw (void)
void M_Media_Draw (menu_t *menu)
{
mpic_t *p;
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))
p = R2D_SafeCachePic ("gfx/p_option.lmp");
if (p)
M_DrawScalePic ( (320-p->width)/2, 4, 144, 24, p);
if (!bgmvolume.value)
M_Print (12, 32, "Not playing - no volume");
else if (!*currenttrack.nicename)
@ -634,18 +681,18 @@ void M_Media_Draw (void)
M_Print (12, 40, currenttrack.nicename);
}
op = selectedoption - (vid.height-52)/16;
if (op + (vid.height-52)/8>numtracks)
op = numtracks - (vid.height-52)/8;
y=52;
op = selectedoption - (vid.height-y)/16;
if (op + (vid.height-y)/8>numtracks)
op = numtracks - (vid.height-y)/8;
if (op < MEDIA_MIN)
op = MEDIA_MIN;
y=52;
while(op < 0)
{
switch(op)
{
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;
break;
case MEDIA_CLEARLIST:
@ -653,11 +700,13 @@ void M_Media_Draw (void)
y+=8;
break;
case MEDIA_FASTFORWARD:
MP_Hightlight (12, y, ">> Fast Forward", op == selectedoption);
y+=8;
break;
case MEDIA_REWIND:
MP_Hightlight (12, y, "<< Rewind", op == selectedoption);
{
float time, duration;
if (S_GetMusicInfo(0, &time, &duration))
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);
else
MP_Hightlight (12, y, "<< skip >>", op == selectedoption);
}
y+=8;
break;
case MEDIA_ADDTRACK:
@ -713,7 +762,7 @@ void M_Media_Draw (void)
char compleatenamepath[MAX_OSPATH];
char compleatenamename[MAX_OSPATH];
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)
compleatenamemultiple = true;
@ -739,17 +788,12 @@ void Com_CompleateOSFileName(char *name)
strcpy(name, compleatenamename);
}
void M_Media_Key (int key)
qboolean M_Media_Key (int key, menu_t *menu)
{
int dir;
if (key == K_ESCAPE)
{
#ifndef NOBUILTINMENUS
M_Menu_Main_f();
#else
m_state = m_none;
Key_Dest_Remove(kdm_menu);
#endif
return false;
}
else if (key == K_RIGHTARROW || key == K_LEFTARROW)
{
@ -766,6 +810,9 @@ void M_Media_Key (int key)
bgmvolume.value = 1;
Cvar_SetValue (&bgmvolume, bgmvolume.value);
break;
case MEDIA_FASTFORWARD:
Media_Seek(15*dir);
break;
default:
if (selectedoption >= 0)
Media_Next_f();
@ -829,9 +876,6 @@ void M_Media_Key (int key)
case MEDIA_FASTFORWARD:
Media_Seek(15);
break;
case MEDIA_REWIND:
Media_Seek(-15);
break;
case MEDIA_CLEARLIST:
{
mediatrack_t *prevtrack;
@ -851,16 +895,9 @@ void M_Media_Key (int key)
break;
case MEDIA_ADDTRACK:
if (*media_iofilename)
{
mediatrack_t *newtrack;
newtrack = Z_Malloc(sizeof(mediatrack_t));
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++;
}
Media_AddTrack(media_iofilename);
else
Cmd_ExecuteString("menu_mediafiles", RESTRICT_LOCAL);
break;
case MEDIA_ADDLIST:
if (*media_iofilename)
@ -878,27 +915,34 @@ void M_Media_Key (int key)
media_playing = true;
nexttrack = selectedoption;
Media_Next_f();
return true;
}
break;
return false;
}
return true;
}
else
{
if (selectedoption == MEDIA_ADDLIST || selectedoption == MEDIA_ADDTRACK)
{
if (key == K_TAB)
{
Com_CompleateOSFileName(media_iofilename);
return true;
}
else if (key == K_BACKSPACE)
{
dir = strlen(media_iofilename);
if (dir)
media_iofilename[dir-1] = '\0';
return true;
}
else if ((key >= 'a' && key <= 'z') || (key >= '0' && key <= '9') || key == '/' || key == '_' || key == '.' || key == ':')
{
dir = strlen(media_iofilename);
media_iofilename[dir] = key;
media_iofilename[dir+1] = '\0';
return true;
}
}
else if (selectedoption>=0)
@ -915,25 +959,40 @@ void M_Media_Key (int key)
num++;
}
if (!tr)
return;
return false;
if (key == K_BACKSPACE)
{
dir = strlen(tr->nicename);
if (dir)
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 == '=')
{
dir = strlen(tr->nicename);
tr->nicename[dir] = key;
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 *trackname;
mediatrack_t *newtrack;
char *data = COM_LoadTempFile(listname);
size_t fsize;
char *data = COM_LoadTempFile(listname, &fsize);
loadedtracknames=true;
@ -1032,21 +1092,33 @@ void Media_LoadTrackNames (char *listname)
}
#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)
{
#ifdef WINAMP
if (media_hijackwinamp.value)
{
WinAmp_Think();
return NULL;
}
#endif
if (bgmvolume.value <= 0 || !media_playing)
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)
Media_EndedTrack();
media_fadeout = false;
#ifndef NOMEDIAMENU
if (!loadedtracknames)
@ -2274,11 +2346,13 @@ qboolean Media_PlayFilm(char *name, qboolean enqueue)
CDAudio_Stop();
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;
}
if (Key_Dest_Has(kdm_gmenu))
Key_Dest_Remove(kdm_gmenu); //FIXME
if (!Key_Dest_Has(kdm_console))
scr_con_current=0;
return true;
@ -3228,7 +3302,7 @@ void Media_RecordDemo_f(void)
Cmd_ShiftArgs(1, false);
Media_RecordFilm_f();
scr_con_current=0;
Key_Dest_Remove(kdm_console|kdm_menu);
Key_Dest_Remove(kdm_console|kdm_emenu|kdm_gmenu);
if (currentcapture_funcs)
recordingdemo = true;
@ -3981,6 +4055,9 @@ void Media_Init(void)
#endif
Cvar_Register(&media_shuffle, "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_RecordFilm_f (void){}
void M_Menu_Media_f (void) {}
float Media_CrossFade(int ch, float vol) {return vol;}
char *Media_NextTrack(int musicchannelnum) {return NULL;}
qboolean Media_PausedDemo(qboolean fortiming) {return false;}

View File

@ -18,7 +18,7 @@ void M_Menu_MultiPlayer_f (void)
static menuresel_t resel;
p = NULL;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
mgt = M_GameType();
@ -442,7 +442,7 @@ void M_Menu_Setup_f (void)
mpic_t *p;
menucustom_t *cu;
m_state = m_complex;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
menu = M_CreateMenu(sizeof(setupmenu_t));
info = menu->data;
@ -468,7 +468,7 @@ void M_Menu_Setup_f (void)
}
#endif
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
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);
}
M_RemoveAllMenus();
M_RemoveAllMenus(true);
return true;
}
@ -656,7 +656,7 @@ void M_Menu_GameOptions_f (void)
int mgt;
int players;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
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;
*y = 32;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
menu = M_CreateMenu(infosize);
@ -365,7 +365,7 @@ void M_Menu_Audio_Speakers_f (void)
audiomenuinfo_t *info;
menu_t *menu;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
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];
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]));
else
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;
menu_t *menu;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
menu = M_CreateMenu(sizeof(*mv));
mv = menu->data;
@ -2996,7 +2996,7 @@ void M_Menu_Mods_f (void)
}
else
{
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
menu = M_CreateMenu(sizeof(modmenu_t));
*(modmenu_t*)menu->data = mods;

View File

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

View File

@ -137,7 +137,7 @@ void M_Menu_Save_f (void)
if (cl.intermission)
return;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
@ -164,7 +164,7 @@ void M_Menu_Load_f (void)
menu_t *menu;
int i;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
@ -201,7 +201,7 @@ void M_Menu_SinglePlayer_f (void)
#endif
static menuresel_t resel;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
#ifdef CLIENTONLY
@ -565,6 +565,7 @@ static qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key, unsigned
ShowDemoMenu(menu, info->selected->name);
else
{
extern int shift_down;
int extnum;
for (extnum = 0; extnum < info->numext; 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;
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;
}
}
@ -832,7 +834,7 @@ void M_Menu_Demos_f (void)
menu_t *menu;
static demoloc_t mediareenterloc = {FS_GAME};
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
Key_Dest_Remove(kdm_console);
m_state = m_complex;
@ -885,7 +887,7 @@ void M_Menu_MediaFiles_f (void)
menu_t *menu;
static demoloc_t mediareenterloc = {FS_GAME};
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
menu = M_CreateMenu(sizeof(demomenu_t));
@ -893,19 +895,28 @@ void M_Menu_MediaFiles_f (void)
info = menu->data;
info->fs = &mediareenterloc;
info->numext = 0;
info->ext[0] = ".m3u";
info->command[0] = "mediaplaylist";
info->ext[1] = ".mp3";
info->command[1] = "mediaadd";
info->ext[2] = ".wav";
info->command[2] = "mediaadd";
info->ext[3] = ".ogg"; //will this ever be added properly?
info->command[3] = "mediaadd";
info->ext[4] = ".roq";
info->command[4] = "playfilm";
info->numext = 5;
info->ext[info->numext] = ".m3u";
info->command[info->numext] = "mediaplaylist";
info->numext++;
#if defined(_WIN32) || defined(FTE_TARGET_WEB)
info->ext[info->numext] = ".mp3";
info->command[info->numext] = "media_add";
info->numext++;
#endif
info->ext[info->numext] = ".wav";
info->command[info->numext] = "media_add";
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.
info->ext[info->numext] = ".avi";
info->command[info->numext] = "playfilm";

View File

@ -300,10 +300,10 @@ int m_save_demonum;
void M_CloseMenu_f (void)
{
if (!Key_Dest_Has(kdm_menu))
if (!Key_Dest_Has(kdm_emenu))
return;
M_RemoveAllMenus();
Key_Dest_Remove(kdm_menu);
M_RemoveAllMenus(false);
Key_Dest_Remove(kdm_emenu);
m_state = m_none;
}
/*
@ -315,7 +315,7 @@ void M_ToggleMenu_f (void)
{
if (m_state)
{
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
return;
}
@ -339,9 +339,9 @@ void M_ToggleMenu_f (void)
#endif
//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;
return;
}
@ -494,7 +494,7 @@ void M_Menu_Keys_f (void)
menu_t *menu;
vfsfile_t *bindslist;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_complex;
menu = M_CreateMenu(0);
@ -618,7 +618,7 @@ struct
void M_Menu_Help_f (void)
{
int i;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
m_state = m_help;
help_page = 0;
@ -734,7 +734,7 @@ void M_Menu_Prompt (void (*callback)(void *, int), void *ctx, char *m1, char *m2
promptmenu_t *m;
char *t;
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
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);
@ -1035,7 +1035,7 @@ void M_Menu_Quit_f (void)
#endif
break;
case 2:
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
Key_Dest_Remove(kdm_console);
m_state = m_complex;
@ -1059,7 +1059,7 @@ void M_Menu_Quit_f (void)
MC_AddBox (quitmenu, 56, 76, 25, 5);
break;
case 1:
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_emenu);
Key_Dest_Remove(kdm_console);
m_state = m_complex;
@ -1139,10 +1139,6 @@ void M_Init_Internal (void)
Cmd_AddCommand ("menu_keys", M_Menu_Keys_f);
Cmd_AddCommand ("help", M_Menu_Help_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 ("modelviewer", M_Menu_ModelViewer_f);
@ -1191,7 +1187,7 @@ void M_Init_Internal (void)
void M_DeInit_Internal (void)
{
M_RemoveAllMenus();
M_RemoveAllMenus(true);
if (!internalmenusregistered)
return;
@ -1208,10 +1204,6 @@ void M_DeInit_Internal (void)
Cmd_RemoveCommand ("menu_keys");
Cmd_RemoveCommand ("help");
Cmd_RemoveCommand ("menu_quit");
#ifndef NOMEDIAMENU
Cmd_RemoveCommand ("menu_media");
#endif
Cmd_RemoveCommand ("menu_mediafiles");
#ifdef CL_MASTER
Cmd_RemoveCommand ("menu_slist");
@ -1286,6 +1278,7 @@ void M_Init (void)
#endif
//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_mediafiles", M_Menu_MediaFiles_f);
@ -1341,18 +1334,18 @@ void M_Draw (int uimenu)
#ifndef NOBUILTINMENUS
if (m_state != m_complex)
{
M_RemoveAllMenus();
M_RemoveAllMenus(false);
menu_mousedown = false;
}
#endif
if (!Key_Dest_Has(kdm_menu))
if (!Key_Dest_Has(kdm_emenu))
{
m_state = m_none;
return;
}
if (m_state == m_none || m_state == m_menu_dat)
if (m_state == m_none)
return;
#ifndef NOBUILTINMENUS
@ -1388,21 +1381,10 @@ void M_Draw (int uimenu)
break;
#endif
#ifndef NOMEDIAMENU
case m_media:
M_Media_Draw ();
break;
#endif
#ifdef PLUGINS
case m_plugin:
Plug_Menu_Event (0, (int)(realtime*1000));
break;
#endif
#ifdef MENU_DAT
case m_menu_dat:
// MP_Draw();
return;
#endif
}
}
@ -1414,7 +1396,7 @@ void M_Keydown (int key, int unicode)
{
default:
case m_none:
Key_Dest_Remove(kdm_menu);
Key_Dest_Remove(kdm_emenu);
return;
#ifndef NOBUILTINMENUS
case m_help:
@ -1429,21 +1411,10 @@ void M_Keydown (int key, int unicode)
return;
#endif
#ifndef NOMEDIAMENU
case m_media:
M_Media_Key (key);
return;
#endif
#ifdef PLUGINS
case m_plugin:
Plug_Menu_Event (1, key);
return;
#endif
#ifdef MENU_DAT
case m_menu_dat:
MP_Keydown(key, unicode);
return;
#endif
}
}
@ -1464,11 +1435,6 @@ void M_Keyup (int key, int unicode)
case m_plugin:
Plug_Menu_Event (2, key);
return;
#endif
#ifdef MENU_DAT
case m_menu_dat:
MP_Keyup(key, unicode);
return;
#endif
default:
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_complex - hirachy of item types
//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_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.
@ -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;
void M_DrawTextBox (int x, int y, int width, int lines);
#define NOMEDIAMENU
#ifndef NOBUILTINMENUS
//
@ -380,7 +373,7 @@ void M_AddMenu (menu_t *menu);
void M_AddMenuFront (menu_t *menu);
void M_HideMenu (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_Draw(void);
@ -404,7 +397,6 @@ void M_Menu_LanConfig_f (void);
void M_Menu_GameOptions_f (void);
void M_Menu_Search_f (void);
void M_Menu_ServerList_f (void);
void M_Menu_Media_f (void);
/*
void M_Main_Draw (void);
@ -440,10 +432,6 @@ void M_Search_Key (int key);
void M_ServerList_Key (int key);
*/
void MasterInfo_Refresh(void);
void M_DrawServers(void);
void M_SListKey(int key);
//drawing funcs
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);
@ -471,9 +459,7 @@ void M_Draw (int uimenu);
void M_FindKeysForCommand (int pnum, const char *command, int *twokeys);
int M_FindKeysForBind (const char *command, int *keylist, int *keymods, int total);
void M_Media_Draw (void);
void M_Media_Key (int key);
#ifdef MENU_DAT
void MP_CvarChanged(cvar_t *var);
qboolean MP_Init (void);
void MP_Shutdown (void);
@ -483,6 +469,7 @@ void MP_RegisterCvarsAndCmds(void);
void MP_Keydown(int key, int unicode);
void MP_Keyup(int key, int unicode);
int MP_BuiltinValid(char *name, int num);
#endif
#define MGT_BAD ~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 *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)
{
@ -3675,7 +3675,7 @@ static void QCBUILTIN PF_cl_te_lightning2 (pubprogfuncs_t *prinst, struct global
float *start = G_VECTOR(OFS_PARM1);
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)
{
@ -3683,7 +3683,7 @@ static void QCBUILTIN PF_cl_te_lightning3 (pubprogfuncs_t *prinst, struct global
float *start = G_VECTOR(OFS_PARM1);
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)
{
@ -3691,7 +3691,7 @@ static void QCBUILTIN PF_cl_te_beam (pubprogfuncs_t *prinst, struct globalvars_s
float *start = G_VECTOR(OFS_PARM1);
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)
{

View File

@ -10,6 +10,8 @@
#if defined(MENU_DAT) || defined(CSQC_DAT)
#include "cl_master.h"
qbyte mpkeysdown[K_MAX/8];
extern unsigned int r2d_be_flags;
#define DRAWFLAG_NORMAL 0
#define DRAWFLAG_ADD 1
@ -391,6 +393,7 @@ void QCBUILTIN PF_CL_drawcolouredstring (pubprogfuncs_t *prinst, struct globalva
float flag = 0;
float r, g, b;
float px, py, ipx;
unsigned int codeflags, codepoint;
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);
while(*str)
{
if ((*str & CON_CHARMASK) == '\n')
str = Font_Decode(str, &codeflags, &codepoint);
if (codepoint == '\n')
py += Font_CharHeight();
else if ((*str & CON_CHARMASK) == '\r')
else if (codepoint == '\r')
px = ipx;
else
px = Font_DrawScaleChar(px, py, *str);
str++;
px = Font_DrawScaleChar(px, py, codeflags, codepoint);
}
Font_InvalidateColour();
Font_EndString(NULL);
@ -682,7 +685,7 @@ void QCBUILTIN PF_CL_drawcharacter (pubprogfuncs_t *prinst, struct globalvars_s
r2d_be_flags = PF_SelectDPDrawFlag(flag);
PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y);
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_EndString(NULL);
r2d_be_flags = 0;
@ -727,7 +730,7 @@ void QCBUILTIN PF_CL_drawrawstring (pubprogfuncs_t *prinst, struct globalvars_s
else if (c & 0x80)
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_EndString(NULL);
@ -1236,25 +1239,25 @@ void QCBUILTIN PF_CL_precache_sound (pubprogfuncs_t *prinst, struct globalvars_s
//void setkeydest(float dest) = #601;
void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
//these arguments are stupid
switch((int)G_FLOAT(OFS_PARM0))
{
case 0:
// 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);
if (cls.state == ca_disconnected)
Key_Dest_Add(kdm_console);
// if (cls.state == ca_disconnected)
// Key_Dest_Add(kdm_console);
}
break;
case 2:
// key_menu
m_state = m_menu_dat;
Key_Dest_Remove(kdm_message);
if (!Key_Dest_Has(kdm_menu))
if (!Key_Dest_Has(kdm_gmenu))
Key_Dest_Remove(kdm_console);
Key_Dest_Add(kdm_menu);
Key_Dest_Add(kdm_gmenu);
break;
case 1:
// key_message
@ -1268,13 +1271,10 @@ void QCBUILTIN PF_cl_setkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr
//float getkeydest(void) = #602;
void QCBUILTIN PF_cl_getkeydest (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (Key_Dest_Has(kdm_menu))
{
if (m_state == m_menu_dat)
G_FLOAT(OFS_RETURN) = 2;
else
G_FLOAT(OFS_RETURN) = 3;
}
if (Key_Dest_Has(kdm_emenu))
G_FLOAT(OFS_RETURN) = 3;
else if (Key_Dest_Has(kdm_gmenu))
G_FLOAT(OFS_RETURN) = 2;
// else if (Key_Dest_Has(kdm_message))
// G_FLOAT(OFS_RETURN) = 1;
else
@ -2241,19 +2241,14 @@ void MP_Shutdown (void)
PR_Common_Shutdown(menu_world.progs, false);
menu_world.progs->CloseProgs(menu_world.progs);
memset(&menu_world, 0, sizeof(menu_world));
PR_ReleaseFonts(kdm_menu);
PR_ReleaseFonts(kdm_gmenu);
#ifdef CL_MASTER
Master_ClearMasks();
#endif
if (m_state == m_menu_dat)
{
Key_Dest_Remove(kdm_menu);
m_state = 0;
}
key_dest_absolutemouse &= ~kdm_menu;
Key_Dest_Remove(kdm_gmenu);
key_dest_absolutemouse &= ~kdm_gmenu;
}
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.user = &menu_world;
menu_world.keydestmask = kdm_menu;
menu_world.keydestmask = kdm_gmenu;
menutime = Sys_DoubleTime();
if (!menu_world.progs)
@ -2537,6 +2532,7 @@ void MP_Draw(void)
inmenuprogs--;
}
void MP_Keydown(int key, int unicode)
{
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();
if (menu_world.g.time)
*menu_world.g.time = menutime;
@ -2584,6 +2582,10 @@ void MP_Keyup(int key, int unicode)
if (setjmp(mp_abort))
return;
if (key && !(mpkeysdown[key>>3] & (1<<(key&7))))
return;
mpkeysdown[key>>3] &= ~(1<<(key&7));
menutime = Sys_DoubleTime();
if (menu_world.g.time)
*menu_world.g.time = menutime;

View File

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

View File

@ -1315,10 +1315,10 @@ void R2D_DrawCrosshair(void)
{
SCR_CrosshairPosition(&cl.playerview[sc], &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;
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_EndString(font_default);
}

View File

@ -582,6 +582,7 @@ extern cvar_t gl_maxdist;
extern cvar_t r_clear;
extern cvar_t gl_poly;
extern cvar_t gl_affinemodels;
extern cvar_t r_renderscale;
extern cvar_t gl_nohwblend;
extern cvar_t r_coronas, r_flashblend, r_flashblendscale;
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_ARCHIVE,
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_wallcolour = CVARAF ("r_wallcolour", "128 128 128",
"r_wallcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken
@ -430,6 +431,8 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS);
Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS);
Cvar_Register (&r_postprocshader, GLRENDEREROPTIONS);
Cvar_Register (&r_fxaa, GLRENDEREROPTIONS);
Cvar_Register (&r_renderscale, GLRENDEREROPTIONS);
Cvar_Register (&dpcompat_psa_ungroup, 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)
{
int px, py;
unsigned int codeflags, codepoint;
Font_BeginString(font_default, x, y, &px, &py);
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);
}
@ -208,6 +210,7 @@ void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean
conchar_t *w;
int px, py;
int fw = 0;
unsigned int codeflags, codepoint;
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);
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)
{
@ -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)
return;
px = Font_DrawChar(px, py, *w);
px = Font_DrawChar(px, py, codeflags, codepoint);
}
Font_EndString(font_default);
}
@ -1115,7 +1121,7 @@ void Sbar_DrawCharacter (float x, float y, int num)
{
int 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);
}
@ -1158,7 +1164,8 @@ void Draw_TinyString (float x, float y, const qbyte *str)
str++;
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);
}
@ -2593,24 +2600,24 @@ static void Sbar_Voice(int y)
float range = loudness/100.0f;
w = 0;
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(0xe081 | CON_WHITEMASK)*16;
w += Font_CharWidth(0xe082 | CON_WHITEMASK);
w += Font_CharWidth('M' | CON_WHITEMASK);
w += Font_CharWidth('i' | CON_WHITEMASK);
w += Font_CharWidth('c' | CON_WHITEMASK);
w += Font_CharWidth(' ' | CON_WHITEMASK);
w += Font_CharWidth(CON_WHITEMASK, 0xe080);
w += Font_CharWidth(CON_WHITEMASK, 0xe081)*16;
w += Font_CharWidth(CON_WHITEMASK, 0xe082);
w += Font_CharWidth(CON_WHITEMASK, 'M');
w += Font_CharWidth(CON_WHITEMASK, 'i');
w += Font_CharWidth(CON_WHITEMASK, 'c');
w += Font_CharWidth(CON_WHITEMASK, ' ');
x -= w/2;
x = Font_DrawChar(x, y, 'M' | CON_WHITEMASK);
x = Font_DrawChar(x, y, 'i' | CON_WHITEMASK);
x = Font_DrawChar(x, y, 'c' | CON_WHITEMASK);
x = Font_DrawChar(x, y, ' ' | CON_WHITEMASK);
x = Font_DrawChar(x, y, 0xe080 | CON_WHITEMASK);
x = Font_DrawChar(x, y, CON_WHITEMASK, 'M');
x = Font_DrawChar(x, y, CON_WHITEMASK, 'i');
x = Font_DrawChar(x, y, CON_WHITEMASK, 'c');
x = Font_DrawChar(x, y, CON_WHITEMASK, ' ');
x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe080);
s = x;
for (i=0 ; i<16 ; i++)
x = Font_DrawChar(x, y, 0xe081 | CON_WHITEMASK);
Font_DrawChar(x, y, 0xe082 | CON_WHITEMASK);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(0xe083 | CON_WHITEMASK)/2, y, 0xe083 | CON_WHITEMASK);
x = Font_DrawChar(x, y, CON_WHITEMASK, 0xe081);
Font_DrawChar(x, y, CON_WHITEMASK, 0xe082);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(CON_WHITEMASK, 0xe083)/2, y, CON_WHITEMASK, 0xe083);
Font_EndString(font_default);
}
#endif
@ -3137,19 +3144,19 @@ ping time frags name
sprintf(num, "%3i",f); \
\
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_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_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) || \
(pv->cam_state != CAM_FREECAM && k == pv->cam_spec_track)) \
{ \
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_DrawChar(cx, cy, 17 | 0xe000 | CON_WHITEMASK); \
Font_DrawChar(cx, cy, CON_WHITEMASK, 17 | 0xe000); \
} \
Font_EndString(font_default); \
} \
@ -3588,19 +3595,19 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
sprintf (num, "%3i",f);
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_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_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) ||
(!cl.spectator && k == pv->playernum))
{
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_DrawChar ( px, py, 17 | 0xe000 | CON_WHITEMASK);
Font_DrawChar ( px, py, CON_WHITEMASK, 17 | 0xe000);
}
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))
{
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_DrawChar(px, py, 17|0xe000|CON_WHITEMASK);
Font_DrawChar(px, py, CON_WHITEMASK, 17|0xe000);
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);
int Font_CharHeight(void);
float Font_CharScaleHeight(void);
int Font_CharWidth(unsigned int charcode);
float Font_CharScaleWidth(unsigned int charcode);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode);
int Font_DrawChar(int px, int py, unsigned int charcode);
float Font_DrawScaleChar(float px, float py, unsigned int charcode); /*avoid using*/
int Font_CharWidth(unsigned int charflags, unsigned int codepoint);
float Font_CharScaleWidth(unsigned int charflags, unsigned int codepoint);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charflags, unsigned int codepoint);
int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint);
float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned int codepoint); /*avoid using*/
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_InvalidateColour(void);
/*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_LineWidth(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)
continue;
if (S_IsPlayingSomewhere(sfx))
continue; //eep?!?
sfx->loadstate = SLS_NOTLOADED;
/*nothing to do if there's no data within*/
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();
}
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)
{
int i;
@ -2448,6 +2493,7 @@ void S_StopAllSounds(qboolean clear)
{
int i;
sfx_t *s;
channel_t musics[NUM_MUSICS];
soundcardinfo_t *sc;
@ -2458,12 +2504,15 @@ void S_StopAllSounds(qboolean clear)
for (sc = sndcardinfo; sc; sc = sc->next)
{
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)
{
s = sc->channel[i].sfx;
if (s->loadstate == SLS_LOADING)
;//COM_WorkerPartialSync(s, &s->loadstate, SLS_LOADING);
else
COM_WorkerPartialSync(s, &s->loadstate, SLS_LOADING);
// else
{
sc->channel[i].sfx = NULL;
if (s->decoder.ended)
@ -2475,12 +2524,15 @@ void S_StopAllSounds(qboolean clear)
sc->ChannelUpdate(sc, &sc->channel[i], true);
}
}
}
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));
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);
}
@ -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
===================
*/
char *Media_NextTrack(int musicchannelnum);
mleaf_t *Q1BSP_LeafForPoint (model_t *model, vec3_t p);
void S_UpdateAmbientSounds (soundcardinfo_t *sc)
{
@ -2656,7 +2720,27 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc)
if (chan->sfx)
{
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;
if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, chan, changed);
@ -3059,9 +3143,14 @@ void S_SoundList_f(void)
total = 0;
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)
{
Con_Printf("S( ) : %s\n", sfx->name);

View File

@ -779,8 +779,10 @@ qboolean S_RegisterSoundInputPlugin(S_LoadSound_t loadfnc)
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
{
Con_SafePrintf ("Couldn't load %s\n", namebuffer);
s->loadstate = SLS_FAILED;
COM_AddWork(0, S_LoadedOrFailed, s, NULL, SLS_FAILED, 0);
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.
Con_DPrintf ("Couldn't load %s\n", namebuffer);
s->loadstate = SLS_FAILED;
COM_AddWork(0, S_LoadedOrFailed, s, NULL, SLS_FAILED, 0);
return;
}
@ -890,7 +892,7 @@ void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
{
s->loadstate = SLS_LOADED;
//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);
return;
}
@ -900,7 +902,7 @@ void S_LoadSoundWorker (void *ctx, void *ctxdata, size_t a, size_t b)
if (s->loadstate != SLS_FAILED)
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);
return;
}

View File

@ -75,9 +75,10 @@ typedef struct {
sfx_t *s;
} ovdecoderbuffer_t;
sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length);
void OV_CancelDecoder(sfx_t *s);
qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer);
static sfxcache_t *OV_Query(struct sfx_s *sfx, struct sfxcache_s *buf);
static sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length);
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)
{
@ -93,6 +94,7 @@ qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
buffer->s = s;
s->decoder.buf = buffer;
s->decoder.decodedata = OV_DecodeSome;
s->decoder.querydata = OV_Query;
s->decoder.purge = 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;
}
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 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;
//check pos
//fixme: seeking might not be supported
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)
{
/*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;
}
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;
s->loadstate = SLS_FAILED;
dec = s->decoder.buf;
s->decoder.buf = NULL;
s->decoder.purge = NULL;
s->decoder.ended = NULL;
s->decoder.querydata = NULL;
s->decoder.decodedata = NULL;
p_ov_clear (&dec->vf); //close the decoder
@ -264,6 +299,11 @@ void OV_CancelDecoder(sfx_t *s)
dec->decodedbuffer = NULL;
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;
}
@ -316,7 +356,7 @@ static ov_callbacks callbacks = {
close_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
static qboolean tried;

View File

@ -40,6 +40,7 @@ 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 *(*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 (*purge) (struct sfx_s *sfx); //sound is being purged from memory. destroy everything.
void *buf;
@ -141,6 +142,10 @@ qboolean S_HaveOutput(void);
void S_Music_Clear(sfx_t *onlyifsample);
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_PrecacheSound (const char *sample);

View File

@ -1540,11 +1540,13 @@ void VARGS Sys_Printf (char *fmt, ...)
out = wide;
in = msg;
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++;
}
}
@ -1686,9 +1688,21 @@ char *Sys_GetClipboard(void)
utf8 = cliputf8 = malloc(l);
while(*clipWText)
{
if (clipWText[0] == '\r' && clipWText[1] == '\n') //bloomin microsoft.
clipWText++;
c = utf8_encode(utf8, *clipWText++, l);
unsigned int cp = *clipWText++;
if (cp == '\r' && *clipWText == '\n') //bloomin microsoft.
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)
break;
l -= c;
@ -1756,13 +1770,14 @@ void Sys_SaveClipboard(char *text)
HANDLE glob;
char *temp;
unsigned short *tempw;
unsigned int codepoint;
if (!OpenClipboard(NULL))
return;
EmptyClipboard();
EmptyClipboard();
if (com_parseutf8.ival > 0)
{
glob = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1)*2);
glob = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1)*4);
if (glob)
{
tempw = GlobalLock(glob);
@ -1771,8 +1786,20 @@ void Sys_SaveClipboard(char *text)
int error;
while(*text)
{
//NOTE: should be \r\n and not just \n
*tempw++ = utf8_decode(&error, text, &text);
codepoint = 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;
GlobalUnlock(glob);
@ -2818,9 +2845,10 @@ BOOL MoveFileU(const char *src, const char *dst)
qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
{
wchar_t wide1[2048];
int ffe = COM_CheckParm("--fromfrontend");
PROCESS_INFORMATION childinfo;
STARTUPINFO startinfo = {sizeof(startinfo)};
STARTUPINFOW startinfo = {sizeof(startinfo)};
char *e;
strtoul(SVNREVISIONSTR, &e, 10);
@ -2847,7 +2875,6 @@ qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
else if (!ffe)
{
//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 updatedpath[MAX_OSPATH];
@ -2881,9 +2908,10 @@ qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
if (*updatedpath)
{
//fixme: unicode paths/commandline.
GetModuleFileName(NULL, frontendpath, sizeof(frontendpath)-1);
if (CreateProcess(updatedpath, va("%s --fromfrontend \"%s\" \"%s\"", GetCommandLineA(), SVNREVISIONSTR, frontendpath), NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &childinfo))
wchar_t widefe[MAX_OSPATH], wargs[2048];
GetModuleFileNameW(NULL, widefe, countof(widefe)-1);
_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;
}
}
@ -2894,7 +2922,6 @@ qboolean Sys_CheckUpdated(char *bindir, size_t bindirsize)
//com_argv[ffe+2] is frontend location
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.
// 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))

View File

@ -956,7 +956,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
nnx-=(nnx - -viewportx)%ts;
}
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)
{
@ -999,7 +999,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
{
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)
viewportx += e - vid.pixelwidth;
if (nx < 0)
@ -1015,12 +1015,12 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
continue;
}
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;
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)
viewportx += e - vid.pixelwidth;
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*/
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)
viewportx += e - vid.pixelwidth;
if (nx < 0)
@ -1058,7 +1058,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
{
if (*tooltip == '\n')
break;
smx = Font_CharEndCoord(font_default, smx, *tooltip);
smx = Font_CharEndCoord(font_default, smx, (COLOR_CYAN<<CON_FGSHIFT), *tooltip);
}
y = Font_CharHeight();
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);
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')
tooltip++;

View File

@ -601,6 +601,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#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
#define FTE_DEPRECATED
#endif

View File

@ -1318,8 +1318,8 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel,
int i, len;
int quotes = 0;
char *str;
char *bestmacro, *bestvar;
int name_length, macro_length, var_length;
char *bestvar;
int name_length, var_length;
qboolean striptrailing;
len = 0;
@ -1340,8 +1340,6 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel,
buf[0] = 0;
buf[1] = 0;
bestvar = NULL;
bestmacro = NULL;
macro_length=0;
var_length = 0;
while ((c = *data) > 32)
{
@ -1350,21 +1348,13 @@ char *Cmd_ExpandString (char *data, char *dest, int destlen, int maxaccesslevel,
data++;
buf[i++] = c;
buf[i] = 0;
if (!bestmacro)
{
if ((str = Cmd_ExpandCvar(buf+striptrailing, maxaccesslevel, &var_length)))
bestvar = str;
}
if (expandmacros && (str = TP_MacroString (buf+striptrailing, &macro_length)))
bestmacro = str;
if (expandcvars && (str = Cmd_ExpandCvar(buf+striptrailing, maxaccesslevel, &var_length)))
bestvar = str;
if (expandmacros && (str = TP_MacroString (buf+striptrailing, &var_length)))
bestvar = str;
}
if (bestmacro)
{
str = bestmacro;
name_length = macro_length;
}
else if (bestvar)
if (bestvar)
{
str = bestvar;
name_length = var_length;
@ -3253,6 +3243,12 @@ static char *Macro_Quote (void)
return "\"";
}
static char *Macro_Random(void)
{
Q_snprintfz(macro_buf, sizeof(macro_buf), "%u", rand());
return macro_buf;
}
/*
============
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_AddMacro("random", Macro_Random, true);
Cmd_AddMacro("time", Macro_Time, true);
Cmd_AddMacro("ukdate", Macro_UKDate, 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.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;
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 = NULL;
if (meshcache.vbo.indicies.sysptr)
*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->snormals_array = inf->ofs_skel_svect;
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
@ -1918,6 +1940,13 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
meshcache.vbo.vertcount = inf->numverts;
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
mesh->xyz_array = p1->ofsverts;
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 offset = LittleLong(src->offset);
qboolean invalid = false;
maxval = min(256,maxval);
maxval = min(256,maxval); //output is bytes.
if (!offset)
{
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 defaultvert = {0,0,0,1};
struct iqmbounds *inbounds;
int memsize;
qbyte *obase=NULL;
vecV_t *opos=NULL;
@ -6752,6 +6783,24 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
}
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++)
{
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;
for (t = 0; t < nt; t++)
{
*idx++ = LittleShort(tris[t].vertex[0]) - offset;
*idx++ = LittleShort(tris[t].vertex[1]) - offset;
*idx++ = LittleShort(tris[t].vertex[2]) - offset;
*idx++ = LittleLong(tris[t].vertex[0]) - offset;
*idx++ = LittleLong(tris[t].vertex[1]) - offset;
*idx++ = LittleLong(tris[t].vertex[2]) - offset;
}
/*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)
{
int i;
galiasinfo_t *root;
struct iqmheader *h = (struct iqmheader *)buffer;
ClearBounds(mod->mins, mod->maxs);
root = Mod_ParseIQMMeshModel(mod, buffer, fsize);
if (!root)
{
@ -6878,9 +6928,7 @@ qboolean QDECL Mod_LoadInterQuakeModel(model_t *mod, void *buffer, size_t fsize)
mod->flags = h->flags;
ClearBounds(mod->mins, mod->maxs);
for (i = 0; i < root->numverts; i++)
AddPointToBounds(root->ofs_skel_xyz[i], mod->mins, mod->maxs);
mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
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
char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, qboolean ignoreflags)
{
unsigned int codeflags, codepoint;
if (!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;
while(str < stop)
{
if ((*str & CON_HIDDEN) && ignoreflags)
str = Font_Decode(str, &codeflags, &codepoint);
if ((codeflags & CON_HIDDEN) && ignoreflags)
{
str++;
continue;
}
if (*str == CON_LINKSTART)
if (codeflags == (CON_LINKSPECIAL | CON_HIDDEN) && codepoint == '[')
{
if (!ignoreflags)
{
@ -2595,7 +2597,7 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
str++;
continue;
}
else if (*str == CON_LINKEND)
else if (codeflags == (CON_LINKSPECIAL | CON_HIDDEN) && codepoint == ']')
{
if (!ignoreflags)
{
@ -2609,9 +2611,9 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
str++;
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 (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, '4', '2', '5',
'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)
break;
outsize -= 2;
d = (*str & CON_FLAGSMASK);
d = codeflags;
*out++ = '^';
*out++ = q3[(*str & CON_FGMASK) >> CON_FGSHIFT];
*out++ = q3[(codeflags & CON_FGMASK) >> CON_FGSHIFT];
}
else
{
@ -2660,7 +2662,7 @@ char *COM_DeFunString(conchar_t *str, conchar_t *stop, char *out, int outsize, q
break;
outsize -= 4;
d = (*str & CON_FLAGSMASK);
d = codeflags;
*out++ = '^';
*out++ = '&';
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
if (ignoreflags && (*str & CON_HIDDEN))
if (ignoreflags && (codeflags & CON_HIDDEN))
continue;
c = unicode_encode(out, (*str++ & CON_CHARMASK), outsize-1, !ignoreflags);
c = unicode_encode(out, codepoint, outsize-1, !ignoreflags);
if (!c)
break;
outsize -= c;
@ -2979,10 +2981,18 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
}
else
{
if (uc > CON_CHARMASK)
if (uc > 0x10ffff)
uc = 0xfffd;
if (!--outsize)
break;
if (uc > 0xffff)
{
if (!--outsize)
break;
*out++ = uc>>16 | CON_LONGCHAR | (ext & CON_HIDDEN);
uc &= 0xffff;
}
*out++ = uc | ext;
str = end;
continue;
@ -3156,11 +3166,18 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
if (str[len] == '}')
len++;
if (uc > CON_CHARMASK)
if (uc > 0x10ffff) //utf-16 imposes a limit on standard unicode codepoints (any encoding)
uc = 0xfffd;
if (!--outsize)
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;
str += len;

View File

@ -31,10 +31,12 @@ extern consolecolours_t consolecolours[MAXCONCOLOURS];
#define MAXQ3COLOURS 10
extern conchar_t q3codemasks[MAXQ3COLOURS];
#define CON_LONGCHAR_MASK (CON_LONGCHAR|CON_RICHFORECOLOUR)
#define CON_NONCLEARBG 0x00800000 //disabled if CON_RICHFORECOLOUR
#define CON_HALFALPHA 0x00400000 //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_BLINKTEXT 0x00040000
#define CON_2NDCHARSETTEXT 0x00020000

View File

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

View File

@ -52,12 +52,6 @@ extern int
#endif
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_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_UVGOGGLES (1u<<3) //usused / reserved
//ROGUE
#define RDF_BLOOM (1u<<16)
#define RDF_FISHEYE (1u<<17)
#define RDF_WATERWARP (1u<<18)
#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
//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++)
{
if (j == 1)
@ -2901,6 +2902,7 @@ static void DrawPass(const shaderpass_t *pass)
tmu++;
}
#endif
//might need to break the pass here
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);
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:
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"
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_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 *bloomrescale;
static shader_t *bloomblur;
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];
fbostate_t fbo_bloom;
static int scrwidth, scrheight;
@ -78,24 +81,23 @@ void R_BloomRegister(void)
{
Cvar_Register (&r_bloom, "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)
{
int i, j;
char name[64];
if (w == scrwidth && h == scrheight && !r_bloom_scale.modified)
if (w == scrwidth && h == scrheight && !r_bloom_initialscale.modified)
return;
r_bloom_scale.modified = false;
r_bloom_initialscale.modified = false;
scrwidth = w;
scrheight = h;
//I'm depending on npot here
w *= r_bloom_scale.value;
h *= r_bloom_scale.value;
w *= r_bloom_initialscale.value;
h *= r_bloom_initialscale.value;
for (i = 0; i < MAXLEVELS; i++)
{
w /= 2;
h /= 2;
/*I'm paranoid*/
if (w < 4)
w = 4;
@ -104,19 +106,19 @@ static void R_SetupBloomTextures(int w, int h)
texwidth[i] = w;
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 (i = 0; i < 2; i++)
{
if (!TEXVALID(pingtex[i][j]))
{
sprintf(name, "***bloom*%c*%i***", 'a'+i, j);
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);
if (TEXVALID(pingtex[i][j]))
Image_UnloadTexture(pingtex[i][j]);
pingtex[i][j] = r_nulltex;
}
}
@ -162,9 +164,6 @@ static void R_SetupBloomTextures(int w, int h)
"map $upperoverlay\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)
{
@ -184,6 +183,12 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h)
{
int i;
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?*/
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*/
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*/
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);
sprintf(name, "***bloom*%c*%i***", 'a'+0, i);
TEXASSIGN(pingtex[0][i], Image_CreateTexture(name, NULL, IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR));
Image_Upload(pingtex[0][i], TF_RGBA32, NULL, NULL, texwidth[i], texheight[i], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR);
}
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*/
GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][i], 1, r_nulltex, 0, 0, 0);
GLBE_FBO_Sources(pingtex[0][i-1], r_nulltex);
qglViewport (0, 0, texwidth[i], texheight[i]);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale);
intex = pingtex[0][i];
r_worldentity.glowmod[0] = 1.0 / intex->width;
}
// }
// for (i = 0; i < MAXLEVELS; i++)
// {
/*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];
else
r_worldentity.glowmod[0] = 2.0 / intex->width;
r_worldentity.glowmod[1] = 0;
GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[1][i], 1, r_nulltex, 0, 0, 0);
GLBE_FBO_Sources(pingtex[0][i], r_nulltex);
qglViewport (0, 0, texwidth[i], texheight[i]);
GLBE_FBO_Sources(intex, r_nulltex);
qglViewport (0, 0, pingtex[1][i]->width, pingtex[1][i]->height);
BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur);
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_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);
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur);
intex = pingtex[0][i];
}
r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 0;
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*/
GLBE_FBO_Pop(oldfbo);
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);
int Font_CharHeight(void);
float Font_CharScaleHeight(void);
int Font_CharWidth(unsigned int charcode);
float Font_CharScaleWidth(unsigned int charcode);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode);
int Font_DrawChar(int px, int py, unsigned int charcode);
float Font_DrawScaleChar(float px, float py, unsigned int charcode); /*avoid using*/
int Font_CharWidth(unsigned int charflags, unsigned int codepoint);
float Font_CharScaleWidth(unsigned int charflags, unsigned int codepoint);
int Font_CharEndCoord(struct font_s *font, int x, unsigned int charflags, unsigned int codepoint);
int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint);
float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned int codepoint); /*avoid using*/
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);
struct font_s *font_default;
@ -29,6 +29,10 @@ struct font_s *font_console;
struct font_s *font_tiny;
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
#include <ft2build.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
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 (charidx >= TRACKERFIRST && charidx < TRACKERFIRST+100)
@ -1575,19 +1585,20 @@ float Font_CharScaleHeight(void)
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.
*/
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;
#define TABWIDTH (8*20)
if (charcode&CON_HIDDEN)
if (charflags&CON_HIDDEN)
return x;
if ((charcode&CON_CHARMASK) == '\t')
if (codepoint == '\t')
return x + ((TABWIDTH - (x % TABWIDTH)) % TABWIDTH);
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if ((charflags & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt;
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
c = Font_GetChar(font, codepoint);
if (!c)
{
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.
//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 font_s *font = curfont;
if (charcode&CON_HIDDEN)
if (charflags&CON_HIDDEN)
return 0;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if ((charflags & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt;
c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK));
c = Font_GetChar(curfont, codepoint);
if (!c)
{
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.
//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 font_s *font = curfont;
if (charcode&CON_HIDDEN)
if (charflags&CON_HIDDEN)
return 0;
if ((charcode & CON_2NDCHARSETTEXT) && font->alt)
if ((charflags & CON_2NDCHARSETTEXT) && font->alt)
font = font->alt;
c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK));
c = Font_GetChar(curfont, codepoint);
if (!c)
{
return 0;
@ -1636,6 +1650,29 @@ float Font_CharScaleWidth(unsigned int charcode)
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
//start+end are the input string
//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
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 foundlines = 0;
struct font_s *font = curfont;
unsigned int codeflags, codepoint;
while (start < end)
{
// 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;
px = Font_CharEndCoord(font, px, start[l]);
l++;
n = Font_Decode(l, &codeflags, &codepoint);
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 (px > maxpixelwidth)
{
bt = l;
//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)
l = bt-1;
if (l == start && bt>start)
l = Font_DecodeReverse(bt, start, &codeflags, &codepoint);
}
starts[foundlines] = start;
ends[foundlines] = start+l;
ends[foundlines] = l;
foundlines++;
if (foundlines == maxlines)
break;
start+=l;
start=l;
if (start == end)
break;
@ -1693,9 +1738,11 @@ int Font_LineWidth(conchar_t *start, conchar_t *end)
//fixme: does this do the right thing with tabs?
int x = 0;
struct font_s *font = curfont;
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;
}
@ -1703,9 +1750,11 @@ float Font_LineScaleWidth(conchar_t *start, conchar_t *end)
{
int x = 0;
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];
}
@ -1713,10 +1762,12 @@ void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end)
{
int lx = 0;
struct font_s *font = curfont;
for (; start < end; start++)
unsigned int codeflags, codepoint;
for (; start < end; )
{
Font_DrawChar(x+lx, y, *start);
lx = Font_CharEndCoord(font, lx, *start);
start = Font_Decode(start, &codeflags, &codepoint);
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.
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;
float s0, s1;
@ -1762,30 +1813,30 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
#else
#define dxbias 0
#endif
if (charcode & CON_HIDDEN)
if (charflags & CON_HIDDEN)
return px;
if (charcode & CON_2NDCHARSETTEXT)
if (charflags & CON_2NDCHARSETTEXT)
{
if (font->alt)
{
font = font->alt;
// charcode &= ~CON_2NDCHARSETTEXT;
// charflags &= ~CON_2NDCHARSETTEXT;
}
else if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff)
charcode &= ~CON_2NDCHARSETTEXT; //don't double-dip
else if ((codepoint) >= 0xe000 && (codepoint) <= 0xe0ff)
charflags &= ~CON_2NDCHARSETTEXT; //don't double-dip
}
//crash if there is no current font.
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
c = Font_GetChar(font, codepoint);
if (!c)
return px;
nextx = px + c->advance;
if ((charcode & CON_CHARMASK) == '\t')
if (codepoint == '\t')
return px + ((TABWIDTH - (px % TABWIDTH)) % TABWIDTH);
if ((charcode & CON_CHARMASK) == ' ')
if (codepoint == ' ')
return nextx;
/* if (charcode & CON_BLINKTEXT)
@ -1795,9 +1846,9 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
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)
{
vec4_t rgba;
@ -1814,7 +1865,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
font_backcolour[1] = 0;
font_backcolour[2] = 0;
font_backcolour[3] = 0;
if (charcode & CON_2NDCHARSETTEXT)
if (charflags & CON_2NDCHARSETTEXT)
{
rgba[0] *= font->alttint[0];
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[2] *= font_foretint[2];
rgba[3] *= font_foretint[3];
if (charcode & CON_BLINKTEXT)
if (charflags & CON_BLINKTEXT)
{
float a = (sin(realtime*3)+1)*0.4 + 0.2;
rgba[3] *= a;
@ -1843,7 +1894,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
}
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)
{
vec4_t rgba;
@ -1851,19 +1902,19 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
Font_Flush();
font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT;
col = (charflags&CON_FGMASK)>>CON_FGSHIFT;
rgba[0] = consolecolours[col].fr*255;
rgba[1] = consolecolours[col].fg*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[1] = consolecolours[col].fg*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[1] *= font->alttint[1];
@ -1879,7 +1930,7 @@ int Font_DrawChar(int px, int py, unsigned int charcode)
rgba[1] *= font_foretint[1];
rgba[2] *= font_foretint[2];
rgba[3] *= font_foretint[3];
if (charcode & CON_BLINKTEXT)
if (charflags & CON_BLINKTEXT)
{
float a = (sin(realtime*3)+1)*0.4 + 0.2;
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*/
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;
float s0, s1;
@ -1988,40 +2039,40 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
// if (!curfont_scaled)
// return Font_DrawChar(px, py, charcode);
if (charcode & CON_2NDCHARSETTEXT)
if (charflags & CON_2NDCHARSETTEXT)
{
if (font->alt)
{
font = font->alt;
charcode &= ~CON_2NDCHARSETTEXT;
charflags &= ~CON_2NDCHARSETTEXT;
}
else if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff)
charcode &= ~CON_2NDCHARSETTEXT; //don't double-dip
else if (codepoint >= 0xe000 && codepoint <= 0xe0ff)
charflags &= ~CON_2NDCHARSETTEXT; //don't double-dip
}
cw = curfont_scale[0];
ch = curfont_scale[1];
//crash if there is no current font.
c = Font_GetChar(font, (CHARIDXTYPE)(charcode&CON_CHARMASK));
c = Font_GetChar(font, codepoint);
if (!c)
return px;
nextx = px + c->advance*cw;
if ((charcode & CON_CHARMASK) == ' ')
if (codepoint == ' ')
return nextx;
if (charcode & CON_BLINKTEXT)
if (charflags & CON_BLINKTEXT)
{
if (!cl_noblink.ival)
if ((int)(realtime*3) & 1)
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)
{
vec4_t rgba;
@ -2039,7 +2090,7 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
font_backcolour[2] = 0;
font_backcolour[3] = 0;
if (charcode & CON_2NDCHARSETTEXT)
if (charflags & CON_2NDCHARSETTEXT)
{
rgba[0] *= font->alttint[0];
rgba[1] *= font->alttint[1];
@ -2063,27 +2114,27 @@ float Font_DrawScaleChar(float px, float py, unsigned int charcode)
}
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)
{
vec4_t rgba;
if (font_backcolour[3] != ((charcode & CON_NONCLEARBG)?127:0))
if (font_backcolour[3] != ((charflags & CON_NONCLEARBG)?127:0))
Font_Flush();
font_colourmask = col;
col = (charcode&CON_FGMASK)>>CON_FGSHIFT;
col = (charflags&CON_FGMASK)>>CON_FGSHIFT;
rgba[0] = consolecolours[col].fr*255;
rgba[1] = consolecolours[col].fg*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[1] = consolecolours[col].fg*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[1] *= font->alttint[1];

View File

@ -125,7 +125,7 @@ static void Mod_MemList_f(void)
#ifndef SERVERONLY
static void Mod_BatchList_f(void)
{
int m, i, lm;
int m, i;
model_t *mod;
batch_t *batch;
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->numedges = LittleLong(inl->numedges);
tn = LittleLong (inl->texinfo);
for (i=0 ; i<MAXRLIGHTMAPS ; i++)
for (i=0 ; i<MAXQ1LIGHTMAPS ; i++)
out->styles[i] = inl->styles[i];
lofs = LittleLong(inl->lightofs);
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->numedges = LittleShort(ins->numedges);
tn = LittleShort (ins->texinfo);
for (i=0 ; i<MAXRLIGHTMAPS ; i++)
for (i=0 ; i<MAXQ1LIGHTMAPS ; i++)
out->styles[i] = ins->styles[i];
lofs = LittleLong(ins->lightofs);
ins++;

View File

@ -56,12 +56,13 @@ extern cvar_t gl_part_flame;
extern cvar_t r_bloom;
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_finish = SCVAR("gl_finish","0");
cvar_t gl_dither = SCVAR("gl_dither", "1");
extern cvar_t r_stereo_separation;
extern cvar_t r_stereo_method;
extern cvar_t r_postprocshader;
extern cvar_t r_postprocshader, r_fxaa;
extern cvar_t gl_screenangle;
@ -87,6 +88,8 @@ cvar_t r_xflip = SCVAR("leftisright", "0");
extern cvar_t scr_fov;
shader_t *scenepp_rescaled;
shader_t *scenepp_antialias;
shader_t *scenepp_waterwarp;
// post processing stuff
@ -141,6 +144,23 @@ void GL_InitSceneProcessingShaders (void)
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;
gl_dither.modified = true; //fixme: bad place for this, but hey
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;
sourcetex = R2D_RT_Configure(restexname, w, h, TF_RGBA32);
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);
}
else
{ //yay, dump it to the screen
//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;
texid_t sourcetex = r_nulltex;
shader_t *custompostproc = NULL;
float renderscale = r_renderscale.value; //extreme, but whatever
checkglerror();
@ -1721,6 +1742,9 @@ void GLR_RenderView (void)
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.
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
@ -1773,11 +1797,21 @@ void GLR_RenderView (void)
flags |= FBO_RB_DEPTH;
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
vid.fbvwidth = vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width;
vid.fbvheight = vid.fbpheight = (r_refdef.vrect.height * vid.pixelheight) / vid.height;
vid.fbpwidth = (r_refdef.vrect.width * vid.pixelwidth) / vid.width;
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);
@ -1861,10 +1895,19 @@ void GLR_RenderView (void)
// SCENE POST PROCESSING
sourcetex = R_RenderPostProcess (sourcetex, RDF_WATERWARP, scenepp_waterwarp, "rt/$waterwarped");
sourcetex = R_RenderPostProcess (sourcetex, RDF_CUSTOMPOSTPROC, custompostproc, "rt/$postproced");
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);
if (renderscale != 1 && !(r_refdef.flags & RDF_ALLPOSTPROC))
{
GLBE_FBO_Sources(sourcetex, r_nulltex);
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);

View File

@ -970,7 +970,9 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
"#define SKELETAL\n",
"#define FOG\n",
"#define FRAMEBLEND\n",
#if MAXRLIGHTMAPS > 1
"#define LIGHTSTYLED\n",
#endif
NULL
};
#define MAXMODIFIERS 64
@ -1340,9 +1342,10 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
initoffset = VFS_GETLEN(blobfile);
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.
if (!p) //give up if permutation 0 failed. that one failing is fatal.
break;
@ -1672,6 +1675,7 @@ struct shader_field_names_s shader_unif_names[] =
{"l_shadowmapproj", SP_LIGHTSHADOWMAPPROJ},
{"l_shadowmapscale", SP_LIGHTSHADOWMAPSCALE},
{"e_sourcesize", SP_SOURCESIZE},
{"e_rendertexturescale", SP_RENDERTEXTURESCALE},
{NULL}
};

View File

@ -3421,6 +3421,9 @@ void Sh_CalcPointLight(vec3_t point, vec3_t light)
if (!(dl->flags & ignoreflags))
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[1] = dl->color[1];
colour[2] = dl->color[2];

View File

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

View File

@ -324,8 +324,10 @@ enum{
PERMUTATION_FRAMEBLEND = 64,
#if MAXRLIGHTMAPS > 1
PERMUTATION_LIGHTSTYLES = 128, //FIXME: make argument
#endif
PERMUTATIONS = 256
#else
PERMUTATIONS = 128
#endif
};
enum shaderattribs_e
@ -399,6 +401,7 @@ typedef struct {
SP_M_INVMODELVIEWPROJECTION,
SP_RENDERTEXTURESCALE, /*multiplier for currentrender->texcoord*/
SP_SOURCESIZE, /*size of $sourcecolour*/
SP_LIGHTRADIUS, /*these light values are realtime lighting*/
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)\
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*/\
comfieldvector(colormod,NULL)\
comfieldvector(colormod,"Provides a colour tint for the entity.")\
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.")\
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_retain=1.0
//add them together
//optionally apply tonemapping
@ -18,10 +19,11 @@ uniform sampler2D s_t1;
uniform sampler2D s_t2;
uniform sampler2D s_t3;
uniform float cvar_r_bloom;
uniform float cvar_r_bloom_retain;
void main ()
{
gl_FragColor =
texture2D(s_t0, tc) +
cvar_r_bloom_retain * texture2D(s_t0, tc) +
cvar_r_bloom*(
texture2D(s_t1, 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