diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 51646e6b5..86fa6da57 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -79,6 +79,19 @@ qboolean CL_FilterModelindex(int modelindex, int frame) //============================================================ +static void CL_ClearDlight(dlight_t *dl, int key) +{ + int st; + st = dl->stexture; + memset (dl, 0, sizeof(*dl)); + dl->stexture = st; + dl->axis[0][0] = 1; + dl->axis[1][1] = 1; + dl->axis[2][2] = 1; + dl->key = key; + dl->flags = LFLAG_DYNAMIC; +} + /* =============== CL_AllocDlight @@ -98,8 +111,7 @@ dlight_t *CL_AllocDlight (int key) { if (dl->key == key) { - memset (dl, 0, sizeof(*dl)); - dl->key = key; + CL_ClearDlight(dl, key); return dl; } } @@ -109,8 +121,7 @@ dlight_t *CL_AllocDlight (int key) if (dlights_running < MAX_DLIGHTS) { dl = &cl_dlights[dlights_running]; - memset (dl, 0, sizeof(*dl)); - dl->key = key; + CL_ClearDlight(dl, key); dlights_running++; if (dlights_software < MAX_SWLIGHTS) dlights_software++; @@ -118,8 +129,7 @@ dlight_t *CL_AllocDlight (int key) } dl = &cl_dlights[0]; - memset (dl, 0, sizeof(*dl)); - dl->key = key; + CL_ClearDlight(dl, key); return dl; } @@ -199,6 +209,12 @@ void CL_DecayLights (void) if (!dl->radius) continue; + if (!dl->die) + { + lastrunning = i; + continue; + } + if (dl->die < (float)cl.time) { dl->radius = 0; @@ -1476,6 +1492,9 @@ void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entities_t * le->oldframechange = le->framechange; le->framechange = newpack->servertime; + if (le->framechange > le->oldframechange + 0.2) + le->oldframechange = le->framechange - 0.2; + le->frame = sold->frame; } } @@ -1745,7 +1764,7 @@ void CL_LinkPacketEntities (void) ent->shaderRGBAf[3] = state->trans/255.0f; #ifdef PEXT_FATNESS //set trans - ent->fatness = state->fatness/2.0; + ent->fatness = state->fatness/16.0; #endif // rotate binary objects locally @@ -1867,6 +1886,7 @@ void CL_LinkPacketEntities (void) if (rad) { dl = CL_AllocDlight (state->number); + memcpy(dl->axis, ent->axis, sizeof(dl->axis)); VectorCopy (ent->origin, dl->origin); dl->die = (float)cl.time; if (model->flags & EF_ROCKET) @@ -2045,7 +2065,7 @@ void CL_LinkPacketEntities (void) #endif #ifdef PEXT_FATNESS //set trans - ent->fatness = s1->fatness/2.0; + ent->fatness = s1->fatness/16.0; #endif // rotate binary objects locally @@ -2558,7 +2578,7 @@ void CL_ParsePlayerinfo (void) #endif #ifdef PEXT_FATNESS if (flags & PF_FATNESS_Z && cls.fteprotocolextensions & PEXT_FATNESS) - state->fatness = (float)MSG_ReadChar() / 2; + state->fatness = (float)MSG_ReadChar() / 16; #endif #ifdef PEXT_HULLSIZE if (cls.fteprotocolextensions & PEXT_HULLSIZE) @@ -2793,20 +2813,51 @@ void CL_LinkPlayers (void) #endif // spawn light flashes, even ones coming from invisible objects - if (r_powerupglow.value && !(r_powerupglow.value == 2 && j == cl.playernum[0])) + if (r_powerupglow.value && !(r_powerupglow.value == 2 && j == cl.playernum[0]) + && (state->effects & (EF_BLUE|EF_RED|EF_BRIGHTLIGHT|EF_DIMLIGHT))) { + vec3_t colour; + float radius; org = (j == cl.playernum[0]) ? cl.simorg[0] : state->origin; + colour[0] = 0; + colour[1] = 0; + colour[2] = 0; + radius = 0; - if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) - CL_NewDlight (j+1, org[0], org[1], org[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 3)->noppl = (j != cl.playernum[0]); - else if (state->effects & EF_BLUE) - CL_NewDlight (j+1, org[0], org[1], org[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 1)->noppl = (j != cl.playernum[0]); - else if (state->effects & EF_RED) - CL_NewDlight (j+1, org[0], org[1], org[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 2)->noppl = (j != cl.playernum[0]); - else if (state->effects & EF_BRIGHTLIGHT) - CL_NewDlight (j+1, org[0], org[1], org[2] + 16, 400 + (r_lightflicker.value?(rand()&31):0), 0.1, 0)->noppl = (j != cl.playernum[0]); - else if (state->effects & EF_DIMLIGHT) - CL_NewDlight (j+1, org[0], org[1], org[2], 200 + (r_lightflicker.value?(rand()&31):0), 0.1, 0)->noppl = (j != cl.playernum[0]); + if (state->effects & EF_BRIGHTLIGHT) + { + radius = max(radius,400); + colour[0] += 0.2; + colour[1] += 0.1; + colour[2] += 0.05; + } + if (state->effects & EF_DIMLIGHT) + { + radius = max(radius,200); + colour[0] += 0.2; + colour[1] += 0.1; + colour[2] += 0.05; + } + if (state->effects & EF_BLUE) + { + radius = max(radius,200); + colour[0] += 0.05; + colour[1] += 0.05; + colour[2] += 0.3; + } + if (state->effects & EF_RED) + { + radius = max(radius,200); + colour[0] += 0.5; + colour[1] += 0.05; + colour[2] += 0.05; + } + + if (radius) + { + radius += r_lightflicker.value?(rand()&31):0; + CL_NewDlightRGB(j+1, org[0], org[1], org[2], radius, 0.1, colour[0], colour[1], colour[2])->flags &= ~LFLAG_ALLOW_FLASH; + } } if (state->modelindex < 1) @@ -2867,7 +2918,7 @@ void CL_LinkPlayers (void) ent->shaderRGBAf[2] = state->colourmod[2]/32; ent->shaderRGBAf[3] = state->alpha/255; - ent->fatness = state->fatness/2; + ent->fatness = state->fatness/16; // // angles // diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 28527ae42..45f90b307 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -725,7 +725,7 @@ void CL_UpdatePrydonCursor(usercmd_t *from, float cursor_screen[2], vec3_t curso temp[1] = (-cursor_screen[1]+1)/2; temp[2] = 1; - Matrix4_UnProject(temp, cursor_end, cl.viewangles[0], vec3_origin, (float)vid.width/vid.height, scr_fov.value ); + Matrix4_UnProject(temp, cursor_end, cl.viewangles[0], vec3_origin, scr_fov.value*(float)vid.width/vid.height, scr_fov.value ); VectorScale(cursor_end, 100000, cursor_end); VectorAdd(cursor_start, cl.simorg[0], cursor_start); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index e12c549f7..c2706e3a9 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -679,7 +679,7 @@ void CL_CheckForResend (void) #endif if (connect_tries == 0) - NET_EnsureRoute(cls.sockets, "conn", cls.servername); + NET_EnsureRoute(cls.sockets, "conn", cls.servername, false); #ifdef NQPROT if (connect_type || ((connect_tries&3)==3)) @@ -844,7 +844,7 @@ void CL_IRCConnect_f (void) { CL_Disconnect_f (); - if (FTENET_AddToCollection(cls.sockets, "TCP", Cmd_Argv(2), FTENET_IRCConnect_EstablishConnection)) + if (FTENET_AddToCollection(cls.sockets, "TCP", Cmd_Argv(2), FTENET_IRCConnect_EstablishConnection, false)) { char *server; server = Cmd_Argv (1); @@ -3530,13 +3530,10 @@ void Host_Init (quakeparms_t *parms) Con_Init (); M_Init (); + //fixme: this difference needs to go. #ifndef _WIN32 IN_Init (); CDAudio_Init (); -// VID_Init (host_basepal); -// Draw_Init (); -// SCR_Init (); -// R_Init (); S_Init (); @@ -3552,6 +3549,7 @@ void Host_Init (quakeparms_t *parms) CL_Init (); IN_Init (); #endif + TranslateInit(); #ifndef CLIENTONLY SV_Init(parms); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 9e23261c8..6146a6c6b 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -456,11 +456,23 @@ void CL_DownloadFinished(void) { if (strncmp(tempname,"skins/",6)) { - FS_Rename(tempname, filename, FS_GAME); + if (!FS_Rename(tempname, filename, FS_GAME)) + { + char nativetmp[MAX_OSPATH], nativefinal[MAX_OSPATH];; + FS_NativePath(tempname, FS_GAME, nativetmp, sizeof(nativetmp)); + FS_NativePath(filename, FS_GAME, nativefinal, sizeof(nativefinal)); + Con_Printf("Couldn't rename %s to %s\n", nativetmp, nativefinal); + } } else { - FS_Rename(tempname+6, filename+6, FS_SKINS); + if (!FS_Rename(tempname+6, filename+6, FS_SKINS)) + { + char nativetmp[MAX_OSPATH], nativefinal[MAX_OSPATH];; + FS_NativePath(tempname+6, FS_SKINS, nativetmp, sizeof(nativetmp)); + FS_NativePath(filename+6, FS_SKINS, nativefinal, sizeof(nativefinal)); + Con_Printf("Couldn't rename %s to %s\n", nativetmp, nativefinal); + } } } } @@ -2104,8 +2116,21 @@ void CL_ParseServerData (void) } // seperate the printfs so the server message can have a color +#if 1 + { + int i; + Con_Printf ("\n\n"); + Con_Printf ("^Ue01d"); + for (i = 34; i-->0; i--) + Con_Printf ("^Ue01e"); + Con_Printf ("^Ue01f"); + Con_Printf ("\n\n"); + } + Con_Printf ("\1%s\n", str); +#else Con_TPrintf (TLC_LINEBREAK_NEWLEVEL); Con_TPrintf (TLC_PC_PS_NL, 2, str); +#endif if (CL_RemoveClientCommands("new")) //mvdsv is really appaling some times. { @@ -3067,7 +3092,7 @@ void CL_ParseStatic (int version) ent->shaderRGBAf[2] = (8.0f/255.0f)*es.colormod[2]; ent->shaderRGBAf[3] = es.trans/255; - ent->fatness = es.fatness/2.0; + ent->fatness = es.fatness/16.0; ent->abslight = es.abslight; VectorCopy (es.origin, ent->origin); @@ -3711,6 +3736,7 @@ void CL_MuzzleFlash (int destsplit) { dl = CL_AllocDlight (-i); VectorCopy (s1->origin, dl->origin); + AngleVectors(s1->angles, dl->axis[0], dl->axis[1], dl->axis[2]); break; } } @@ -3722,9 +3748,10 @@ void CL_MuzzleFlash (int destsplit) dl = CL_AllocDlight (-i); VectorCopy (pl->origin, dl->origin); //set it's origin + AngleVectors(pl->viewangles, dl->axis[0], dl->axis[1], dl->axis[2]); AngleVectors (pl->viewangles, fv, rv, uv); //shift it up a little - VectorMA (dl->origin, 18, fv, dl->origin); + VectorMA (dl->origin, 15, fv, dl->origin); } else return; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index f721d373a..656b683c2 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -358,7 +358,7 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode) Cbuf_AddText("f_centerprint\n", RESTRICT_LOCAL); } - COM_ParseFunString(CON_WHITEMASK, str, scr_centerstring[pnum], sizeof(scr_centerstring[pnum])); + COM_ParseFunString(CON_WHITEMASK, str, scr_centerstring[pnum], sizeof(scr_centerstring[pnum]), false); scr_centertime_off[pnum] = scr_centertime.value; scr_centertime_start[pnum] = cl.time; @@ -412,11 +412,11 @@ void SCR_CenterPrintBreaks(conchar_t *start, int *lines, int *maxlength) { // scan the width of the line for (l=0 ; l<40 ; l++) - if ((start[l]&255) == '\n' || !(start[l]&255)) + if ((start[l]&CON_CHARMASK) == '\n' || !(start[l]&CON_CHARMASK)) break; if (l == 40) { - while(l > 0 && (start[l-1]&255)>' ') + while(l > 0 && (start[l-1]&CON_CHARMASK)>' ') { l--; } @@ -430,9 +430,9 @@ void SCR_CenterPrintBreaks(conchar_t *start, int *lines, int *maxlength) // for (l=0 ; l<40 && *start && *start != '\n'; l++) // start++; - if (!(*start&255)) + if (!(*start&CON_CHARMASK)) break; - else if ((*start&255) == '\n'||!l) + else if ((*start&CON_CHARMASK) == '\n'||!l) start++; // skip the \n } while (1); } @@ -474,14 +474,14 @@ void SCR_DrawCenterString (int pnum) screenwidth = 40;//vid.width/8; - if ((start[0]&255) == '/') + if ((start[0]&CON_CHARMASK) == '/') { - if ((start[1]&255) == 'O') + if ((start[1]&CON_CHARMASK) == 'O') { - telejanostyle = (start[1]&255); + telejanostyle = (start[1]&CON_CHARMASK); start+=2; } - else if ((start[1]&255) == 'P') + else if ((start[1]&CON_CHARMASK) == 'P') { //hexen2 style plaque. int lines, len; start+=2; @@ -495,11 +495,11 @@ void SCR_DrawCenterString (int pnum) { // scan the width of the line for (l=0 ; l<=screenwidth ; l++) - if ((start[l]&255) == '\n' || !(start[l]&255)) + if ((start[l]&CON_CHARMASK) == '\n' || !(start[l]&CON_CHARMASK)) break; if (l == screenwidth+1) { - while(l > 0 && (start[l-1]&255)>' ' && (start[l-1]&255) != ' '+128) + while(l > 0 && (start[l-1]&CON_CHARMASK)>' ' && (start[l-1]&CON_CHARMASK) != ' '+128) { l--; } @@ -525,9 +525,9 @@ void SCR_DrawCenterString (int pnum) // for (l=0 ; l<40 && *start && *start != '\n'; l++) // start++; - if (!(*start&255)) + if (!(*start&CON_CHARMASK)) break; - else if ((*start&255) == '\n'||!l) + else if ((*start&CON_CHARMASK) == '\n'||!l) start++; // skip the \n } while (1); } @@ -1038,7 +1038,7 @@ void SCR_CrosshairPosition(int pnum, int *x, int *y) adj+=v_viewheight.value; start[2]+=adj; - Matrix4_Project(tr.endpos, end, cl.simangles[pnum], start, (float)rect.width/rect.height, r_refdef.fov_y); + Matrix4_Project(tr.endpos, end, cl.simangles[pnum], start, r_refdef.fov_x, r_refdef.fov_y); *x = rect.x+rect.width*end[0]; *y = rect.y+rect.height*(1-end[1]); return; diff --git a/engine/client/client.h b/engine/client/client.h index 3596582a9..c9fc00703 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -244,11 +244,20 @@ typedef struct #define MAX_DLIGHTS MAX_RTLIGHTS #endif +#define LFLAG_NORMALMODE (1<<0) +#define LFLAG_REALTIMEMODE (1<<1) + +#define LFLAG_NOSHADOWS (1<<15) +#define LFLAG_ALLOW_LMHACK (1<<16) +#define LFLAG_ALLOW_FLASH (1<<17) +#define LFLAG_ALLOW_PPL (1<<18) +#define LFLAG_ALLOW_PPL (1<<18) + +#define LFLAG_DYNAMIC (LFLAG_ALLOW_PPL | LFLAG_ALLOW_LMHACK | LFLAG_ALLOW_FLASH | LFLAG_NORMALMODE | LFLAG_REALTIMEMODE) typedef struct dlight_s { int key; // so entities can reuse same entry - qboolean noppl, nodynamic, noflash, isstatic; vec3_t origin; vec3_t axis[3]; float radius; @@ -258,6 +267,8 @@ typedef struct dlight_s float color[3]; float channelfade[3]; + unsigned int flags; + //the following are used for rendering (client code should clear on create) struct shadowmesh_s *worldshadowmesh; int stexture; diff --git a/engine/client/console.c b/engine/client/console.c index d3faac9a3..3304fe784 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -24,6 +24,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. console_t con_main; console_t *con_current; // point to either con_main +//#undef AVAIL_FREETYPE +#ifdef AVAIL_FREETYPE + extern struct font_s *conchar_font; + int GLFont_DrawChar(struct font_s *font, int px, int py, unsigned int charcode); + void GLFont_BeginString(struct font_s *font, int vx, int vy, int *px, int *py); + + #define Font_DrawChar(x,y,c) (conchar_font?GLFont_DrawChar(conchar_font, x, y, c):(Draw_ColouredCharacter(x, y, c),(x)+8)) + + #define Font_CharWidth(c) (conchar_font?GLFont_CharWidth(conchar_font, c):8) + #define Font_CharHeight() (conchar_font?GLFont_CharHeight(conchar_font):8) +#else + #define Font_DrawChar(x,y,c) (Draw_ColouredCharacter(x, y, c),(x)+8) + #define Font_CharWidth(c) 8 + #define Font_CharHeight() 8 +#endif + +static int Con_LineBreaks(conchar_t *start, conchar_t *end, int scrwidth, int maxlines, conchar_t **starts, conchar_t **ends); +void Con_DrawProgress(int left, int right, int y); + #ifdef QTERM #include typedef struct qterm_s { @@ -53,6 +72,7 @@ cvar_t con_numnotifylines = SCVAR("con_notifylines","4"); //max lines to show cvar_t con_notifytime = SCVAR("con_notifytime","3"); //seconds cvar_t con_centernotify = SCVAR("con_centernotify", "0"); cvar_t con_displaypossibilities = SCVAR("con_displaypossibilities", "1"); +cvar_t con_maxlines = SCVAR("con_maxlines", "1024"); cvar_t cl_chatmode = SCVAR("cl_chatmode", "2"); #define NUM_CON_TIMES 24 @@ -364,13 +384,16 @@ Con_Clear_f */ void Con_Clear_f (void) { - int i; - //wide chars, not standard ascii - for (i = 0; i < sizeof(con_main.text)/sizeof(conchar_t); i++) + conline_t *t; + while (con_main.current) { - con_main.text[i] = CON_DEFAULTCHAR; -// Q_memset (con_main.text, ' ', sizeof(con_main.text)); + t = con_main.current; + con_main.current = t->older; + Z_Free(t); } + con_main.display = con_main.current = con_main.oldest = NULL; + + Con_ResizeCon(&con_main); } @@ -418,62 +441,13 @@ Con_Resize */ void Con_ResizeCon (console_t *con) { - int i, j, width, oldwidth, oldtotallines, numlines, numchars; - conchar_t tbuf[CON_TEXTSIZE]; - - if (scr_chatmode == 2) - width = (vid.width >> 4) - 2; - else - width = (vid.width >> 3) - 2; - - if (width == con->linewidth) - return; - - if (width < 1) // video hasn't been initialized yet + if (con->current == NULL) { - width = 38; - con->linewidth = width; - con->totallines = CON_TEXTSIZE / con->linewidth; - for (i = 0; i < CON_TEXTSIZE; i++) - con->text[i] = CON_DEFAULTCHAR; -// Q_memset (con->text, ' ', sizeof(con->text)); + con->oldest = con->current = Z_Malloc(sizeof(conline_t)); + con->linecount = 0; } - else - { - oldwidth = con->linewidth; - con->linewidth = width; - oldtotallines = con->totallines; - con->totallines = CON_TEXTSIZE / con->linewidth; - numlines = oldtotallines; - - if (con->totallines < numlines) - numlines = con->totallines; - - numchars = oldwidth; - - if (con->linewidth < numchars) - numchars = con->linewidth; - - Q_memcpy (tbuf, con->text, sizeof(con->text)); - for (i = 0; i < sizeof(con->text)/sizeof(conchar_t); i++) - con->text[i] = CON_DEFAULTCHAR; -// Q_memset (con->text, ' ', sizeof(con->text)); - - for (i=0 ; itext[(con->totallines - 1 - i) * con->linewidth + j] = - tbuf[((con->current - i + oldtotallines) % - oldtotallines) * oldwidth + j]; - } - } - - Con_ClearNotify (); - } - - con->current = con->totallines - 1; - con->display = con->current; + if (con->display == NULL) + con->display = con->current; } /* @@ -508,9 +482,7 @@ void Con_Init (void) con_current = &con_main; con_main.linebuffered = Con_ExecuteLine; con_main.commandcompletion = true; - con_main.linewidth = -1; Con_CheckResize (); - Con_Printf ("Console initialized.\n"); // @@ -521,6 +493,7 @@ void Con_Init (void) Cvar_Register (&con_numnotifylines, "Console controls"); Cvar_Register (&con_displaypossibilities, "Console controls"); Cvar_Register (&cl_chatmode, "Console controls"); + Cvar_Register (&con_maxlines, "Console controls"); Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f); Cmd_AddCommand ("togglechat", Con_ToggleChat_f); @@ -535,29 +508,6 @@ void Con_Init (void) Log_Init(); } - -/* -=============== -Con_Linefeed -=============== -*/ -void Con_Linefeed (console_t *con) -{ - int i, min, max; - con->x = 0; - if (con->display == con->current) - con->display++; - con->current++; - - min = (con->current%con->totallines)*con->linewidth; - max = min + con->linewidth; - for (i = min; i < max; i++) - con->text[i] = CON_DEFAULTCHAR; - -// Q_memset (&con->text[(con->current%con_totallines)*con_linewidth] -// , ' ', con_linewidth*sizeof(unsigned short)); -} - /* ================ Con_Print @@ -572,62 +522,66 @@ void Con_PrintCon (console_t *con, char *txt) { conchar_t expanded[4096]; conchar_t *c; - int y; - int l; static int cr; - COM_ParseFunString(CON_WHITEMASK, txt, expanded, sizeof(expanded)); + COM_ParseFunString(CON_WHITEMASK, txt, expanded, sizeof(expanded), false); c = expanded; while (*c) { + conchar_t *o; + if ((*c&CON_CHARMASK)=='\t') *c = (*c&~CON_CHARMASK)|' '; - // count word length - for (l=0 ; l< con->linewidth ; l++) - if ( (c[l]&CON_CHARMASK) <= ' ') - break; - - // word wrap - if (l != con->linewidth && (con->x + l > con->linewidth) ) - con->x = 0; - - if (cr) - { - con->current--; - cr = false; - } - - - if (!con->x) - { - Con_Linefeed (con); - // mark time for transparent overlay - con_times[con->current % NUM_CON_TIMES] = realtime; - } - switch (*c & (CON_CHARMASK&~CON_HIGHCHARSMASK)) { - case '\n': - con->x = 0; - break; - case '\r': - con->x = 0; - cr = 1; + cr = true; break; + case '\n': + if (cr) + cr = false; + while (con->linecount >= con_maxlines.value) + { + if (con->oldest == con->current) + break; - default: // display character and advance - y = con->current % con->totallines; - con->text[y*con->linewidth+con->x] = *c; - con->x++; - if (con->x >= con->linewidth) - con->x = 0; + if (con->display == con->oldest) + con->display = con->oldest->newer; + con->oldest = con->oldest->newer; + Z_Free(con->oldest->older); + con->oldest->older = NULL; + con->linecount--; + } + con->linecount++; + if (con == &con_main) + con_times[con->linesprinted++%NUM_CON_TIMES] = realtime; + con->current->newer = Z_Malloc(sizeof(sizeof(conline_t))); + con->current->newer->older = con->current; + con->current = con->current->newer; + con->current->length = 0; + if (con->display == con->current->older) + con->display = con->current; + break; + default: + if (cr) + con->current->length = 0; + if (con->display == con->current) + { + con->current = BZ_Realloc(con->current, sizeof(*con->current)+(con->current->length+1)*sizeof(conchar_t)); + con->display = con->current; + } + else + con->current = BZ_Realloc(con->current, sizeof(*con->current)+(con->current->length+1)*sizeof(conchar_t)); + if (con->current->older) + con->current->older->newer = con->current; + o = (conchar_t *)(con->current+1)+con->current->length; + *o = *c; + con->current->length+=1; break; } c++; - } } @@ -768,7 +722,7 @@ void VARGS Con_DPrintf (char *fmt, ...) va_list argptr; char msg[MAXPRINTMSG]; extern cvar_t log_developer; - + if (!developer.value && !log_developer.value) return; // early exit @@ -779,7 +733,7 @@ void VARGS Con_DPrintf (char *fmt, ...) if (!developer.value) Con_Log(msg); else - Con_Printf("%s", msg); + Con_PrintCon(&con_main, msg); } /* @@ -798,23 +752,20 @@ Con_DrawInput The input line scrolls horizontally if typing goes beyond the right edge ================ */ -void Con_DrawInput (void) +void Con_DrawInput (int left, int right, int y) { #ifdef _WIN32 extern qboolean ActiveApp; #endif - int y; int i; + int lhs, rhs; int p; unsigned char *text, *fname; extern int con_commandmatch; conchar_t maskedtext[MAXCMDLINE]; + conchar_t *endmtext; - conchar_t mask=CON_WHITEMASK; - int maskstack[4]; - int maskstackdepth = 0; - - int si, x; + int x; if (key_dest != key_console && con_current->vislines != vid.height) return; // don't draw anything (always draw if not active) @@ -829,118 +780,79 @@ void Con_DrawInput (void) //if it's not a command, and the cursor is at the end of the line, leave it as is, // but add to the end to show what the compleation will be. - for (i = 0; text[i]; i++) - { - if (text[i] == '^') //is this an escape code? - { - if (text[i+1]>='0' && text[i+1]<='9') - mask = q3codemasks[text[i+1]-'0'] | (mask&~CON_Q3MASK); //change colour only. - else if (text[i+1] == '&') // extended code - { - if (isextendedcode(text[i+2]) && isextendedcode(text[i+3])) - { - if (text[i+2] == '-') // default for FG - mask = (COLOR_WHITE << CON_FGSHIFT) | (mask&~CON_FGMASK); - else if (text[i+2] >= 'A') - mask = ((text[i+2] - ('A' - 10)) << CON_FGSHIFT) | (mask&~CON_FGMASK); - else - mask = ((text[i+2] - '0') << CON_FGSHIFT) | (mask&~CON_FGMASK); - if (text[i+3] == '-') // default (clear) for BG - mask &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (text[i+3] >= 'A') - mask = ((text[i+3] - ('A' - 10)) << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - else - mask = ((text[i+3] - '0') << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - } - } - else if (text[i+1] == 'b') - mask ^= CON_BLINKTEXT; - else if (text[i+1] == 'a') //alternate - mask ^= CON_2NDCHARSETTEXT; - else if (text[i+1] == 'h') // half-alpha - mask ^= CON_HALFALPHA; - else if (text[i+1] == 's') //store on stack (it's great for names) - { - if (maskstackdepth < sizeof(maskstack)/sizeof(maskstack[0])) - { - maskstack[maskstackdepth] = mask; - maskstackdepth++; - } - } - else if (text[i+1] == 'r') //restore from stack (it's great for names) - { - if (maskstackdepth) - { - maskstackdepth--; - mask = maskstack[maskstackdepth]; - } - } - else if (text[i+1] == '^')//next does nothing either - { - maskedtext[i] = (unsigned char)text[i] | mask; - i++; - } - } + endmtext = COM_ParseFunString(CON_WHITEMASK, text, maskedtext, sizeof(maskedtext)-1*sizeof(conchar_t), true); - maskedtext[i] = (unsigned char)text[i] | mask; - } //that's the default compleation applied + //FIXME: key_linepos is not corrected for multibyte codes. + if (endmtext < maskedtext+key_linepos) + key_linepos = endmtext-maskedtext; - maskedtext[i] = '\0'; - maskedtext[i+1] = '\0'; //just in case i==key_linepos - x = 8; - y = con_current->vislines-22; - - if (i >= con_current->linewidth) //work out the start point - si = i - con_current->linewidth; - else - si = 0; + endmtext[1] = 0; + i = 0; + x = left; if (con_current->commandcompletion) { if (text[1] == '/' || Cmd_IsCommand(text+1)) { //color the first token yellow, it's a valid command - for (p = 1; (maskedtext[p]&255)>' '; p++) - maskedtext[p] = (maskedtext[p]&255) | (COLOR_YELLOW<' '; p++) + maskedtext[p] = (maskedtext[p]&CON_CHARMASK) | (COLOR_YELLOW<linewidth); +// else +// Plug_SpellCheckMaskedText(maskedtext+1, i-1, x, y, 8, si, con_current->linewidth); - if (key_linepos == i) //cursor is at end + if (!text[key_linepos]) //cursor is at end { int cmdstart; cmdstart = text[1] == '/'?2:1; fname = Cmd_CompleteCommand(text+cmdstart, true, true, con_commandmatch); if (fname) //we can compleate it to: { - for (p = i-cmdstart; fname[p]>' '; p++) - maskedtext[p+cmdstart] = (unsigned char)fname[p] | (COLOR_GREEN<' '; p++) + maskedtext[p+cmdstart] = (unsigned int)fname[p] | (COLOR_GREEN<linewidth); +// else +// Plug_SpellCheckMaskedText(maskedtext+1, i-1, x, y, 8, si, con_current->linewidth); #ifdef _WIN32 if (ActiveApp) #endif if (((int)(realtime*con_cursorspeed)&1)) { - maskedtext[key_linepos] = 11|CON_WHITEMASK; //make it blink + maskedtext[key_linepos] = 0xe000|11|CON_WHITEMASK; //make it blink } - for (i=0,p=0; x<=con_current->linewidth*8 ; p++) //draw it + for (lhs = 0, i = key_linepos-1; i >= 0; i--) { - if (!maskedtext[p]) - break; - if (si <= i) - { - Draw_ColouredCharacter ( x, con_current->vislines - 22, maskedtext[p]); - x+=8; - } - i++; + lhs += Font_CharWidth(maskedtext[i]); + } + for (rhs = 0, i = key_linepos+1; maskedtext[i]; i++) + { + rhs += Font_CharWidth(maskedtext[i]); + } + + //put the cursor in the middle + x = (right-left)/2; + //move the line to the right if there's not enough text to touch the right hand side + if (x < right-rhs) + x = right - rhs; + //if the left hand side is on the right of the left point (overrides right alignment) + if (x - lhs > 0) + x = lhs; + + lhs = x - lhs + left; + for (i = 0; i < key_linepos; i++) + { + lhs = Font_DrawChar(lhs, y, maskedtext[i]); + } + rhs = x + left; + for (i = key_linepos; maskedtext[i]; i++) + { + rhs = Font_DrawChar(rhs, y, maskedtext[i]); } } @@ -953,25 +865,17 @@ Draws the last few lines of output transparently over the game top */ void Con_DrawNotify (void) { - int x, v; - conchar_t *text; - int i; - float time; - char *s; - int skip; + conchar_t *starts[NUM_CON_TIMES], *ends[NUM_CON_TIMES]; + conchar_t *c; + conline_t *l; + console_t *con = &con_main; + int lines=NUM_CON_TIMES; + int line; + int x = 0, y = 0; + unsigned int cn = con->linesprinted+NUM_CON_TIMES; + int maxlines; - int inset; - - int mask=CON_WHITEMASK; - int maskstack[4]; - int maskstackdepth = 0; - - console_t *con = &con_main; //notify text should never use a chat console - -#ifdef QTERM - if (qterms) - QT_Update(); -#endif + float t; maxlines = con_numnotifylines.value; if (maxlines < 0) @@ -979,222 +883,320 @@ void Con_DrawNotify (void) if (maxlines > NUM_CON_TIMES) maxlines = NUM_CON_TIMES; - v = 0; - if (con_centernotify.value) + Con_DrawProgress(0, vid.width, 0); + y += 8; + + l = con->current; + if (!l->length) + l = l->older; + for (; l && cn > con->linesprinted && lines > NUM_CON_TIMES-maxlines; l = l->older) { - for (i= con->current-maxlines+1 ; i<=con->current ; i++) + t = con_times[--cn % NUM_CON_TIMES]; + if (!t) + break; //cleared + t = realtime - t; + if (t > con_notifytime.value) + break; + + line = Con_LineBreaks((conchar_t*)(l+1), (conchar_t*)(l+1)+l->length, vid.width, lines, starts, ends); + if (!line && lines > 0) { - if (i < 0) - continue; - time = con_times[i % NUM_CON_TIMES]; - if (time == 0) - continue; - time = realtime - time; - if (time > con_notifytime.value) - continue; - text = con->text + (i % con->totallines)*con->linewidth; - - clearnotify = 0; - scr_copytop = 1; - - for (x = con->linewidth-1 ; x >= 0 ; x--) - { - if ((text[x]&0xff) != ' ') - break; - } - inset = con->linewidth*4-x*4; - - for (x = 0 ; x < con->linewidth ; x++) - Draw_ColouredCharacter ( inset + ((x+1)<<3), v, text[x]); - - v += 8; + lines--; + starts[lines] = NULL; + ends[lines] = NULL; } - + while(line --> 0 && lines > 0) + { + lines--; + starts[lines] = starts[line]; + ends[lines] = ends[line]; + } + if (lines == 0) + break; } - else + //clamp it properly + while (lines < NUM_CON_TIMES-maxlines) + lines++; + while (lines < NUM_CON_TIMES) { - for (i= con->current-maxlines+1 ; i<=con->current ; i++) + x = 0; + if (con_centernotify.value) { - if (i < 0) - continue; - time = con_times[i % NUM_CON_TIMES]; - if (time == 0) - continue; - time = realtime - time; - if (time > con_notifytime.value) - continue; - text = con->text + (i % con->totallines)*con->linewidth; - - clearnotify = 0; - scr_copytop = 1; - - for (x = 0 ; x < con->linewidth ; x++) - Draw_ColouredCharacter ( (x+1)<<3, v, text[x]); - - v += 8; + for (c = starts[lines]; c < ends[lines]; c++) + { +#ifdef AVAIL_FREETYPE + x += GLFont_CharWidth(conchar_font, *c); +#else + x += 8; +#endif + } + x = (vid.width - x) / 2; } + for (c = starts[lines]; c < ends[lines]; c++) + x = Font_DrawChar(x, y, *c); + + y += 8; + + lines++; } if (key_dest == key_message) { - clearnotify = 0; - scr_copytop = 1; - - if (chat_team) + conchar_t *starts[8]; + conchar_t *ends[8]; + conchar_t markup[MAXCMDLINE+64]; + conchar_t *c; + int lines, i; + c = COM_ParseFunString(CON_WHITEMASK, va(chat_team?"say_team: %s":"say: %s", chat_buffer), markup, sizeof(markup), true); + *c++ = (0xe00a+((int)(realtime*con_cursorspeed)&1))|CON_WHITEMASK; + lines = Con_LineBreaks(markup, c, vid.width, 8, starts, ends); + for (i = 0; i < lines; i++) { - Draw_FunString (8, v, "say_team:"); //make sure we get coloration right - skip = 11; - } - else - { - Draw_FunString (8, v, "say:"); - skip = 5; - } - - s = chat_buffer; - if (chat_bufferlen > (vid.width>>3)-(skip+1)) - s += chat_bufferlen - ((vid.width>>3)-(skip+1)); - x = chat_buffer - s; - - while(x < 0) - { - if (s[x] == '^') + c = starts[i]; + x = 0; + while (c < ends[i]) { - if (s[x+1]>='0' && s[x+1]<='9') - mask = q3codemasks[s[x+1]-'0'] | (mask&~CON_Q3MASK); //change colour only. - else if (s[x+1] == '&') // extended code - { - if (isextendedcode(s[x+2]) && isextendedcode(s[x+3])) - { - if (s[x+2] == '-') // default for FG - mask = (COLOR_WHITE << CON_FGSHIFT) | (mask&~CON_FGMASK); - else if (s[x+2] >= 'A') - mask = ((s[x+2] - ('A' - 10)) << CON_FGSHIFT) | (mask&~CON_FGMASK); - else - mask = ((s[x+2] - '0') << CON_FGSHIFT) | (mask&~CON_FGMASK); - if (s[x+3] == '-') // default (clear) for BG - mask &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (s[x+3] >= 'A') - mask = ((s[x+3] - ('A' - 10)) << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - else - mask = ((s[x+3] - '0') << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - } - } - else if (s[x+1] == 'b') - mask ^= CON_BLINKTEXT; - else if (s[x+1] == 'a') //alternate - mask ^= CON_2NDCHARSETTEXT; - else if (s[x+1] == 'h') //half-alpha - mask ^= CON_HALFALPHA; - else if (s[x+1] == 's') //store on stack (it's great for names) - { - if (maskstackdepth < sizeof(maskstack)/sizeof(maskstack[0])) - { - maskstack[maskstackdepth] = mask; - maskstackdepth++; - } - } - else if (s[x+1] == 'r') //restore from stack (it's great for names) - { - if (maskstackdepth) - { - maskstackdepth--; - mask = maskstack[maskstackdepth]; - } - } + x = Font_DrawChar(x, y, *c++); } - x++; + y += Font_CharHeight(); } - - while(s[x]) - { - if (s[x] == '^') - { - if (s[x+1]>='0' && s[x+1]<='9') - mask = q3codemasks[s[x+1]-'0'] | (mask&~CON_Q3MASK); //change colour only. - else if (s[x+1] == '&') // extended code - { - if (isextendedcode(s[x+2]) && isextendedcode(s[x+3])) - { - if (s[x+2] == '-') // default for FG - mask = (COLOR_WHITE << CON_FGSHIFT) | (mask&~CON_FGMASK); - else if (s[x+2] >= 'A') - mask = ((s[x+2] - ('A' - 10)) << CON_FGSHIFT) | (mask&~CON_FGMASK); - else - mask = ((s[x+2] - '0') << CON_FGSHIFT) | (mask&~CON_FGMASK); - if (s[x+3] == '-') // default (clear) for BG - mask &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (s[x+3] >= 'A') - mask = ((s[x+3] - ('A' - 10)) << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - else - mask = ((s[x+3] - '0') << CON_BGSHIFT) | (mask&~CON_BGMASK) | CON_NONCLEARBG; - } - } - else if (s[x+1] == 'b') - mask ^= CON_BLINKTEXT; - else if (s[x+1] == 'a') //alternate - mask ^= CON_2NDCHARSETTEXT; - else if (s[x+1] == 'h') //halfalpha - mask ^= CON_HALFALPHA; - else if (s[x+1] == 's') //store on stack (it's great for names) - { - if (maskstackdepth < sizeof(maskstack)/sizeof(maskstack[0])) - { - maskstack[maskstackdepth] = mask; - maskstackdepth++; - } - } - else if (s[x+1] == 'r') //restore from stack (it's great for names) - { - if (maskstackdepth) - { - maskstackdepth--; - mask = maskstack[maskstackdepth]; - } - } - } - - Draw_ColouredCharacter ( (x+skip)<<3, v, s[x]|mask); - x++; - } - Draw_ColouredCharacter ( (x+skip)<<3, v, (10+((int)(realtime*con_cursorspeed)&1))|CON_WHITEMASK); - v += 8; } - if (v > con_notifylines) - con_notifylines = v; + if (y > con_notifylines) + con_notifylines = y; } //send all the stuff that was con_printed to sys_print. //This is so that system consoles in windows can scroll up and have all the text. void Con_PrintToSys(void) { - int line, row, x, spc, content; - conchar_t *text; console_t *curcon = &con_main; - - content = 0; - row = curcon->current - curcon->totallines+1; - for (line = 0; line < curcon->totallines-1; line++, row++) + conline_t *l; + int i; + conchar_t *t; + for (l = curcon->oldest; l; l = l->newer) { - text = curcon->text + (row % curcon->totallines)*curcon->linewidth; - spc = 0; - for (x = 0; x < curcon->linewidth; x++) + t = (conchar_t*)(l+1); + //fixme: utf8? + for (i = 0; i < l->length; i++) + Sys_Printf("%c", t[i]&0xff); + Sys_Printf("\n"); + } +} + +static int Con_LineBreaks(conchar_t *start, conchar_t *end, int scrwidth, int maxlines, conchar_t **starts, conchar_t **ends) +{ + int l, bt; + int px; + int foundlines = 0; + + while (start < end) + { + // scan the width of the line + for (px=0, l=0 ; px <= scrwidth;) { - if (((qbyte)text[x]&255) == ' ') - spc++; // track spaces but don't print yet + if ((start[l]&CON_CHARMASK) == '\n' || (start+l >= end)) + break; + l++; + px += Font_CharWidth(start[l]); + } + //if we did get to the end + if (px > scrwidth) + { + bt = l; + //backtrack until we find a space + while(l > 0 && (start[l-1]&CON_CHARMASK)>' ') + { + l--; + } + if (l == 0 && bt>0) + l = bt-1; + px -= Font_CharWidth(start[l]); + } + + starts[foundlines] = start; + ends[foundlines] = start+l; + foundlines++; + if (foundlines == maxlines) + break; + + start+=l; +// for (l=0 ; l<40 && *start && *start != '\n'; l++) + // start++; + + if ((*start&CON_CHARMASK) == '\n'||!l) + start++; // skip the \n + } + + return foundlines; +} + +void Con_DrawProgress(int left, int right, int y) +{ +#ifdef RUNTIMELIGHTING + extern model_t *lightmodel; + extern int relitsurface; +#endif + + conchar_t dlbar[1024]; + unsigned char progresspercenttext[128]; + char *progresstext = NULL; + char *txt; + int x, tw; + int i, j; + int barwidth, barleft; + float progresspercent = 0; + *progresspercenttext = 0; + + // draw the download bar + // figure out width + if (cls.downloadmethod) + { + unsigned int count, total; + qboolean extra; + progresstext = cls.downloadlocalname; + progresspercent = cls.downloadpercent; + + if ((int)(realtime/2)&1) + sprintf(progresspercenttext, " %02d%% (%ukbps)", (int)progresspercent, CL_DownloadRate()/1000); + else + { + CL_GetDownloadSizes(&count, &total, &extra); + if (total == 0) + { + //just show progress + sprintf(progresspercenttext, " %02d%%", progresspercent); + } else { - content = 1; // start printing blank lines - for (; spc > 0; spc--) - Sys_Printf(" "); // print leading spaces - Sys_Printf("%c", (qbyte)text[x]&255); + sprintf(progresspercenttext, " %02d%% (%u%skb)", (int)progresspercent, total/1024, extra?"+":""); } } - if (content) - Sys_Printf("\n"); } +#ifdef RUNTIMELIGHTING + else if (lightmodel) + { + if (relitsurface < lightmodel->numsurfaces) + { + progresstext = "light"; + progresspercent = (relitsurface*100.0f) / lightmodel->numsurfaces; + sprintf(progresspercenttext, " %02d%%", (int)progresspercent); + } + } +#endif + + //at this point: + //progresstext: what is being downloaded/done (can end up truncated) + //progresspercent: its percentage (used only for the slider) + //progresspercenttext: that percent as text, essentually the right hand part of the bar. + + if (progresstext) + { + //chop off any leading path + if ((txt = strrchr(progresstext, '/')) != NULL) + txt++; + else + txt = progresstext; + + x = 0; + COM_ParseFunString(CON_WHITEMASK, txt, dlbar, sizeof(dlbar), false); + for (i = 0; dlbar[i]; ) + { + x += Font_CharWidth(dlbar[i]); + i++; + } + + //if the string is wider than a third of the screen + if (x > (right - left)/3) + { + //truncate the file name and add ... + x += 3*Font_CharWidth('.'|CON_WHITEMASK); + while (x > (right - left)/3 && i > 0) + { + i--; + x -= Font_CharWidth(dlbar[i]); + } + + dlbar[i++] = '.'|CON_WHITEMASK; + dlbar[i++] = '.'|CON_WHITEMASK; + dlbar[i++] = '.'|CON_WHITEMASK; + dlbar[i] = 0; + } + + //i is the char index of the dlbar so far, x is the char width of it. + + //add a couple chars + dlbar[i] = ':'|CON_WHITEMASK; + x += Font_CharWidth(dlbar[i]); + i++; + dlbar[i] = ' '|CON_WHITEMASK; + x += Font_CharWidth(dlbar[i]); + i++; + + COM_ParseFunString(CON_WHITEMASK, progresspercenttext, dlbar+i, sizeof(dlbar)-i*sizeof(conchar_t), false); + for (j = i, tw = 0; dlbar[j]; ) + { + tw += Font_CharWidth(dlbar[j]); + j++; + } + + 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]); + + //draw the left hand side + x = left; + for (j = 0; j < i; j++) + x = Font_DrawChar(x, y, dlbar[j]); + + //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); + barleft = x; + for(;;) + { + if (x + Font_CharWidth(0xe081|CON_WHITEMASK) > barleft+barwidth) + break; + x = Font_DrawChar(x, y, 0xe081|CON_WHITEMASK); + } + x = Font_DrawChar(x, y, 0xe082|CON_WHITEMASK); + + Font_DrawChar(barleft+(barwidth*progresspercent)/100 - Font_CharWidth(0xe083|CON_WHITEMASK)/2, y, 0xe083|CON_WHITEMASK); + } +} + +//draws console selection choices at the top of the screen, if multiple consoles are available +//its ctrl+tab to switch between them +int Con_DrawAlternateConsoles(int lines) +{ + char *txt; + int x, y = 0; + if (lines == scr_conlines && con_main.next) + { + console_t *con = con_current; + for (x = 0, con = &con_main; con; con = con->next) + { + if (con == &con_main) + txt = "MAIN"; + else + txt = con->name; + + if (x != 0 && x+(strlen(txt)+1)*8 > vid.width) + { + x = 0; + y += 8; + } + Draw_FunString(x, y, va("^&F%i%s", (con==con_current)+con->unseentext*4, txt)); + x+=(strlen(txt)+1)*8; + } + y += 8; + } + return y; } /* @@ -1206,25 +1208,16 @@ Draws the console with the solid background */ void Con_DrawConsole (int lines, qboolean noback) { - int i, j, x, y; - float n; - int rows; - conchar_t *text; - char *txt; - int row; - unsigned char dlbar[1024]; - unsigned char progresspercenttext[128]; - char *progresstext; - int progresspercent; extern qboolean scr_con_forcedraw; + int x, y, sx, ex, linecount, linelength; + conline_t *l; + conchar_t *s; + int selsx, selsy, selex, seley, selactive; + int top; + conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])]; + int i; + extern int glwidth; -#ifdef RUNTIMELIGHTING - extern model_t *lightmodel; - extern int relitsurface; -#endif - - console_t *curcon = con_current; - if (lines <= 0) return; @@ -1239,158 +1232,169 @@ void Con_DrawConsole (int lines, qboolean noback) con_current->unseentext = false; -// draw the text con_current->vislines = lines; - -// changed to line things up better - rows = (lines-22)>>3; // rows of text to draw - y = lines - 30; + x = 8; + y = lines; - if (lines == scr_conlines && con_main.next) + selactive = Key_GetConsoleSelectionBox(&selsx, &selsy, &selex, &seley); + +#ifdef AVAIL_FREETYPE + if (conchar_font) { - console_t *con = con_current; - rows--; - for (x = 0, con = &con_main; con; con = con->next) - { - if (con == &con_main) - txt = "MAIN"; - else - txt = con->name; - - if (x != 0 && x+(strlen(txt)+1)*8 > curcon->linewidth*8) - { - x = 0; - rows--; - } - Draw_FunString(x, 0, va("^&F%i%s", (con==con_current)+con->unseentext*4, txt)); - x+=(strlen(txt)+1)*8; - } - rows--; - } - - Key_ConsoleDrawSelectionBox(); - -// draw from the bottom up - if (curcon->display != curcon->current) - { - // draw arrows to show the buffer is backscrolled - for (x=0 ; xlinewidth ; x+=4) - Draw_Character ( (x+1)<<3, y, '^'); - - y -= 8; - rows--; - } - - row = curcon->display; - for (i=0 ; icurrent - row >= curcon->totallines) - break; // past scrollback wrap point - - text = curcon->text + (row % curcon->totallines)*curcon->linewidth; - - for (x=0 ; xlinewidth ; x++) - { - if (text[x]) - Draw_ColouredCharacter ( (x+1)<<3, y, text[x]); - } - } - - progresstext = NULL; - progresspercent = 0; - *progresspercenttext = 0; - - // draw the download bar - // figure out width - if (cls.downloadmethod) - { - unsigned int count, total; - qboolean extra; - progresstext = cls.downloadlocalname; - progresspercent = cls.downloadpercent; - - if ((int)(realtime/2)&1) - sprintf(progresspercenttext, " %02d%% (%ukbps)", progresspercent, CL_DownloadRate()/1000); - else - { - CL_GetDownloadSizes(&count, &total, &extra); - if (total == 0) - { - //just show progress - sprintf(progresspercenttext, " %02d%%", progresspercent); - } - else - { - sprintf(progresspercenttext, " %02d%% (%u%skb)", progresspercent, total/1024, extra?"+":""); - } - } - } -#ifdef RUNTIMELIGHTING - else if (lightmodel) - { - if (relitsurface < lightmodel->numsurfaces) - { - progresstext = "light"; - progresspercent = (int)((relitsurface*100.0f) / lightmodel->numsurfaces); - sprintf(progresspercenttext, " %02d%%", progresspercent); - } + GLFont_BeginString(conchar_font, x, y, &x, &y); + GLFont_BeginString(conchar_font, selsx, selsy, &selsx, &selsy); + GLFont_BeginString(conchar_font, selex, seley, &selex, &seley); + ex = glwidth; } + else #endif + ex = vid.width; + sx = x; + ex -= sx; - if (progresstext) + y -= Font_CharHeight(); + Con_DrawProgress(x, ex - x, y); + y -= Font_CharHeight(); + Con_DrawInput (x, ex - x, y); + + if (selactive) { - if ((txt = strrchr(progresstext, '/')) != NULL) - txt++; - else - txt = progresstext; + if (selsx < x) + selsx = x; + if (selex < x) + selex = x; - x = curcon->linewidth;// - ((curcon->linewidth * 7) / 40); - y = x - strlen(txt) - 4; - i = curcon->linewidth/3; - if (strlen(txt) > i) + if (selsy > y) + selsy = y; + if (seley > y) + seley = y; + + selsy -= y; + seley -= y; + selsy /= Font_CharHeight(); + seley /= Font_CharHeight(); + selsy--; + seley--; + + if (selsy == seley) { - y = x - i - 7; - Q_strncpyN(dlbar, txt, i); - strcat(dlbar, "..."); + //single line selected backwards + if (selex < selsx) + { + x = selex; + selex = selsx; + selsx = x; + } } - else - strcpy(dlbar, txt); - y -= strlen(progresspercenttext); - strcat(dlbar, ": "); - i = strlen(dlbar); - dlbar[i++] = '\x80'; - // where's the dot go? - if (progresspercent == 0) - n = 0; - else - n = y * progresspercent / 100; + if (seley < selsy) + { //selection goes upwards + x = selsy; + selsy = seley; + seley = x; - x = i; - for (j = 0; j < y; j++) - { -// if (j == n) -// dlbar[i++] = '\x83'; -// else - dlbar[i++] = '\x81'; + x = selex; + selex = selsx; + selsx = x; } - dlbar[i++] = '\x82'; - dlbar[i] = 0; - - strcpy(dlbar + strlen(dlbar), progresspercenttext); - - // draw it - y = curcon->vislines-22 + 8; - for (i = 0; i < strlen(dlbar); i++) - Draw_ColouredCharacter ( (i+1)<<3, y, (unsigned char)dlbar[i] | CON_WHITEMASK); - - Draw_ColouredCharacter ((n+1+x)*8, y, (unsigned char)'\x83' | CON_WHITEMASK); + selsy *= Font_CharHeight(); + seley *= Font_CharHeight(); + selsy += y; + seley += y; } - + + top = Con_DrawAlternateConsoles(lines); + + if (!con_current->display) + con_current->display = con_current->current; + l = con_current->display; + + if (l != con_current->current) + { + y -= 8; + // draw arrows to show the buffer is backscrolled + for (x = sx ; xcurrent && l->length == 0) + l = l->older; + for (; l; l = l->older) + { + s = (conchar_t*)(l+1); + + linecount = Con_LineBreaks(s, s+l->length, ex-sx, sizeof(starts)/sizeof(starts[0]), starts, ends); + + //if Con_LineBreaks didn't find any lines at all, then it was an empty line, and we need to ensure that its still drawn + if (linecount == 0) + { + linecount = 1; + starts[0] = ends[0] = NULL; + } + + while (linecount-- > 0) + { + s = starts[linecount]; + linelength = ends[linecount] - s; + + y -= Font_CharHeight(); + + if (top && y < top) + break; + + if (selactive) + { + if (y >= selsy) + { + if (y <= seley) + { + int sstart; + int send; + sstart = sx; + send = sstart+linelength*8; + + //show something on blank lines + if (send == sstart) + send = sstart + Font_CharWidth(' '); + + if (y >= seley) + { + send = sstart; + for (i = 0; i < linelength; i++) + { + send += Font_CharWidth(s[i]); + if (send > selex) + break; + } + } + if (y <= selsy) + { + for (i = 0; i < linelength; i++) + { + x = Font_CharWidth(s[i]); + if (sstart + x > selsx) + break; + sstart += x; + } + } + + Draw_Fill(sstart, y, send - sstart, Font_CharHeight(), 0); + } + } + } + + x = sx; + for (i = 0; i < linelength; i++) + { + x = Font_DrawChar(x, y, *s++); + } + + if (!top && y < top) + break; + } + } + // draw the input prompt, user text, and cursor if desired - Con_DrawInput (); DrawCursor(); } diff --git a/engine/client/in_win.c b/engine/client/in_win.c index ad41237d3..c00de0520 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -58,6 +58,7 @@ cvar_t m_forcewheel = SCVAR("m_forcewheel", "1"); cvar_t m_forcewheel_threshold = SCVAR("m_forcewheel_threshold", "32"); cvar_t in_mwhook = SCVARF("in_mwhook","0", CVAR_ARCHIVE); cvar_t in_dinput = SCVARF("in_dinput","0", CVAR_ARCHIVE); +cvar_t in_builtinkeymap = SCVARF("in_builtinkeymap", "1", CVAR_ARCHIVE); cvar_t m_accel_noforce = SCVAR("m_accel_noforce", "0"); cvar_t m_threshold_noforce = SCVAR("m_threshold_noforce", "0"); @@ -370,11 +371,11 @@ void MW_Hook_Message (long buttons) buttons &= 0xFFFF; switch (buttons ^ old_buttons) { - case 8: Key_Event(K_MOUSE4, buttons > old_buttons ? true : false); break; - case 16: Key_Event(K_MOUSE5, buttons > old_buttons ? true : false); break; - case 32: Key_Event(K_MOUSE6, buttons > old_buttons ? true : false); break; - case 64: Key_Event(K_MOUSE7, buttons > old_buttons ? true : false); break; - case 128: Key_Event(K_MOUSE8, buttons > old_buttons ? true : false); break; + case 8: Key_Event(K_MOUSE4, 0, buttons > old_buttons ? true : false); break; + case 16: Key_Event(K_MOUSE5, 0, buttons > old_buttons ? true : false); break; + case 32: Key_Event(K_MOUSE6, 0, buttons > old_buttons ? true : false); break; + case 64: Key_Event(K_MOUSE7, 0, buttons > old_buttons ? true : false); break; + case 128: Key_Event(K_MOUSE8, 0, buttons > old_buttons ? true : false); break; default: break; } @@ -1276,6 +1277,7 @@ void IN_Init (void) Cvar_Register (&in_mwhook, "Input Controls"); Cvar_Register (&in_dinput, "Input Controls"); + Cvar_Register (&in_builtinkeymap, "Input Controls"); Cvar_Register (&m_accel_noforce, "Input Controls"); Cvar_Register (&m_threshold_noforce, "Input Controls"); @@ -1383,13 +1385,13 @@ void IN_MouseEvent (int mstate) if ( (mstate & (1<buttons & (1<oldbuttons & (1<buttons & (1<oldbuttons & (1<oldbuttons = mouse->buttons; @@ -1432,15 +1434,15 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) { while(mouse->wheeldelta <= -mfwt) { - Key_Event (K_MWHEELUP, true); - Key_Event (K_MWHEELUP, false); + Key_Event (K_MWHEELUP, 0, true); + Key_Event (K_MWHEELUP, 0, false); mouse->wheeldelta += mfwt; } while(mouse->wheeldelta >= mfwt) { - Key_Event (K_MWHEELDOWN, true); - Key_Event (K_MWHEELDOWN, false); + Key_Event (K_MWHEELDOWN, 0, true); + Key_Event (K_MWHEELDOWN, 0, false); mouse->wheeldelta -= mfwt; } } @@ -1864,38 +1866,38 @@ void IN_RawInput_MouseRead(HANDLE in_device_handle) // buttons if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_DOWN) - Key_Event(K_MOUSE1, true); + Key_Event(K_MOUSE1, 0, true); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_1_UP) - Key_Event(K_MOUSE1, false); + Key_Event(K_MOUSE1, 0, false); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_DOWN) - Key_Event(K_MOUSE2, true); + Key_Event(K_MOUSE2, 0, true); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_2_UP) - Key_Event(K_MOUSE2, false); + Key_Event(K_MOUSE2, 0, false); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_DOWN) - Key_Event(K_MOUSE3, true); + Key_Event(K_MOUSE3, 0, true); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_3_UP) - Key_Event(K_MOUSE3, false); + Key_Event(K_MOUSE3, 0, false); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) - Key_Event(K_MOUSE4, true); + Key_Event(K_MOUSE4, 0, true); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_4_UP) - Key_Event(K_MOUSE4, false); + Key_Event(K_MOUSE4, 0, false); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) - Key_Event(K_MOUSE5, true); + Key_Event(K_MOUSE5, 0, true); if (raw->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP) - Key_Event(K_MOUSE5, false); + Key_Event(K_MOUSE5, 0, false); // mouse wheel if (raw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) { // If the current message has a mouse_wheel message if ((SHORT)raw->data.mouse.usButtonData > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); + Key_Event(K_MWHEELUP, 0, true); + Key_Event(K_MWHEELUP, 0, false); } if ((SHORT)raw->data.mouse.usButtonData < 0) { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); + Key_Event(K_MWHEELDOWN, 0, true); + Key_Event(K_MWHEELDOWN, 0, false); } } @@ -1905,12 +1907,12 @@ void IN_RawInput_MouseRead(HANDLE in_device_handle) { if ( (tbuttons & (1<>16)&255; @@ -2523,3 +2521,28 @@ int MapKey (int vkey) Con_DPrintf("key 0x%02x has no translation\n", key); return scantokey[key]; } + +void IN_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down) +{ + extern cvar_t in_builtinkeymap; + int qcode; + int unicode; + + qcode = MapKey(lParam); + unicode = (qcode < 128)?qcode:0; + + if (WinNT && !in_builtinkeymap.value) + { + BYTE keystate[256]; + WCHAR wchars[2]; + GetKeyboardState(keystate); + if (ToUnicode(wParam, HIWORD(lParam), keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + //ignore if more, its probably a compose and > 65535 anyway. we can't represent that. +// if (!wchars[1]) + unicode = wchars[0]; + } + } + + Key_Event (qcode, unicode, down); +} diff --git a/engine/client/keys.c b/engine/client/keys.c index 09b01e18f..764358362 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -253,7 +253,7 @@ int PaddedPrint (char *s, int x) { int nextcolx = 0; - if (x) +/* if (x) nextcolx = (int)((x + COLUMNWIDTH)/COLUMNWIDTH)*COLUMNWIDTH; if (nextcolx > con_main.linewidth - MINCOLUMNWIDTH @@ -262,7 +262,7 @@ int PaddedPrint (char *s, int x) Con_Printf ("\n"); x=0; } - +*/ if (x) { Con_Printf (" "); @@ -434,49 +434,19 @@ void GetSelectionCoords(int *selectcoords) } */ -void Key_ConsoleDrawSelectionBox(void) +qboolean Key_GetConsoleSelectionBox(int *sx, int *sy, int *ex, int *ey) { - extern cvar_t vid_conwidth, vid_conheight; extern int mousecursor_x, mousecursor_y; - int xpos, ypos, temp; - int xpos2, ypos2; - int yadj; - + if (!con_mousedown[2]) - return; - - xpos2 = con_mousedown[0]; - ypos2 = con_mousedown[1]; - - xpos = (int)((mousecursor_x*vid_conwidth.value)/(vid.width*8)); - ypos = (int)((mousecursor_y*vid_conheight.value)/(vid.height*8)); - - if (xpos2 < 1) - xpos2 = 1; - if (xpos < 1) - xpos = 1; - if (xpos2 > con_current->linewidth) - xpos2 = con_current->linewidth; - if (xpos > con_current->linewidth) - xpos = con_current->linewidth; - if (xpos2 > xpos) { - temp = xpos; - xpos = xpos2; - xpos2 = temp; + *sx = *sy = *ex = *ey = 0; + return false; } - xpos++; - if (ypos2 > ypos) - { - temp = ypos; - ypos = ypos2; - ypos2 = temp; - } - ypos++; - - yadj = (con_current->vislines-22) % 8; - - Draw_FillRGB(xpos2*8, yadj+ypos2*8, (xpos - xpos2)*8, (ypos - ypos2)*8, sccolor[0], sccolor[1], sccolor[2]); + *sx = con_mousedown[0]; + *sy = con_mousedown[1]; + *ex = mousecursor_x; + *ey = mousecursor_y; } void Key_ConsoleRelease(int key) @@ -485,6 +455,7 @@ void Key_ConsoleRelease(int key) con_mousedown[2] = false; if (key == K_MOUSE2 && con_mousedown[2]) { +#if 0 extern cvar_t vid_conwidth, vid_conheight; extern int mousecursor_x, mousecursor_y; int xpos, ypos, temp; @@ -552,6 +523,7 @@ void Key_ConsoleRelease(int key) Sys_SaveClipboard(bufhead); Z_Free(bufhead); +#endif } } @@ -562,7 +534,7 @@ Key_Console Interactive line editing and console scrollback ==================== */ -void Key_Console (int key) +void Key_Console (unsigned int unicode, int key) { char *clipText; int upperconbound; @@ -588,8 +560,8 @@ void Key_Console (int key) int xpos, ypos; xpos = (int)((mousecursor_x*vid_conwidth.value)/(vid.width*8)); ypos = (int)((mousecursor_y*vid_conheight.value)/(vid.height*8)); - con_mousedown[0] = xpos; - con_mousedown[1] = ypos; + con_mousedown[0] = mousecursor_x; + con_mousedown[1] = mousecursor_y; if (ypos == 0 && con_main.next) { console_t *con; @@ -740,61 +712,41 @@ void Key_Console (int key) return; } - upperconbound = con_current->current - con_current->totallines + 1; - if (key == K_PGUP || key==K_MWHEELUP) { - // con_current->vislines actually contains the height of the console in - // pixels (and not the number of lines). It's 22 pixels larger - // than the text area to include borders I guess... weird shit. - // - Molgrum + int i = 2; if (keydown[K_CTRL]) + i = 8; + if (con_current->display == con_current->current) + i+=2; //skip over the blank input line, and extra so we actually move despite the addition of the ^^^^^ line + while (i-->0) { - if (con_current->display == con_current->current) - { - con_current->display -= ( ( con_current->vislines - 22 ) / 8 ); - } - else - { - con_current->display -= ( ( con_current->vislines - 30 ) / 8 ); - } + if (con_current->display->older == NULL) + break; + con_current->display = con_current->display->older; } - else - con_current->display -= 2; - - if (con_current->display < upperconbound) - con_current->display = upperconbound; return; } - if (key == K_PGDN || key==K_MWHEELDOWN) { - // con_current->vislines actually contains the height of the console in - // pixels (and not the number of lines). It's 22 pixels larger - // than the text area to include borders I guess... weird shit. - // - Molgrum + int i = 2; if (keydown[K_CTRL]) - con_current->display += ( ( con_current->vislines - 30 ) / 8 ); - else - con_current->display += 2; - - if (con_current->display < upperconbound) - con_current->display = upperconbound; - - // Changed this to prevent the following scenario: PGUP, ENTER, PGDN ,(you'll - // see the ^^^^ indicator), PGDN, (the indicator disappears but the console position - // is still the same). - // - Molgrum - if (con_current->display >= ( con_current->current - 1 )) + i = 8; + while (i-->0) + { + if (con_current->display->newer == NULL) + break; + con_current->display = con_current->display->newer; + } + if (con_current->display->newer && con_current->display->newer == con_current->current) con_current->display = con_current->current; - return; } if (key == K_HOME) { if (keydown[K_CTRL]) - con_current->display = upperconbound; + con_current->display = con_current->oldest; else key_linepos = 1; return; @@ -844,8 +796,35 @@ void Key_Console (int key) return; } - if (key < 32 || key > 127) - return; // non printable + key = unicode; + if (!key) + return; + + { + unsigned char c1; + unsigned char c2; + + if (unicode > 127) + { + extern cvar_t com_parseutf8; + if (com_parseutf8.value) + { + c1 = 0xc0 | ((unicode>>6)&0x1f); + c2 = 0x80 | (unicode&0x3f); + if (key_linepos < MAXCMDLINE-2) + { + memmove(key_lines[edit_line]+key_linepos+2, key_lines[edit_line]+key_linepos, strlen(key_lines[edit_line]+key_linepos)+1); + key_lines[edit_line][key_linepos] = c1; + key_linepos++; + key_lines[edit_line][key_linepos] = c2; + key_linepos++; + // key_lines[edit_line][key_linepos] = 0; + } + return; + } + unicode = '?'; //sorry + } + } if (keydown[K_CTRL]) { if (key >= '0' && key <= '9') @@ -877,7 +856,7 @@ void Key_Console (int key) - if (key_linepos < MAXCMDLINE-1) + if (strlen(key_lines[edit_line])+1 < MAXCMDLINE-1) { memmove(key_lines[edit_line]+key_linepos+1, key_lines[edit_line]+key_linepos, strlen(key_lines[edit_line]+key_linepos)+1); key_lines[edit_line][key_linepos] = key; @@ -988,7 +967,13 @@ int Key_StringToKeynum (char *str, int *modifier) if (!str || !str[0]) return -1; if (!str[1]) //single char. + { +#if 0//def _WIN32 + return VkKeyScan(str[0]); +#else return str[0]; +#endif + } if (!strncmp(str, "K_", 2)) str+=2; @@ -999,7 +984,9 @@ int Key_StringToKeynum (char *str, int *modifier) return kn->keynum; } if (atoi(str)) //assume ascii code. (prepend with a 0 if needed) + { return atoi(str); + } return -1; } @@ -1400,13 +1387,13 @@ Called by the system between frames for both key up and key down events Should NOT be called during an interrupt! =================== */ -void Key_Event (int key, qboolean down) +void Key_Event (int key, unsigned int unicode, qboolean down) { char *kb; char cmd[1024]; int keystate, oldstate; -// Con_Printf ("%i : %i\n", key, down); //@@@ +// Con_Printf ("%i : %i : %i\n", key, unicode, down); //@@@ oldstate = KeyModifier(keydown[K_SHIFT], keydown[K_ALT], keydown[K_CTRL]); @@ -1515,7 +1502,9 @@ void Key_Event (int key, qboolean down) } if (key == K_SHIFT) + { shift_down = down; + } if (key == K_ESCAPE) if (shift_down) @@ -1687,7 +1676,7 @@ void Key_Event (int key, qboolean down) } if (shift_down) - key = keyshift[key]; + unicode = keyshift[unicode]; if (!down) { @@ -1719,7 +1708,7 @@ void Key_Event (int key, qboolean down) case key_console: if ((key >= ' ' && key <= 127) || key == K_ENTER || key == K_TAB) key_dest = key_console; - Key_Console (key); + Key_Console (unicode, key); break; default: Sys_Error ("Bad key_dest"); diff --git a/engine/client/keys.h b/engine/client/keys.h index ad70eb03c..cf308d6cf 100644 --- a/engine/client/keys.h +++ b/engine/client/keys.h @@ -176,7 +176,7 @@ extern char chat_buffer[]; extern int chat_bufferlen; extern qboolean chat_team; -void Key_Event (int key, qboolean down); +void Key_Event (int key, unsigned int unicode, qboolean down); void Key_Init (void); void Key_WriteBindings (vfsfile_t *f); void Key_SetBinding (int keynum, int modifier, char *binding, int cmdlevel); diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index f335fafec..0555e5069 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -428,13 +428,18 @@ void PF_CL_stringwidth(progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *text = PR_GetStringOfs(prinst, OFS_PARM0); qboolean usecolours = G_FLOAT(OFS_PARM1); + float fontsize; + if (*prinst->callargc > 2) + fontsize = G_FLOAT(OFS_PARM2); + else + fontsize = 8; if (usecolours) { - G_FLOAT(OFS_RETURN) = COM_FunStringLength(text)*8; + G_FLOAT(OFS_RETURN) = COM_FunStringLength(text)*fontsize; } else { - G_FLOAT(OFS_RETURN) = strlen(text)*8; + G_FLOAT(OFS_RETURN) = strlen(text)*fontsize; } } diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 241a7f575..e36f049cb 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -2294,6 +2294,8 @@ float r_view_matrix[16]; void MYgluPerspective(double fovx, double fovy, double zNear, double zFar) { + Matrix4_Projection_Far(r_projection_matrix, fovx, fovy, zNear, zFar); + /* double xmin, xmax, ymin, ymax; ymax = zNear * tan( fovy * M_PI / 360.0 ); @@ -2321,6 +2323,7 @@ void MYgluPerspective(double fovx, double fovy, double zNear, double zFar) r_projection_matrix[7] = 0; r_projection_matrix[11] = -1; r_projection_matrix[15] = 0; + */ } void GL_InfinatePerspective(double fovx, double fovy, diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 6965fe8cd..898b8332e 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -158,7 +158,7 @@ void Draw_ExpandedString(int x, int y, conchar_t *str) void Draw_FunString(int x, int y, unsigned char *str) { conchar_t buffer[2048]; - COM_ParseFunString(CON_WHITEMASK, str, buffer, sizeof(buffer)); + COM_ParseFunString(CON_WHITEMASK, str, buffer, sizeof(buffer), false); Draw_ExpandedString(x, y, buffer); } @@ -167,9 +167,11 @@ void Draw_FunStringLen(int x, int y, unsigned char *str, int numchars) { conchar_t buffer[2048]; - if (numchars > sizeof(buffer)-1) - numchars = sizeof(buffer)-1; - COM_ParseFunString(CON_WHITEMASK, str, buffer, numchars+1); + numchars *= sizeof(conchar_t); //numchars should now be the size of the chars. + + if (numchars > sizeof(buffer)) + numchars = sizeof(buffer); + COM_ParseFunString(CON_WHITEMASK, str, buffer, numchars, false); Draw_ExpandedString(x, y, buffer); } diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index bdf141be7..ae3690a3f 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -350,19 +350,19 @@ LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam) //Trap the Left Windowskey if (pkbhs->vkCode == VK_LWIN) { - Key_Event (K_LWIN, !(pkbhs->flags & LLKHF_UP)); + Key_Event (K_LWIN, 0, !(pkbhs->flags & LLKHF_UP)); return 1; } //Trap the Right Windowskey if (pkbhs->vkCode == VK_RWIN) { - Key_Event (K_RWIN, !(pkbhs->flags & LLKHF_UP)); + Key_Event (K_RWIN, 0, !(pkbhs->flags & LLKHF_UP)); return 1; } //Trap the Application Key (what a pointless key) if (pkbhs->vkCode == VK_APPS) { - Key_Event (K_APP, !(pkbhs->flags & LLKHF_UP)); + Key_Event (K_APP, 0, !(pkbhs->flags & LLKHF_UP)); return 1; } @@ -1114,7 +1114,8 @@ void Sys_SendKeyEvents (void) if (!GetMessage (&msg, NULL, 0, 0)) break; // Sys_Quit (); - TranslateMessage (&msg); +// if (TranslateMessage (&msg)) +// continue; DispatchMessage (&msg); } #endif diff --git a/engine/client/view.c b/engine/client/view.c index 53392c260..f24e76807 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1383,7 +1383,7 @@ void R_DrawNameTags(void) { VectorCopy(state->origin, tagcenter); tagcenter[2] += 32; - Matrix4_Project(tagcenter, center, r_refdef.viewangles, r_refdef.vieworg, (float)r_refdef.vrect.width/r_refdef.vrect.height, r_refdef.fov_y); + Matrix4_Project(tagcenter, center, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); if (center[2] > 1) continue; Draw_FunString(center[0]*r_refdef.vrect.width+r_refdef.vrect.x, (1-center[1])*r_refdef.vrect.height+r_refdef.vrect.y, cl.players[i].name); diff --git a/engine/client/winquake.h b/engine/client/winquake.h index 75f0cfe7a..05a2a1eee 100644 --- a/engine/client/winquake.h +++ b/engine/client/winquake.h @@ -173,7 +173,7 @@ extern HWND hwnd_dialog; void IN_UpdateClipCursor (void); void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify); -int MapKey (int key); +void IN_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down); void MW_Hook_Message (long buttons); void S_BlockSound (void); diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index e4f8bef7a..1ecf5179c 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -83,6 +83,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #undef AVAIL_MASM #endif +//#define AVAIL_FREETYPE +//#define NEWBACKEND //set any additional defines or libs in win32 #ifndef AVAIL_MASM diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 78270497e..667e4859d 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -2567,6 +2567,24 @@ void Cmd_Vstr_f( void ) Cbuf_InsertText(v, Cmd_ExecLevel, true); } +void Cmd_toggle_f(void) +{ + cvar_t *v; + if (Cmd_Argc()<2) + { + Con_Printf("missing cvar name\n"); + return; + } + v = Cvar_Get(Cmd_Argv(1), "0", 0, "Custom variables"); + if (!v) + return; + + if (v->value) + Cvar_Set(v, "0"); + else + Cvar_Set(v, "1"); +} + void Cmd_set_f(void) { void *mark; @@ -2798,31 +2816,20 @@ void Cmd_Condump_f(void) // print out current contents of console // stripping out starting blank lines and blank spaces { - conchar_t *text; - int row, line, x, spc, content; console_t *curcon = &con_main; - - content = 0; - row = curcon->current - curcon->totallines+1; - for (line = 0; line < curcon->totallines-1; line++, row++) + conline_t *l; + int i; + conchar_t *t; + for (l = curcon->oldest; l; l = l->newer) { - text = curcon->text + (row % curcon->totallines)*curcon->linewidth; - spc = 0; - for (x = 0; x < curcon->linewidth; x++) + t = (conchar_t*)(l+1); + //FIXME: utf8? + for (i = 0; i < l->length; i++) { - if (((qbyte)text[x]&255) == ' ') - spc++; - else - { - content = 1; - for (; spc > 0; spc--) - VFS_WRITE(f, " ", 1); - c = (qbyte)text[x]&255; - VFS_WRITE(f, &c, 1); - } + c = (qbyte)t[i]&0xff; + VFS_WRITE(f, &c, 1); } - if (content) - VFS_WRITE(f, "\n", 1); + VFS_WRITE(f, "\n", 1); } } @@ -2875,6 +2882,7 @@ void Cmd_Init (void) // Cmd_AddCommand ("msg_trigger", Cmd_Msg_Trigger_f); // Cmd_AddCommand ("filter", Cmd_Msg_Filter_f); + Cmd_AddCommand ("toggle", Cmd_toggle_f); Cmd_AddCommand ("set", Cmd_set_f); Cmd_AddCommand ("set_calc", Cmd_set_f); Cmd_AddCommand ("seta", Cmd_set_f); diff --git a/engine/common/common.c b/engine/common/common.c index a1dad9afd..a91bc540c 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1746,8 +1746,19 @@ void COM_DeFunString(conchar_t *str, char *out, int outsize, qboolean ignoreflag } } -//Takes a q3-style fun string, and returns an expanded string-with-flags -void COM_ParseFunString(conchar_t defaultflags, char *str, conchar_t *out, int outsize) +static int dehex(int i) +{ + if (i >= '0' && i <= '9') + return (i-'0'); + else if (i >= 'A' && i <= 'F') + return (i-'A'+10); + else + return (i-'a'+10); +} + +//Takes a q3-style fun string, and returns an expanded string-with-flags (actual return value is the null terminator) +//outsize parameter is in _BYTES_ (so sizeof is safe). +conchar_t *COM_ParseFunString(conchar_t defaultflags, char *str, conchar_t *out, int outsize, qboolean keepmarkup) { conchar_t extstack[4]; int extstackdepth = 0; @@ -1756,18 +1767,26 @@ void COM_ParseFunString(conchar_t defaultflags, char *str, conchar_t *out, int o conchar_t ext; + outsize /= sizeof(conchar_t); + if (!outsize) + return out; + //then outsize is decremented then checked before each write, so the trailing null has space + #if 0 while(*str) { *out++ = CON_WHITEMASK|(unsigned char)*str++; } *out = 0; - return; + return out; #endif if (*str == 1 || *str == 2) { - defaultflags |= CON_HIGHCHARSMASK; + if (com_parseutf8.value) + defaultflags = (defaultflags&~CON_FGMASK) | (COLOR_MAGENTA<= '0' && *str <= '9') + if (str[1] >= '0' && str[1] <= '9') { - ext = q3codemasks[*str++-'0'] | (ext&~CON_Q3MASK); //change colour only. - continue; + ext = q3codemasks[str[1]-'0'] | (ext&~CON_Q3MASK); //change colour only. } - else if (*str == '&') // extended code + else if (str[1] == '&') // extended code { - if (isextendedcode(str[1]) && isextendedcode(str[2])) + if (isextendedcode(str[2]) && isextendedcode(str[3])) { - str++;// foreground char - if (*str == '-') // default for FG + // foreground char + if (str[2] == '-') // default for FG ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~CON_FGMASK); - else if (*str >= 'A') - ext = ((*str - ('A' - 10)) << CON_FGSHIFT) | (ext&~CON_FGMASK); + else if (str[2] >= 'A') + ext = ((str[2] - ('A' - 10)) << CON_FGSHIFT) | (ext&~CON_FGMASK); else - ext = ((*str - '0') << CON_FGSHIFT) | (ext&~CON_FGMASK); - str++; // background char - if (*str == '-') // default (clear) for BG + ext = ((str[2] - '0') << CON_FGSHIFT) | (ext&~CON_FGMASK); + // background char + if (str[3] == '-') // default (clear) for BG ext &= ~CON_BGMASK & ~CON_NONCLEARBG; - else if (*str >= 'A') - ext = ((*str - ('A' - 10)) << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; + else if (str[3] >= 'A') + ext = ((str[3] - ('A' - 10)) << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; else - ext = ((*str - '0') << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; - str++; - continue; + ext = ((str[3] - '0') << CON_BGSHIFT) | (ext&~CON_BGMASK) | CON_NONCLEARBG; + + if (!keepmarkup) + { + str += 4; + continue; + } } // else invalid code goto messedup; } - else if (*str == 'a') + else if (str[1] == 'a') { - str++; ext ^= CON_2NDCHARSETTEXT; - continue; } - else if (*str == 'b') + else if (str[1] == 'b') { - str++; ext ^= CON_BLINKTEXT; - continue; } - else if (*str == 'd') + else if (str[1] == 'd') { - str++; ext = defaultflags; - continue; } - else if (*str == 'm') + else if (str[1] == 'm') { - str++; - ext ^= CON_HIGHCHARSMASK; - continue; + if (com_parseutf8.value) + { + if ((ext & CON_FGMASK) != (COLOR_MAGENTA<= '0' && x <= '9') || (x >= 'A' && x <= 'F') || x == '-') #define ishexcode(x) ((x >= '0' && x <= '9') || (x >= 'A' && x <= 'F') || (x >= 'a' && x <= 'f')) +typedef struct conline_s { + struct conline_s *older; + unsigned int length; + struct conline_s *newer; +} conline_t; + typedef struct console_s { char name[64]; - conchar_t text[CON_TEXTSIZE]; - int current; // line where next message will be printed + int linecount; + conline_t *oldest; + conline_t *current; // line where next message will be printed int x; // offset in current line for next print - int display; // bottom of console displays this line - int linewidth; - int totallines; - int vislines; + conline_t *display; // bottom of console displays this line + int vislines; // pixel lines + int linesprinted; // for notify times qboolean unseentext; int commandcompletion; //allows tab completion of quake console commands void (*linebuffered) (struct console_s *con, char *line); //if present, called on enter, causes the standard console input to appear. diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 20325d75b..5e6bfe031 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -2768,6 +2768,11 @@ qboolean CModQ3_LoadRFaces (lump_t *l, qboolean useshaders) out->mesh = Hunk_Alloc(sizeof(mesh_t) + (sizeof(vec3_t)) * numverts); out->mesh->normals_array= map_normals_array + LittleLong(in->firstvertex); + +#pragma message("s/t vectors not calculated for q3bsp") + out->mesh->snormals_array = out->mesh->normals_array; + out->mesh->tnormals_array = out->mesh->normals_array; + out->mesh->colors_array = map_colors_array + LittleLong(in->firstvertex); out->mesh->indexes = map_surfindexes + LittleLong(in->firstindex); out->mesh->xyz_array = map_verts + LittleLong(in->firstvertex); diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index d5fea1da2..60af7d005 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -373,7 +373,7 @@ void VectorAngles(float *forward, float *up, float *result) //up may be NULL result[2] = roll; } -void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) +void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) { float angle; float sr, sp, sy, cr, cp, cy; @@ -419,7 +419,7 @@ int VectorCompare (vec3_t v1, vec3_t v2) return 1; } -void VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc) +void _VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc) { vecc[0] = veca[0] + scale*vecb[0]; vecc[1] = veca[1] + scale*vecb[1]; @@ -1027,7 +1027,47 @@ void Matrix4_Identity(float *outm) outm[15] = 1; } -void Matrix4_Projection(float *proj, float wdivh, float fovy, float neard) +void Matrix4_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard) +{ + double xmin, xmax, ymin, ymax; + + //proj + ymax = neard * tan( fovy * M_PI / 360.0 ); + ymin = -ymax; + + if (fovx == fovy) + { + xmax = ymax; + xmin = ymin; + } + else + { + xmax = neard * tan( fovx * M_PI / 360.0 ); + xmin = -xmax; + } + + proj[0] = (2*neard) / (xmax - xmin); + proj[4] = 0; + proj[8] = (xmax + xmin) / (xmax - xmin); + proj[12] = 0; + + proj[1] = 0; + proj[5] = (2*neard) / (ymax - ymin); + proj[9] = (ymax + ymin) / (ymax - ymin); + proj[13] = 0; + + proj[2] = 0; + proj[6] = 0; + proj[10] = (fard+neard)/(neard-fard); + proj[14] = (2*fard*neard)/(neard-fard); + + proj[3] = 0; + proj[7] = 0; + proj[11] = -1; + proj[15] = 0; +} + +void Matrix4_Projection_Inf(float *proj, float fovx, float fovy, float neard) { float xmin, xmax, ymin, ymax; float nudge = 1; @@ -1036,8 +1076,16 @@ void Matrix4_Projection(float *proj, float wdivh, float fovy, float neard) ymax = neard * tan( fovy * M_PI / 360.0 ); ymin = -ymax; - xmin = ymin * wdivh; - xmax = ymax * wdivh; + if (fovx == fovy) + { + xmax = ymax; + xmin = ymin; + } + else + { + xmax = neard * tan( fovx * M_PI / 360.0 ); + xmin = -xmax; + } proj[0] = (2*neard) / (xmax - xmin); proj[4] = 0; @@ -1297,6 +1345,18 @@ qboolean Matrix4_Invert(const float *m, float *out) void Matrix3x4_InvertTo3x3(float *in, float *result) { + float t1[16], tr[16]; + memcpy(t1, in, sizeof(float)*12); + t1[12] = 0; + t1[13] = 0; + t1[14] = 0; + t1[15] = 1; + Matrix4_Invert(t1, tr); + VectorCopy(tr+0, result+0); + VectorCopy(tr+4, result+3); + VectorCopy(tr+8, result+6); + return; +/* #define A(x,y) in[x+y*4] #define result(x,y) result[x+y*3] double determinant = +A(0,0)*(A(1,1)*A(2,2)-A(2,1)*A(1,2)) @@ -1312,18 +1372,19 @@ void Matrix3x4_InvertTo3x3(float *in, float *result) result(0,2) = (A(1,0)*A(2,1)-A(2,0)*A(1,1))*invdet; result(1,2) = -(A(0,0)*A(2,1)-A(2,0)*A(0,1))*invdet; result(2,2) = (A(0,0)*A(1,1)-A(1,0)*A(0,1))*invdet; + */ } //screen->3d -void Matrix4_UnProject(vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy) +void Matrix4_UnProject(vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float fovx, float fovy) { float modelview[16]; float proj[16]; float tempm[16]; Matrix4_ModelViewMatrix(modelview, viewangles, vieworg); - Matrix4_Projection(proj, wdivh, fovy, 4); + Matrix4_Projection_Inf(proj, fovx, fovy, 4); Matrix4_Multiply(proj, modelview, tempm); Matrix4_Invert(tempm, proj); @@ -1346,13 +1407,13 @@ void Matrix4_UnProject(vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, //returns fractions of screen. //uses GL style rotations and translations and stuff. //3d -> screen (fixme: offscreen return values needed) -void Matrix4_Project (vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy) +void Matrix4_Project (vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float fovx, float fovy) { float modelview[16]; float proj[16]; Matrix4_ModelViewMatrix(modelview, viewangles, vieworg); - Matrix4_Projection(proj, wdivh, fovy, 4); + Matrix4_Projection_Inf(proj, fovx, fovy, 4); { float v[4], tempv[4]; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 7d41b0c92..fd880e958 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -51,6 +51,7 @@ extern int nanmask; #define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) #define VectorLength(a) Length(a) +#define VectorMA(a,s,b,c) do{c[0] = a[0] + s*b[0];c[1] = a[1] + s*b[1];c[2] = a[2] + s*b[2];}while(0) @@ -86,7 +87,7 @@ void _VectorCopy (vec3_t in, vec3_t out); void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out); void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); float anglemod (float a); -void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); +void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); void VectorAngles (float *forward, float *up, float *angles); //up may be NULL void VARGS BOPS_Error (void); int VARGS BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane); @@ -109,12 +110,19 @@ void Matrix4_ModelMatrixFromAxis (float *modelview, vec3_t pn, vec3_t right, ve void Matrix4_ModelViewMatrix (float *modelview, vec3_t viewangles, vec3_t vieworg); void Matrix4_ModelViewMatrixFromAxis (float *modelview, vec3_t pn, vec3_t right, vec3_t up, vec3_t vieworg); void Matrix4_Multiply (float *a, float *b, float *out); -void Matrix4_Orthographic (float *proj, float xmin, float xmax, float ymax, float ymin, float znear, float zfar); -void Matrix4_Project (vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy); -void Matrix4_Projection2 (float *proj, float fovx, float fovy, float neard); +void Matrix4_Project (vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float fovx, float fovy); void Matrix4_Transform3 (float *matrix, float *vector, float *product); void Matrix4_Transform4 (float *matrix, float *vector, float *product); -void Matrix4_UnProject (vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy); +void Matrix4_UnProject (vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float fovx, float fovy); + +//projection matricies of different types... gesh +void Matrix4_Orthographic (float *proj, float xmin, float xmax, float ymax, float ymin, float znear, float zfar); +void Matrix4_Projection_Far(float *proj, float fovx, float fovy, float neard, float fard); +void Matrix4_Projection2 (float *proj, float fovx, float fovy, float neard); +void Matrix4_Projection_Inf(float *proj, float fovx, float fovy, float neard); + +fixed16_t Mul16_30 (fixed16_t multiplier, fixed16_t multiplicand); +int Q_log2 (int val); void Matrix3x4_InvertTo3x3(float *in, float *result); @@ -126,7 +134,7 @@ void R_ConcatTransforms (matrix3x4 in1, matrix3x4 in2, matrix3x4 out); void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); int VectorCompare (vec3_t v1, vec3_t v2); void VectorInverse (vec3_t v); -void VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc); +void _VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc); float VectorNormalize (vec3_t v); // returns vector length vec_t VectorNormalize2 (vec3_t v, vec3_t out); void VectorNormalizeFast(vec3_t v); diff --git a/engine/common/net.h b/engine/common/net.h index 478586931..025f261ce 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -83,7 +83,7 @@ void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t to); int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_t *remote, netadr_t *local, int idx); void NET_PrintAddresses(struct ftenet_connections_s *collection); qboolean NET_AddressSmellsFunny(netadr_t a); -void NET_EnsureRoute(struct ftenet_connections_s *collection, char *routename, char *host); +void NET_EnsureRoute(struct ftenet_connections_s *collection, char *routename, char *host, qboolean islisten); qboolean NET_CompareAdr (netadr_t a, netadr_t b); qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b); diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 5bf510a26..7840fd1c9 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -1333,7 +1333,7 @@ ftenet_connections_t *FTENET_CreateCollection(qboolean listen) return col; } -qboolean FTENET_AddToCollection(ftenet_connections_t *col, const char *name, const char *address, ftenet_generic_connection_t *(*establish)(qboolean isserver, const char *address)) +qboolean FTENET_AddToCollection(ftenet_connections_t *col, const char *name, const char *address, ftenet_generic_connection_t *(*establish)(qboolean isserver, const char *address), qboolean islisten) { int i; if (!col) @@ -1369,7 +1369,7 @@ qboolean FTENET_AddToCollection(ftenet_connections_t *col, const char *name, con { if (!col->conn[i]) { - col->conn[i] = establish(col->islisten, address); + col->conn[i] = establish(islisten, address); if (!col->conn[i]) return false; col->conn[i]->name = name; @@ -1994,28 +1994,19 @@ ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, closesocket(newsocket); return NULL; } + + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); } else { - if (!NET_StringToAdr(address, &adr)) + if (!NET_PortToAdr(affamily, address, &adr)) return NULL; //couldn't resolve the name - - temp = NetadrToSockadr(&adr, &qs); - family = ((struct sockaddr_in*)&qs)->sin_family; - - if ((newsocket = socket (family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) + newsocket = TCP_OpenStream(adr); + if (newsocket == INVALID_SOCKET) return NULL; - - if (connect(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET) - { - closesocket(newsocket); - return NULL; - } } - if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) - Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); - //this isn't fatal setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (char *)&_true, sizeof(_true)); @@ -2639,7 +2630,7 @@ ftenet_generic_connection_t *FTENET_IRCConnect_EstablishConnection(qboolean isse newcon->generic.SendPacket = FTENET_IRCConnect_SendPacket; newcon->generic.Close = FTENET_IRCConnect_Close; - newcon->generic.islisten = true; + newcon->generic.islisten = isserver; newcon->generic.addrtype[0] = NA_IRC; newcon->generic.addrtype[1] = NA_INVALID; @@ -2758,7 +2749,7 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) Con_Printf("No route - open some ports\n"); } -void NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char *host) +void NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char *host, qboolean islisten) { netadr_t adr; NET_StringToAdr(host, &adr); @@ -2767,17 +2758,17 @@ void NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char *ho { #ifdef TCPCONNECT case NA_TCP: - FTENET_AddToCollection(collection, routename, host, FTENET_TCP4Connect_EstablishConnection); + FTENET_AddToCollection(collection, routename, host, FTENET_TCP4Connect_EstablishConnection, islisten); break; #ifdef IPPROTO_IPV6 case NA_TCPV6: - FTENET_AddToCollection(collection, routename, host, FTENET_TCP6Connect_EstablishConnection); + FTENET_AddToCollection(collection, routename, host, FTENET_TCP6Connect_EstablishConnection, islisten); break; #endif #endif #ifdef IRCCONNECT case NA_IRC: - FTENET_AddToCollection(collection, routename, host, FTENET_IRCConnect_EstablishConnection); + FTENET_AddToCollection(collection, routename, host, FTENET_IRCConnect_EstablishConnection, islisten); break; #endif default: @@ -3185,7 +3176,7 @@ void SVNET_AddPort(void) { svs.sockets = FTENET_CreateCollection(true); #ifndef SERVERONLY - FTENET_AddToCollection(svs.sockets, "SVLoopback", "27500", FTENET_Loop_EstablishConnection); + FTENET_AddToCollection(svs.sockets, "SVLoopback", "27500", FTENET_Loop_EstablishConnection, true); #endif } @@ -3194,30 +3185,30 @@ void SVNET_AddPort(void) switch(adr.type) { case NA_IP: - FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_UDP4_EstablishConnection); + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_UDP4_EstablishConnection, true); break; #ifdef IPPROTO_IPV6 case NA_IPV6: - FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_UDP6_EstablishConnection); + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_UDP6_EstablishConnection, true); break; #endif #ifdef USEIPX case NA_IPX: - FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_IPX_EstablishConnection); + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_IPX_EstablishConnection, true); break; #endif #ifdef IRCCONNECT case NA_IRC: - FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_IRCConnect_EstablishConnection); + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_IRCConnect_EstablishConnection, true); break; #endif #ifdef IRCCONNECT case NA_TCP: - FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_TCP4Connect_EstablishConnection); + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_TCP4Connect_EstablishConnection, true); break; #ifdef IPPROTO_IPV6 case NA_TCPV6: - FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_TCP6Connect_EstablishConnection); + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_TCP6Connect_EstablishConnection, true); break; #endif #endif @@ -3285,14 +3276,14 @@ void NET_InitClient(void) cls.sockets = FTENET_CreateCollection(false); #ifndef CLIENTONLY - FTENET_AddToCollection(cls.sockets, "CLLoopback", port, FTENET_Loop_EstablishConnection); + FTENET_AddToCollection(cls.sockets, "CLLoopback", port, FTENET_Loop_EstablishConnection, false); #endif - FTENET_AddToCollection(cls.sockets, "CLUDP4", port, FTENET_UDP4_EstablishConnection); + FTENET_AddToCollection(cls.sockets, "CLUDP4", port, FTENET_UDP4_EstablishConnection, true); #ifdef IPPROTO_IPV6 - FTENET_AddToCollection(cls.sockets, "CLUDP6", port, FTENET_UDP6_EstablishConnection); + FTENET_AddToCollection(cls.sockets, "CLUDP6", port, FTENET_UDP6_EstablishConnection, true); #endif #ifdef USEIPX - FTENET_AddToCollection(cls.sockets, "CLIPX", port, FTENET_IPX_EstablishConnection); + FTENET_AddToCollection(cls.sockets, "CLIPX", port, FTENET_IPX_EstablishConnection, true); #endif // @@ -3316,29 +3307,29 @@ void NET_InitClient(void) #ifndef CLIENTONLY void SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue) { - FTENET_AddToCollection(svs.sockets, "SVTCP4", var->string, FTENET_TCP4Connect_EstablishConnection); + FTENET_AddToCollection(svs.sockets, "SVTCP4", var->string, FTENET_TCP4Connect_EstablishConnection, true); } #ifdef IPPROTO_IPV6 void SV_Tcpport6_Callback(struct cvar_s *var, char *oldvalue) { - FTENET_AddToCollection(svs.sockets, "SVTCP6", var->string, FTENET_TCP6Connect_EstablishConnection); + FTENET_AddToCollection(svs.sockets, "SVTCP6", var->string, FTENET_TCP6Connect_EstablishConnection, true); } #endif void SV_Port_Callback(struct cvar_s *var, char *oldvalue) { - FTENET_AddToCollection(svs.sockets, "SVUDP4", var->string, FTENET_UDP4_EstablishConnection); + FTENET_AddToCollection(svs.sockets, "SVUDP4", var->string, FTENET_UDP4_EstablishConnection, true); } #ifdef IPPROTO_IPV6 void SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue) { - FTENET_AddToCollection(svs.sockets, "SVUDP6", var->string, FTENET_UDP6_EstablishConnection); + FTENET_AddToCollection(svs.sockets, "SVUDP6", var->string, FTENET_UDP6_EstablishConnection, true); } #endif #ifdef USEIPX void SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue) { - FTENET_AddToCollection(svs.sockets, "SVIPX", var->string, FTENET_IPX_EstablishConnection); + FTENET_AddToCollection(svs.sockets, "SVIPX", var->string, FTENET_IPX_EstablishConnection, true); } #endif #endif @@ -3360,7 +3351,7 @@ void NET_InitServer(void) { svs.sockets = FTENET_CreateCollection(true); #ifndef SERVERONLY - FTENET_AddToCollection(svs.sockets, "SVLoopback", port, FTENET_Loop_EstablishConnection); + FTENET_AddToCollection(svs.sockets, "SVLoopback", port, FTENET_Loop_EstablishConnection, true); #endif } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 1e61a8e32..7f4e03019 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1530,7 +1530,7 @@ void PF_strdecolorize (progfuncs_t *prinst, struct globalvars_s *pr_globals) char *in = PR_GetStringOfs(prinst, OFS_PARM0); char result[8192]; unsigned long flagged[8192]; - COM_ParseFunString(CON_WHITEMASK, in, flagged, sizeof(flagged)/sizeof(flagged[0])); + COM_ParseFunString(CON_WHITEMASK, in, flagged, sizeof(flagged), false); COM_DeFunString(flagged, result, sizeof(result), true); RETURN_TSTRING(result); @@ -1796,14 +1796,70 @@ void PF_crc16 (progfuncs_t *prinst, struct globalvars_s *pr_globals) // #510 string(string in) uri_escape = #510; void PF_uri_escape (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *s = PR_GetStringOfs(prinst, OFS_PARM0); - RETURN_TSTRING(s); + static const char *hex = "0123456789ABCDEF"; + + unsigned char result[8192]; + unsigned char *o = result; + unsigned char *s = PR_GetStringOfs(prinst, OFS_PARM0); + *result = 0; + while (*s && o < result+sizeof(result)-4) + { + if ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') || (*s >= '0' && *s <= '9') + || *s == '.' || *s == '-' || *s == '_') + *o++ = *s++; + else + { + *o++ = '%'; + *o++ = hex[*s>>4]; + *o++ = hex[*s&0xf]; + s++; + } + } + *o = 0; + RETURN_TSTRING(result); } // #511 string(string in) uri_unescape = #511; void PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - char *s = PR_GetStringOfs(prinst, OFS_PARM0); + unsigned char *s = (unsigned char*)PR_GetStringOfs(prinst, OFS_PARM0); + unsigned char *i, *o; + unsigned char hex; + i = s; o = s; + while (*i) + { + if (*i == '%') + { + hex = 0; + if (i[1] >= 'A' && i[1] <= 'F') + hex += i[1]-'A'+10; + else if (i[1] >= 'a' && i[1] <= 'f') + hex += i[1]-'a'+10; + else if (i[1] >= '0' && i[1] <= '9') + hex += i[1]-'0'; + else + { + *o++ = *i++; + continue; + } + hex <<= 4; + if (i[2] >= 'A' && i[2] <= 'F') + hex += i[2]-'A'+10; + else if (i[2] >= 'a' && i[2] <= 'f') + hex += i[2]-'a'+10; + else if (i[2] >= '0' && i[2] <= '9') + hex += i[2]-'0'; + else + { + *o++ = *i++; + continue; + } + *o++ = hex; + i += 3; + } + *o++ = *i++; + } + *o = 0; RETURN_TSTRING(s); } diff --git a/engine/common/translate.c b/engine/common/translate.c index 74ac65aaa..fcb9f017b 100644 --- a/engine/common/translate.c +++ b/engine/common/translate.c @@ -230,7 +230,7 @@ static char *defaultlanguagetext = "TLC_HOSTFATALERROR \"Host_Error: %s\\n\"\n" "TLC_CONFIGCFG_WRITEFAILED \"Couldn't write config.cfg.\\n\"\n" "TLC_HOSTSPEEDSOUTPUT \"%3i tot %3i server %3i gfx %3i snd\\n\"\n" -"TLC_QUAKEWORLD_INITED \"€ QuakeWorld Initialized ‚\\n\"\n" +"TLC_QUAKEWORLD_INITED \"^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081 QuakeWorld Initialized ^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082\\n\"\n" "TLC_DEDICATEDCANNOTCONNECT \"Connect ignored - dedicated. set a renderer first\\n\"\n" "TLC_Q2CONLESSPACKET_UNKNOWN \"unknown connectionless packet for q2: %s\\n\"\n" "TL_NORELATIVEPATHS \"Refusing to download a path with ..\\n\"\n" diff --git a/engine/d3d/d3d_draw.c b/engine/d3d/d3d_draw.c index 51cb13e56..124f1a8f9 100644 --- a/engine/d3d/d3d_draw.c +++ b/engine/d3d/d3d_draw.c @@ -763,14 +763,14 @@ void (D3D7_Draw_ImageColours) (float r, float g, float b, float a) c[3] = a*255; } -void (D3D7_Draw_ConsoleBackground) (int lines) +void (D3D7_Draw_ConsoleBackground) (int firstline, int lastline, qboolean forceopaque) { D3D7_Draw_ImageColours(1,1,1,1); - D3D7_Draw_Image(0, 0, vid.width, lines, 0, 1 - (float)lines/vid.height, 1, 1, conback_tex); + D3D7_Draw_Image(0, 0, vid.width, lastline, 0, 1 - (float)lastline/vid.height, 1, 1, conback_tex); } void (D3D7_Draw_EditorBackground) (int lines) { - D3D7_Draw_ConsoleBackground(lines); + D3D7_Draw_ConsoleBackground(0, lines, false); } diff --git a/engine/d3d/d3d_rmain.c b/engine/d3d/d3d_rmain.c index 1237f5075..0f04bc9bd 100644 --- a/engine/d3d/d3d_rmain.c +++ b/engine/d3d/d3d_rmain.c @@ -344,7 +344,7 @@ void D3D7_DrawTextureChains(void) continue; t->texturechain = NULL; -pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)t->gl_texturenum); +pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)t->tn.base); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); @@ -466,7 +466,7 @@ void D3D7_BaseBModelTextures(entity_t *e) { t = R_TextureAnimation(s->texinfo->texture); - pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)t->gl_texturenum); + pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, (LPDIRECTDRAWSURFACE7)t->tn.base); pD3DDev->lpVtbl->SetTexture(pD3DDev, 1, (LPDIRECTDRAWSURFACE7)lightmap_d3dtextures[s->lightmaptexturenum]); { m = s->mesh; diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 73b8d0b45..ce6e73e5a 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -303,13 +303,13 @@ static LRESULT WINAPI D3D7_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA case WM_KEYDOWN: case WM_SYSKEYDOWN: if (!vid_initializing) - Key_Event (MapKey(lParam), true); + IN_TranslateKeyEvent(wParam, lParam, true); break; case WM_KEYUP: case WM_SYSKEYUP: if (!vid_initializing) - Key_Event (MapKey(lParam), false); + IN_TranslateKeyEvent(wParam, lParam, false); break; case WM_SYSCHAR: @@ -372,13 +372,13 @@ static LRESULT WINAPI D3D7_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA { if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); + Key_Event(K_MWHEELUP, 0, true); + Key_Event(K_MWHEELUP, 0, false); } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); + Key_Event(K_MWHEELDOWN, 0, true); + Key_Event(K_MWHEELDOWN, 0, false); } } break; @@ -716,7 +716,7 @@ void (D3D7_Mod_NowLoadExternal) (void) void (D3D7_Mod_Think) (void) { } -qboolean(D3D7_Mod_GetTag) (struct model_s *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) +qboolean(D3D7_Mod_GetTag) (struct model_s *model, int tagnum, framestate_t *fstate, float *result) { return false; } @@ -728,6 +728,10 @@ int (D3D7_Mod_SkinForName) (struct model_s *model, char *name) { return 0; } +int (D3D7_Mod_FrameForName) (struct model_s *model, char *name) +{ + return 0; +} void (D3D7_VID_DeInit) (void) { @@ -1185,6 +1189,7 @@ rendererinfo_t d3d7rendererinfo = D3D7_Mod_GetTag, D3D7_Mod_TagNumForName, D3D7_Mod_SkinForName, + D3D7_Mod_FrameForName, D3D7_VID_Init, diff --git a/engine/d3d9/d3d9_draw.c b/engine/d3d9/d3d9_draw.c index 236bf5f79..db86a8565 100644 --- a/engine/d3d9/d3d9_draw.c +++ b/engine/d3d9/d3d9_draw.c @@ -803,14 +803,14 @@ void D3D9_Draw_ImageColours (float r, float g, float b, float a) c[3] = a*255; } -void D3D9_Draw_ConsoleBackground (int lines) +void D3D9_Draw_ConsoleBackground (int firstline, int lastline, qboolean forceopaque) { D3D9_Draw_ImageColours(1,1,1,1); - D3D9_Draw_Image(0, 0, vid.width, lines, 0, 1 - (float)lines/vid.height, 1, 1, conback_tex); + D3D9_Draw_Image(0, 0, vid.width, lastline, 0, 1 - (float)lastline/vid.height, 1, 1, conback_tex); } void D3D9_Draw_EditorBackground (int lines) { - D3D9_Draw_ConsoleBackground(lines); + D3D9_Draw_ConsoleBackground(0, lines, false); } diff --git a/engine/d3d9/d3d9_rmain.c b/engine/d3d9/d3d9_rmain.c index 04c5cbfd0..3bc3822d8 100644 --- a/engine/d3d9/d3d9_rmain.c +++ b/engine/d3d9/d3d9_rmain.c @@ -600,12 +600,12 @@ void D3D9_DrawTextureChains(void) if (s->flags & SURF_DRAWTURB) { - IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->gl_texturenum); + IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->tn.base); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 0, D3DTSS_TEXCOORDINDEX, 0); -IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->gl_texturenum); +IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->tn.base); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 1, D3DTSS_TEXCOORDINDEX, 1); -IDirect3DDevice9_SetTexture(pD3DDev9, 1, (void*)t->gl_texturenum); +IDirect3DDevice9_SetTexture(pD3DDev9, 1, (void*)t->tn.base); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); @@ -654,7 +654,7 @@ IDirect3DDevice9_SetTextureStageState(pD3DDev9, 1, D3DTSS_COLOROP, D3DTOP_MODULA continue; } -IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->gl_texturenum); +IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->tn.base); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); IDirect3DDevice9_SetTextureStageState(pD3DDev9, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); @@ -792,7 +792,7 @@ void D3D9_BaseBModelTextures(entity_t *e) if (s->lightmaptexturenum < 0) continue; - IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->gl_texturenum); + IDirect3DDevice9_SetTexture(pD3DDev9, 0, (void*)t->tn.base); IDirect3DDevice9_SetTexture(pD3DDev9, 1, (void*)lightmap_d3d9textures[s->lightmaptexturenum]); { m = s->mesh; diff --git a/engine/d3d9/d3d9quake.h b/engine/d3d9/d3d9quake.h index d0cdce19c..76672c553 100644 --- a/engine/d3d9/d3d9quake.h +++ b/engine/d3d9/d3d9quake.h @@ -16,7 +16,7 @@ void D3D9_Draw_BeginDisc (void); mpic_t* D3D9_Draw_CachePic (char *path); void D3D9_Draw_Character (int x, int y, unsigned int num); void D3D9_Draw_ColouredCharacter (int x, int y, unsigned int num); -void D3D9_Draw_ConsoleBackground (int lines); +void D3D9_Draw_ConsoleBackground (int firstline, int lastline, qboolean forceopaque); void D3D9_Draw_Crosshair (void); void D3D9_Draw_DebugChar (qbyte num); void D3D9_Draw_EditorBackground (int lines); diff --git a/engine/d3d9/vid_d3d9.c b/engine/d3d9/vid_d3d9.c index 791f14fd9..0748b0404 100644 --- a/engine/d3d9/vid_d3d9.c +++ b/engine/d3d9/vid_d3d9.c @@ -310,13 +310,13 @@ static LRESULT WINAPI D3D9_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA case WM_KEYDOWN: case WM_SYSKEYDOWN: if (!vid_initializing) - Key_Event (MapKey(lParam), true); + IN_TranslateKeyEvent (wParam, lParam, true); break; case WM_KEYUP: case WM_SYSKEYUP: if (!vid_initializing) - Key_Event (MapKey(lParam), false); + IN_TranslateKeyEvent (wParam, lParam, false); break; case WM_SYSCHAR: @@ -379,13 +379,13 @@ static LRESULT WINAPI D3D9_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA { if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); + Key_Event(K_MWHEELUP, 0, true); + Key_Event(K_MWHEELUP, 0, false); } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); + Key_Event(K_MWHEELDOWN, 0, true); + Key_Event(K_MWHEELDOWN, 0, false); } } break; @@ -897,6 +897,10 @@ int (D3D9_Mod_SkinForName) (struct model_s *model, char *name) { return 0; } +int (D3D9_Mod_FrameForName) (struct model_s *model, char *name) +{ + return 0; +} void (D3D9_VID_DeInit) (void) { @@ -1310,7 +1314,7 @@ void (D3D9_Draw_ScalePic) (int x, int y, int width, int height, mpic_t *pic); void (D3D9_Draw_SubPic) (int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height); void (D3D9_Draw_TransPic) (int x, int y, mpic_t *pic); void (D3D9_Draw_TransPicTranslate) (int x, int y, int w, int h, qbyte *pic, qbyte *translation); -void (D3D9_Draw_ConsoleBackground) (int lines); +void D3D9_Draw_ConsoleBackground (int firstline, int lastline, qboolean forceopaque); void (D3D9_Draw_EditorBackground) (int lines); void (D3D9_Draw_TileClear) (int x, int y, int w, int h); void (D3D9_Draw_Fill) (int x, int y, int w, int h, unsigned int c); @@ -1449,6 +1453,7 @@ rendererinfo_t d3d9rendererinfo = Mod_GetTag, Mod_TagNumForName, D3D9_Mod_SkinForName, + D3D9_Mod_FrameForName, D3D9_VID_Init, diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index f3693d96e..db46eddd5 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1598,7 +1598,7 @@ qglColor3f(0,0,1); } //returns result in the form of the result vector -void RotateLightVector(vec3_t *axis, vec3_t origin, vec3_t lightpoint, vec3_t result) +void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result) { vec3_t offs; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 1beb6410d..32074b5c9 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -1277,6 +1277,10 @@ void R_ModifyTextureCoords ( shaderpass_t *pass, int unit ) { qglTexCoordPointer(2, GL_FLOAT, 0, lightmapCoordsArray); } + else if (pass->tcgen == TC_GEN_NORMAL) + { + qglTexCoordPointer(3, GL_FLOAT, 0, normalsArray); + } else { qglTexCoordPointer(2, GL_FLOAT, 0, R_VertexTCBase(pass->tcgen, unit)); @@ -2080,7 +2084,20 @@ void R_RenderMeshProgram ( meshbuffer_t *mb, shaderpass_t *pass ) switch(s->progparm[i].type) { case SP_EYEPOS: - qglUniform3fvARB(s->progparm[i].handle, 1, r_origin); + { + vec3_t t, v; + VectorSubtract(r_origin, currententity->origin, t); + + if (!Matrix3_Compare(currententity->axis, axisDefault)) + { + Matrix3_Multiply_Vec3(currententity->axis, t, v ); + } + else + { + VectorCopy(t, v); + } + qglUniform3fvARB(s->progparm[i].handle, 1, v); + } break; case SP_TIME: qglUniform1fARB(s->progparm[i].handle, r_localShaderTime); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index f5959fe21..7e6cfbf59 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -47,6 +47,10 @@ index_t r_quad_indexes[6] = {0, 1, 2, 0, 2, 3}; extern qbyte gammatable[256]; +#ifdef AVAIL_FREETYPE +struct font_s *conchar_font; +#endif + unsigned char *d_15to8table; qboolean inited15to8; extern cvar_t crosshair, crosshairimage, crosshairalpha, cl_crossx, cl_crossy, crosshaircolor, crosshairsize; @@ -1185,6 +1189,10 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); #ifdef PLUGINS Plug_DrawReloadImages(); #endif + +#ifdef AVAIL_FREETYPE + conchar_font = Font_LoadFont(16, "C:/Windows/Fonts/cour.ttf"); +#endif } void GLDraw_Init (void) @@ -1213,6 +1221,12 @@ void GLDraw_Init (void) void GLDraw_DeInit (void) { Cmd_RemoveCommand ("gl_texture_anisotropic_filtering"); +#ifdef AVAIL_FREETYPE + if (conchar_font) + Font_Free(conchar_font); + conchar_font = NULL; + Font_Shutdown(); +#endif draw_disc = NULL; @@ -1307,10 +1321,11 @@ void GLDraw_Character (int x, int y, unsigned int num) if (y <= -8) return; // totally off screen - num &= 255; - + num &= CON_CHARMASK; if (num == 32) return; // space +// if ((num&0xff00) != 0xe000 && num & ~0x7f) +// num = '?'; row = num>>4; col = num&15; @@ -2356,6 +2371,8 @@ void GL_Font_Callback(struct cvar_s *var, char *oldvalue) mpic_t *pic; int old_char_texture = char_texture; + //testfont = Font_LoadFont(testfontheight, var->string); + if (!*var->string || (!(char_texture=Mod_LoadHiResTexture(var->string, "fonts", false, true, true)) && !(char_texture=Mod_LoadHiResTexture(var->string, "charsets", false, true, true)))) diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c new file mode 100644 index 000000000..19c0cec9d --- /dev/null +++ b/engine/gl/gl_font.c @@ -0,0 +1,516 @@ +#include "quakedef.h" + +#ifdef AVAIL_FREETYPE +#include "glquake.h" + +#pragma comment(lib, "../libs/freetype2/objs/freetype239.lib") +#include +#include FT_FREETYPE_H + +static FT_Library fontlib; + +#define FONTCHARS (1<<16) +#define FONTPLANES (1<<2) //no more than 16 textures per font +#define PLANEIDXTYPE unsigned char +#define CHARIDXTYPE unsigned short + +#define INVALIDPLANE ((1<<(8*sizeof(PLANEIDXTYPE)))-1) +#define PLANEWIDTH (1<<8) +#define PLANEHEIGHT PLANEWIDTH + + + +#define GEN_CONCHAR_GLYPHS 0 //set to 0 or 1 to define whether to generate glyphs from conchars too, or if it should just draw them as glquake always used to +extern cvar_t cl_noblink; + + + +typedef struct font_s +{ + struct charcache_s + { + struct charcache_s *nextchar; + PLANEIDXTYPE texplane; + unsigned char bmx; + unsigned char bmy; + unsigned char bmw; + unsigned char bmh; + short top; + short left; + unsigned char advance; //how wide this char is, when drawn + char pad; + } chars[FONTCHARS]; + + short charheight; + + FT_Face face; +} font_t; + +typedef struct { + int texnum[FONTPLANES]; + unsigned char plane[PLANEWIDTH*PLANEHEIGHT][4]; //tracks the current plane + PLANEIDXTYPE activeplane; + unsigned char planerowx; + unsigned char planerowy; + unsigned char planerowh; + qboolean planechanged; + + struct charcache_s *oldestchar; + struct charcache_s *newestchar; +} fontplanes_t; + +static fontplanes_t fontplanes; + +void Font_Shutdown(void) +{ + int i; + for (i = 0; i < FONTPLANES; i++) + fontplanes.texnum[i] = 0; + fontplanes.activeplane = 0; + fontplanes.oldestchar = NULL; + fontplanes.newestchar = NULL; + fontplanes.planechanged = 0; + fontplanes.planerowx = 0; + fontplanes.planerowy = 0; + fontplanes.planerowh = 0; +} + +void Font_FlushPlane(font_t *f) +{ + /* + assumption: + oldest chars must be of the oldest plane + */ + if (fontplanes.planechanged) + { + GL_Bind(fontplanes.texnum[fontplanes.activeplane]); + GL_Upload32(NULL, (void*)fontplanes.plane, PLANEWIDTH, PLANEHEIGHT, false, true); + fontplanes.planechanged = false; + } + + fontplanes.activeplane++; + fontplanes.activeplane = fontplanes.activeplane % FONTPLANES; + fontplanes.planerowh = 0; + fontplanes.planerowx = 0; + fontplanes.planerowy = 0; + for (; fontplanes.oldestchar; fontplanes.oldestchar = fontplanes.oldestchar->nextchar) + { + if (fontplanes.oldestchar->texplane != fontplanes.activeplane) + break; + + //invalidate it + fontplanes.oldestchar->texplane = INVALIDPLANE; + } + if (!fontplanes.oldestchar) + fontplanes.newestchar = NULL; +} + +struct charcache_s *Font_GetChar(font_t *f, CHARIDXTYPE charidx) +{ + struct charcache_s *c = &f->chars[charidx]; + if (c->texplane == INVALIDPLANE) + { + //not cached, can't get. + return NULL; + } + return c; +} + +struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, int alphaonly, void *data, unsigned char bmw, unsigned char bmh, unsigned int pitch) +{ + int x, y; + unsigned char *out; + struct charcache_s *c = &f->chars[charidx]; + + if (fontplanes.planerowx + (int)bmw >= PLANEWIDTH) + { + fontplanes.planerowx = 0; + fontplanes.planerowy += fontplanes.planerowh; + fontplanes.planerowh = 0; + } + + if (fontplanes.planerowy+(int)bmh >= PLANEHEIGHT) + Font_FlushPlane(f); + + if (fontplanes.newestchar) + fontplanes.newestchar->nextchar = c; + else + fontplanes.oldestchar = c; + fontplanes.newestchar = c; + c->nextchar = NULL; + + c->texplane = fontplanes.activeplane; + c->bmx = fontplanes.planerowx; + c->bmy = fontplanes.planerowy; + c->bmw = bmw; + c->bmh = bmh; + + if (fontplanes.planerowh < (int)bmh) + fontplanes.planerowh = bmh; + fontplanes.planerowx += bmw; + + out = (unsigned char *)&fontplanes.plane[c->bmx+(int)c->bmy*PLANEHEIGHT]; + if (alphaonly) + { + for (y = 0; y < bmh; y++) + { + for (x = 0; x < bmw; x++) + { + *(unsigned int *)&out[x*4] = 0xffffffff; + out[x*4+3] = ((unsigned char*)data)[x]; + } + data = (char*)data + pitch; + out += PLANEWIDTH*4; + } + } + else + { + pitch*=4; + for (y = 0; y < bmh; y++) + { + for (x = 0; x < bmw; x++) + { + ((unsigned int*)out)[x] = ((unsigned int*)data)[x]; + } + data = (char*)data + pitch; + out += PLANEWIDTH*4; + } + } + fontplanes.planechanged = true; + return c; +} + +struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) +{ + struct charcache_s *c; + FT_GlyphSlot slot; + FT_Bitmap *bm; + +#if GEN_CONCHAR_GLYPHS != 0 + if (charidx >= 0xe000 && charidx <= 0xe0ff && draw_chars) + { + int cpos = charidx & 0xff; + unsigned int img[64*64], *d; + unsigned char *s; + int scale; + int x,y, ys; + if (draw_chars) + { + d = img; + s = draw_chars + 8*(cpos&15)+128*8*(cpos/16); + + scale = f->charheight/8; + if (scale < 1) + scale = 1; + if (scale > 64/8) + scale = 64/8; + + for (y = 0; y < 8; y++) + { + for (ys = 0; ys < scale; ys++) + { + for (x = 0; x < 8*scale; x++) + d[x] = d_8to24rgbtable[s[x/scale]]; + d+=8*scale; + } + s+=128; + } + c = Font_LoadGlyphData(f, charidx, false, img, 8*scale, 8*scale, 8*scale); + if (c) + { + c->advance = 8*scale; + c->left = 0; + c->top = 7*scale; + } + return c; + } + charidx &= 0x7f; + } +#endif + + if (FT_Load_Char(f->face, charidx, FT_LOAD_RENDER)) + return NULL; + + slot = f->face->glyph; + bm = &slot->bitmap; + c = Font_LoadGlyphData(f, charidx, true, bm->buffer, bm->width, bm->rows, bm->pitch); + + if (c) + { + c->advance = slot->advance.x >> 6; + c->left = slot->bitmap_left; + c->top = slot->bitmap_top; + } + return c; +} + +struct font_s *Font_LoadFont(int height, char *fontfilename) +{ + int i; + struct font_s *f; + FT_Face face; + int error; + if (!fontlib) + { + error = FT_Init_FreeType(&fontlib); + if (error) + return NULL; + } + + //fixme: use FT_Open_Face eventually + if (FT_New_Face(fontlib, fontfilename, 0, &face)) + { + return NULL; + } + + error = FT_Set_Pixel_Sizes(face, 0, height); + if (error) + { + return NULL; + } + + f = malloc(sizeof(*f)); + memset(f, 0, sizeof(*f)); + f->face = face; + f->charheight = height; + fontplanes.texnum[0] = GL_AllocNewTexture(); + fontplanes.texnum[1] = GL_AllocNewTexture(); + fontplanes.texnum[2] = GL_AllocNewTexture(); + fontplanes.texnum[3] = GL_AllocNewTexture(); + + for (i = 0; i < FONTCHARS; i++) + { + f->chars[i].texplane = INVALIDPLANE; + } + return f; +} + +void Font_Free(struct font_s *f) +{ + FT_Done_Face(f->face); + free(f); +} + +void GLFont_BeginString(struct font_s *font, int vx, int vy, int *px, int *py) +{ + *px = (vx*glwidth) / (float)vid.width; + *py = (vy*glheight) / (float)vid.height; +} + +int GLFont_CharHeight(struct font_s *font, unsigned int charcode) +{ + if (!font) + return 8; + + return font->charheight; +} + +int GLFont_CharWidth(struct font_s *font, unsigned int charcode) +{ + struct charcache_s *c; + + if (!font) + return 8; + +#if GEN_CONCHAR_GLYPHS == 0 + if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff) + return font->charheight; +#endif + + c = Font_GetChar(font, charcode&CON_CHARMASK); + if (!c) + { + c = Font_TryLoadGlyph(font, charcode&CON_CHARMASK); + if (!c) + return 0; + } + + return c->advance; +} + +int GLFont_LineBreaks(struct font_s *font, conchar_t *start, conchar_t *end, int scrwidth, int maxlines, conchar_t **starts, conchar_t **ends) +{ + int l, bt; + int px; + int foundlines = 0; + + while (start < end) + { + // scan the width of the line + for (px=0, l=0 ; px <= scrwidth;) + { + if ((start[l]&CON_CHARMASK) == '\n' || (start+l >= end)) + break; + l++; + px += GLFont_CharWidth(font, start[l]); + } + //if we did get to the end + if (px > scrwidth) + { + bt = l; + //backtrack until we find a space + while(l > 0 && (start[l-1]&CON_CHARMASK)>' ') + { + l--; + } + if (l == 0 && bt>0) + l = bt-1; + px -= GLFont_CharWidth(font, start[l]); + } + + starts[foundlines] = start; + ends[foundlines] = start+l; + foundlines++; + if (foundlines == maxlines) + break; + + start+=l; +// for (l=0 ; l<40 && *start && *start != '\n'; l++) + // start++; + + if ((*start&CON_CHARMASK) == '\n'||!l) + start++; // skip the \n + } + + return foundlines; +} + +void GLDraw_FillRGB (int x, int y, int w, int h, float r, float g, float b); +int GLFont_DrawChar(struct font_s *font, int px, int py, unsigned int charcode) +{ + struct charcache_s *c; + float s0, s1; + float t0, t1; + float nextx; + float sx, sy, sw, sh; + int col; + + if (!font) + return px; + +#if GEN_CONCHAR_GLYPHS == 0 + if ((charcode&CON_CHARMASK) >= 0xe000 && (charcode&CON_CHARMASK) <= 0xe0ff) + { + extern char_texture; + + if (charcode == 32) + return px+font->charheight; // space + + if (charcode & CON_BLINKTEXT) + { + if (!cl_noblink.value) + if ((int)(realtime*3) & 1) + return px+font->charheight; + } + + qglEnable(GL_BLEND); + qglDisable(GL_ALPHA_TEST); + + col = (charcode & CON_FGMASK) >> CON_FGSHIFT; + qglColor4f(consolecolours[col].fr, consolecolours[col].fg, consolecolours[col].fb, (charcode & CON_HALFALPHA)?0.5:1); + + charcode &= 0xff; + + sx = ((px)*vid.width) / (float)glwidth; + sy = ((py+font->charheight/8)*vid.height) / (float)glheight; + sw = ((font->charheight)*vid.width) / (float)glwidth; + sh = ((font->charheight)*vid.height) / (float)glheight; + + col = charcode&15; + s0 = (float)col/16; + s1 = (float)(col+1)/16; + + col = charcode>>4; + t0 = (float)col/16; + t1 = (float)(col+1)/16; + + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_Bind(char_texture); + + qglBegin(GL_QUADS); + qglTexCoord2f(s0, t0); + qglVertex2f(sx, sy); + qglTexCoord2f(s1, t0); + qglVertex2f(sx+sw, sy); + qglTexCoord2f(s1, t1); + qglVertex2f(sx+sw, sy+sh); + qglTexCoord2f(s0, t1); + qglVertex2f(sx, sy+sh); + qglEnd(); + qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + return px+font->charheight; + } +#endif + + c = Font_GetChar(font, charcode&CON_CHARMASK); + if (!c) + { + c = Font_TryLoadGlyph(font, charcode&CON_CHARMASK); + if (!c) + return px; + } + + nextx = px + c->advance; + + if (charcode & CON_BLINKTEXT) + { + if (!cl_noblink.value) + if ((int)(realtime*3) & 1) + return nextx; + } + + // draw background + if (charcode & CON_NONCLEARBG) + { + sx = ((px)*vid.width) / (float)glwidth; + sy = ((py+font->charheight/3)*vid.height) / (float)glheight; + sw = ((c->advance)*vid.width) / (float)glwidth; + sh = ((font->charheight)*vid.height) / (float)glheight; + + col = (charcode & CON_BGMASK) >> CON_BGSHIFT; + GLDraw_FillRGB(sx, sy, sw, sh, consolecolours[col].fr, consolecolours[col].fg, consolecolours[col].fb); + } + + + sx = ((px+c->left)*vid.width) / (float)glwidth; + sy = ((py+font->charheight-c->top)*vid.height) / (float)glheight; + sw = ((c->bmw)*vid.width) / (float)glwidth; + sh = ((c->bmh)*vid.height) / (float)glheight; + + s0 = (float)c->bmx/PLANEWIDTH; + t0 = (float)c->bmy/PLANEWIDTH; + s1 = (float)(c->bmx+c->bmw)/PLANEWIDTH; + t1 = (float)(c->bmy+c->bmh)/PLANEWIDTH; + + qglEnable(GL_BLEND); + qglDisable(GL_ALPHA_TEST); + + col = (charcode & CON_FGMASK) >> CON_FGSHIFT; + qglColor4f(consolecolours[col].fr, consolecolours[col].fg, consolecolours[col].fb, (charcode & CON_HALFALPHA)?0.5:1); + + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (fontplanes.planechanged) + { + GL_Bind(fontplanes.texnum[fontplanes.activeplane]); + GL_Upload32(NULL, (void*)fontplanes.plane, PLANEWIDTH, PLANEHEIGHT, false, true); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + fontplanes.planechanged = false; + } + GL_Bind(fontplanes.texnum[c->texplane]); + + qglBegin(GL_QUADS); + qglTexCoord2f(s0, t0); + qglVertex2f(sx, sy); + qglTexCoord2f(s1, t0); + qglVertex2f(sx+sw, sy); + qglTexCoord2f(s1, t1); + qglVertex2f(sx+sw, sy+sh); + qglTexCoord2f(s0, t1); + qglVertex2f(sx, sy+sh); + qglEnd(); + qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return nextx; +} +#endif diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 4b1936f58..b5c4c1855 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -327,12 +327,7 @@ void GLMod_ClearAll (void) { if (!mod->textures[t]) continue; - if (mod->textures[t]->gl_vboe) - qglDeleteBuffersARB(1, &mod->textures[t]->gl_vboe); - if (mod->textures[t]->gl_vbov) - qglDeleteBuffersARB(1, &mod->textures[t]->gl_vbov); - mod->textures[t]->gl_vboe = 0; - mod->textures[t]->gl_vbov = 0; + GL_ClearVBO(&mod->textures[t]->vbo); } } @@ -932,7 +927,6 @@ Mod_LoadTextures */ qboolean GLMod_LoadTextures (lump_t *l) { - extern cvar_t gl_shadeq1, gl_shadeq1_name; extern int gl_bumpmappingpossible; int i, j, pixels, num, max, altmax; miptex_t *mt; @@ -996,14 +990,9 @@ TRACE(("dbg: GLMod_LoadTextures: inittexturedescs\n")); if (!mt->offsets[0]) //this is a hl external style texture, load it a little later (from a wad) { -// tx->gl_texturenum = Mod_LoadReplacementTexture("light1_4", true, false); continue; } -// for (j=0 ; joffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); - // the pixels immediately follow the structures -// memcpy ( tx+1, mt+1, pixels); //have to be saved for dynamic screen changing (done by reloading entire vid/draw subsystem and all textures) - + if (!Q_strncmp(mt->name,"sky",3)) { tx->offsets[0] = (char *)mt + mt->offsets[0] - (char *)tx; @@ -1094,30 +1083,6 @@ TRACE(("dbg: GLMod_LoadTextures: inittexturedescs\n")); } } } -#ifdef NEWBACKEND - tx->shader = R_RegisterCustom(mt->name, Shader_DefaultBSP, &tx->tn); -#pragma message("warning: fix the following block") -#endif -#ifdef Q3SHADERS //load q3 syntax shader last, after the textures inside the bsp have been loaded and stuff. - if (cls.allow_shaders && gl_shadeq1.value && *gl_shadeq1_name.string) - { - char *star; - //find the * - if (!strcmp(gl_shadeq1_name.string, "*")) - // tx->shader = R_RegisterCustom(mt->name, NULL); //just load the regular name. - tx->shader = R_RegisterShader(mt->name); //just load the regular name. - else if (!(star = strchr(gl_shadeq1_name.string, '*')) || (strlen(gl_shadeq1_name.string)+strlen(mt->name)+1>=sizeof(altname))) //it's got to fit. - tx->shader = R_RegisterCustom(gl_shadeq1_name.string, NULL, NULL); - else - { - strncpy(altname, gl_shadeq1_name.string, star-gl_shadeq1_name.string); //copy the left - altname[star-gl_shadeq1_name.string] = '\0'; - strcat(altname, mt->name); //insert the * - strcat(altname, star+1); //add any final text. - tx->shader = R_RegisterCustom(altname, NULL, NULL); - } - } -#endif } // // sequence the animations @@ -1229,14 +1194,13 @@ TRACE(("dbg: GLMod_LoadTextures: inittexturedescs\n")); void GLMod_NowLoadExternal(void) { + extern cvar_t gl_shadeq1, gl_shadeq1_name; + extern int gl_bumpmappingpossible; int i, width, height; qboolean alphaed; texture_t *tx; - if (loadmodel->fromgame != fg_halflife) - return; - for (i=0 ; inumtextures ; i++) { tx = loadmodel->textures[i]; @@ -1287,6 +1251,33 @@ void GLMod_NowLoadExternal(void) tx->tn.bump = R_LoadTexture8Bump (va("%s_bump", tx->name), width, height, heightmap-j, true, r_shadow_bumpscale_basetexture.value); } } + + +#ifdef NEWBACKEND + tx->shader = R_RegisterCustom(tx->name, Shader_DefaultBSP, &tx->tn); +#pragma message("warning: fix the following block") +#endif +#ifdef Q3SHADERS //load q3 syntax shader last, after the textures inside the bsp have been loaded and stuff. + if (cls.allow_shaders && gl_shadeq1.value && *gl_shadeq1_name.string) + { + char altname[MAX_QPATH]; + char *star; + //find the * + if (!strcmp(gl_shadeq1_name.string, "*")) + // tx->shader = R_RegisterCustom(mt->name, NULL); //just load the regular name. + tx->shader = R_RegisterShader(tx->name); //just load the regular name. + else if (!(star = strchr(gl_shadeq1_name.string, '*')) || (strlen(gl_shadeq1_name.string)+strlen(tx->name)+1>=sizeof(altname))) //it's got to fit. + tx->shader = R_RegisterCustom(gl_shadeq1_name.string, NULL, NULL); + else + { + strncpy(altname, gl_shadeq1_name.string, star-gl_shadeq1_name.string); //copy the left + altname[star-gl_shadeq1_name.string] = '\0'; + strcat(altname, tx->name); //insert the * + strcat(altname, star+1); //add any final text. + tx->shader = R_RegisterCustom(altname, NULL, NULL); + } + } +#endif } } diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index b4ccc8a94..433f1d41b 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -77,6 +77,8 @@ typedef struct mesh_s int numvertexes; vec3_t *xyz_array; vec3_t *normals_array; + vec3_t *snormals_array; + vec3_t *tnormals_array; vec2_t *st_array; vec2_t *lmst_array; byte_vec4_t *colors_array; @@ -173,6 +175,26 @@ typedef struct { int fullbright; } texnums_t; +typedef struct +{ + int vboe; + index_t *indicies; + + int vbocoord; + vec3_t *coord; + int vbotexcoord; + vec2_t *texcoord; + int vbolmcoord; + vec2_t *lmcoord; + + int vbonormals; + vec3_t *normals; + int vbosvector; + vec3_t *svector; + int vbotvector; + vec3_t *tvector; +} vbo_t; + typedef struct texture_s { char name[64]; @@ -187,8 +209,7 @@ typedef struct texture_s struct shader_s *shader; - int gl_vbov; - int gl_vboe; + vbo_t vbo; struct msurface_s *texturechain; // for gl_texsort drawing int anim_total; // total tenths in sequence ( 0 = no) @@ -197,14 +218,18 @@ typedef struct texture_s struct texture_s *alternate_anims; // bmodels in frmae 1 use these unsigned offsets[MIPLEVELS]; // four mip maps stored } texture_t; - +/* typedef struct { float coord[3]; float texcoord[2]; float lmcoord[2]; -} vbovertex_t; + float normals[3]; + float svector[3]; + float tvector[3]; +} vbovertex_t; +*/ #define SURF_DRAWSKYBOX 0x00001 #define SURF_PLANEBACK 0x00002 #define SURF_DRAWSKY 0x00004 diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index 2c23ee0e6..c333ba8ef 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -498,10 +498,10 @@ static void PPL_BaseChain_VBO_NoBump_2TMU_Overbright(msurface_t *s, texture_t *t varrayactive = false; qglDisableClientState(GL_COLOR_ARRAY); qglEnableClientState(GL_VERTEX_ARRAY); - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tex->gl_vbov); - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tex->gl_vboe); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tex->vbo.vboe); - qglVertexPointer(3, GL_FLOAT, sizeof(vbovertex_t), ((vbovertex_t*)NULL)->coord); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tex->vbo.vbocoord); + qglVertexPointer(3, GL_FLOAT, 0, tex->vbo.coord); if (tex->alphaed || currententity->shaderRGBAf[3]<1) { @@ -526,11 +526,13 @@ static void PPL_BaseChain_VBO_NoBump_2TMU_Overbright(msurface_t *s, texture_t *t GL_MBind(GL_TEXTURE0_ARB, tex->tn.base); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(vbovertex_t), ((vbovertex_t*)NULL)->texcoord); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tex->vbo.vbotexcoord); + qglTexCoordPointer(2, GL_FLOAT, 0, tex->vbo.texcoord); GL_SelectTexture(GL_TEXTURE1_ARB); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, sizeof(vbovertex_t), ((vbovertex_t*)NULL)->lmcoord); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, tex->vbo.vbolmcoord); + qglTexCoordPointer(2, GL_FLOAT, 0, tex->vbo.lmcoord); GL_TexEnv(GL_MODULATE); @@ -762,7 +764,7 @@ static void PPL_BaseChain_Bump_2TMU(msurface_t *first, texture_t *tex) lightmap[vi]->deluxmodified = false; theRect = &lightmap[vi]->deluxrectchange; qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, + LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, lightmap[vi]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); theRect->l = LMBLOCK_WIDTH; theRect->t = LMBLOCK_HEIGHT; @@ -1705,8 +1707,7 @@ static void PPL_BaseTextureChain(msurface_t *first) dl->radius = 50; //flashblend only - dl->noppl = true; - dl->nodynamic = true; + dl->flags = LFLAG_ALLOW_FLASH; first = first->texturechain; } @@ -1851,7 +1852,7 @@ static void PPL_BaseTextureChain(msurface_t *first) { // PPL_BaseChain_NoBump_2TMU_TEST(first, t); // PPL_BaseChain_NoBump_2TMU(first, t); - if (t->gl_vbov) + if (t->vbo.vbocoord) PPL_BaseChain_VBO_NoBump_2TMU_Overbright(first, t); else PPL_BaseChain_NoBump_2TMU_Overbright(first, t); @@ -2037,7 +2038,7 @@ void PPL_BaseBModelTextures(entity_t *e) { if (!cl_dlights[k].radius) continue; - if (cl_dlights[k].nodynamic) + if (!(cl_dlights[k].flags & LFLAG_ALLOW_LMHACK)) continue; currentmodel->funcs.MarkLights (&cl_dlights[k], 1<radius || l->noppl) + if (!l->radius || !(l->flags & LFLAG_ALLOW_PPL)) continue; if (l->color[0]<0) continue; //quick check for darklight - if (l->isstatic) + if (l->flags & LFLAG_REALTIMEMODE) { if (!r_shadow_realtime_world.value) continue; @@ -5236,21 +5237,9 @@ void PPL_DrawWorld (void) for (l = lc; l; l = l->next) //we now have our quotaed list { #endif - if(!l->isstatic) - { - l->color[0]*=10; - l->color[1]*=10; - l->color[2]*=10; - } TRACE(("dbg: calling PPL_AddLight\n")); if (PPL_AddLight(l)) numlights++; - if(!l->isstatic) - { - l->color[0]/=10; - l->color[1]/=10; - l->color[2]/=10; - } } qglEnable(GL_TEXTURE_2D); @@ -5507,7 +5496,7 @@ void PPL_BeginShadowMesh(dlight_t *dl) if (buildingmesh) return; - if (!dl->isstatic) + if (dl->die) return; sh_maxverts = 0; diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 4ac7bae10..60359ad84 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -188,7 +188,7 @@ void GLR_RenderDlights (void) l = cl_dlights; for (i=0 ; iradius || l->noflash) + if (!l->radius || !(l->flags & LFLAG_ALLOW_FLASH)) continue; //dlights emitting from the local player are not visible as flashblends @@ -399,7 +399,7 @@ void GLR_PushDlights (void) l = cl_dlights; for (i=0 ; iradius || l->nodynamic) + if (!l->radius || !(l->flags & LFLAG_ALLOW_LMHACK)) continue; currentmodel->funcs.MarkLights( l, 1<nodes ); } diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 7071e70d9..84d585b01 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1045,17 +1045,18 @@ void R_SetupGL (void) screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; if (r_refdef.useperspective) { - if ((!r_shadows.value || !gl_canstencil) && gl_maxdist.value>256)//gl_nv_range_clamp) + if ((!r_shadows.value || !gl_canstencil) && gl_maxdist.value>=100)//gl_nv_range_clamp) { // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; // yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect; // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI; // MYgluPerspective (yfov, screenaspect, 4, 4096); - MYgluPerspective (fov_x, fov_y, gl_mindist.value, gl_maxdist.value); + + Matrix4_Projection_Far(r_projection_matrix, fov_x, fov_y, gl_mindist.value, gl_maxdist.value); } else { - GL_InfinatePerspective(fov_x, fov_y, gl_mindist.value); + Matrix4_Projection_Inf(r_projection_matrix, fov_x, fov_y, gl_mindist.value); } } else @@ -1151,7 +1152,7 @@ void R_RenderScene (void) r_refdef.flags |= Q2RDF_NOWORLDMODEL; #ifdef NEWBACKEND - PPL_GenShadowMaps(); + Sh_GenShadowMaps(); #endif GLR_SetupFrame (); diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 00e0f85d0..0f02a3a3d 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -24,6 +24,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "glquake.h" #include "gl_draw.h" +void R_ReloadRTLights_f(void); + + #ifdef WATERLAYERS cvar_t r_waterlayers = SCVAR("r_waterlayers","3"); #endif @@ -716,6 +719,7 @@ void GLR_DeInit (void) { Cmd_RemoveCommand ("timerefresh"); Cmd_RemoveCommand ("envmap"); + Cmd_RemoveCommand ("r_editlights_reload"); Cmd_RemoveCommand ("pointfile"); Cmd_RemoveCommand ("makewad"); @@ -750,6 +754,7 @@ void GLR_Init (void) { Cmd_AddRemCommand ("timerefresh", GLR_TimeRefresh_f); Cmd_AddRemCommand ("envmap", R_Envmap_f); + Cmd_AddRemCommand ("r_editlights_reload", R_ReloadRTLights_f); // Cmd_AddRemCommand ("makewad", R_MakeTexWad_f); @@ -779,6 +784,224 @@ void GLR_Init (void) GLR_ReInit(); } +void R_ImportRTLights(char *entlump) +{ + typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t; + + /*I'm using the DP code so I know I'll get the DP results*/ + int entnum, style, islight, skin, pflags, effects, n; + lighttype_t type; + float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4]; + char key[256], value[8192]; + + for (entnum = 0; ;entnum++) + { + entlump = COM_Parse(entlump); + if (com_token[0] != '{') + break; + + type = LIGHTTYPE_MINUSX; + origin[0] = origin[1] = origin[2] = 0; + originhack[0] = originhack[1] = originhack[2] = 0; + angles[0] = angles[1] = angles[2] = 0; + color[0] = color[1] = color[2] = 1; + light[0] = light[1] = light[2] = 1;light[3] = 300; + overridecolor[0] = overridecolor[1] = overridecolor[2] = 1; + fadescale = 1; + lightscale = 1; + style = 0; + skin = 0; + pflags = 0; + effects = 0; + islight = false; + while (1) + { + entlump = COM_Parse(entlump); + if (!entlump) + break; // error + if (com_token[0] == '}') + break; // end of entity + if (com_token[0] == '_') + Q_strncpyz(key, com_token + 1, sizeof(key)); + else + Q_strncpyz(key, com_token, sizeof(key)); + while (key[strlen(key)-1] == ' ') // remove trailing spaces + key[strlen(key)-1] = 0; + entlump = COM_Parse(entlump); + if (!entlump) + break; // error + Q_strncpyz(value, com_token, sizeof(value)); + + // now that we have the key pair worked out... + if (!strcmp("light", key)) + { + n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]); + if (n == 1) + { + // quake + light[0] = vec[0] * (1.0f / 256.0f); + light[1] = vec[0] * (1.0f / 256.0f); + light[2] = vec[0] * (1.0f / 256.0f); + light[3] = vec[0]; + } + else if (n == 4) + { + // halflife + light[0] = vec[0] * (1.0f / 255.0f); + light[1] = vec[1] * (1.0f / 255.0f); + light[2] = vec[2] * (1.0f / 255.0f); + light[3] = vec[3]; + } + } + else if (!strcmp("delay", key)) + type = atoi(value); + else if (!strcmp("origin", key)) + sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]); + else if (!strcmp("angle", key)) + angles[0] = 0, angles[1] = atof(value), angles[2] = 0; + else if (!strcmp("angles", key)) + sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]); + else if (!strcmp("color", key)) + sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]); + else if (!strcmp("wait", key)) + fadescale = atof(value); + else if (!strcmp("classname", key)) + { + if (!strncmp(value, "light", 5)) + { + islight = true; + if (!strcmp(value, "light_fluoro")) + { + originhack[0] = 0; + originhack[1] = 0; + originhack[2] = 0; + overridecolor[0] = 1; + overridecolor[1] = 1; + overridecolor[2] = 1; + } + if (!strcmp(value, "light_fluorospark")) + { + originhack[0] = 0; + originhack[1] = 0; + originhack[2] = 0; + overridecolor[0] = 1; + overridecolor[1] = 1; + overridecolor[2] = 1; + } + if (!strcmp(value, "light_globe")) + { + originhack[0] = 0; + originhack[1] = 0; + originhack[2] = 0; + overridecolor[0] = 1; + overridecolor[1] = 0.8; + overridecolor[2] = 0.4; + } + if (!strcmp(value, "light_flame_large_yellow")) + { + originhack[0] = 0; + originhack[1] = 0; + originhack[2] = 0; + overridecolor[0] = 1; + overridecolor[1] = 0.5; + overridecolor[2] = 0.1; + } + if (!strcmp(value, "light_flame_small_yellow")) + { + originhack[0] = 0; + originhack[1] = 0; + originhack[2] = 0; + overridecolor[0] = 1; + overridecolor[1] = 0.5; + overridecolor[2] = 0.1; + } + if (!strcmp(value, "light_torch_small_white")) + { + originhack[0] = 0; + originhack[1] = 0; + originhack[2] = 0; + overridecolor[0] = 1; + overridecolor[1] = 0.5; + overridecolor[2] = 0.1; + } + if (!strcmp(value, "light_torch_small_walltorch")) + { + originhack[0] = 0; + originhack[1] = 0; + originhack[2] = 0; + overridecolor[0] = 1; + overridecolor[1] = 0.5; + overridecolor[2] = 0.1; + } + } + } + else if (!strcmp("style", key)) + style = atoi(value); + else if (!strcmp("skin", key)) + skin = (int)atof(value); + else if (!strcmp("pflags", key)) + pflags = (int)atof(value); + else if (!strcmp("effects", key)) + effects = (int)atof(value); + + else if (!strcmp("scale", key)) + lightscale = atof(value); + else if (!strcmp("fade", key)) + fadescale = atof(value); + } + if (!islight) + continue; + if (lightscale <= 0) + lightscale = 1; + if (fadescale <= 0) + fadescale = 1; + if (color[0] == color[1] && color[0] == color[2]) + { + color[0] *= overridecolor[0]; + color[1] *= overridecolor[1]; + color[2] *= overridecolor[2]; + } + radius = light[3] * 1/*r_editlights_quakelightsizescale*/ * lightscale / fadescale; + color[0] = color[0] * light[0]; + color[1] = color[1] * light[1]; + color[2] = color[2] * light[2]; + switch (type) + { + case LIGHTTYPE_MINUSX: + break; + case LIGHTTYPE_RECIPX: + radius *= 2; + VectorScale(color, (1.0f / 16.0f), color); + break; + case LIGHTTYPE_RECIPXX: + radius *= 2; + VectorScale(color, (1.0f / 16.0f), color); + break; + default: + case LIGHTTYPE_NONE: + break; + case LIGHTTYPE_SUN: + break; + case LIGHTTYPE_MINUSXX: + break; + } + VectorAdd(origin, originhack, origin); + if (radius >= 1) + { + dlight_t *dl = CL_AllocDlight(0); + VectorCopy(origin, dl->origin); + AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); + dl->radius = radius; + VectorCopy(color, dl->color); + dl->flags |= LFLAG_REALTIMEMODE; + dl->flags |= (pflags & PFLAGS_CORONA)?LFLAG_ALLOW_FLASH:0; + dl->flags |= (pflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0; + dl->style = style+1; + + //FIXME: cubemaps if skin >= 16 + } + } +} void R_LoadRTLights(void) { @@ -791,6 +1014,9 @@ void R_LoadRTLights(void) vec3_t org; float radius; vec3_t rgb; + unsigned int flags; + + vec3_t angles; //delete all old lights dlights_running = 0; @@ -800,8 +1026,7 @@ void R_LoadRTLights(void) strncat(fname, ".rtlights", MAX_QPATH-1); file = COM_LoadTempFile(fname); - if (!file) - return; + if (file) while(1) { end = strchr(file, '\n'); @@ -822,26 +1047,55 @@ void R_LoadRTLights(void) radius = atof(com_token); file = COM_Parse(file); - rgb[0] = atof(com_token); + rgb[0] = file?atof(com_token):1; file = COM_Parse(file); - rgb[1] = atof(com_token); + rgb[1] = file?atof(com_token):1; file = COM_Parse(file); - rgb[2] = atof(com_token); + rgb[2] = file?atof(com_token):1; file = COM_Parse(file); - style = atoi(com_token); + style = file?atof(com_token):0; - if (file) + file = COM_Parse(file); + //cubemap + + file = COM_Parse(file); + //corona + + file = COM_Parse(file); + angles[0] = atof(com_token); + file = COM_Parse(file); + angles[1] = atof(com_token); + file = COM_Parse(file); + angles[2] = atof(com_token); + + file = COM_Parse(file); + //corrona scale + + file = COM_Parse(file); + //ambient + + file = COM_Parse(file); + //diffuse + + file = COM_Parse(file); + //specular + + file = COM_Parse(file); + if (*com_token) + flags = atoi(com_token); + else + flags = LFLAG_REALTIMEMODE; + + if (radius) { dl = CL_AllocDlight(0); VectorCopy(org, dl->origin); dl->radius = radius; VectorCopy(rgb, dl->color); - dl->die = cl.time + 0x7fffffff; - dl->isstatic = true; - - dl->nodynamic = true; - dl->noflash = true; + dl->die = 0; + dl->flags = flags; + AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); dl->style = style+1; } @@ -849,6 +1103,25 @@ void R_LoadRTLights(void) } } +void R_ReloadRTLights_f(void) +{ + if (!cl.worldmodel) + { + Con_Printf("Cannot reload lights at this time\n"); + return; + } + dlights_running = 0; + dlights_software = 0; + if (strcmp(Cmd_Argv(1), "bsp")) + R_LoadRTLights(); + + if (!dlights_running) + { + Con_Printf("Importing rtlights from BSP\n"); + R_ImportRTLights(cl.worldmodel->entities); + } +} + /* =============== R_NewMap diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index a735561fa..01a770f5a 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -384,7 +384,7 @@ void GLR_AddDynamicLights (msurface_t *surf) if ( !(surf->dlightbits & (1<dlightbits & (1<mesh = mesh = Hunk_Alloc(size); mesh->xyz_array = (vec3_t*)(mesh + 1); mesh->normals_array = (vec3_t*)(mesh->xyz_array + lnumverts); - mesh->st_array = (vec2_t*)(mesh->normals_array + lnumverts); + mesh->snormals_array = (vec3_t*)(mesh->normals_array + lnumverts); + mesh->tnormals_array = (vec3_t*)(mesh->snormals_array + lnumverts); + mesh->st_array = (vec2_t*)(mesh->tnormals_array + lnumverts); mesh->lmst_array = (vec2_t*)(mesh->st_array + lnumverts); mesh->colors_array = (byte_vec4_t*)(mesh->lmst_array + lnumverts); mesh->indexes = (index_t*)(mesh->colors_array + lnumverts); @@ -2845,6 +2847,8 @@ void GL_BuildSurfaceDisplayList (msurface_t *fa) VectorNegate(fa->plane->normal, mesh->normals_array[i]); else VectorCopy(fa->plane->normal, mesh->normals_array[i]); + VectorCopy(fa->texinfo->vecs[0], mesh->snormals_array[i]); + VectorCopy(fa->texinfo->vecs[1], mesh->tnormals_array[i]); mesh->colors_array[i][0] = 255; mesh->colors_array[i][1] = 255; @@ -2922,6 +2926,93 @@ void GLSurf_DeInit(void) numlightmaps=0; } +void GL_ClearVBO(vbo_t *vbo) +{ + int vboh[7]; + int i, j; + vboh[0] = vbo->vboe; + vboh[1] = vbo->vbocoord; + vboh[2] = vbo->vbotexcoord; + vboh[3] = vbo->vbolmcoord; + vboh[4] = vbo->vbonormals; + vboh[5] = vbo->vbosvector; + vboh[6] = vbo->vbotvector; + + for (i = 0; i < 7; i++) + { + if (!vboh[i]) + continue; + for (j = 0; j < 7; j++) + { + if (vboh[j] == vboh[i]) + break; //already freed by one of the other ones + } + if (j == 7) + qglDeleteBuffersARB(1, &vboh[i]); + } + memset(vbo, 0, sizeof(*vbo)); +} + +qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int elementsize) +{ + unsigned int vbos[2]; + +// if (!qglGenBuffersARB) + return false; + + qglGenBuffersARB(2, vbos); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbos[0]); + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vsize, vdata, GL_STATIC_DRAW_ARB); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vbos[1]); + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, elementsize, edata, GL_STATIC_DRAW_ARB); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + if (qglGetError()) + { + qglDeleteBuffersARB(2, vbos); + return false; + } + + //opengl ate our data, fixup the vbo arrays to point to the vbo instead of the raw data + + if (vbo->indicies) + { + vbo->vboe = vbos[1]; + vbo->indicies = (index_t*)((char*)vbo->indicies - (char*)edata); + } + if (vbo->coord) + { + vbo->vbocoord = vbos[0]; + vbo->coord = (vec3_t*)((char*)vbo->coord - (char*)vdata); + } + if (vbo->texcoord) + { + vbo->vbotexcoord = vbos[0]; + vbo->texcoord = (vec2_t*)((char*)vbo->texcoord - (char*)vdata); + } + if (vbo->lmcoord) + { + vbo->vbolmcoord = vbos[0]; + vbo->lmcoord = (vec2_t*)((char*)vbo->lmcoord - (char*)vdata); + } + if (vbo->normals) + { + vbo->vbonormals = vbos[0]; + vbo->normals = (vec3_t*)((char*)vbo->normals - (char*)vdata); + } + if (vbo->svector) + { + vbo->vbosvector = vbos[0]; + vbo->svector = (vec3_t*)((char*)vbo->svector - (char*)vdata); + } + if (vbo->tvector) + { + vbo->vbotvector = vbos[0]; + vbo->tvector = (vec3_t*)((char*)vbo->tvector - (char*)vdata); + } + return true; +} + static void GL_GenBrushModelVBO(model_t *mod) { unsigned int maxvboverts; @@ -2929,23 +3020,24 @@ static void GL_GenBrushModelVBO(model_t *mod) unsigned int t; unsigned int i; - unsigned int vbos[2]; unsigned int v; unsigned int vcount, ecount; - vbovertex_t *vbovdata; - index_t *vboedata; - mesh_t *m; + unsigned int pervertsize; //erm, that name wasn't intentional - if (!qglGenBuffersARB || !mod->numsurfaces) + vbo_t *vbo; + char *vboedata; + mesh_t *m; + char *vbovdata; + + if (!mod->numsurfaces) return; for (t = 0; t < mod->numtextures; t++) { if (!mod->textures[t]) continue; - - mod->textures[t]->gl_vbov = 0; - mod->textures[t]->gl_vboe = 0; + vbo = &mod->textures[t]->vbo; + GL_ClearVBO(vbo); maxvboverts = 0; maxvboelements = 0; @@ -2964,13 +3056,27 @@ static void GL_GenBrushModelVBO(model_t *mod) continue; //fixme: stop this from leaking! - qglGenBuffersARB(2, vbos); - mod->textures[t]->gl_vbov = vbos[0]; - mod->textures[t]->gl_vboe = vbos[1]; vcount = 0; ecount = 0; - vbovdata = Hunk_TempAlloc(maxvboverts*sizeof(vbovertex_t)); - vboedata = Hunk_TempAllocMore(maxvboelements*sizeof(index_t)); + + pervertsize = sizeof(vec3_t)+ //cord + sizeof(vec2_t)+ //tex + sizeof(vec2_t)+ //lm + sizeof(vec3_t)+ //normal + sizeof(vec3_t)+ //sdir + sizeof(vec3_t); //tdir + + vbovdata = BZ_Malloc(maxvboverts*pervertsize); + vboedata = BZ_Malloc(maxvboelements*sizeof(index_t)); + + vbo->coord = (vec3_t*)(vbovdata); + vbo->texcoord = (vec2_t*)((char*)vbo->coord+maxvboverts*sizeof(*vbo->coord)); + vbo->lmcoord = (vec2_t*)((char*)vbo->texcoord+maxvboverts*sizeof(*vbo->texcoord)); + vbo->normals = (vec3_t*)((char*)vbo->lmcoord+maxvboverts*sizeof(*vbo->lmcoord)); + vbo->svector = (vec3_t*)((char*)vbo->normals+maxvboverts*sizeof(*vbo->normals)); + vbo->tvector = (vec3_t*)((char*)vbo->svector+maxvboverts*sizeof(*vbo->svector)); + vbo->indicies = (index_t*)vboedata; + for (i=0 ; inumsurfaces ; i++) { if (mod->surfaces[i].texinfo->texture != mod->textures[t]) @@ -2980,31 +3086,41 @@ static void GL_GenBrushModelVBO(model_t *mod) m->vbofirstvert = vcount; m->vbofirstelement = ecount; for (v = 0; v < m->numindexes; v++) - vboedata[ecount++] = vcount + m->indexes[v]; + vbo->indicies[ecount++] = vcount + m->indexes[v]; for (v = 0; v < m->numvertexes; v++) { - vbovdata[vcount+v].coord[0] = m->xyz_array[v][0]; - vbovdata[vcount+v].coord[1] = m->xyz_array[v][1]; - vbovdata[vcount+v].coord[2] = m->xyz_array[v][2]; + vbo->coord[vcount+v][0] = m->xyz_array[v][0]; + vbo->coord[vcount+v][1] = m->xyz_array[v][1]; + vbo->coord[vcount+v][2] = m->xyz_array[v][2]; if (m->st_array) { - vbovdata[vcount+v].texcoord[0] = m->st_array[v][0]; - vbovdata[vcount+v].texcoord[1] = m->st_array[v][1]; + vbo->texcoord[vcount+v][0] = m->st_array[v][0]; + vbo->texcoord[vcount+v][1] = m->st_array[v][1]; } if (m->lmst_array) { - vbovdata[vcount+v].lmcoord[0] = m->lmst_array[v][0]; - vbovdata[vcount+v].lmcoord[1] = m->lmst_array[v][1]; + vbo->lmcoord[vcount+v][0] = m->lmst_array[v][0]; + vbo->lmcoord[vcount+v][1] = m->lmst_array[v][1]; } + vbo->normals[vcount+v][0] = m->normals_array[v][0]; + vbo->normals[vcount+v][1] = m->normals_array[v][1]; + vbo->normals[vcount+v][2] = m->normals_array[v][2]; + vbo->svector[vcount+v][0] = m->snormals_array[v][0]; + vbo->svector[vcount+v][1] = m->snormals_array[v][1]; + vbo->svector[vcount+v][2] = m->snormals_array[v][2]; + vbo->tvector[vcount+v][0] = m->tnormals_array[v][0]; + vbo->tvector[vcount+v][1] = m->tnormals_array[v][1]; + vbo->tvector[vcount+v][2] = m->tnormals_array[v][2]; + } vcount += v; } - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, mod->textures[t]->gl_vbov); - qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vcount*sizeof(vbovertex_t), vbovdata, GL_STATIC_DRAW_ARB); - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mod->textures[t]->gl_vboe); - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ecount*sizeof(vboedata[0]), vboedata, GL_STATIC_DRAW_ARB); - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + + if (GL_BuildVBO(vbo, vbovdata, vcount*pervertsize, vboedata, ecount*sizeof(index_t))) + { + BZ_Free(vbovdata); + BZ_Free(vboedata); + } } } diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index e14340789..c805c1390 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -46,6 +46,9 @@ extern cvar_t vid_conautoscale; // console size manipulation callbacks void GLVID_Console_Resize(void) { +#ifdef AVAIL_FREETYPE + extern struct font_s *conchar_font; +#endif extern cvar_t vid_conwidth, vid_conheight; int cwidth, cheight; float xratio; @@ -96,6 +99,12 @@ void GLVID_Console_Resize(void) vid.recalc_refdef = true; Con_CheckResize(); +#ifdef AVAIL_FREETYPE + if (conchar_font) + Font_Free(conchar_font); + conchar_font = Font_LoadFont(8*glheight/vid.height, "C:/Windows/Fonts/cour.ttf"); +#endif + #ifdef PLUGINS Plug_ResChanged(); #endif diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index d623c9b25..659d7743e 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -542,14 +542,62 @@ static void Shader_ProgramName ( shader_t *shader, shaderpass_t *pass, char **pt token = Shader_ParseString ( ptr ); return; } + + + token = *ptr; + while (*token == ' ' || *token == '\t' || *token == '\r') + token++; + if (*token == '\n') + { + int count; + token++; + while (*token == ' ' || *token == '\t') + token++; + if (*token != '{') + { + Con_Printf("shader \"%s\" missing program string\n", shader->name); + } + else + { + token++; + vert = frag = token; + for (count = 1; *token; token++) + { + if (*token == '}') + { + count--; + if (!count) + break; + } + else if (*token == '{') + count++; + } + *token = 0; + *ptr = token+1; + + shader->programhandle = GLSlang_CreateProgram("", (char *)vert, (char *)frag); + frag = NULL; + vert = NULL; + + return; + } + } token = Shader_ParseString ( ptr ); FS_LoadFile(token, &vert); token = Shader_ParseString ( ptr ); - FS_LoadFile(token, &frag); + if (!*token) + frag = vert; + else + FS_LoadFile(token, &frag); + if (vert && frag) shader->programhandle = GLSlang_CreateProgram("", (char *)vert, (char *)frag); if (vert) + { + if (frag == vert) + frag = NULL; FS_FreeFile(vert); + } if (frag) FS_FreeFile(frag); } @@ -1090,6 +1138,12 @@ static void Shaderpass_TcGen ( shader_t *shader, shaderpass_t *pass, char **ptr pass->tcgen = TC_GEN_ENVIRONMENT; } else if ( !Q_stricmp (token, "vector") ) { pass->tcgen = TC_GEN_BASE; + } else if ( !Q_stricmp (token, "normal") ) { + pass->tcgen = TC_GEN_NORMAL; + } else if ( !Q_stricmp (token, "svector") ) { + pass->tcgen = TC_GEN_SVECTOR; + } else if ( !Q_stricmp (token, "tvector") ) { + pass->tcgen = TC_GEN_TVECTOR; } } static void Shaderpass_EnvMap ( shader_t *shader, shaderpass_t *pass, char **ptr ) //for alienarena @@ -1678,6 +1732,7 @@ void Shader_SetFeatures ( shader_t *s ) s->features |= MF_LMCOORDS; break; case TC_GEN_ENVIRONMENT: + case TC_GEN_NORMAL: s->features |= MF_NORMALS; break; } diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 09f904759..811fb64b9 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -63,6 +63,7 @@ void (APIENTRY *qglTexEnvf) (GLenum target, GLenum pname, GLfloat param); void (APIENTRY *qglTexEnvfv) (GLenum target, GLenum pname, const GLfloat *param); void (APIENTRY *qglTexEnvi) (GLenum target, GLenum pname, GLint param); void (APIENTRY *qglTexGeni) (GLenum coord, GLenum pname, GLint param); +void (APIENTRY *qglTexGenfv) (GLenum coord, GLenum pname, const GLfloat *param); void (APIENTRY *qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); void (APIENTRY *qglTexParameteri) (GLenum target, GLenum pname, GLint param); void (APIENTRY *qglTexParameterf) (GLenum target, GLenum pname, GLfloat param); @@ -412,15 +413,27 @@ GLhandleARB GLSlang_CreateShader (char *precompilerconstants, char *shadersource GLint compiled; char str[1024]; - char *prstrings[2]; + char *prstrings[3]; if (!precompilerconstants) precompilerconstants = ""; - prstrings[0] = precompilerconstants; - prstrings[1] = shadersource; + switch (shadertype) + { + case GL_FRAGMENT_SHADER_ARB: + prstrings[0] = "#define FRAGMENT_SHADER\n"; + break; + case GL_VERTEX_SHADER_ARB: + prstrings[0] = "#define VERTEX_SHADER\n"; + break; + default: + prstrings[0] = "#define UNKNOWN_SHADER\n"; + break; + } + prstrings[1] = precompilerconstants; + prstrings[2] = shadersource; shader = qglCreateShaderObjectARB(shadertype); - qglShaderSourceARB(shader, 2, (const GLcharARB**)prstrings, NULL); + qglShaderSourceARB(shader, 3, (const GLcharARB**)prstrings, NULL); qglCompileShaderARB(shader); qglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); @@ -553,6 +566,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglTexEnvfv = (void *)getglcore("glTexEnvfv"); qglTexEnvi = (void *)getglcore("glTexEnvi"); qglTexGeni = (void *)getglcore("glTexGeni"); + qglTexGenfv = (void *)getglcore("glTexGenfv"); qglTexImage2D = (void *)getglcore("glTexImage2D"); qglTexParameteri = (void *)getglcore("glTexParameteri"); qglTexParameterf = (void *)getglcore("glTexParameterf"); diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 36fee709e..801104c44 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -1393,7 +1393,7 @@ void ClearAllStates (void) // send an up event for each key, to make sure the server clears them all for (i=0 ; i<256 ; i++) { - Key_Event (i, false); + Key_Event (i, 0, false); } Key_ClearStates (); @@ -1521,17 +1521,26 @@ LONG WINAPI GLMainWndProc ( case WM_KEYDOWN: case WM_SYSKEYDOWN: if (!vid_initializing) - Key_Event (MapKey(lParam), true); + { + IN_TranslateKeyEvent(wParam, lParam, true); + } + break; + +// case WM_UNICHAR: + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + case WM_CHAR: + case WM_SYSCHAR: +// if (!vid_initializing) +// IN_TranslateKeyEvent(wParam, lParam, true); break; case WM_KEYUP: case WM_SYSKEYUP: if (!vid_initializing) - Key_Event (MapKey(lParam), false); - break; - - case WM_SYSCHAR: - // keep Alt-Space from happening + { + IN_TranslateKeyEvent(wParam, lParam, false); + } break; // this is complicated because Win32 seems to pack multiple mouse events into @@ -1595,13 +1604,13 @@ LONG WINAPI GLMainWndProc ( { if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); + Key_Event(K_MWHEELUP, 0, true); + Key_Event(K_MWHEELUP, 0, false); } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); + Key_Event(K_MWHEELDOWN, 0, true); + Key_Event(K_MWHEELDOWN, 0, false); } } break; diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index daf77a76c..a18a233f6 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -218,7 +218,7 @@ void GL_DrawSkyChain (msurface_t *s) #ifdef D3DQUAKE static void R_DrawSkyBoxChain (msurface_t *s); -static void D3D7_DrawSkyChain (msurface_t *s) +void D3D7_DrawSkyChain (msurface_t *s) { //msurface_t *fa; @@ -271,7 +271,7 @@ static void D3D7_DrawSkyChain (msurface_t *s) D3D7_DrawSkySphere(s); } -static void D3D9_DrawSkyChain (msurface_t *s) +void D3D9_DrawSkyChain (msurface_t *s) { //msurface_t *fa; diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 2491cf10a..a3c417d99 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -343,9 +343,7 @@ void R_AddSkySurface (msurface_t *fa); #endif #ifdef D3DQUAKE void D3D7_DrawSkyChain (msurface_t *s); -void D3D7_DrawSkySphere (msurface_t *fa); void D3D9_DrawSkyChain (msurface_t *s); -void D3D9_DrawSkySphere (msurface_t *fa); #endif // @@ -452,7 +450,7 @@ typedef struct { //gl_ppl.c void PPL_DrawWorld (void); qboolean PPL_ShouldDraw(void); -void RotateLightVector(vec3_t *angles, vec3_t origin, vec3_t lightpoint, vec3_t result); +void RotateLightVector(const vec3_t *angles, const vec3_t origin, const vec3_t lightpoint, vec3_t result); // // gl_refrag.c @@ -932,4 +930,210 @@ extern vec3_t r_pright, r_pup, r_ppn; extern float xscaleshrink, yscaleshrink; #endif + + + + + + + + + + + + +/* +//opengl 3 deprecation + +. Application-generated object names - the names of all object types, such as +buffer, query, and texture objects, must be generated using the corresponding +Gen* commands. Trying to bind an object name not returned by a Gen* +command will result in an INVALID OPERATION error. This behavior is +already the case for framebuffer, renderbuffer, and vertex array objects. Object +types which have default objects (objects named zero) , such as vertex +array, framebuffer, and texture objects, may also bind the default object, even +though it is not returned by Gen*. + +. OpenGL Shading Language versions 1.10 and 1.20. These versions of the +shading language depend on many API features that have also been deprecated. + +. Pixel transfer modes and operations - all pixel transfer modes, including +pixel maps, shift and bias, color table lookup, color matrix, and convolution +commands and state, and all associated state and commands defining +that state. + +. Legacy OpenGL 1.0 pixel formats - the values 1, 2, 3, and 4 are no longer +accepted as internal formats by TexImage* or any other command taking +an internal format argument. The initial internal format of a texel array is +RGBA instead of 1. + +. Texture borders - the border value to TexImage* must always be zero, or +an INVALID VALUE error is generated (section 3.8.1); all language in section +3.8 referring to nonzero border widths during texture image specification +and texture sampling; and all associated state. + +GL_COLOR_INDEX + +glBegin +glEnd +glEdgeFlag*; +glColor*, +glFogCoord* +glIndex* +glNormal3* +glSecondaryColor3* +glTexCoord* +glVertex* + +glColorPointer +glEdgeFlagPointer +glFogCoordPointer +glIndexPointer +glNormalPointer +glSecondary- +glColorPointer, +glTexCoordPointer +glVertexPointer +glEnableClientState +glDisableClientState, + +glInterleavedArrays +glClientActiveTexture +glFrustum, +glLoadIdentity +glLoadMatrix +glLoadTransposeMatrix +glMatrixMode, +glMultMatrix +glMultTransposeMatrix +glOrtho +glPopMatrix +glPushMatrix, +glRotate +glScale +glTranslate +GL_RESCALE_NORMAL +GL_NORMALIZE +glTexGen* +GL_TEXTURE_GEN_*, +Material* +glLight* +glLightModel* +glColorMaterial +glShadeModel +GL_LIGHTING +GL_VERTEX_PROGRAM_TWO_SIDE +GL_LIGHTi, +GL_COLOR_MATERIAL +glClipPlane +GL_CLAMP_VERTEX_COLOR +GL_CLAMP_FRAGMENT_COLOR +glRect* + +glRasterPos* +glWindowPos* + +GL_POINT_SMOOTH +GL_POINT_SPRITE + +glLineStipple +GL_LINE_STIPPLE +GL_POLYGON +GL_QUADS +GL_QUAD_STRIP +glPolygonMode +glPolygonStipple +GL_POLYGON_STIPPLE +glDrawPixels +glPixelZoom +glBitmap +GL_BITMAP + +GL_TEXTURE_COMPONENTS +GL_ALPHA +GL_LUMINANCE +GL_LUMINANCE_ALPHA +GL_INTENSITY + +GL_DEPTH_TEXTURE_MODE + +GL_CLAMP + +GL_GENERATE_MIPMAP + +glAreTexturesResident +glPrioritizeTextures, +GL_TEXTURE_PRIORITY +GL_TEXTURE_ENV +GL_TEXTURE_FILTER_CONTROL +GL_TEXTURE_LOD_BIAS + +GL_TEXTURE_1D +GL_TEXTURE_2D, +GL_TEXTURE_3D +GL_TEXTURE_1D_ARRAY +GL_TEXTURE_2D_ARRAY +GL_TEXTURE_CUBE_MAP +GL_COLOR_SUM +GL_FOG +glFog +GL_MAX_TEXTURE_UNITS +GL_MAX_TEXTURE_COORDS +glAlphaFunc +GL_ALPHA_TEST + +glClearAccum +GL_ACCUM_BUFFER_BIT + +glCopyPixels + +GL_AUX0 +GL_RED_BITS +GL_GREEN_BITS +GL_BLUE_BITS +GL_ALPHA_BITS +GL_DEPTH_BITS +STENCIL BITS +glMap* +glEvalCoord* +glMapGrid* +glEvalMesh* +glEvalPoint* + +glRenderMode +glInitNames +glPopName +glPushName +glLoadName +glSelectBuffer +glFeedbackBuffer +glPassThrough +glNewList +glEndList +glCallList +glCallLists +glListBase +glGenLists, +glIsList +glDeleteLists + + +GL_PERSPECTIVE_CORRECTION_HINT +GL_POINT_SMOOTH_HINT, +GL_FOG_HINT +GL_GENERATE_MIPMAP_HINT + +glPushAttrib +glPushClientAttrib +glPopAttrib +glPopClientAttrib, +GL_MAX_ATTRIB_STACK_DEPTH, +GL_MAX_CLIENT_ATTRIB_STACK_DEPTH +GL_ATTRIB_STACK_DEPTH +GL_CLIENT_ATTRIB_STACK_DEPTH +GL_ALL_ATTRIB_BITS +GL_CLIENT_ALL_ATTRIB_BITS. +GL_EXTENSIONS +*/ + #endif diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index 90b13f034..4dfab5ace 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -99,10 +99,24 @@ extern qlpMTex2FUNC qglMultiTexCoord2fARB; #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C #endif +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B +#endif +#ifndef GL_ARB_shadow +#define GL_ARB_shadow +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E +#endif #ifndef GL_EXT_texture3D -#define define GL_EXT_texture3D 1 +#define GL_EXT_texture3D 1 #define GL_PACK_SKIP_IMAGES 0x806B #define GL_PACK_SKIP_IMAGES_EXT 0x806B #define GL_PACK_IMAGE_HEIGHT 0x806C diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 47da8ba41..ad40cac36 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -130,7 +130,12 @@ typedef struct shaderpass_s { TC_GEN_LIGHTMAP, //use loaded lightmap coords TC_GEN_ENVIRONMENT, TC_GEN_DOTPRODUCT, - TC_GEN_VECTOR + TC_GEN_VECTOR, + + //these are really for use only in glsl stuff. + TC_GEN_NORMAL, + TC_GEN_SVECTOR, + TC_GEN_TVECTOR, } tcgen; enum { RGB_GEN_WAVE, diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 7ff5f5799..c0d16c95d 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1355,7 +1355,7 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) #endif #ifdef PEXT_FATNESS if (pflags & PF_FATNESS_Z) - MSG_WriteChar (msg, ent->fatness*2); + MSG_WriteChar (msg, ent->fatness*10); #endif #ifdef PEXT_HULLSIZE //shrunken or crouching in halflife levels. (possibly enlarged) if (pflags & PF_HULLSIZE_Z) @@ -2332,7 +2332,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli } #endif #ifdef PEXT_FATNESS - state->fatness = ent->xv->fatness*2; + state->fatness = ent->xv->fatness*16; #endif } diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index e6de6d7c6..e5b67253f 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -268,7 +268,7 @@ void SV_EdictToEntState (int num, edict_t *ent, entity_state_t *state) else state->scale = ent->xv->scale*16; - state->fatness = ent->xv->fatness*2; + state->fatness = ent->xv->fatness*16; } void SVNQ_CreateBaseline (void) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 7953256a1..8aee7b025 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -3770,6 +3770,9 @@ void Master_Heartbeat (void) } else { + if (sv_masterlist[i].adr.type == NA_TCP || sv_masterlist[i].adr.type == NA_TCPV6) + NET_EnsureRoute(svs.sockets, sv_masterlist[i].cv.name, sv_masterlist[i].cv.string, false); + //choose default port switch (sv_masterlist[i].protocol) { diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 74d1921d4..5612ced88 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -3781,6 +3781,7 @@ void Cmd_FPSList_f(void) frames = 0; inbytes = 0; outbytes = 0; + msecs = 0; if (!cl->state) continue; diff --git a/engine/sw/vid_win2.c b/engine/sw/vid_win2.c index e2926e694..0ba8de5e0 100644 --- a/engine/sw/vid_win2.c +++ b/engine/sw/vid_win2.c @@ -383,13 +383,13 @@ LONG WINAPI MainWndProc ( case WM_KEYDOWN: case WM_SYSKEYDOWN: if (!vid_initializing) - Key_Event (MapKey(lParam), true); + IN_TranslateKeyEvent(wParam, lParam, true); break; case WM_KEYUP: case WM_SYSKEYUP: if (!vid_initializing) - Key_Event (MapKey(lParam), false); + IN_TranslateKeyEvent(wParam, lParam, false); break; // this is complicated because Win32 seems to pack multiple mouse events into @@ -446,11 +446,11 @@ LONG WINAPI MainWndProc ( // Event. case WM_MOUSEWHEEL: if ((short) HIWORD(wParam) > 0) { - Key_Event(K_MWHEELUP, true); - Key_Event(K_MWHEELUP, false); + Key_Event(K_MWHEELUP, 0, true); + Key_Event(K_MWHEELUP, 0, false); } else { - Key_Event(K_MWHEELDOWN, true); - Key_Event(K_MWHEELDOWN, false); + Key_Event(K_MWHEELDOWN, 0, true); + Key_Event(K_MWHEELDOWN, 0, false); } break; case WM_INPUT: @@ -953,7 +953,6 @@ void SWVID_Shutdown (void) void SWVID_Update (vrect_t *rects) //end frame... { extern qboolean mouseactive; - qboolean mouse; #ifdef MGL if (usingmgl) {