fix server crash (on two pk3s with the same pure path)
fix fteqcc issue unintentionally stripping things added model event support. added support for a couple of extra twiddles in the iqm format. modelviewer now highlights meshes (to display hitmesh areas). modelviewer now shows ragdolls, because I can. fixed some nq download issues/crashes/fallbacks. fixed 8bit bmp palette issue. added capturethrottlesize cvar to throttle recording speed if disk space is getting low (to avoid Maverick's demo encoder getting swamped). com_protocolname can now list multiple protocol names to list multiple server types. only the first will be reported to other clients however. can now be compiled without support for q1bsp or q1mdl. not useful, but hey. increase max_channels, by as much as is necessary. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5038 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
cd75caeb27
commit
c4ded89ad7
53 changed files with 2749 additions and 1325 deletions
|
@ -47,6 +47,8 @@ extern cvar_t gl_simpleitems;
|
|||
extern cvar_t cl_gibfilter, cl_deadbodyfilter;
|
||||
extern int cl_playerindex;
|
||||
|
||||
extern world_t csqc_world;
|
||||
|
||||
static struct predicted_player
|
||||
{
|
||||
int flags;
|
||||
|
@ -3126,6 +3128,13 @@ static void CL_UpdateNetFrameLerpState(qboolean force, int curframe, int curbase
|
|||
}
|
||||
le->newframe[fst] = frame;
|
||||
le->newframestarttime[fst] = cl.servertime;
|
||||
|
||||
// if (force)
|
||||
// {
|
||||
// //if its new, we need to tweak the age of the animation. looping anims won't appear any different, while non-looping ones will clamp to the last pose of the animation when its new.
|
||||
// le->oldframestarttime[fst] -= Mod_GetFrameDuration(le->model, 0, le->oldframe[fst]);
|
||||
// le->newframestarttime[fst] -= Mod_GetFrameDuration(le->model, 0, le->newframe[fst]);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4075,7 +4084,7 @@ void CL_LinkPacketEntities (void)
|
|||
|
||||
#ifdef RAGDOLL
|
||||
if (model && (model->dollinfo || le->skeletalobject))
|
||||
rag_updatedeltaent(ent, le);
|
||||
rag_updatedeltaent(&csqc_world, ent, le);
|
||||
#endif
|
||||
ent->framestate.g[FS_REG].frame[0] &= ~0x8000;
|
||||
ent->framestate.g[FS_REG].frame[1] &= ~0x8000;
|
||||
|
|
|
@ -35,7 +35,7 @@ void QDECL Name_Callback(struct cvar_s *var, char *oldvalue);
|
|||
#define Name_Callback NULL
|
||||
#endif
|
||||
|
||||
void CL_ForceStopDownload (qdownload_t *dl, qboolean finish);
|
||||
static void CL_ForceStopDownload (qboolean finish);
|
||||
|
||||
// we need to declare some mouse variables here, because the menu system
|
||||
// references them even when on a unix system.
|
||||
|
@ -160,7 +160,7 @@ cvar_t cl_sendguid = CVARD("cl_sendguid", "0", "Send a randomly generated 'gl
|
|||
cvar_t cl_downloads = CVARFD("cl_downloads", "1", CVAR_NOTFROMSERVER, "Allows you to block all automatic downloads.");
|
||||
cvar_t cl_download_csprogs = CVARFD("cl_download_csprogs", "1", CVAR_NOTFROMSERVER, "Download updated client gamecode if available. Warning: If you clear this to avoid downloading vm code, you should also clear cl_download_packages.");
|
||||
cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "2", CVAR_NOTFROMSERVER, "Follow download redirection to download packages instead of individual files. Also allows the server to send nearly arbitary download commands.\n2: allows redirection only to named packages files (and demos/*.mvd), which is a bit safer.");
|
||||
cvar_t cl_download_mapsrc = CVARD("cl_download_mapsrc", "", "Specifies an http location prefix for map downloads. EG: \"http://bigfoot.morphos-team.net/misc/quakemaps/\"");
|
||||
cvar_t cl_download_mapsrc = CVARFD("cl_download_mapsrc", "", CVAR_ARCHIVE, "Specifies an http location prefix for map downloads. EG: \"http://bigfoot.morphos-team.net/misc/quakemaps/\"");
|
||||
cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Download and load packages as needed (does not affect games which do not use this package). 2=Do download and install permanently (use with caution!)");
|
||||
cvar_t requiredownloads = CVARFD("requiredownloads","1", CVAR_ARCHIVE, "0=join the game before downloads have even finished (might be laggy). 1=wait for all downloads to complete before joining.");
|
||||
|
||||
|
@ -3684,8 +3684,9 @@ void CL_DownloadSize_f(void)
|
|||
}
|
||||
|
||||
void CL_FinishDownload(char *filename, char *tempname);
|
||||
void CL_ForceStopDownload (qdownload_t *dl, qboolean finish)
|
||||
static void CL_ForceStopDownload (qboolean finish)
|
||||
{
|
||||
qdownload_t *dl = cls.download;
|
||||
if (Cmd_IsInsecure())
|
||||
{
|
||||
Con_Printf(CON_WARNING "Execution from server rejected for %s\n", Cmd_Argv(0));
|
||||
|
@ -3713,15 +3714,13 @@ void CL_ForceStopDownload (qdownload_t *dl, qboolean finish)
|
|||
// get another file if needed
|
||||
CL_RequestNextDownload ();
|
||||
}
|
||||
|
||||
void CL_SkipDownload_f (void)
|
||||
{
|
||||
CL_ForceStopDownload(cls.download, false);
|
||||
CL_ForceStopDownload(false);
|
||||
}
|
||||
|
||||
void CL_FinishDownload_f (void)
|
||||
{
|
||||
CL_ForceStopDownload(cls.download, true);
|
||||
CL_ForceStopDownload(true);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(WINRT)
|
||||
|
@ -5795,13 +5794,15 @@ void Host_Shutdown(void)
|
|||
HTTP_CL_Terminate();
|
||||
#endif
|
||||
|
||||
//disconnect server/client/etc
|
||||
CL_Disconnect_f();
|
||||
|
||||
M_Shutdown(true);
|
||||
|
||||
#ifdef PLUGINS
|
||||
Plug_Shutdown(false);
|
||||
#endif
|
||||
|
||||
//disconnect server/client/etc
|
||||
CL_Disconnect_f();
|
||||
|
||||
#ifdef CSQC_DAT
|
||||
CSQC_Shutdown();
|
||||
#endif
|
||||
|
@ -5821,7 +5822,6 @@ void Host_Shutdown(void)
|
|||
#endif
|
||||
CL_FreeDlights();
|
||||
CL_FreeVisEdicts();
|
||||
M_Shutdown(true);
|
||||
Mod_Shutdown(true);
|
||||
Wads_Flush();
|
||||
Con_History_Save(); //do this outside of the console code so that the filesystem is still running at this point but still allowing the filesystem to make console prints (you might not see them, but they should be visible to sys_printf still, for debugging).
|
||||
|
|
|
@ -680,7 +680,11 @@ void CL_DisenqueDownload(char *filename)
|
|||
void CL_WebDownloadFinished(struct dl_download *dl)
|
||||
{
|
||||
if (dl->status == DL_FAILED)
|
||||
{
|
||||
CL_DownloadFailed(dl->url, &dl->qdownload);
|
||||
if (dl->qdownload.flags & DLLF_ALLOWWEB) //re-enqueue it if allowed, but this time not from the web server.
|
||||
CL_EnqueDownload(dl->qdownload.localname, dl->qdownload.localname, dl->qdownload.flags & ~DLLF_ALLOWWEB);
|
||||
}
|
||||
else if (dl->status == DL_FINISHED)
|
||||
{
|
||||
if (dl->file)
|
||||
|
@ -697,9 +701,17 @@ void CL_SendDownloadStartRequest(char *filename, char *localname, unsigned int f
|
|||
qdownload_t *dl;
|
||||
|
||||
#ifdef WEBCLIENT
|
||||
if (!strncmp(filename, "http://", 7))
|
||||
if (!strncmp(filename, "http://", 7) || !strncmp(filename, "https://", 8))
|
||||
{
|
||||
if (!HTTP_CL_Get(filename, localname, CL_WebDownloadFinished))
|
||||
struct dl_download *wdl = HTTP_CL_Get(filename, localname, CL_WebDownloadFinished);
|
||||
if (wdl)
|
||||
{
|
||||
if (!(flags & DLLF_TEMPORARY))
|
||||
Con_TPrintf ("Downloading %s to %s...\n", wdl->url, wdl->localname);
|
||||
wdl->qdownload.flags = flags;
|
||||
cls.download = &wdl->qdownload;
|
||||
}
|
||||
else
|
||||
CL_DownloadFailed(filename, NULL);
|
||||
return;
|
||||
}
|
||||
|
@ -898,13 +910,22 @@ qboolean CL_CheckOrEnqueDownloadFile (const char *filename, const char *localnam
|
|||
|
||||
SCR_EndLoadingPlaque(); //release console.
|
||||
|
||||
if (*cl_download_mapsrc.string)
|
||||
if (!strncmp(filename, "maps/", 5))
|
||||
if (!strcmp(filename + strlen(filename)-4, ".bsp"))
|
||||
if (flags & DLLF_ALLOWWEB)
|
||||
{
|
||||
char base[MAX_QPATH];
|
||||
COM_FileBase(filename, base, sizeof(base));
|
||||
filename = va("%s%s.bsp", cl_download_mapsrc.string, base);
|
||||
flags &= ~DLLF_ALLOWWEB;
|
||||
if (*cl_download_mapsrc.string)
|
||||
if (!strcmp(filename, localname))
|
||||
if (!strncmp(filename, "maps/", 5))
|
||||
if (!strcmp(filename + strlen(filename)-4, ".bsp"))
|
||||
{
|
||||
char base[MAX_QPATH];
|
||||
COM_FileBase(filename, base, sizeof(base));
|
||||
if (!strncmp(cl_download_mapsrc.string, "http://", 7) || !strncmp(cl_download_mapsrc.string, "https://", 8))
|
||||
filename = va("%s%s.bsp", cl_download_mapsrc.string, base);
|
||||
else
|
||||
filename = va("http://%s/%s.bsp", cl_download_mapsrc.string, base);
|
||||
flags |= DLLF_ALLOWWEB;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CL_EnqueDownload(filename, localname, flags))
|
||||
|
@ -2310,6 +2331,7 @@ void DL_Abort(qdownload_t *dl, enum qdlabort aborttype)
|
|||
|
||||
if (dl->flags & DLLF_BEGUN)
|
||||
{
|
||||
dl->flags &= ~DLLF_BEGUN;
|
||||
if (aborttype == QDL_COMPLETED)
|
||||
{
|
||||
//this file isn't needed now the download has finished.
|
||||
|
@ -2414,7 +2436,8 @@ void DL_Abort(qdownload_t *dl, enum qdlabort aborttype)
|
|||
}
|
||||
dl->dlblocks = NULL;
|
||||
|
||||
Z_Free(dl);
|
||||
if (dl->method != DL_HTTP)
|
||||
Z_Free(dl);
|
||||
if (cls.download == dl)
|
||||
cls.download = NULL;
|
||||
}
|
||||
|
@ -2654,6 +2677,8 @@ void CLDP_ParseDownloadBegin(char *s)
|
|||
return;
|
||||
}
|
||||
|
||||
if (dl->method == DL_QWPENDING)
|
||||
dl->method = DL_DARKPLACES;
|
||||
if (dl->method != DL_DARKPLACES)
|
||||
{
|
||||
Con_Printf("Warning: download method isn't right.\n");
|
||||
|
@ -3571,7 +3596,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
|
|||
}
|
||||
strcpy (cl.model_name[nummodels], str);
|
||||
if (*str != '*' && strcmp(str, "null")) //not inline models!
|
||||
CL_CheckOrEnqueDownloadFile(str, NULL, ((nummodels==1)?DLLF_REQUIRED:0));
|
||||
CL_CheckOrEnqueDownloadFile(str, NULL, ((nummodels==1)?DLLF_REQUIRED|DLLF_ALLOWWEB:0));
|
||||
Mod_TouchModel (str);
|
||||
}
|
||||
|
||||
|
|
|
@ -550,6 +550,7 @@ typedef struct downloadlist_s {
|
|||
#define DLLF_USEREXPLICIT (1u<<7) //use explicitly requested it, ignore the cl_downloads cvar.
|
||||
|
||||
#define DLLF_BEGUN (1u<<8) //server has confirmed that the file exists, is readable, and we've opened a file. should not be set on new requests.
|
||||
#define DLLF_ALLOWWEB (1u<<9) //failed http downloads should retry but from the game server itself
|
||||
struct downloadlist_s *next;
|
||||
} downloadlist_t;
|
||||
|
||||
|
|
|
@ -1623,11 +1623,6 @@ void Con_PrintToSys(void)
|
|||
//returns the bottom of the progress bar
|
||||
static int Con_DrawProgress(int left, int right, int y)
|
||||
{
|
||||
#ifdef RUNTIMELIGHTING
|
||||
extern model_t *lightmodel;
|
||||
extern long relitsurface;
|
||||
#endif
|
||||
|
||||
conchar_t dlbar[1024], *chr;
|
||||
unsigned char progresspercenttext[128];
|
||||
char *progresstext = NULL;
|
||||
|
|
|
@ -2108,7 +2108,7 @@ qbyte *ReadBMPFile(qbyte *buf, int length, int *width, int *height)
|
|||
|
||||
for (i = 0; i < h.NumofColorIndices; i++)
|
||||
{
|
||||
pal[i] = data[i*4+0] + (data[i*4+1]<<8) + (data[i*4+2]<<16) + (255/*data[i*4+3]*/<<16);
|
||||
pal[i] = data[i*4+2] + (data[i*4+1]<<8) + (data[i*4+0]<<16) + (255/*data[i*4+3]*/<<24);
|
||||
}
|
||||
|
||||
buf += h.OffsetofBMPBits;
|
||||
|
@ -4436,6 +4436,7 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
|
|||
int firstex = (tex->flags & IF_EXACTEXTENSION)?tex_extensions_count-1:0;
|
||||
char *altname;
|
||||
char *nextalt;
|
||||
qboolean exactext = !!(tex->flags & IF_EXACTEXTENSION);
|
||||
|
||||
// Sys_Sleep(0.3);
|
||||
|
||||
|
@ -4453,18 +4454,26 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
|
|||
}
|
||||
|
||||
//see if we recognise the extension, and only strip it if we do.
|
||||
COM_FileExtension(altname, nicename, sizeof(nicename));
|
||||
e = 0;
|
||||
if (strcmp(nicename, "lmp") && strcmp(nicename, "wal"))
|
||||
for (; e < tex_extensions_count; e++)
|
||||
{
|
||||
if (!strcmp(nicename, (*tex_extensions[e].name=='.')?tex_extensions[e].name+1:tex_extensions[e].name))
|
||||
break;
|
||||
}
|
||||
if (exactext)
|
||||
e = tex_extensions_count;
|
||||
else
|
||||
{
|
||||
COM_FileExtension(altname, nicename, sizeof(nicename));
|
||||
e = 0;
|
||||
if (strcmp(nicename, "lmp") && strcmp(nicename, "wal"))
|
||||
for (; e < tex_extensions_count; e++)
|
||||
{
|
||||
if (!strcmp(nicename, (*tex_extensions[e].name=='.')?tex_extensions[e].name+1:tex_extensions[e].name))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//strip it and try replacements if we do, otherwise assume that we're meant to be loading progs/foo.mdl_0.tga or whatever
|
||||
if (e == tex_extensions_count || (tex->flags & IF_EXACTEXTENSION))
|
||||
if (e == tex_extensions_count || exactext)
|
||||
{
|
||||
exactext = true;
|
||||
Q_strncpyz(nicename, altname, sizeof(nicename));
|
||||
}
|
||||
else
|
||||
COM_StripExtension(altname, nicename, sizeof(nicename));
|
||||
|
||||
|
@ -4511,7 +4520,7 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
|
|||
|
||||
s = COM_SkipPath(nicename);
|
||||
n = basename;
|
||||
while (*s && *s != '.' && n < basename+sizeof(basename)-5)
|
||||
while (*s && (*s != '.'||exactext) && n < basename+sizeof(basename)-5)
|
||||
*n++ = *s++;
|
||||
s = strchr(s, '_');
|
||||
if (s)
|
||||
|
|
|
@ -16,6 +16,14 @@
|
|||
#define WINAVI
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && !defined(ANDROID)
|
||||
//should really include posix 2001 systems in general
|
||||
#define HAVE_STATVFS
|
||||
#endif
|
||||
#ifdef HAVE_STATVFS
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct mediatrack_s{
|
||||
char filename[MAX_QPATH];
|
||||
|
@ -2737,13 +2745,21 @@ int captureoldfbo;
|
|||
qboolean capturingfbo;
|
||||
texid_t capturetexture;
|
||||
qboolean captureframeforce;
|
||||
|
||||
#if defined(GLQUAKE) && !defined(GLESONLY)
|
||||
//ring buffer
|
||||
int pbo_handles[4];
|
||||
enum uploadfmt pbo_format;
|
||||
#define CAN_USE_PBOS
|
||||
#define GLQUAKE_PBOS
|
||||
#endif
|
||||
int pbo_oldest;
|
||||
struct
|
||||
{
|
||||
#ifdef GLQUAKE_PBOS
|
||||
int pbo_handle;
|
||||
#endif
|
||||
enum uploadfmt format;
|
||||
int width;
|
||||
int height;
|
||||
} offscreen_queue[4]; //ringbuffer of offscreen_captureframe...captureframe
|
||||
int offscreen_captureframe;
|
||||
enum uploadfmt offscreen_format;
|
||||
|
||||
#define CAPTURECODECDESC_DEFAULT "tga"
|
||||
#ifdef WINAVI
|
||||
|
@ -2765,6 +2781,7 @@ cvar_t capturesound = CVARD("capturesound", "1", "Enables the capturing of game
|
|||
cvar_t capturesoundchannels = CVAR("capturesoundchannels", "2");
|
||||
cvar_t capturesoundbits = CVAR("capturesoundbits", "16");
|
||||
cvar_t capturemessage = CVAR("capturemessage", "");
|
||||
cvar_t capturethrottlesize = CVARD("capturethrottlesize", "0", "If set, capturing will slow down significantly if there is less disk space available than this cvar (in mb). This is useful when recording a stream to (ram)disk while another program is simultaneously consuming frames.");
|
||||
qboolean recordingdemo;
|
||||
|
||||
media_encoder_funcs_t *currentcapture_funcs;
|
||||
|
@ -2834,6 +2851,34 @@ static void QDECL capture_raw_video (void *vctx, void *data, int frame, int widt
|
|||
ctx->frames = frame+1;
|
||||
Q_snprintfz(filename, sizeof(filename), "%s%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension);
|
||||
SCR_ScreenShot(filename, ctx->fsroot, &data, 1, width, height, fmt);
|
||||
|
||||
if (capturethrottlesize.ival)
|
||||
{
|
||||
char base[MAX_QPATH];
|
||||
Q_strncpyz(base, ctx->videonameprefix, sizeof(base));
|
||||
*COM_SkipPath(base) = 0;
|
||||
if (FS_NativePath(base, FS_GAMEONLY, filename, sizeof(filename)))
|
||||
{
|
||||
#if HAVE_STATVFS
|
||||
//posix 2001
|
||||
struct statvfs inf;
|
||||
if(0==statvfs(filename, &inf))
|
||||
{
|
||||
if (inf.f_frsize*(double)inf.f_blocks < (1024.*1024)*capturethrottlesize.value)
|
||||
Sys_Sleep(1);
|
||||
}
|
||||
#elif defined( _WIN32)
|
||||
wchar_t ffs[MAX_OSPATH];
|
||||
ULARGE_INTEGER freebytes;
|
||||
if (GetDiskFreeSpaceExW(widen(ffs, sizeof(ffs), filename), &freebytes, NULL, NULL))
|
||||
if (freebytes.QuadPart < (ULONGLONG)(1024*1024)*capturethrottlesize.value)
|
||||
Sys_Sleep(1);
|
||||
#else
|
||||
Con_Printf("capturethrottlesize is unsupported in this build\n");
|
||||
capturethrottlesize.ival = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
|
||||
{
|
||||
|
@ -2882,10 +2927,10 @@ static void QDECL capture_avi_end(void *vctx)
|
|||
{
|
||||
struct capture_avi_ctx *ctx = vctx;
|
||||
|
||||
if (ctx->uncompressed_video_stream) qAVIStreamRelease(ctx->uncompressed_video_stream);
|
||||
if (ctx->compressed_video_stream) qAVIStreamRelease(ctx->compressed_video_stream);
|
||||
if (ctx->uncompressed_audio_stream) qAVIStreamRelease(ctx->uncompressed_audio_stream);
|
||||
if (ctx->file) qAVIFileRelease(ctx->file);
|
||||
if (ctx->uncompressed_video_stream) qAVIStreamRelease(ctx->uncompressed_video_stream);
|
||||
if (ctx->compressed_video_stream) qAVIStreamRelease(ctx->compressed_video_stream);
|
||||
if (ctx->uncompressed_audio_stream) qAVIStreamRelease(ctx->uncompressed_audio_stream);
|
||||
if (ctx->file) qAVIFileRelease(ctx->file);
|
||||
Z_Free(ctx);
|
||||
}
|
||||
|
||||
|
@ -3230,7 +3275,7 @@ void Media_RecordFrame (void)
|
|||
y = vid.height-8;
|
||||
|
||||
#ifdef GLQUAKE
|
||||
if (capturingfbo)
|
||||
if (capturingfbo && qrenderer == QR_OPENGL)
|
||||
{
|
||||
shader_t *pic;
|
||||
GLBE_FBO_Pop(captureoldfbo);
|
||||
|
@ -3301,56 +3346,69 @@ void Media_RecordFrame (void)
|
|||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
|
||||
#ifdef CAN_USE_PBOS
|
||||
if (pbo_format != TF_INVALID)
|
||||
#ifdef GLQUAKE_PBOS
|
||||
if (offscreen_format != TF_INVALID && qrenderer == QR_OPENGL)
|
||||
{
|
||||
int imagesize = vid.fbpwidth * vid.fbpheight;
|
||||
switch(pbo_format)
|
||||
int frame;
|
||||
//encode the frame if we're about to stomp on it
|
||||
while (offscreen_captureframe + countof(offscreen_queue) <= captureframe)
|
||||
{
|
||||
case TF_BGR24:
|
||||
case TF_RGB24:
|
||||
imagesize *= 3;
|
||||
break;
|
||||
case TF_BGRA32:
|
||||
case TF_RGBA32:
|
||||
imagesize *= 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while (pbo_oldest + countof(pbo_handles) <= captureframe)
|
||||
{
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[pbo_oldest%countof(pbo_handles)]);
|
||||
frame = offscreen_captureframe%countof(offscreen_queue);
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, offscreen_queue[frame].pbo_handle);
|
||||
buffer = qglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
|
||||
if (buffer)
|
||||
{
|
||||
//FIXME: thread these (with audio too, to avoid races)
|
||||
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, pbo_oldest, vid.fbpwidth, vid.fbpheight, pbo_format);
|
||||
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, offscreen_captureframe, offscreen_queue[frame].width, offscreen_queue[frame].height, offscreen_queue[frame].format);
|
||||
qglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
}
|
||||
pbo_oldest++;
|
||||
offscreen_captureframe++;
|
||||
}
|
||||
|
||||
if (!pbo_handles[captureframe%countof(pbo_handles)])
|
||||
frame = captureframe%countof(offscreen_queue);
|
||||
//if we have no pbo yet, create one.
|
||||
if (!offscreen_queue[frame].pbo_handle)
|
||||
{
|
||||
qglGenBuffersARB(1, &pbo_handles[captureframe%countof(pbo_handles)]);
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[captureframe%countof(pbo_handles)]);
|
||||
int imagesize = 0;
|
||||
offscreen_queue[frame].format = offscreen_format;
|
||||
offscreen_queue[frame].width = vid.pixelwidth;
|
||||
offscreen_queue[frame].height = vid.pixelheight;
|
||||
switch(offscreen_queue[frame].format)
|
||||
{
|
||||
case TF_BGR24:
|
||||
case TF_RGB24:
|
||||
imagesize = 3;
|
||||
break;
|
||||
case TF_BGRA32:
|
||||
case TF_RGBA32:
|
||||
imagesize = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
imagesize *= offscreen_queue[frame].width * offscreen_queue[frame].height;
|
||||
|
||||
qglGenBuffersARB(1, &offscreen_queue[frame].pbo_handle);
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, offscreen_queue[frame].pbo_handle);
|
||||
qglBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imagesize, NULL, GL_STATIC_READ_ARB);
|
||||
}
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[captureframe%countof(pbo_handles)]);
|
||||
switch(pbo_format)
|
||||
|
||||
//get the gpu to copy the texture into the pbo. the driver should pipeline this read until we actually map the pbo, hopefully avoiding stalls
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, offscreen_queue[frame].pbo_handle);
|
||||
switch(offscreen_queue[frame].format)
|
||||
{
|
||||
case TF_BGR24:
|
||||
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_BGR_EXT, GL_UNSIGNED_BYTE, 0);
|
||||
qglReadPixels(0, 0, offscreen_queue[frame].width, offscreen_queue[frame].height, GL_BGR_EXT, GL_UNSIGNED_BYTE, 0);
|
||||
break;
|
||||
case TF_BGRA32:
|
||||
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
|
||||
qglReadPixels(0, 0, offscreen_queue[frame].width, offscreen_queue[frame].height, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
|
||||
break;
|
||||
case TF_RGB24:
|
||||
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
qglReadPixels(0, 0, offscreen_queue[frame].width, offscreen_queue[frame].height, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
break;
|
||||
case TF_RGBA32:
|
||||
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
qglReadPixels(0, 0, offscreen_queue[frame].width, offscreen_queue[frame].height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -3359,8 +3417,38 @@ void Media_RecordFrame (void)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
#if 0//def VKQUAKE
|
||||
if (offscreen_format != TF_INVALID && qrenderer == QR_VULKAN)
|
||||
{
|
||||
pbo_oldest = captureframe+1;
|
||||
//try and collect any finished frames
|
||||
while (offscreen_captureframe + countof(offscreen_queue) <= captureframe)
|
||||
{
|
||||
frame = offscreen_captureframe%countof(offscreen_queue);
|
||||
vkFenceWait();
|
||||
buffer = NULL;//qglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
|
||||
if (buffer)
|
||||
{
|
||||
//FIXME: thread these (with audio too, to avoid races)
|
||||
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, offscreen_captureframe, offscreen_queue[frame].width, offscreen_queue[frame].height, offscreen_queue[frame].format);
|
||||
//qglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
}
|
||||
offscreen_captureframe++;
|
||||
}
|
||||
|
||||
frame = captureframe%countof(offscreen_queue);
|
||||
if (no frame yet)
|
||||
{
|
||||
create a buffer
|
||||
map the buffer persistently
|
||||
}
|
||||
|
||||
vkCopyImageToBuffer
|
||||
vkSubmitFence
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
offscreen_captureframe = captureframe+1;
|
||||
//submit the current video frame. audio will be mixed to match.
|
||||
buffer = VID_GetRGBInfo(&truewidth, &trueheight, &fmt);
|
||||
if (buffer)
|
||||
|
@ -3388,7 +3476,7 @@ skipframe:
|
|||
y = vid.height-8;
|
||||
|
||||
#ifdef GLQUAKE
|
||||
if (capturingfbo)
|
||||
if (capturingfbo && qrenderer == QR_OPENGL)
|
||||
{
|
||||
shader_t *pic;
|
||||
GLBE_FBO_Pop(captureoldfbo);
|
||||
|
@ -3553,29 +3641,55 @@ void Media_InitFakeSoundDevice (int speed, int channels, int samplebits)
|
|||
|
||||
void Media_StopRecordFilm_f (void)
|
||||
{
|
||||
#ifdef CAN_USE_PBOS
|
||||
if (pbo_format)
|
||||
#ifdef GLQUAKE_PBOS
|
||||
if (offscreen_format && qrenderer == QR_OPENGL)
|
||||
{
|
||||
int i;
|
||||
while (pbo_oldest < captureframe)
|
||||
int frame;
|
||||
qbyte *buffer;
|
||||
while (offscreen_captureframe < captureframe)
|
||||
{
|
||||
qbyte *buffer;
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[pbo_oldest%countof(pbo_handles)]);
|
||||
frame = offscreen_captureframe%countof(offscreen_queue);
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, offscreen_queue[frame].pbo_handle);
|
||||
buffer = qglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
|
||||
if (buffer)
|
||||
{
|
||||
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, pbo_oldest, vid.fbpwidth, vid.fbpheight, TF_BGR24);
|
||||
// currentcapture_funcs->capture_video(currentcapture_ctx, buffer, pbo_oldest, vid.fbpwidth, vid.fbpheight, TF_BGRA32);
|
||||
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, offscreen_captureframe, offscreen_queue[frame].width, offscreen_queue[frame].height, offscreen_queue[frame].format);
|
||||
qglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
}
|
||||
pbo_oldest++;
|
||||
offscreen_captureframe++;
|
||||
}
|
||||
|
||||
for (i = 0; i < countof(pbo_handles); i++)
|
||||
for (frame = 0; frame < countof(offscreen_queue); frame++)
|
||||
{
|
||||
if (pbo_handles[i])
|
||||
qglDeleteBuffersARB(1, &pbo_handles[i]);
|
||||
pbo_handles[i] = 0;
|
||||
if (offscreen_queue[frame].pbo_handle)
|
||||
qglDeleteBuffersARB(1, &offscreen_queue[frame].pbo_handle);
|
||||
memset(&offscreen_queue[frame], 0, sizeof(offscreen_queue[frame]));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 0//def VKQUAKE
|
||||
if (pbo_format && qrenderer == QR_VULKAN)
|
||||
{
|
||||
int frame;
|
||||
while (offscreen_captureframe < captureframe)
|
||||
{
|
||||
frame = offscreen_captureframe%countof(offscreen_queue);
|
||||
qbyte *buffer;
|
||||
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, offscreen_queue[frame].pbo_handle);
|
||||
buffer = qglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
|
||||
if (buffer)
|
||||
{
|
||||
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, offscreen_captureframe, offscreen_queue[frame].width, offscreen_queue[frame].height, offscreen_queue[frame].format);
|
||||
qglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
}
|
||||
offscreen_captureframe++;
|
||||
}
|
||||
|
||||
for (frame = 0; frame < countof(offscreen_queue); frame++)
|
||||
{
|
||||
if (offscreen_queue[frame].pbo_handle)
|
||||
qglDeleteBuffersARB(1, &offscreen_queue[frame].pbo_handle);
|
||||
memset(&offscreen_queue[frame], 0, sizeof(offscreen_queue[frame]));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -3596,7 +3710,7 @@ void Media_StopRecordFilm_f (void)
|
|||
currentcapture_funcs = NULL;
|
||||
|
||||
#ifdef GLQUAKE
|
||||
if (capturingfbo)
|
||||
if (capturingfbo && qrenderer == QR_OPENGL)
|
||||
{
|
||||
GLBE_FBO_Pop(captureoldfbo);
|
||||
GLBE_FBO_Destroy(&capturefbo);
|
||||
|
@ -3627,7 +3741,7 @@ static void Media_RecordFilm (char *recordingname, qboolean demo)
|
|||
|
||||
Con_ClearNotify();
|
||||
|
||||
captureframe = pbo_oldest = 0;
|
||||
captureframe = offscreen_captureframe = 0;
|
||||
for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
|
||||
{
|
||||
if (pluginencodersfunc[i])
|
||||
|
@ -3668,17 +3782,26 @@ static void Media_RecordFilm (char *recordingname, qboolean demo)
|
|||
vid.fbpheight = captureheight.ival;
|
||||
vid.framebuffer = capturetexture;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
vid.fbpwidth = vid.pixelwidth;
|
||||
vid.fbpheight = vid.pixelheight;
|
||||
}
|
||||
|
||||
#ifdef CAN_USE_PBOS
|
||||
pbo_format = TF_INVALID;
|
||||
offscreen_format = TF_INVALID;
|
||||
#ifdef GLQUAKE_PBOS
|
||||
if (qrenderer == QR_OPENGL && !gl_config.gles && gl_config.glversion >= 2.1)
|
||||
{ //both tgas and vfw favour bgr24, so lets get the gl drivers to suffer instead of us, where possible.
|
||||
if (vid.fbpwidth & 3)
|
||||
pbo_format = TF_BGRA32; //don't bother changing pack alignment, just use something that is guarenteed to not need anything.
|
||||
offscreen_format = TF_BGRA32; //don't bother changing pack alignment, just use something that is guarenteed to not need anything.
|
||||
else
|
||||
pbo_format = TF_BGR24;
|
||||
offscreen_format = TF_BGR24;
|
||||
}
|
||||
#endif
|
||||
#ifdef VKQUAKE
|
||||
// if (qrenderer == QR_VULKAN)
|
||||
// offscreen_format = TF_BGRA32; //use the native format, the driver won't do byteswapping for us.
|
||||
#endif
|
||||
|
||||
recordingdemo = demo;
|
||||
|
@ -4531,6 +4654,7 @@ void Media_Init(void)
|
|||
Cvar_Register(&captureheight, "AVI capture controls");
|
||||
Cvar_Register(&capturedriver, "AVI capture controls");
|
||||
Cvar_Register(&capturecodec, "AVI capture controls");
|
||||
Cvar_Register(&capturethrottlesize, "AVI capture controls");
|
||||
|
||||
#if defined(WINAVI)
|
||||
Cvar_Register(&capturesoundbits, "AVI capture controls");
|
||||
|
|
|
@ -2753,6 +2753,11 @@ void M_Menu_Video_f (void)
|
|||
}
|
||||
|
||||
#ifndef MINIMAL
|
||||
|
||||
#ifdef RAGDOLL
|
||||
#include "pr_common.h"
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
enum {
|
||||
|
@ -2760,7 +2765,8 @@ typedef struct
|
|||
MV_BONES,
|
||||
MV_SHADER,
|
||||
MV_TEXTURE,
|
||||
MV_COLLISION
|
||||
MV_COLLISION,
|
||||
MV_EVENTS,
|
||||
} mode;
|
||||
int surfaceidx;
|
||||
int skingroup;
|
||||
|
@ -2776,6 +2782,17 @@ typedef struct
|
|||
|
||||
char shaderfile[MAX_QPATH];
|
||||
char *shadertext;
|
||||
|
||||
#ifdef RAGDOLL
|
||||
lerpents_t ragent;
|
||||
world_t ragworld;
|
||||
wedict_t ragworldedict;
|
||||
comentvars_t ragworldvars;
|
||||
comextentvars_t ragworldextvars;
|
||||
pubprogfuncs_t ragfuncs;
|
||||
qboolean flop; //ragdoll flopping enabled.
|
||||
float fixedrate;
|
||||
#endif
|
||||
} modelview_t;
|
||||
|
||||
static unsigned int genhsv(float h_, float s, float v)
|
||||
|
@ -2823,9 +2840,9 @@ static void M_BoneDisplayLame(entity_t *e, int *y, int depth, int parent, int fi
|
|||
if (Mod_GetTag(e->model, i+1, &e->framestate, result))
|
||||
{
|
||||
#if 0//def _DEBUG
|
||||
Draw_FunString(depth*16, *y, va("%s%i: %s (%g %g %g)", (i==sel)?"^1":"", i, bname, result[3], result[7], result[11]));
|
||||
Draw_FunString(depth*16, *y, va("%s%i: %s (%g %g %g)", (i==sel)?"^1":"", i+1, bname, result[3], result[7], result[11]));
|
||||
#else
|
||||
Draw_FunString(depth*16, *y, va("%s%i: %s", (i==sel)?"^1":"", i, bname));
|
||||
Draw_FunString(depth*16, *y, va("%s%i: %s", (i==sel)?"^1":"", i+1, bname));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -2836,6 +2853,17 @@ static void M_BoneDisplayLame(entity_t *e, int *y, int depth, int parent, int fi
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int tobit(unsigned int bitmask)
|
||||
{
|
||||
unsigned int b;
|
||||
for (b = 0; b < 32; b++)
|
||||
{
|
||||
if (bitmask & (1<<b))
|
||||
return b;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_s *m)
|
||||
{
|
||||
static playerview_t pv;
|
||||
|
@ -2935,16 +2963,40 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
ent.framestate.bonestate = bones;
|
||||
ent.framestate.bonecount = Mod_GetBoneRelations(ent.model, 0, MAX_BONES, &ent.framestate, ent.framestate.bonestate);
|
||||
ent.framestate.skeltype = SKEL_RELATIVE;
|
||||
|
||||
#ifdef RAGDOLL
|
||||
if (mods->flop)
|
||||
ent.framestate.g[FS_REG].frame[0] |= 0x8000;
|
||||
if (ent.model->dollinfo)
|
||||
{
|
||||
float rate = 1.0/60;
|
||||
rag_doallanimations(&mods->ragworld);
|
||||
mods->fixedrate += host_frametime;
|
||||
if (mods->fixedrate > 1)
|
||||
mods->fixedrate = 1;
|
||||
while (mods->fixedrate >= rate)
|
||||
{
|
||||
sv.world.rbe->Frame(&mods->ragworld, rate, 800);
|
||||
mods->fixedrate -= rate;
|
||||
}
|
||||
|
||||
rag_updatedeltaent(&mods->ragworld, &ent, &mods->ragent);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (mods->mode == MV_COLLISION)
|
||||
{
|
||||
shader_t *s = R_RegisterShader("bboxshader_nodepth", SUF_NONE,
|
||||
shader_t *s;
|
||||
|
||||
#ifdef HALFLIFEMODELS
|
||||
if (ent.model->type == mod_halflife)
|
||||
HLMDL_DrawHitBoxes(&ent);
|
||||
else
|
||||
#endif
|
||||
if (1)
|
||||
{
|
||||
s = R_RegisterShader("hitbox_nodepth", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
|
@ -2955,16 +3007,25 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
"nodepthtest\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
|
||||
#ifdef HALFLIFEMODELS
|
||||
if (ent.model->type == mod_halflife)
|
||||
HLMDL_DrawHitBoxes(&ent);
|
||||
Mod_AddSingleSurface(&ent, mods->surfaceidx, s);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
VectorAdd(ent.model->mins, ent.origin, mins);
|
||||
VectorAdd(ent.model->maxs, ent.origin, maxs);
|
||||
|
||||
s = R_RegisterShader("bboxshader_nodepth", SUF_NONE,
|
||||
"{\n"
|
||||
"polygonoffset\n"
|
||||
"{\n"
|
||||
"map $whiteimage\n"
|
||||
"blendfunc gl_src_alpha gl_one\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"nodepthtest\n"
|
||||
"}\n"
|
||||
"}\n");
|
||||
CLQ1_AddOrientedCube(s, mins, maxs, NULL, 1, 1, 1, 0.2);
|
||||
}
|
||||
|
||||
|
@ -2986,7 +3047,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
"}\n"
|
||||
"}\n");
|
||||
|
||||
if (ent.model->funcs.NativeTrace(ent.model, 0, &ent.framestate, NULL, v1, v2, vec3_origin, vec3_origin, false, ~0, &tr))
|
||||
if (ent.model->funcs.NativeTrace && ent.model->funcs.NativeTrace(ent.model, 0, &ent.framestate, NULL, v1, v2, vec3_origin, vec3_origin, false, ~0, &tr))
|
||||
{
|
||||
vec3_t dir;
|
||||
float f;
|
||||
|
@ -3067,13 +3128,26 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
R_RenderView();
|
||||
|
||||
y = 0;
|
||||
|
||||
fname = Mod_SurfaceNameForNum(ent.model, mods->surfaceidx);
|
||||
if (!fname)
|
||||
fname = "Unknown Surface";
|
||||
Draw_FunString(0, y, va("Surf %i: %s", mods->surfaceidx, fname));
|
||||
y+=8;
|
||||
|
||||
{
|
||||
fname = Mod_SurfaceNameForNum(ent.model, mods->surfaceidx);
|
||||
if (!fname)
|
||||
fname = "Unknown Surface";
|
||||
Draw_FunString(0, y, va("Surf %i: %s", mods->surfaceidx, fname));
|
||||
y+=8;
|
||||
}
|
||||
{
|
||||
fname = Mod_SkinNameForNum(ent.model, mods->surfaceidx, mods->skingroup);
|
||||
if (!fname)
|
||||
{
|
||||
Draw_FunString(0, y, va("Skin %i: <invalid skin>", mods->skingroup));
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup);
|
||||
Draw_FunString(0, y, va("Skin %i: \"%s\", shader \"%s\"", mods->skingroup, fname, shader?shader->name:"NO SHADER"));
|
||||
}
|
||||
y+=8;
|
||||
}
|
||||
{
|
||||
char *fname;
|
||||
int numframes = 0;
|
||||
|
@ -3084,12 +3158,6 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
Draw_FunString(0, y, va("Frame%i: %s (%i poses, %f/%f secs, %s)", mods->framegroup, fname, numframes, ent.framestate.g[FS_REG].frametime[0], duration, loop?"looped":"unlooped"));
|
||||
y+=8;
|
||||
}
|
||||
fname = Mod_SkinNameForNum(ent.model, mods->surfaceidx, mods->skingroup);
|
||||
if (!fname)
|
||||
fname = "Unknown Skin";
|
||||
shader = Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup);
|
||||
Draw_FunString(0, y, va("Skin %i: (%s) %s", mods->skingroup, fname, shader?shader->name:"NO SHADER"));
|
||||
y+=8;
|
||||
|
||||
switch(mods->mode)
|
||||
{
|
||||
|
@ -3100,22 +3168,75 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
"s: zoom out\n"
|
||||
"m: mode\n"
|
||||
"r: reset times\n"
|
||||
"home: skin-=1\n"
|
||||
"end: skin+=1\n"
|
||||
"home: skin+=1\n"
|
||||
"end: skin-=1\n"
|
||||
"pgup: frame+=1\n"
|
||||
"pgdn: frame-=1\n"
|
||||
"mins: %g %g %g, maxs: %g %g %g\n", ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2])
|
||||
, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);
|
||||
break;
|
||||
case MV_COLLISION:
|
||||
if (ent.model->type != mod_halflife)
|
||||
if (!ent.model)
|
||||
;
|
||||
else if (ent.model->type == mod_alias)
|
||||
{
|
||||
galiasinfo_t *inf = Mod_Extradata(ent.model);
|
||||
int surfnum = mods->surfaceidx;
|
||||
while(inf && surfnum-->0)
|
||||
inf = inf->nextsurf;
|
||||
if (inf)
|
||||
{
|
||||
char contents[512];
|
||||
unsigned int i;
|
||||
char *contentnames[32] = {NULL};
|
||||
contentnames[tobit(FTECONTENTS_SOLID)] = "solid";
|
||||
contentnames[tobit(FTECONTENTS_LAVA)] = "lava";
|
||||
contentnames[tobit(FTECONTENTS_SLIME)] = "slime";
|
||||
contentnames[tobit(FTECONTENTS_WATER)] = "water";
|
||||
contentnames[tobit(FTECONTENTS_LADDER)] = "ladder";
|
||||
contentnames[tobit(FTECONTENTS_PLAYERCLIP)] = "playerclip";
|
||||
contentnames[tobit(FTECONTENTS_MONSTERCLIP)] = "monsterclip";
|
||||
contentnames[tobit(FTECONTENTS_BODY)] = "body";
|
||||
contentnames[tobit(FTECONTENTS_CORPSE)] = "corpse";
|
||||
contentnames[tobit(FTECONTENTS_SKY)] = "sky";
|
||||
for (*contents = 0, i = 0; i < 32; i++)
|
||||
{
|
||||
if (inf->contents & (1<<i))
|
||||
{
|
||||
if (*contents)
|
||||
Q_strncatz(contents, "|", sizeof(contents));
|
||||
if (contentnames[i])
|
||||
Q_strncatz(contents, contentnames[i], sizeof(contents));
|
||||
else
|
||||
Q_strncatz(contents, va("%#x", 1<<i), sizeof(contents));
|
||||
}
|
||||
}
|
||||
if (!*contents)
|
||||
Q_strncatz(contents, "non-solid", sizeof(contents));
|
||||
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y,
|
||||
va( "mins: %g %g %g, maxs: %g %g %g\n"
|
||||
"contents: %s\n"
|
||||
"surfflags: %#x\n"
|
||||
"body: %i\n"
|
||||
"geomset: %i %i%s\n"
|
||||
"numverts: %i\nnumtris: %i\n"
|
||||
, ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2],
|
||||
contents,
|
||||
inf->csurface.flags,
|
||||
inf->surfaceid,
|
||||
inf->geomset>=MAX_GEOMSETS?-1:inf->geomset, inf->geomid, inf->geomset>=MAX_GEOMSETS?" (always)":"",
|
||||
inf->numverts, inf->numindexes/3
|
||||
)
|
||||
, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y,
|
||||
va("mins: %g %g %g, maxs: %g %g %g\n", ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2])
|
||||
, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs);
|
||||
break;
|
||||
}
|
||||
//fallthrough
|
||||
break;
|
||||
case MV_BONES:
|
||||
#ifdef SKELETALMODELS
|
||||
{
|
||||
|
@ -3131,6 +3252,21 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_
|
|||
}
|
||||
#endif
|
||||
break;
|
||||
case MV_EVENTS:
|
||||
{
|
||||
int i;
|
||||
float timestamp = 0;
|
||||
int code = 0;
|
||||
char *data = NULL;
|
||||
Draw_FunString(0, y, va("Events: "));
|
||||
y+=8;
|
||||
for (i = 0; Mod_GetModelEvent(ent.model, mods->framegroup, i, ×tamp, &code, &data); y+=8, i++)
|
||||
{
|
||||
Draw_FunString(0, y, va("%i %f: %i %s", i, timestamp, code, data));
|
||||
}
|
||||
Draw_FunString(0, y, va("%f: <end of animation>", Mod_GetFrameDuration(ent.model, 0, mods->framegroup)));
|
||||
}
|
||||
break;
|
||||
case MV_SHADER:
|
||||
{
|
||||
if (!mods->shadertext)
|
||||
|
@ -3184,7 +3320,8 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k
|
|||
case MV_BONES: mods->mode = MV_SHADER; break;
|
||||
case MV_SHADER: mods->mode = MV_TEXTURE; break;
|
||||
case MV_TEXTURE: mods->mode = MV_COLLISION; break;
|
||||
case MV_COLLISION: mods->mode = MV_NONE; break;
|
||||
case MV_COLLISION: mods->mode = MV_EVENTS; break;
|
||||
case MV_EVENTS: mods->mode = MV_NONE; break;
|
||||
}
|
||||
}
|
||||
else if (key == 'r')
|
||||
|
@ -3192,6 +3329,14 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k
|
|||
mods->framechangetime = realtime;
|
||||
mods->skinchangetime = realtime;
|
||||
}
|
||||
#ifdef RAGDOLL
|
||||
else if (key == 'f')
|
||||
{
|
||||
mods->flop ^= 1;
|
||||
if (!mods->flop)
|
||||
rag_removedeltaent(&mods->ragent);
|
||||
}
|
||||
#endif
|
||||
else if (key == '[')
|
||||
mods->boneidx--;
|
||||
else if (key == ']')
|
||||
|
@ -3204,14 +3349,14 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k
|
|||
mods->yaw -= 5;
|
||||
else if (key == K_RIGHTARROW)
|
||||
mods->yaw += 5;
|
||||
else if (key == K_HOME)
|
||||
else if (key == K_END)
|
||||
{
|
||||
mods->skingroup = max(0, mods->skingroup-1);
|
||||
mods->skinchangetime = realtime;
|
||||
Z_Free(mods->shadertext);
|
||||
mods->shadertext = NULL;
|
||||
}
|
||||
else if (key == K_END)
|
||||
else if (key == K_HOME)
|
||||
{
|
||||
mods->skingroup += 1;
|
||||
mods->skinchangetime = realtime;
|
||||
|
@ -3230,13 +3375,13 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k
|
|||
mods->framegroup += 1;
|
||||
mods->framechangetime = realtime;
|
||||
}
|
||||
else if (key == K_INS)
|
||||
else if (key == K_DEL)
|
||||
{
|
||||
mods->surfaceidx = max(0, mods->surfaceidx-1);
|
||||
Z_Free(mods->shadertext);
|
||||
mods->shadertext = NULL;
|
||||
}
|
||||
else if (key == K_DEL)
|
||||
else if (key == K_INS)
|
||||
{
|
||||
mods->surfaceidx += 1;
|
||||
Z_Free(mods->shadertext);
|
||||
|
@ -3253,12 +3398,31 @@ static qboolean M_ModelViewerKey(struct menucustom_s *c, struct menu_s *m, int k
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef RAGDOLL
|
||||
void M_Modelviewer_Shutdown(struct menu_s *menu)
|
||||
{
|
||||
modelview_t *mv = menu->data;
|
||||
rag_removedeltaent(&mv->ragent);
|
||||
skel_reset(&mv->ragworld);
|
||||
World_RBE_Shutdown(&mv->ragworld);
|
||||
}
|
||||
//haxors, for skeletal objects+RBE
|
||||
char *PDECL M_Modelviewer_AddString(pubprogfuncs_t *prinst, const char *val, int minlength, pbool demarkup)
|
||||
{
|
||||
return Z_Malloc(minlength);
|
||||
}
|
||||
struct edict_s *PDECL M_Modelviewer_ProgsToEdict(pubprogfuncs_t *prinst, int num)
|
||||
{
|
||||
return (struct edict_s*)prinst->edicttable[num];
|
||||
}
|
||||
#endif
|
||||
|
||||
void M_Menu_ModelViewer_f(void)
|
||||
{
|
||||
modelview_t *mv;
|
||||
menucustom_t *c;
|
||||
menu_t *menu;
|
||||
|
||||
|
||||
Key_Dest_Add(kdm_emenu);
|
||||
|
||||
menu = M_CreateMenu(sizeof(*mv));
|
||||
|
@ -3268,10 +3432,28 @@ void M_Menu_ModelViewer_f(void)
|
|||
c->draw = M_ModelViewerDraw;
|
||||
c->key = M_ModelViewerKey;
|
||||
|
||||
mv->yaw = 180 + crandom()*45;
|
||||
mv->yaw = 180;// + crandom()*45;
|
||||
mv->dist = 150;
|
||||
Q_strncpyz(mv->modelname, Cmd_Argv(1), sizeof(mv->modelname));
|
||||
Q_strncpyz(mv->forceshader, Cmd_Argv(2), sizeof(mv->forceshader));
|
||||
|
||||
#ifdef RAGDOLL
|
||||
menu->remove = M_Modelviewer_Shutdown;
|
||||
mv->ragworld.progs = &mv->ragfuncs;
|
||||
mv->ragfuncs.AddString = M_Modelviewer_AddString;
|
||||
mv->ragfuncs.ProgsToEdict = M_Modelviewer_ProgsToEdict;
|
||||
mv->ragfuncs.edicttable = (edict_t**)&mv->ragworld.edicts;
|
||||
mv->ragworld.edicts = &mv->ragworldedict;
|
||||
mv->ragworld.edicts->v = &mv->ragworldvars;
|
||||
mv->ragworld.edicts->xv = &mv->ragworldextvars;
|
||||
mv->ragworld.num_edicts = 1;
|
||||
mv->ragworld.edicts->v->solid = SOLID_BBOX;
|
||||
VectorSet(mv->ragworld.edicts->v->mins, -1000, -1000, -101);
|
||||
VectorSet(mv->ragworld.edicts->v->maxs, 1000, 1000, -100);
|
||||
|
||||
mv->ragworld.worldmodel = Mod_ForName("", MLV_SILENT);
|
||||
World_RBE_Start(&mv->ragworld);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void M_Menu_ModelViewer_f(void)
|
||||
|
|
|
@ -172,7 +172,10 @@ extern void Mod_TouchModel (const char *name);
|
|||
extern const char *Mod_FixName (const char *modname, const char *worldname); //remaps the name appropriately
|
||||
const char *Mod_ParseWorldspawnKey (struct model_s *mod, const char *key, char *buffer, size_t sizeofbuffer);
|
||||
|
||||
extern long relitsurface;
|
||||
extern struct model_s *lightmodel;
|
||||
extern void Mod_Think (void);
|
||||
extern qboolean Mod_GetModelEvent (struct model_s *model, int animation, int eventidx, float *timestamp, int *eventcode, char **eventdata);
|
||||
extern int Mod_SkinNumForName (struct model_s *model, int surfaceidx, const char *name);
|
||||
extern int Mod_FrameNumForName (struct model_s *model, int surfaceidx, const char *name);
|
||||
extern float Mod_GetFrameDuration (struct model_s *model, int surfaceidx, int framenum);
|
||||
|
@ -183,6 +186,7 @@ extern int Mod_GetFrameCount (struct model_s *model);
|
|||
extern qboolean Mod_GetTag (struct model_s *model, int tagnum, framestate_t *framestate, float *transforms);
|
||||
extern int Mod_TagNumForName (struct model_s *model, const char *name);
|
||||
|
||||
void Mod_AddSingleSurface(struct entity_s *ent, int surfaceidx, shader_t *shader);
|
||||
int Mod_GetNumBones(struct model_s *model, qboolean allowtags);
|
||||
int Mod_GetBoneRelations(struct model_s *model, int firstbone, int lastbone, framestate_t *fstate, float *result);
|
||||
int Mod_GetBoneParent(struct model_s *model, int bonenum);
|
||||
|
|
|
@ -17,7 +17,9 @@ void Master_DetermineMasterTypes(void)
|
|||
{
|
||||
if (com_protocolname.modified)
|
||||
{
|
||||
char tok[MAX_QPATH];
|
||||
char *prot = com_protocolname.string;
|
||||
char *game;
|
||||
com_protocolname.modified = 0;
|
||||
|
||||
sb_enabledarkplaces = true; //dpmaster is not specific to any single game/mod, so can be left enabled even when running q2 etc, for extra redundancy.
|
||||
|
@ -26,19 +28,24 @@ void Master_DetermineMasterTypes(void)
|
|||
sb_enablenetquake = false;
|
||||
sb_enablequakeworld = false;
|
||||
|
||||
//this is stupid
|
||||
if (!Q_strncasecmp(prot, "FTE-", 4))
|
||||
prot += 4;
|
||||
else if (!Q_strncasecmp(prot, "DarkPlaces-", 11))
|
||||
prot += 11;
|
||||
for (prot = com_protocolname.string; *prot;)
|
||||
{
|
||||
prot = COM_ParseOut(prot, tok, sizeof(tok));
|
||||
game = tok;
|
||||
//this is stupid, but hey
|
||||
if (!Q_strncasecmp(game, "FTE-", 4))
|
||||
game += 4;
|
||||
else if (!Q_strncasecmp(game, "DarkPlaces-", 11))
|
||||
game += 11;
|
||||
|
||||
if (!strcmp(prot, "Quake2"))
|
||||
sb_enablequake2 = true;
|
||||
if (!strcmp(prot, "Quake3"))
|
||||
sb_enablequake3 = true;
|
||||
//for DP compatibility, we consider these separate(ish) games.
|
||||
if (!strcmp(prot, "Quake") || !strcmp(com_protocolname.string, "Hipnotic") || !strcmp(com_protocolname.string, "Rogue"))
|
||||
sb_enablenetquake = sb_enablequakeworld = true;
|
||||
if (!strcmp(game, "Quake2"))
|
||||
sb_enablequake2 = true;
|
||||
if (!strcmp(game, "Quake3"))
|
||||
sb_enablequake3 = true;
|
||||
//for DP compatibility, we consider these separate(ish) games.
|
||||
if (!strcmp(game, "Quake") || !strcmp(game, "Hipnotic") || !strcmp(game, "Rogue"))
|
||||
sb_enablenetquake = sb_enablequakeworld = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1974,7 +1981,7 @@ int Master_CheckPollSockets(void)
|
|||
s = MSG_ReadString();
|
||||
|
||||
old = Info_ValueForKey(info->moreinfo->info, selectedserver.lastrule);
|
||||
if (strcmp(s, old))
|
||||
if (strcmp(s, old) && !strchr(s, '\"') && !strchr(s, '\\'))
|
||||
Info_SetValueForStarKey(info->moreinfo->info, selectedserver.lastrule, s, sizeof(info->moreinfo->info));
|
||||
|
||||
//... and now try to query the next one... because everyone gives up after the first, right?... dude... I hate this shit.
|
||||
|
@ -2352,13 +2359,20 @@ void MasterInfo_Request(master_t *mast)
|
|||
case MP_DPMASTER:
|
||||
{
|
||||
char *str;
|
||||
//for compat with dp, we use the nq netchan version. which is stupid, but whatever
|
||||
//we ask for ipv6 addresses from ipv6 masters (assuming it resolved okay)
|
||||
if (mast->adr.type == NA_IPV6)
|
||||
str = va("%c%c%c%cgetserversExt %s %u empty full ipv6"/*\x0A\n"*/, 255, 255, 255, 255, com_protocolname.string, NQ_NETCHAN_VERSION);
|
||||
else
|
||||
str = va("%c%c%c%cgetservers %s %u empty full"/*\x0A\n"*/, 255, 255, 255, 255, com_protocolname.string, NQ_NETCHAN_VERSION);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
char game[MAX_QPATH];
|
||||
char *games = com_protocolname.string;
|
||||
while(*games)
|
||||
{ //send a request for each game listed.
|
||||
games = COM_ParseOut(games, game, sizeof(game));
|
||||
|
||||
//for compat with dp, we use the nq netchan version. which is stupid, but whatever
|
||||
//we ask for ipv6 addresses from ipv6 masters (assuming it resolved okay)
|
||||
if (mast->adr.type == NA_IPV6)
|
||||
str = va("%c%c%c%cgetserversExt %s %u empty full ipv6"/*\x0A\n"*/, 255, 255, 255, 255, game, NQ_NETCHAN_VERSION);
|
||||
else
|
||||
str = va("%c%c%c%cgetservers %s %u empty full"/*\x0A\n"*/, 255, 255, 255, 255, game, NQ_NETCHAN_VERSION);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
|
|
@ -133,6 +133,7 @@ extern sfx_t *cl_sfx_r_exp3;
|
|||
globalfloat(frametime, "frametime"); /*float Client render frame interval*/ \
|
||||
globalfloat(gamespeed, "gamespeed"); /*float Multiplier for real time -> simulation time*/ \
|
||||
globalfloat(cltime, "cltime"); /*float Clientside map uptime indepent of gamespeed, latency, and the server in general*/ \
|
||||
globalfloat(clframetime, "clframetime"); /*float time since last video frame*/ \
|
||||
globalfloat(netnewtime, "servertime"); /*float Server time of latest inbound network frame*/ \
|
||||
globalfloat(netoldtime, "serverprevtime"); /*float Server time of previous inbound network frame */ \
|
||||
globalfloat(netdeltatime, "serverdeltatime"); /*float new-old */ \
|
||||
|
@ -600,7 +601,7 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t
|
|||
out->bonecount = 0;
|
||||
out->bonestate = NULL;
|
||||
if (in->xv->skeletonindex)
|
||||
skel_lookup(csqcprogs, in->xv->skeletonindex, out);
|
||||
skel_lookup(&csqc_world, in->xv->skeletonindex, out);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1715,7 +1716,7 @@ static void QCBUILTIN PF_R_ClearScene (pubprogfuncs_t *prinst, struct globalvars
|
|||
CL_DecayLights ();
|
||||
|
||||
#if defined(SKELETALOBJECTS) || defined(RAGDOLLS)
|
||||
skel_dodelete(csqcprogs);
|
||||
skel_dodelete(&csqc_world);
|
||||
#endif
|
||||
CL_ClearEntityLists();
|
||||
|
||||
|
@ -3416,7 +3417,7 @@ static const char *PF_cs_getplayerkey_internal (unsigned int pnum, const char *k
|
|||
static char buffer[64];
|
||||
char *ret;
|
||||
|
||||
if (pnum < 0 || pnum >= cl.allocated_client_slots)
|
||||
if ((unsigned int)pnum >= (unsigned int)cl.allocated_client_slots)
|
||||
ret = "";
|
||||
else if (!strcmp(keyname, "viewentity")) //compat with DP. Yes, I know this is in the wrong place. This is an evil hack.
|
||||
{
|
||||
|
@ -4565,6 +4566,7 @@ static void CSQC_LerpStateToCSQC(lerpents_t *le, csqcedict_t *ent, qboolean nole
|
|||
ent->xv->baseframe2 = le->oldframe[FST_BASE];
|
||||
ent->xv->baseframe2time = max(0, cl.servertime - le->oldframestarttime[FST_BASE]);
|
||||
ent->xv->baselerpfrac = bound(0, 1-(ent->xv->baseframe1time) / le->framelerpdeltatime[FST_BASE], 1);
|
||||
ent->xv->basebone = le->basebone;
|
||||
|
||||
|
||||
if (nolerp)
|
||||
|
@ -5156,9 +5158,6 @@ static void QCBUILTIN PF_V_CalcRefdef(pubprogfuncs_t *prinst, struct globalvars_
|
|||
|
||||
CL_DecayLights ();
|
||||
|
||||
#if defined(SKELETALOBJECTS) || defined(RAGDOLLS)
|
||||
skel_dodelete(csqcprogs);
|
||||
#endif
|
||||
CL_ClearEntityLists();
|
||||
|
||||
V_ClearRefdef(csqc_playerview);
|
||||
|
@ -5706,6 +5705,9 @@ static struct {
|
|||
{"skel_delete", PF_skel_delete, 275},//void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS)
|
||||
{"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #276 (FTE_CSQC_SKELETONOBJECTS)
|
||||
{"frameduration", PF_frameduration, 277},//void(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS)
|
||||
{"processmodelevents", PF_processmodelevents, 0},
|
||||
{"getnextmodelevent", PF_getnextmodelevent, 0},
|
||||
{"getmodeleventidx", PF_getmodeleventidx, 0},
|
||||
|
||||
{"crossproduct", PF_crossproduct, 0},
|
||||
|
||||
|
@ -6336,7 +6338,15 @@ static qboolean QDECL CSQC_Event_ContentsTransition(world_t *w, wedict_t *ent, i
|
|||
|
||||
static model_t *QDECL CSQC_World_ModelForIndex(world_t *w, int modelindex)
|
||||
{
|
||||
return CSQC_GetModelForIndex(modelindex);
|
||||
model_t *mod = CSQC_GetModelForIndex(modelindex);
|
||||
if (mod && mod->loadstate != MLS_LOADED)
|
||||
{
|
||||
if (mod->loadstate == MLS_LOADING)
|
||||
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
|
||||
if (mod->loadstate != MLS_LOADED)
|
||||
mod = NULL; //gah, it failed!
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
static void QDECL CSQC_World_GetFrameState(world_t *w, wedict_t *win, framestate_t *out)
|
||||
{
|
||||
|
@ -7310,6 +7320,8 @@ qboolean CSQC_DrawView(void)
|
|||
else
|
||||
*csqcg.frametime = host_frametime;
|
||||
}
|
||||
if (csqcg.clframetime)
|
||||
*csqcg.clframetime = host_frametime;
|
||||
|
||||
if (csqcg.numclientseats)
|
||||
*csqcg.numclientseats = cl.splitclients;
|
||||
|
|
|
@ -1838,7 +1838,9 @@ static void QCBUILTIN PF_m_clearscene(pubprogfuncs_t *prinst, struct globalvars_
|
|||
// CL_DecayLights ();
|
||||
|
||||
#if defined(SKELETALOBJECTS) || defined(RAGDOLLS)
|
||||
skel_dodelete(prinst);
|
||||
world_t *world = prinst->parms->user;
|
||||
if (world)
|
||||
skel_dodelete(world);
|
||||
#endif
|
||||
CL_ClearEntityLists();
|
||||
|
||||
|
|
|
@ -482,6 +482,19 @@ static qboolean rag_dollline(dollcreatectx_t *ctx, int linenum)
|
|||
ctx->body->dimensions[1] = atof(Cmd_Argv(2));
|
||||
ctx->body->dimensions[2] = atof(Cmd_Argv(3));
|
||||
}
|
||||
else if (ctx->body && argc == 4 && !stricmp(cmd, "offset"))
|
||||
{
|
||||
vec3_t ang;
|
||||
ctx->body->isoffset = true;
|
||||
ctx->body->relmatrix[3] = atof(val);
|
||||
ctx->body->relmatrix[7] = atof(Cmd_Argv(2));
|
||||
ctx->body->relmatrix[11] = atof(Cmd_Argv(3));
|
||||
ang[0] = atof(Cmd_Argv(4));
|
||||
ang[1] = atof(Cmd_Argv(5));
|
||||
ang[2] = atof(Cmd_Argv(6));
|
||||
AngleVectorsFLU(ang, &ctx->body->relmatrix[0], &ctx->body->relmatrix[4], &ctx->body->relmatrix[8]);
|
||||
Matrix3x4_Invert_Simple(ctx->body->relmatrix, ctx->body->inverserelmatrix);
|
||||
}
|
||||
|
||||
//joint properties
|
||||
else if (ctx->joint && argc == 2 && !stricmp(cmd, "type"))
|
||||
|
@ -966,13 +979,13 @@ void skel_info_f(void)
|
|||
}
|
||||
|
||||
/*destroys all skeletons*/
|
||||
void skel_reset(pubprogfuncs_t *prinst)
|
||||
void skel_reset(world_t *world)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < countof(skelobjects); i++)
|
||||
{
|
||||
if (skelobjects[i].world == prinst->parms->user)
|
||||
if (skelobjects[i].world == world)
|
||||
{
|
||||
#ifdef RAGDOLL
|
||||
rag_uninstanciate(&skelobjects[i]);
|
||||
|
@ -992,7 +1005,7 @@ void skel_reset(pubprogfuncs_t *prinst)
|
|||
}
|
||||
|
||||
/*deletes any skeletons marked for deletion*/
|
||||
void skel_dodelete(pubprogfuncs_t *prinst)
|
||||
void skel_dodelete(world_t *world)
|
||||
{
|
||||
int skelidx;
|
||||
if (!pendingkill)
|
||||
|
@ -1014,7 +1027,7 @@ void skel_dodelete(pubprogfuncs_t *prinst)
|
|||
numskelobjectsused--;
|
||||
}
|
||||
|
||||
static skelobject_t *skel_create(pubprogfuncs_t *prinst, int bonecount)
|
||||
static skelobject_t *skel_create(world_t *world, int bonecount)
|
||||
{
|
||||
unsigned int skelidx;
|
||||
//invalid if the bonecount is not set...
|
||||
|
@ -1023,7 +1036,7 @@ static skelobject_t *skel_create(pubprogfuncs_t *prinst, int bonecount)
|
|||
|
||||
for (skelidx = 0; skelidx < numskelobjectsused; skelidx++)
|
||||
{
|
||||
if (!skelobjects[skelidx].inuse && skelobjects[skelidx].numbones == bonecount && skelobjects[skelidx].world == prinst->parms->user)
|
||||
if (!skelobjects[skelidx].inuse && skelobjects[skelidx].numbones == bonecount && skelobjects[skelidx].world == world)
|
||||
{
|
||||
skelobjects[skelidx].inuse = 1;
|
||||
return &skelobjects[skelidx];
|
||||
|
@ -1034,14 +1047,14 @@ static skelobject_t *skel_create(pubprogfuncs_t *prinst, int bonecount)
|
|||
{
|
||||
if (!skelobjects[skelidx].inuse &&
|
||||
(!skelobjects[skelidx].numbones || skelobjects[skelidx].numbones == bonecount) &&
|
||||
(!skelobjects[skelidx].world || skelobjects[skelidx].world == prinst->parms->user))
|
||||
(!skelobjects[skelidx].world || skelobjects[skelidx].world == world))
|
||||
{
|
||||
if (!skelobjects[skelidx].numbones)
|
||||
{
|
||||
skelobjects[skelidx].numbones = bonecount;
|
||||
skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount, false);
|
||||
skelobjects[skelidx].bonematrix = (float*)PR_AddString(world->progs, "", sizeof(float)*12*bonecount, false);
|
||||
}
|
||||
skelobjects[skelidx].world = prinst->parms->user;
|
||||
skelobjects[skelidx].world = world;
|
||||
if (numskelobjectsused <= skelidx)
|
||||
numskelobjectsused = skelidx + 1;
|
||||
skelobjects[skelidx].model = NULL;
|
||||
|
@ -1052,7 +1065,7 @@ static skelobject_t *skel_create(pubprogfuncs_t *prinst, int bonecount)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
static skelobject_t *skel_get(pubprogfuncs_t *prinst, int skelidx)
|
||||
static skelobject_t *skel_get(world_t *world, int skelidx)
|
||||
{
|
||||
skelidx--;
|
||||
if ((unsigned int)skelidx >= numskelobjectsused)
|
||||
|
@ -1062,9 +1075,9 @@ static skelobject_t *skel_get(pubprogfuncs_t *prinst, int skelidx)
|
|||
return &skelobjects[skelidx];
|
||||
}
|
||||
|
||||
void skel_lookup(pubprogfuncs_t *prinst, int skelidx, framestate_t *out)
|
||||
void skel_lookup(world_t *world, int skelidx, framestate_t *out)
|
||||
{
|
||||
skelobject_t *sko = skel_get(prinst, skelidx);
|
||||
skelobject_t *sko = skel_get(world, skelidx);
|
||||
if (sko && sko->inuse)
|
||||
{
|
||||
out->skeltype = sko->type;
|
||||
|
@ -1075,9 +1088,10 @@ void skel_lookup(pubprogfuncs_t *prinst, int skelidx, framestate_t *out)
|
|||
|
||||
void QCBUILTIN PF_skel_mmap(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *world = prinst->parms->user;
|
||||
int skelidx = G_FLOAT(OFS_PARM0);
|
||||
skelobject_t *sko = skel_get(prinst, skelidx);
|
||||
if (!sko || sko->world != prinst->parms->user)
|
||||
skelobject_t *sko = skel_get(world, skelidx);
|
||||
if (!sko || sko->world != world)
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
else
|
||||
G_INT(OFS_RETURN) = (char*)sko->bonematrix - prinst->stringtable;
|
||||
|
@ -1118,9 +1132,17 @@ static void rag_uninstanciate(skelobject_t *sko)
|
|||
}
|
||||
static void rag_genbodymatrix(skelobject_t *sko, rbebodyinfo_t *dollbody, float *emat, float *result)
|
||||
{
|
||||
float tmp[12];
|
||||
float *bmat;
|
||||
int bone = dollbody->bone;
|
||||
bmat = sko->bonematrix + bone*12;
|
||||
|
||||
if (dollbody->isoffset)
|
||||
{
|
||||
R_ConcatTransforms((void*)dollbody->relmatrix, (void*)bmat, (void*)tmp);
|
||||
bmat = tmp;
|
||||
}
|
||||
|
||||
R_ConcatTransforms((void*)emat, (void*)bmat, (void*)result);
|
||||
|
||||
if (dollbody->orient)
|
||||
|
@ -1331,8 +1353,15 @@ static void rag_derive(skelobject_t *sko, skelobject_t *asko, float *emat)
|
|||
{
|
||||
//bones with a body are given an absolute pose matching that body.
|
||||
sko->world->rbe->RagMatrixFromBody(sko->world, &sko->body[doll->bone[i].bodyidx].odebody, bodymat);
|
||||
//that body matrix is in world space, so transform to model space for our result
|
||||
R_ConcatTransforms((void*)invemat, (void*)bodymat, (void*)((float*)bmat+i*12));
|
||||
if (doll->body[doll->bone[i].bodyidx].isoffset)
|
||||
{
|
||||
float tmp[12];
|
||||
R_ConcatTransforms((void*)doll->body[doll->bone[i].bodyidx].inverserelmatrix, (void*)bodymat, (void*)tmp);
|
||||
R_ConcatTransforms((void*)invemat, (void*)tmp, (void*)((float*)bmat+i*12));
|
||||
}
|
||||
else
|
||||
//that body matrix is in world space, so transform to model space for our result
|
||||
R_ConcatTransforms((void*)invemat, (void*)bodymat, (void*)((float*)bmat+i*12));
|
||||
}
|
||||
else if (amat) //FIXME: don't do this when the bone has an unanimated child body.
|
||||
{
|
||||
|
@ -1399,7 +1428,7 @@ void rag_removedeltaent(lerpents_t *le)
|
|||
return;
|
||||
le->skeletalobject = 0;
|
||||
|
||||
skelobj = skel_get(csqc_world.progs, skelidx);
|
||||
skelobj = skel_get(&csqc_world, skelidx);
|
||||
if (skelobj)
|
||||
{
|
||||
skelobj->inuse = 2; //2 means don't reuse yet.
|
||||
|
@ -1421,7 +1450,7 @@ void rag_lerpdeltaent(lerpents_t *le, unsigned int bonecount, short *newstate, f
|
|||
skelobject_t *sko;
|
||||
if (le->skeletalobject)
|
||||
{
|
||||
sko = skel_get(csqc_world.progs, le->skeletalobject);
|
||||
sko = skel_get(&csqc_world, le->skeletalobject);
|
||||
if (sko->numbones != bonecount)
|
||||
{ //unusable, discard it and create a new one.
|
||||
sko->inuse = 2; //2 means don't reuse yet.
|
||||
|
@ -1435,7 +1464,7 @@ void rag_lerpdeltaent(lerpents_t *le, unsigned int bonecount, short *newstate, f
|
|||
|
||||
if (!sko || sko->inuse != 1)
|
||||
{
|
||||
sko = skel_create(csqc_world.progs, bonecount);
|
||||
sko = skel_create(&csqc_world, bonecount);
|
||||
if (!sko)
|
||||
return; //couldn't get one, ran out of memory or something?
|
||||
sko->model = NULL;
|
||||
|
@ -1480,10 +1509,8 @@ void rag_lerpdeltaent(lerpents_t *le, unsigned int bonecount, short *newstate, f
|
|||
}
|
||||
}
|
||||
|
||||
void rag_updatedeltaent(entity_t *ent, lerpents_t *le)
|
||||
void rag_updatedeltaent(world_t *w, entity_t *ent, lerpents_t *le)
|
||||
{
|
||||
extern world_t csqc_world;
|
||||
world_t *w;
|
||||
model_t *mod = ent->model;
|
||||
skelobject_t *sko;
|
||||
float emat[12];
|
||||
|
@ -1494,13 +1521,12 @@ void rag_updatedeltaent(entity_t *ent, lerpents_t *le)
|
|||
|
||||
if (mod->dollinfo)
|
||||
{
|
||||
w = &csqc_world;
|
||||
if (!w->rbe)
|
||||
return;
|
||||
|
||||
if (!le->skeletalobject)
|
||||
{
|
||||
sko = skel_create(w->progs, Mod_GetNumBones(mod, false));
|
||||
sko = skel_create(w, Mod_GetNumBones(mod, false));
|
||||
if (!sko)
|
||||
return; //couldn't get one, ran out of memory or something?
|
||||
sko->model = mod;
|
||||
|
@ -1509,7 +1535,7 @@ void rag_updatedeltaent(entity_t *ent, lerpents_t *le)
|
|||
}
|
||||
else
|
||||
{
|
||||
sko = skel_get(w->progs, le->skeletalobject);
|
||||
sko = skel_get(w, le->skeletalobject);
|
||||
if (!sko)
|
||||
{
|
||||
le->skeletalobject = 0;
|
||||
|
@ -1551,8 +1577,7 @@ void rag_updatedeltaent(entity_t *ent, lerpents_t *le)
|
|||
}
|
||||
else if (le->skeletalobject)
|
||||
{
|
||||
w = &csqc_world;
|
||||
sko = skel_get(w->progs, le->skeletalobject);
|
||||
sko = skel_get(w, le->skeletalobject);
|
||||
if (!sko)
|
||||
{
|
||||
le->skeletalobject = 0;
|
||||
|
@ -1574,6 +1599,7 @@ void QCBUILTIN PF_skel_ragedit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
{
|
||||
//do we want to be able to generate a ragdoll object with this function too?
|
||||
#ifdef RAGDOLL
|
||||
world_t *w = prinst->parms->user;
|
||||
wedict_t *wed = (wedict_t*)G_EDICT(prinst, OFS_PARM0);
|
||||
const char *ragname = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||
int parentskel = G_FLOAT(OFS_PARM2);
|
||||
|
@ -1594,11 +1620,11 @@ void QCBUILTIN PF_skel_ragedit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
G_FLOAT(OFS_RETURN) = 0;
|
||||
|
||||
//the parent skeletal object must be relative, if specified.
|
||||
psko = skel_get(prinst, parentskel);
|
||||
psko = skel_get(w, parentskel);
|
||||
if (psko && psko->type != SKEL_RELATIVE)
|
||||
return;
|
||||
|
||||
sko = skel_get(prinst, skelidx);
|
||||
sko = skel_get(w, skelidx);
|
||||
if (!sko)
|
||||
{
|
||||
Con_DPrintf("PF_skel_ragedit: invalid skeletal object\n");
|
||||
|
@ -1747,7 +1773,7 @@ void QCBUILTIN PF_skel_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
return; //this isn't a skeletal model.
|
||||
}
|
||||
|
||||
skelobj = skel_create(prinst, numbones);
|
||||
skelobj = skel_create(w, numbones);
|
||||
if (!skelobj)
|
||||
return; //couldn't get one, ran out of memory or something?
|
||||
|
||||
|
@ -1804,9 +1830,9 @@ void QCBUILTIN PF_skel_build(pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
|
|||
}
|
||||
|
||||
if (!skelidx)
|
||||
skelobj = skel_create(prinst, numbones);
|
||||
skelobj = skel_create(w, numbones);
|
||||
else
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
if (!skelobj)
|
||||
return; //couldn't get one, ran out of memory or something?
|
||||
|
||||
|
@ -1888,10 +1914,11 @@ void QCBUILTIN PF_skel_build(pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
|
|||
//float(float skel) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS)
|
||||
void QCBUILTIN PF_skel_get_numbones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
int skelidx = G_FLOAT(OFS_PARM0);
|
||||
skelobject_t *skelobj;
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
|
||||
if (!skelobj)
|
||||
G_FLOAT(OFS_RETURN) = 0;
|
||||
|
@ -1902,11 +1929,12 @@ void QCBUILTIN PF_skel_get_numbones (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
//string(float skel, float bonenum) skel_get_bonename (FTE_CSQC_SKELETONOBJECTS) (returns tempstring)
|
||||
void QCBUILTIN PF_skel_get_bonename (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
int skelidx = G_FLOAT(OFS_PARM0);
|
||||
int boneidx = G_FLOAT(OFS_PARM1);
|
||||
skelobject_t *skelobj;
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
|
||||
if (!skelobj)
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
|
@ -1919,11 +1947,12 @@ void QCBUILTIN PF_skel_get_bonename (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
//float(float skel, float bonenum) skel_get_boneparent (FTE_CSQC_SKELETONOBJECTS)
|
||||
void QCBUILTIN PF_skel_get_boneparent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
int skelidx = G_FLOAT(OFS_PARM0);
|
||||
int boneidx = G_FLOAT(OFS_PARM1);
|
||||
skelobject_t *skelobj;
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
|
||||
if (!skelobj)
|
||||
G_FLOAT(OFS_RETURN) = 0;
|
||||
|
@ -1934,11 +1963,12 @@ void QCBUILTIN PF_skel_get_boneparent (pubprogfuncs_t *prinst, struct globalvars
|
|||
//float(float skel, string tagname) skel_find_bone (FTE_CSQC_SKELETONOBJECTS)
|
||||
void QCBUILTIN PF_skel_find_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
int skelidx = G_FLOAT(OFS_PARM0);
|
||||
const char *bname = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||
skelobject_t *skelobj;
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
if (!skelobj)
|
||||
G_FLOAT(OFS_RETURN) = 0;
|
||||
else
|
||||
|
@ -1951,7 +1981,7 @@ void QCBUILTIN PF_skel_get_bonerel (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
world_t *w = prinst->parms->user;
|
||||
int skelidx = G_FLOAT(OFS_PARM0);
|
||||
int boneidx = G_FLOAT(OFS_PARM1)-1;
|
||||
skelobject_t *skelobj = skel_get(prinst, skelidx);
|
||||
skelobject_t *skelobj = skel_get(w, skelidx);
|
||||
if (!skelobj || (unsigned int)boneidx >= skelobj->numbones)
|
||||
bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
|
||||
else if (skelobj->type!=SKEL_RELATIVE)
|
||||
|
@ -1977,7 +2007,7 @@ void QCBUILTIN PF_skel_get_boneabs (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
int boneidx = G_FLOAT(OFS_PARM1)-1;
|
||||
float workingm[12], tempmatrix[3][4];
|
||||
int i;
|
||||
skelobject_t *skelobj = skel_get(prinst, skelidx);
|
||||
skelobject_t *skelobj = skel_get(w, skelidx);
|
||||
|
||||
if (!skelobj || (unsigned int)boneidx >= skelobj->numbones)
|
||||
bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
|
||||
|
@ -2050,7 +2080,7 @@ void QCBUILTIN PF_skel_set_bone_world (pubprogfuncs_t *prinst, struct globalvars
|
|||
}
|
||||
|
||||
/*make sure the skeletal object is correct*/
|
||||
skelobj = skel_get(prinst, ent->xv->skeletonindex);
|
||||
skelobj = skel_get(w, ent->xv->skeletonindex);
|
||||
if (!skelobj || boneidx >= skelobj->numbones)
|
||||
return;
|
||||
|
||||
|
@ -2101,7 +2131,7 @@ void QCBUILTIN PF_skel_set_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
matrix[2] = w->g.v_up;
|
||||
}
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
if (!skelobj || boneidx >= skelobj->numbones)
|
||||
return;
|
||||
|
||||
|
@ -2123,7 +2153,7 @@ void QCBUILTIN PF_skel_mul_bone (pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
else
|
||||
bonemat_fromqcvectors((float*)mult, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_PARM2));
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
if (!skelobj || boneidx >= skelobj->numbones)
|
||||
return;
|
||||
//testme
|
||||
|
@ -2148,7 +2178,7 @@ void QCBUILTIN PF_skel_mul_bones (pubprogfuncs_t *prinst, struct globalvars_s *p
|
|||
else
|
||||
bonemat_fromqcvectors((float*)mult, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_PARM3));
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
if (!skelobj)
|
||||
return;
|
||||
|
||||
|
@ -2173,6 +2203,7 @@ void QCBUILTIN PF_skel_mul_bones (pubprogfuncs_t *prinst, struct globalvars_s *p
|
|||
//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones (FTE_CSQC_SKELETONOBJECTS)
|
||||
void QCBUILTIN PF_skel_copybones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
int skeldst = G_FLOAT(OFS_PARM0);
|
||||
int skelsrc = G_FLOAT(OFS_PARM1);
|
||||
int startbone = G_FLOAT(OFS_PARM2)-1;
|
||||
|
@ -2181,8 +2212,8 @@ void QCBUILTIN PF_skel_copybones (pubprogfuncs_t *prinst, struct globalvars_s *p
|
|||
skelobject_t *skelobjdst;
|
||||
skelobject_t *skelobjsrc;
|
||||
|
||||
skelobjdst = skel_get(prinst, skeldst);
|
||||
skelobjsrc = skel_get(prinst, skelsrc);
|
||||
skelobjdst = skel_get(w, skeldst);
|
||||
skelobjsrc = skel_get(w, skelsrc);
|
||||
if (!skelobjdst || !skelobjsrc)
|
||||
return;
|
||||
if (startbone == -1)
|
||||
|
@ -2220,10 +2251,11 @@ void QCBUILTIN PF_skel_copybones (pubprogfuncs_t *prinst, struct globalvars_s *p
|
|||
//void(float skel) skel_delete (FTE_CSQC_SKELETONOBJECTS)
|
||||
void QCBUILTIN PF_skel_delete (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
int skelidx = G_FLOAT(OFS_PARM0);
|
||||
skelobject_t *skelobj;
|
||||
|
||||
skelobj = skel_get(prinst, skelidx);
|
||||
skelobj = skel_get(w, skelidx);
|
||||
if (skelobj)
|
||||
{
|
||||
skelobj->inuse = 2; //2 means don't reuse yet.
|
||||
|
@ -2344,6 +2376,238 @@ void QCBUILTIN PF_modelframecount (pubprogfuncs_t *prinst, struct globalvars_s *
|
|||
G_FLOAT(OFS_RETURN) = 0;
|
||||
}
|
||||
|
||||
//void(float modidx, float framenum, __inout float basetime, float targettime, void(float timestamp, int code, string data) callback)
|
||||
void QCBUILTIN PF_processmodelevents (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
unsigned int modelindex = G_FLOAT(OFS_PARM0);
|
||||
unsigned int frame = G_FLOAT(OFS_PARM1);
|
||||
float basetime = G_FLOAT(OFS_PARM2);
|
||||
float targettime = G_FLOAT(OFS_PARM3);
|
||||
func_t callback = G_INT(OFS_PARM4);
|
||||
model_t *mod = w->Get_CModel(w, modelindex);
|
||||
float starttime, timestamp;
|
||||
|
||||
if (targettime == basetime)
|
||||
return; //don't refire the same event multiple times.
|
||||
|
||||
//returns all basetime <= eventtime < targettime
|
||||
|
||||
if (mod)
|
||||
{
|
||||
if (mod->type == mod_alias)
|
||||
{ //slightly more optimised path that is kinda redundant, but w/e
|
||||
galiasinfo_t *ga = Mod_Extradata(mod);
|
||||
galiasanimation_t *anim = ga->ofsanimations + frame;
|
||||
galiasevent_t *ev;
|
||||
float loopduration;
|
||||
if (frame < (unsigned int)ga->numanimations && anim->events)
|
||||
{
|
||||
if (anim->loop)
|
||||
{
|
||||
loopduration = anim->rate * anim->numposes;
|
||||
starttime = loopduration*(unsigned int)(basetime/loopduration);
|
||||
}
|
||||
else
|
||||
starttime = loopduration = 0;
|
||||
for (ev = anim->events; ; )
|
||||
{
|
||||
//be careful to use as consistent timings as we can
|
||||
timestamp = starttime + ev->timestamp;
|
||||
if (timestamp >= targettime)
|
||||
break; //this is in the future.
|
||||
if (timestamp >= basetime)
|
||||
{
|
||||
G_FLOAT(OFS_PARM0) = timestamp;
|
||||
G_INT(OFS_PARM1) = ev->code;
|
||||
G_INT(OFS_PARM2) = PR_TempString(prinst, ev->data);
|
||||
PR_ExecuteProgram(prinst, callback);
|
||||
}
|
||||
|
||||
ev = ev->next;
|
||||
if (!ev)
|
||||
{
|
||||
if (loopduration)
|
||||
ev = anim->events;
|
||||
else
|
||||
break; //animation ends here, so no more events possible
|
||||
starttime += loopduration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HALFLIFEMODELS
|
||||
else //actually this is a generic version that would work for iqm etc too, but is less efficient due to repeated lookups. oh well.
|
||||
{
|
||||
int ev, code;
|
||||
char *data;
|
||||
float loopduration;
|
||||
qboolean looping;
|
||||
|
||||
if (Mod_FrameInfoForNum(mod, 0, frame, &data, &code, &loopduration, &looping))
|
||||
{
|
||||
if (looping && loopduration)
|
||||
starttime = loopduration*(unsigned int)(basetime/loopduration);
|
||||
else
|
||||
starttime = loopduration = 0;
|
||||
for (ev = 0; ; ev++)
|
||||
{
|
||||
if (!Mod_GetModelEvent(mod, frame, ev, ×tamp, &code, &data))
|
||||
{
|
||||
if (looping && Mod_GetModelEvent(mod, frame, 0, ×tamp, &code, &data))
|
||||
{
|
||||
ev = 0;
|
||||
starttime += loopduration;
|
||||
}
|
||||
else
|
||||
break; //end of anim
|
||||
}
|
||||
|
||||
//be careful to use as consistent timings as we can...
|
||||
timestamp += starttime;
|
||||
if (timestamp >= targettime)
|
||||
break; //this is in the future.
|
||||
if (timestamp >= basetime)
|
||||
{
|
||||
G_FLOAT(OFS_PARM0) = timestamp;
|
||||
G_INT(OFS_PARM1) = code;
|
||||
G_INT(OFS_PARM2) = PR_TempString(prinst, data);
|
||||
PR_ExecuteProgram(prinst, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
G_FLOAT(OFS_PARM2) = targettime;
|
||||
}
|
||||
|
||||
//float(float modidx, float framenum, __inout float basetime, float targettime, __out int code, __out string data)
|
||||
void QCBUILTIN PF_getnextmodelevent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
unsigned int modelindex = G_FLOAT(OFS_PARM0);
|
||||
unsigned int frame = G_FLOAT(OFS_PARM1);
|
||||
float basetime = G_FLOAT(OFS_PARM2);
|
||||
float targettime = G_FLOAT(OFS_PARM3);
|
||||
model_t *mod = w->Get_CModel(w, modelindex);
|
||||
float starttime, timestamp;
|
||||
//default return values
|
||||
G_FLOAT(OFS_RETURN) = false;
|
||||
G_FLOAT(OFS_PARM2) = targettime;
|
||||
G_INT(OFS_PARM4) = 0;
|
||||
G_INT(OFS_PARM5) = 0;
|
||||
|
||||
if (mod)
|
||||
{
|
||||
if (mod->type == mod_alias)
|
||||
{ //slightly more optimised path that is kinda redundant, but w/e
|
||||
galiasinfo_t *ga = Mod_Extradata(mod);
|
||||
galiasanimation_t *anim = ga->ofsanimations + frame;
|
||||
galiasevent_t *ev;
|
||||
float loopduration;
|
||||
if (frame >= (unsigned int)ga->numanimations || !anim->events)
|
||||
return;
|
||||
if (anim->loop)
|
||||
{
|
||||
loopduration = anim->rate * anim->numposes;
|
||||
starttime = loopduration*(unsigned int)(basetime/loopduration);
|
||||
}
|
||||
else
|
||||
starttime = loopduration = 0;
|
||||
for (ev = anim->events; ; )
|
||||
{
|
||||
//be careful to use as consistent timings as we can
|
||||
timestamp = starttime + ev->timestamp;
|
||||
if (timestamp > targettime)
|
||||
break; //this is in the future.
|
||||
if (timestamp > basetime)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = true;
|
||||
G_FLOAT(OFS_PARM2) = timestamp;
|
||||
G_INT(OFS_PARM4) = ev->code;
|
||||
G_INT(OFS_PARM5) = PR_TempString(prinst, ev->data);
|
||||
return;
|
||||
}
|
||||
|
||||
ev = ev->next;
|
||||
if (!ev)
|
||||
{
|
||||
if (loopduration)
|
||||
ev = anim->events;
|
||||
else
|
||||
return; //animation ended here, so no more events
|
||||
starttime += loopduration;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HALFLIFEMODELS
|
||||
else //actually this is a generic version that would work for iqm etc too, but is less efficient due to repeated lookups. oh well.
|
||||
{
|
||||
int ev, code;
|
||||
char *data;
|
||||
float loopduration;
|
||||
qboolean looping;
|
||||
|
||||
if (!Mod_FrameInfoForNum(mod, 0, frame, &data, &code, &loopduration, &looping))
|
||||
return; //invalid frame
|
||||
|
||||
if (looping && loopduration)
|
||||
starttime = loopduration*(unsigned int)(basetime/loopduration);
|
||||
else
|
||||
starttime = loopduration = 0;
|
||||
for (ev = 0; ; ev++)
|
||||
{
|
||||
if (!Mod_GetModelEvent(mod, frame, ev, ×tamp, &code, &data))
|
||||
{
|
||||
if (looping && Mod_GetModelEvent(mod, frame, 0, ×tamp, &code, &data))
|
||||
{
|
||||
ev = 0;
|
||||
starttime += loopduration;
|
||||
}
|
||||
else
|
||||
break; //end of anim
|
||||
}
|
||||
|
||||
//be careful to use as consistent timings as we can...
|
||||
timestamp += starttime;
|
||||
if (timestamp > targettime)
|
||||
break; //this is in the future.
|
||||
if (timestamp > basetime)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = true;
|
||||
G_FLOAT(OFS_PARM2) = timestamp;
|
||||
G_INT(OFS_PARM4) = code;
|
||||
G_INT(OFS_PARM5) = PR_TempString(prinst, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//float(float modidx, float framenum, int idx, __out float timestamp, __out int code, __out string data)
|
||||
void QCBUILTIN PF_getmodeleventidx (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
world_t *w = prinst->parms->user;
|
||||
unsigned int modelindex = G_FLOAT(OFS_PARM0);
|
||||
unsigned int frame = G_FLOAT(OFS_PARM1);
|
||||
int eventindex = G_INT(OFS_PARM2);
|
||||
model_t *mod = w->Get_CModel(w, modelindex);
|
||||
//default return values
|
||||
float timestamp = 0;
|
||||
int code = 0;
|
||||
char *data = NULL;
|
||||
|
||||
G_FLOAT(OFS_RETURN) = Mod_GetModelEvent(mod, frame, eventindex, ×tamp, &code, &data);
|
||||
G_FLOAT(OFS_PARM3) = timestamp;
|
||||
G_INT(OFS_PARM4) = code;
|
||||
if (data)
|
||||
G_INT(OFS_PARM5) = PR_TempString(prinst, data);
|
||||
else
|
||||
G_INT(OFS_PARM5) = 0;
|
||||
}
|
||||
|
||||
//string(float modidx, float skinnum) skintoname
|
||||
void QCBUILTIN PF_skintoname (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
|
|
|
@ -660,6 +660,7 @@ void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic)
|
|||
{
|
||||
Vector2Copy(points[i], draw_mesh_xyz[i]);
|
||||
Vector2Copy(texcoords[i], draw_mesh_st[i]);
|
||||
Vector4Copy(draw_active_colour, draw_mesh_colors[i]);
|
||||
}
|
||||
|
||||
BE_DrawMesh_Single(pic, &draw_mesh, NULL, r2d_be_flags);
|
||||
|
|
|
@ -1160,7 +1160,7 @@ void P_DefaultTrail (unsigned int entityeffects, unsigned int modelflags, int *t
|
|||
*trailid = P_FindParticleType("tr_scarab");
|
||||
*trailpalidx = 254;
|
||||
}
|
||||
else if (modelflags & MFH2_ROCKET)
|
||||
else if (modelflags & MFH2_SPIDERBLOOD)
|
||||
{
|
||||
//spiders
|
||||
*trailid = P_FindParticleType("TR_GREENBLOOD");
|
||||
|
|
|
@ -1889,7 +1889,7 @@ start:
|
|||
Surf_RecursiveWorldNode (node->children[side], clipflags);
|
||||
|
||||
// draw stuff
|
||||
c = node->numsurfaces;
|
||||
c = node->numsurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
|
@ -2907,6 +2907,8 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef Q1BSPS
|
||||
if (es->wmodel->fromgame == fg_quake || es->wmodel->fromgame == fg_halflife)
|
||||
{
|
||||
//maybe we should just use fatpvs instead, and wait for completion when outside?
|
||||
if (es->leaf[1])
|
||||
|
@ -2926,6 +2928,11 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b)
|
|||
}
|
||||
Surf_SimpleWorld_Q1BSP(es, pvs);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
//panic
|
||||
}
|
||||
|
||||
COM_AddWork(WG_MAIN, R_GeneratedWorldEBO, es, NULL, 0, 0);
|
||||
}
|
||||
|
@ -2963,12 +2970,12 @@ void Surf_DrawWorld (void)
|
|||
{
|
||||
RSpeedRemark();
|
||||
|
||||
Surf_LightmapShift(cl.worldmodel);
|
||||
Surf_LightmapShift(currentmodel);
|
||||
|
||||
#ifdef THREADEDWORLD
|
||||
if ((r_dynamic.ival < 0 || cl.worldmodel->numbatches) && !r_refdef.recurse && cl.worldmodel->type == mod_brush)
|
||||
if ((r_dynamic.ival < 0 || currentmodel->numbatches) && !r_refdef.recurse && currentmodel->type == mod_brush)
|
||||
{
|
||||
if (webostate && webostate->wmodel != cl.worldmodel)
|
||||
if (webostate && webostate->wmodel != currentmodel)
|
||||
{
|
||||
R_DestroyWorldEBO(webostate);
|
||||
webostate = NULL;
|
||||
|
@ -2976,7 +2983,8 @@ void Surf_DrawWorld (void)
|
|||
|
||||
if (qrenderer != QR_OPENGL && qrenderer != QR_VULKAN)
|
||||
;
|
||||
else if (cl.worldmodel->fromgame == fg_quake)
|
||||
#ifdef Q1BSPS
|
||||
else if (currentmodel->fromgame == fg_quake || currentmodel->fromgame == fg_halflife)
|
||||
{
|
||||
int i = MAX_LIGHTSTYLES;
|
||||
if (webostate && !webogenerating)
|
||||
|
@ -2993,21 +3001,21 @@ void Surf_DrawWorld (void)
|
|||
if (!webogenerating)
|
||||
{
|
||||
int i;
|
||||
if (!cl.worldmodel->numbatches)
|
||||
if (!currentmodel->numbatches)
|
||||
{
|
||||
int sortid;
|
||||
batch_t *batch;
|
||||
cl.worldmodel->numbatches = 0;
|
||||
currentmodel->numbatches = 0;
|
||||
for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++)
|
||||
for (batch = cl.worldmodel->batches[sortid]; batch != NULL; batch = batch->next)
|
||||
for (batch = currentmodel->batches[sortid]; batch != NULL; batch = batch->next)
|
||||
{
|
||||
batch->ebobatch = cl.worldmodel->numbatches;
|
||||
cl.worldmodel->numbatches++;
|
||||
batch->ebobatch = currentmodel->numbatches;
|
||||
currentmodel->numbatches++;
|
||||
}
|
||||
}
|
||||
webogeneratingstate = true;
|
||||
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (cl.worldmodel->numbatches-1));
|
||||
webogenerating->wmodel = cl.worldmodel;
|
||||
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (currentmodel->numbatches-1));
|
||||
webogenerating->wmodel = currentmodel;
|
||||
webogenerating->leaf[0] = r_viewleaf;
|
||||
webogenerating->leaf[1] = r_viewleaf2;
|
||||
for (i = 0; i < MAX_LIGHTSTYLES; i++)
|
||||
|
@ -3017,7 +3025,9 @@ void Surf_DrawWorld (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (cl.worldmodel->fromgame == fg_quake3)
|
||||
#endif
|
||||
#ifdef Q3BSPS
|
||||
else if (currentmodel->fromgame == fg_quake3)
|
||||
{
|
||||
if (webostate && webostate->cluster[0] == r_viewcluster && webostate->cluster[1] == r_viewcluster2)
|
||||
{
|
||||
|
@ -3026,21 +3036,21 @@ void Surf_DrawWorld (void)
|
|||
{
|
||||
if (!webogenerating)
|
||||
{
|
||||
if (!cl.worldmodel->numbatches)
|
||||
if (!currentmodel->numbatches)
|
||||
{
|
||||
int sortid;
|
||||
batch_t *batch;
|
||||
cl.worldmodel->numbatches = 0;
|
||||
currentmodel->numbatches = 0;
|
||||
for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++)
|
||||
for (batch = cl.worldmodel->batches[sortid]; batch != NULL; batch = batch->next)
|
||||
for (batch = currentmodel->batches[sortid]; batch != NULL; batch = batch->next)
|
||||
{
|
||||
batch->ebobatch = cl.worldmodel->numbatches;
|
||||
cl.worldmodel->numbatches++;
|
||||
batch->ebobatch = currentmodel->numbatches;
|
||||
currentmodel->numbatches++;
|
||||
}
|
||||
}
|
||||
webogeneratingstate = true;
|
||||
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (cl.worldmodel->numbatches-1));
|
||||
webogenerating->wmodel = cl.worldmodel;
|
||||
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (currentmodel->numbatches-1));
|
||||
webogenerating->wmodel = currentmodel;
|
||||
webogenerating->cluster[0] = r_viewcluster;
|
||||
webogenerating->cluster[1] = r_viewcluster2;
|
||||
Q_strncpyz(webogenerating->dbgid, "webostate", sizeof(webogenerating->dbgid));
|
||||
|
@ -3048,6 +3058,7 @@ void Surf_DrawWorld (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (webostate)
|
||||
{
|
||||
|
@ -3065,7 +3076,7 @@ void Surf_DrawWorld (void)
|
|||
BE_DrawWorld(webostate->rbatches);
|
||||
|
||||
/*FIXME: move this away*/
|
||||
if (cl.worldmodel->fromgame == fg_quake || cl.worldmodel->fromgame == fg_halflife)
|
||||
if (currentmodel->fromgame == fg_quake || currentmodel->fromgame == fg_halflife)
|
||||
Surf_LessenStains();
|
||||
return;
|
||||
}
|
||||
|
@ -3073,26 +3084,34 @@ void Surf_DrawWorld (void)
|
|||
#endif
|
||||
|
||||
|
||||
Surf_PushChains(cl.worldmodel->batches);
|
||||
Surf_PushChains(currentmodel->batches);
|
||||
|
||||
#ifdef TERRAIN
|
||||
if (currentmodel->type == mod_heightmap)
|
||||
{
|
||||
frustumvis = NULL;
|
||||
entvis = surfvis = NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef Q2BSPS
|
||||
if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
|
||||
if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3)
|
||||
{
|
||||
frustumvis = frustumvis_;
|
||||
memset(frustumvis, 0, (cl.worldmodel->numclusters + 7)>>3);
|
||||
memset(frustumvis, 0, (currentmodel->numclusters + 7)>>3);
|
||||
|
||||
if (!r_refdef.areabitsknown)
|
||||
{ //generate the info each frame, as the gamecode didn't tell us what to use.
|
||||
int leafnum = CM_PointLeafnum (cl.worldmodel, r_refdef.vieworg);
|
||||
int clientarea = CM_LeafArea (cl.worldmodel, leafnum);
|
||||
CM_WriteAreaBits(cl.worldmodel, r_refdef.areabits, clientarea, false);
|
||||
int leafnum = CM_PointLeafnum (currentmodel, r_refdef.vieworg);
|
||||
int clientarea = CM_LeafArea (currentmodel, leafnum);
|
||||
CM_WriteAreaBits(currentmodel, r_refdef.areabits, clientarea, false);
|
||||
r_refdef.areabitsknown = true;
|
||||
}
|
||||
#ifdef Q3BSPS
|
||||
if (cl.worldmodel->fromgame == fg_quake3)
|
||||
if (currentmodel->fromgame == fg_quake3)
|
||||
{
|
||||
entvis = surfvis = R_MarkLeaves_Q3 ();
|
||||
Surf_RecursiveQ3WorldNode (cl.worldmodel->nodes, (1<<r_refdef.frustum_numworldplanes)-1);
|
||||
Surf_RecursiveQ3WorldNode (currentmodel->nodes, (1<<r_refdef.frustum_numworldplanes)-1);
|
||||
//Surf_LeafWorldNode ();
|
||||
}
|
||||
else
|
||||
|
@ -3100,7 +3119,7 @@ void Surf_DrawWorld (void)
|
|||
{
|
||||
entvis = surfvis = R_MarkLeaves_Q2 ();
|
||||
VectorCopy (r_refdef.vieworg, modelorg);
|
||||
Surf_RecursiveQ2WorldNode (cl.worldmodel->nodes);
|
||||
Surf_RecursiveQ2WorldNode (currentmodel->nodes);
|
||||
}
|
||||
|
||||
surfvis = frustumvis;
|
||||
|
@ -3108,9 +3127,9 @@ void Surf_DrawWorld (void)
|
|||
else
|
||||
#endif
|
||||
#ifdef MAP_PROC
|
||||
if (cl.worldmodel->fromgame == fg_doom3)
|
||||
if (currentmodel->fromgame == fg_doom3)
|
||||
{
|
||||
entvis = surfvis = D3_CalcVis(cl.worldmodel, r_origin);
|
||||
entvis = surfvis = D3_CalcVis(currentmodel, r_origin);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -3122,14 +3141,8 @@ void Surf_DrawWorld (void)
|
|||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef TERRAIN
|
||||
if (currentmodel->type == mod_heightmap)
|
||||
{
|
||||
frustumvis = NULL;
|
||||
entvis = surfvis = NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef Q1BSPS
|
||||
if (1)
|
||||
{
|
||||
//extern cvar_t temp1;
|
||||
// if (0)//temp1.value)
|
||||
|
@ -3141,15 +3154,21 @@ void Surf_DrawWorld (void)
|
|||
VectorCopy (r_origin, modelorg);
|
||||
|
||||
frustumvis = frustumvis_;
|
||||
memset(frustumvis, 0, (cl.worldmodel->numclusters + 7)>>3);
|
||||
memset(frustumvis, 0, (currentmodel->numclusters + 7)>>3);
|
||||
|
||||
if (r_refdef.useperspective)
|
||||
Surf_RecursiveWorldNode (cl.worldmodel->nodes, 0x1f);
|
||||
Surf_RecursiveWorldNode (currentmodel->nodes, 0x1f);
|
||||
else
|
||||
Surf_OrthoRecursiveWorldNode (cl.worldmodel->nodes, 0x1f);
|
||||
Surf_OrthoRecursiveWorldNode (currentmodel->nodes, 0x1f);
|
||||
surfvis = frustumvis;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
frustumvis = NULL;
|
||||
entvis = surfvis = NULL;
|
||||
}
|
||||
|
||||
RSpeedEnd(RSPEED_WORLDNODE);
|
||||
|
||||
|
|
|
@ -1046,6 +1046,7 @@ rendererinfo_t swrendererinfo;
|
|||
#endif
|
||||
#ifdef VKQUAKE
|
||||
rendererinfo_t vkrendererinfo;
|
||||
//rendererinfo_t headlessvkrendererinfo;
|
||||
#endif
|
||||
rendererinfo_t headlessrenderer;
|
||||
|
||||
|
@ -1074,6 +1075,9 @@ rendererinfo_t *rendererinfo[] =
|
|||
&dedicatedrendererinfo,
|
||||
#endif
|
||||
&headlessrenderer,
|
||||
#ifdef VKQUAKE
|
||||
//&headlessvkrendererinfo,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -1863,7 +1867,7 @@ void R_SetRenderer_f (void)
|
|||
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
|
||||
{
|
||||
if (rendererinfo[i]->description)
|
||||
Con_Printf("^1%s^7: %s%s\n", rendererinfo[i]->name[0], rendererinfo[i]->description, (currentrendererstate.renderer == rendererinfo[i])?" ^2(current)":"");
|
||||
Con_Printf("^[%s\\type\\/setrenderer %s^]^7: %s%s\n", rendererinfo[i]->name[0], rendererinfo[i]->name[0], rendererinfo[i]->description, (currentrendererstate.renderer == rendererinfo[i])?" ^2(current)":"");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1880,7 +1884,7 @@ void R_SetRenderer_f (void)
|
|||
Cvar_Set(&vid_bpp, Cmd_Argv(2));
|
||||
}
|
||||
|
||||
if (newr.renderer->rtype != QR_HEADLESS) //don't save headless in the vid_renderer cvar via the setrenderer command. 'setrenderer headless;vid_restart' can then do what is most sane.
|
||||
if (newr.renderer->rtype != QR_HEADLESS && !strstr(param, "headless")) //don't save headless in the vid_renderer cvar via the setrenderer command. 'setrenderer headless;vid_restart' can then do what is most sane.
|
||||
Cvar_Set(&vid_renderer, param);
|
||||
|
||||
if (!r_blockvidrestart)
|
||||
|
@ -2279,6 +2283,7 @@ qbyte *R_MarkLeaves_Q2 (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q1BSPS
|
||||
#if 0
|
||||
qbyte *R_CalcVis_Q1 (void)
|
||||
{
|
||||
|
@ -2420,6 +2425,7 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
|
|||
}
|
||||
return vis;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
|
|
|
@ -321,8 +321,8 @@ extern cvar_t snd_doppler;
|
|||
|
||||
typedef struct
|
||||
{
|
||||
#define NUM_SOURCES MAX_CHANNELS
|
||||
ALuint source[NUM_SOURCES];
|
||||
ALuint *source;
|
||||
size_t max_sources;
|
||||
|
||||
ALCdevice *OpenAL_Device;
|
||||
ALCcontext *OpenAL_Context;
|
||||
|
@ -582,8 +582,12 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned
|
|||
int chnum = chan - sc->channel;
|
||||
ALuint buf;
|
||||
|
||||
if (chnum >= NUM_SOURCES)
|
||||
if (chnum >= oali->max_sources)
|
||||
{
|
||||
size_t nc = chnum+1+64;
|
||||
Z_ReallocElements((void**)&oali->source, &oali->max_sources, nc, sizeof(*oali->source));
|
||||
return;
|
||||
}
|
||||
|
||||
//alcMakeContextCurrent
|
||||
|
||||
|
@ -966,7 +970,7 @@ static qboolean OpenAL_Init(soundcardinfo_t *sc, const char *devname)
|
|||
//S_Info();
|
||||
|
||||
//fixme...
|
||||
memset(oali->source, 0, sizeof(oali->source));
|
||||
memset(oali->source, 0, sizeof(*oali->source)*oali->max_sources);
|
||||
PrintALError("alGensources for normal sources");
|
||||
|
||||
palListenerfv(AL_POSITION, oali->ListenPos);
|
||||
|
@ -1107,7 +1111,7 @@ static void OpenAL_Shutdown (soundcardinfo_t *sc)
|
|||
|
||||
//alcMakeContextCurrent
|
||||
|
||||
palDeleteSources(NUM_SOURCES, oali->source);
|
||||
palDeleteSources(oali->max_sources, oali->source);
|
||||
|
||||
/*make sure the buffers are cleared from the sound effects*/
|
||||
for (i=0;i<num_sfx;i++)
|
||||
|
|
|
@ -233,7 +233,7 @@ void S_SoundInfo_f(void)
|
|||
Con_DPrintf(" %s (%i %i, %g %g %g, inactive)\n", sc->channel[i].sfx->name, sc->channel[i].entnum, sc->channel[i].entchannel, sc->channel[i].origin[0], sc->channel[i].origin[1], sc->channel[i].origin[2]);
|
||||
}
|
||||
}
|
||||
Con_Printf(" %d/%d/%d/%d active/known/highest/max\n", active, known, sc->total_chans, MAX_CHANNELS);
|
||||
Con_Printf(" %d/%d/%d/%d active/known/highest/max\n", active, known, sc->total_chans, sc->max_chans);
|
||||
for (i = 0; i < sc->sn.numchannels; i++)
|
||||
{
|
||||
Con_Printf(" chan %i: fwd:%-4g rt:%-4g up:%-4g dist:%-4g\n", i, sc->speakerdir[i][0], sc->speakerdir[i][1], sc->speakerdir[i][2], sc->dist[i]);
|
||||
|
@ -2845,9 +2845,10 @@ void S_StopAllSounds(qboolean clear)
|
|||
}
|
||||
|
||||
sc->total_chans = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS + NUM_MUSICS; // no statics
|
||||
Z_ReallocElements((void**)&sc->channel, &sc->max_chans, sc->total_chans, sizeof(*sc->channel));
|
||||
|
||||
memcpy(musics, &sc->channel[MUSIC_FIRST], sizeof(musics));
|
||||
Q_memset(sc->channel, 0, MAX_CHANNELS * sizeof(channel_t));
|
||||
Q_memset(sc->channel, 0, sc->max_chans * sizeof(channel_t));
|
||||
memcpy(&sc->channel[MUSIC_FIRST], musics, sizeof(musics));
|
||||
|
||||
if (clear && !sc->selfpainting) //if its self-painting, then the mixer will continue painting anyway (which is important if its still painting music, but otherwise don't stutter at all when loading)
|
||||
|
@ -2903,10 +2904,13 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
|
|||
|
||||
for (scard = sndcardinfo; scard; scard = scard->next)
|
||||
{
|
||||
if (scard->total_chans == MAX_CHANNELS)
|
||||
if (scard->total_chans == scard->max_chans)
|
||||
{
|
||||
Con_Printf ("total_channels == MAX_CHANNELS\n");
|
||||
continue;
|
||||
if (!ZF_ReallocElements((void**)&scard->channel, &scard->max_chans, scard->max_chans+64, sizeof(*scard->channel)))
|
||||
{
|
||||
Con_Printf ("total_channels == MAX_CHANNELS\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!S_LoadSound (sfx))
|
||||
|
@ -3004,11 +3008,14 @@ S_UpdateAmbientSounds
|
|||
mleaf_t *Q1BSP_LeafForPoint (model_t *model, vec3_t p);
|
||||
void S_UpdateAmbientSounds (soundcardinfo_t *sc)
|
||||
{
|
||||
mleaf_t *l;
|
||||
float vol, oldvol;
|
||||
float vol;
|
||||
channel_t *chan;
|
||||
int i;
|
||||
#ifdef Q1BSPS
|
||||
mleaf_t *l;
|
||||
float oldvol;
|
||||
int ambientlevel[NUM_AMBIENTS];
|
||||
#endif
|
||||
|
||||
if (!snd_ambient)
|
||||
return;
|
||||
|
@ -3073,7 +3080,7 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef Q1BSPS
|
||||
// calc ambient sound levels
|
||||
for (i = 0; i < NUM_AMBIENTS; i++)
|
||||
ambientlevel[i] = 0;
|
||||
|
@ -3140,6 +3147,7 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc)
|
|||
if (sc->ChannelUpdate)
|
||||
sc->ChannelUpdate(sc, chan, (oldvol == 0) ^ (sc->ambientlevels[i] == 0));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sndreverbproperties_s *reverbproperties;
|
||||
|
|
|
@ -255,7 +255,6 @@ void OpenAL_CvarInit(void);
|
|||
// User-setable variables
|
||||
// ====================================================================
|
||||
|
||||
#define MAX_CHANNELS 1024/*tracked sounds (including statics)*/
|
||||
#define MAX_DYNAMIC_CHANNELS 64 /*playing sounds (identical ones merge)*/
|
||||
|
||||
|
||||
|
@ -331,8 +330,9 @@ struct soundcardinfo_s { //windows has one defined AFTER directsound
|
|||
|
||||
//info on which sound effects are playing
|
||||
//FIXME: use a linked list
|
||||
channel_t channel[MAX_CHANNELS];
|
||||
channel_t *channel;
|
||||
int total_chans;
|
||||
int max_chans;
|
||||
|
||||
float ambientlevels[NUM_AMBIENTS]; //we use a float instead of the channel's int volume value to avoid framerate dependancies with slow transitions.
|
||||
|
||||
|
|
|
@ -367,12 +367,13 @@ void Sys_CloseLibrary(dllhandle_t *lib)
|
|||
}
|
||||
HMODULE LoadLibraryU(const char *name)
|
||||
{
|
||||
HMODULE ret;
|
||||
if (WinNT)
|
||||
{
|
||||
wchar_t wide[MAX_OSPATH];
|
||||
widen(wide, sizeof(wide), name);
|
||||
|
||||
return LoadLibraryW(wide);
|
||||
ret = LoadLibraryW(wide);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -380,8 +381,9 @@ HMODULE LoadLibraryU(const char *name)
|
|||
char ansi[MAX_OSPATH];
|
||||
widen(wide, sizeof(wide), name);
|
||||
ansi[WideCharToMultiByte(CP_ACP, 0, wide, wcslen(wide), ansi, sizeof(ansi)-1, NULL, NULL)] = 0;
|
||||
return LoadLibraryA(ansi);
|
||||
ret = LoadLibraryA(ansi);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
|
||||
{
|
||||
|
@ -4186,7 +4188,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
|
|||
{
|
||||
isDedicated = isClusterSlave = true;
|
||||
#ifdef _DEBUG
|
||||
MessageBox(0, "Cluster slave", "gah", 0);
|
||||
MessageBox(0, "New cluster slave starting\nAttach to process now, if desired.", "FTEQW", 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -281,4 +281,112 @@ rendererinfo_t headlessrenderer =
|
|||
Headless_BE_RenderToTextureUpdate2d,
|
||||
""
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0//def VKQUAKE
|
||||
#include "../vk/vkrenderer.h"
|
||||
static qboolean HeadlessVK_CreateSurface(void)
|
||||
{
|
||||
vk.surface = VK_NULL_HANDLE; //nothing to create, we're using offscreen rendering.
|
||||
return true;
|
||||
}
|
||||
//static void HeadlessVK_Present(struct vkframe *theframe)
|
||||
//{
|
||||
//VK_DoPresent(theframe);
|
||||
//}
|
||||
static qboolean HeadlessVK_Init (rendererstate_t *info, unsigned char *palette)
|
||||
{
|
||||
extern cvar_t vid_conautoscale;
|
||||
#ifdef VK_NO_PROTOTYPES
|
||||
static dllhandle_t *hInstVulkan = NULL;
|
||||
dllfunction_t vkfuncs[] =
|
||||
{
|
||||
{(void**)&vkGetInstanceProcAddr, "vkGetInstanceProcAddr"},
|
||||
{NULL}
|
||||
};
|
||||
if (!hInstVulkan)
|
||||
hInstVulkan = *info->subrenderer?Sys_LoadLibrary(info->subrenderer, vkfuncs):NULL;
|
||||
#ifdef _WIN32
|
||||
if (!hInstVulkan)
|
||||
hInstVulkan = Sys_LoadLibrary("vulkan-1.dll", vkfuncs);
|
||||
#else
|
||||
if (!hInstVulkan)
|
||||
hInstVulkan = Sys_LoadLibrary("libvulkan.so.1", vkfuncs);
|
||||
if (!hInstVulkan)
|
||||
hInstVulkan = Sys_LoadLibrary("libvulkan.so", vkfuncs);
|
||||
#endif
|
||||
if (!hInstVulkan)
|
||||
{
|
||||
Con_Printf("Unable to load vulkan library\nNo Vulkan drivers are installed\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
vid.pixelwidth = 1920;
|
||||
vid.pixelheight = 1080;
|
||||
if (!VK_Init(info, NULL, HeadlessVK_CreateSurface, NULL))
|
||||
return false;
|
||||
Cvar_ForceCallback(&vid_conautoscale);
|
||||
return true;
|
||||
}
|
||||
|
||||
rendererinfo_t headlessvkrendererinfo =
|
||||
{
|
||||
"Headless Vulkan",
|
||||
{
|
||||
"vkheadless"
|
||||
},
|
||||
QR_VULKAN,
|
||||
|
||||
VK_Draw_Init,
|
||||
VK_Draw_Shutdown,
|
||||
|
||||
VK_UpdateFiltering,
|
||||
VK_LoadTextureMips,
|
||||
VK_DestroyTexture,
|
||||
|
||||
VK_R_Init,
|
||||
VK_R_DeInit,
|
||||
VK_R_RenderView,
|
||||
|
||||
HeadlessVK_Init,
|
||||
GLVID_DeInit,
|
||||
GLVID_SwapBuffers,
|
||||
GLVID_ApplyGammaRamps,
|
||||
WIN_CreateCursor,
|
||||
WIN_SetCursor,
|
||||
WIN_DestroyCursor,
|
||||
GLVID_SetCaption,
|
||||
VKVID_GetRGBInfo,
|
||||
|
||||
VK_SCR_UpdateScreen,
|
||||
|
||||
VKBE_SelectMode,
|
||||
VKBE_DrawMesh_List,
|
||||
VKBE_DrawMesh_Single,
|
||||
VKBE_SubmitBatch,
|
||||
VKBE_GetTempBatch,
|
||||
VKBE_DrawWorld,
|
||||
VKBE_Init,
|
||||
VKBE_GenBrushModelVBO,
|
||||
VKBE_ClearVBO,
|
||||
VKBE_UploadAllLightmaps,
|
||||
VKBE_SelectEntity,
|
||||
VKBE_SelectDLight,
|
||||
VKBE_Scissor,
|
||||
VKBE_LightCullModel,
|
||||
|
||||
VKBE_VBO_Begin,
|
||||
VKBE_VBO_Data,
|
||||
VKBE_VBO_Finish,
|
||||
VKBE_VBO_Destroy,
|
||||
|
||||
VKBE_RenderToTextureUpdate2d,
|
||||
|
||||
"no more"
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -173,6 +173,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define SPRMODELS //quake1 sprite models
|
||||
#define INTERQUAKEMODELS
|
||||
#define RTLIGHTS //realtime lighting
|
||||
#define Q1BSPS //quake 1 bsp support, because we're still a quake engine
|
||||
#define Q2BSPS //quake 2 bsp support (a dependancy of q3bsp)
|
||||
#define Q3BSPS //quake 3 bsp support
|
||||
// #define TERRAIN //heightmap support
|
||||
|
@ -234,6 +235,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
// #define DSPMODELS //doom sprites (only needs DOOMWADS to generate the right wad file names)
|
||||
#define SPRMODELS //quake1 sprite models
|
||||
#define SP2MODELS //quake2 sprite models
|
||||
#define MD1MODELS //quake1 alias models
|
||||
#define MD2MODELS //quake2 alias models
|
||||
#define MD3MODELS //quake3 alias models
|
||||
#define MD5MODELS //doom3 models
|
||||
|
@ -249,6 +251,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
// #define MAP_DOOM //doom map support
|
||||
#define MAP_PROC //doom3/quake4 map support
|
||||
//#define WOLF3DSUPPORT //wolfenstein3d map support (not started yet)
|
||||
#define Q1BSPS //quake 1 bsp support, because we're still a quake engine
|
||||
#define Q2BSPS //quake 2 bsp support
|
||||
#define Q3BSPS //quake 3 bsp support
|
||||
#define TERRAIN //heightmap support
|
||||
|
|
|
@ -552,7 +552,7 @@ typedef struct
|
|||
#define Q2CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
|
||||
#define Q2CONTENTS_LADDER 0x20000000
|
||||
//0x40000000
|
||||
//0x80000000
|
||||
//FTECONTENTS_SKY //0x80000000
|
||||
|
||||
|
||||
#define Q3CONTENTS_SOLID FTECONTENTS_SOLID //0x00000001 // should never be on a brush, only in game
|
||||
|
@ -580,7 +580,7 @@ typedef struct
|
|||
#define Q3CONTENTS_BOTCLIP 0x00400000
|
||||
#define Q3CONTENTS_MOVER 0x00800000
|
||||
#define Q3CONTENTS_ORIGIN Q2CONTENTS_ORIGIN //0x01000000
|
||||
#define Q3CONTENTS_BODY 0x02000000
|
||||
#define Q3CONTENTS_BODY FTECONTENTS_BODY //0x02000000
|
||||
#define Q3CONTENTS_CORPSE FTECONTENTS_CORPSE //0x04000000
|
||||
#define Q3CONTENTS_DETAIL Q2CONTENTS_DETAIL //0x08000000
|
||||
#define Q3CONTENTS_STRUCTURAL 0x10000000
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -32,6 +32,14 @@ typedef struct
|
|||
vec3_t scale_origin;
|
||||
} galiaspose_t;
|
||||
|
||||
typedef struct galiasevent_s
|
||||
{
|
||||
struct galiasevent_s *next;
|
||||
float timestamp;
|
||||
int code;
|
||||
char *data;
|
||||
} galiasevent_t;
|
||||
|
||||
//a frame group (aka: animation)
|
||||
typedef struct
|
||||
{
|
||||
|
@ -44,6 +52,7 @@ typedef struct
|
|||
int numposes;
|
||||
float rate;
|
||||
galiaspose_t *poseofs;
|
||||
galiasevent_t *events;
|
||||
char name[64];
|
||||
} galiasanimation_t;
|
||||
|
||||
|
@ -120,6 +129,14 @@ typedef struct galiasinfo_s
|
|||
index_t *ofs_indexes;
|
||||
int numindexes;
|
||||
|
||||
//for hitmodel
|
||||
unsigned int contents; //default CONTENTS_BODY
|
||||
q2csurface_t csurface; //flags, and also collision name, if useful...
|
||||
unsigned int surfaceid; //the body reported to qc via trace_surface
|
||||
|
||||
float mindist;
|
||||
float maxdist;
|
||||
|
||||
int *ofs_trineighbours;
|
||||
float lerpcutoff; //hack. should probably be part of the entity structure, but I really don't want new models (and thus code) to have access to this ugly inefficient hack. make your models properly in the first place.
|
||||
|
||||
|
@ -148,8 +165,6 @@ typedef struct galiasinfo_s
|
|||
float *baseframeofs; /*non-heirachical*/
|
||||
int numbones;
|
||||
galiasbone_t *ofsbones;
|
||||
//FTE_DEPRECATED int numswtransforms;
|
||||
//FTE_DEPRECATED galisskeletaltransforms_t *ofsswtransforms;
|
||||
|
||||
vecV_t *ofs_skel_xyz;
|
||||
vec3_t *ofs_skel_norm;
|
||||
|
|
|
@ -143,10 +143,10 @@ static void QDECL World_Bullet_End(world_t *world)
|
|||
struct bulletcontext_s *ctx = (struct bulletcontext_s*)world->rbe;
|
||||
world->rbe = NULL;
|
||||
delete ctx->dworld;
|
||||
delete ctx->solver;
|
||||
delete ctx->collisionconfig;
|
||||
delete ctx->collisiondispatcher;
|
||||
delete ctx->broadphase;
|
||||
delete ctx->solver;
|
||||
delete ctx->collisionconfig;
|
||||
delete ctx->collisiondispatcher;
|
||||
delete ctx->broadphase;
|
||||
delete ctx->ownerfilter;
|
||||
Z_Free(ctx);
|
||||
}
|
||||
|
@ -819,24 +819,24 @@ public:
|
|||
trans.setOrigin(org);
|
||||
}
|
||||
QCMotionState(wedict_t *ed, world_t *w)
|
||||
{
|
||||
{
|
||||
dirty = qtrue;
|
||||
edict = ed;
|
||||
world = w;
|
||||
|
||||
ReloadMotionState();
|
||||
}
|
||||
}
|
||||
virtual ~QCMotionState()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void getWorldTransform(btTransform &worldTrans) const
|
||||
{
|
||||
virtual void getWorldTransform(btTransform &worldTrans) const
|
||||
{
|
||||
worldTrans = trans;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setWorldTransform(const btTransform &worldTrans)
|
||||
{
|
||||
virtual void setWorldTransform(const btTransform &worldTrans)
|
||||
{
|
||||
vec3_t fwd, left, up, offset;
|
||||
trans = worldTrans;
|
||||
|
||||
|
@ -872,7 +872,7 @@ public:
|
|||
// mSceneNode ->setOrientation(rot.w(), rot.x(), rot.y(), rot.z());
|
||||
// btVector3 pos = worldTrans.getOrigin();
|
||||
// mSceneNode ->setPosition(pos.x(), pos.y(), pos.z());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
|
||||
|
|
|
@ -766,7 +766,7 @@ static int QDECL COM_Dir_List(const char *name, qofs_t size, time_t mtime, void
|
|||
|| !Q_strcasecmp(link, "ent") || !Q_strcasecmp(link, "rtlights")
|
||||
|| !Q_strcasecmp(link, "shader") || !Q_strcasecmp(link, "framegroups"))
|
||||
Q_snprintfz(link, sizeof(link), "\\edit\\%s", name);
|
||||
else if (!Q_strcasecmp(link, "tga") || !Q_strcasecmp(link, "png") || !Q_strcasecmp(link, "jpg") || !Q_strcasecmp(link, "jpeg") || !Q_strcasecmp(link, "lmp") || !Q_strcasecmp(link, "pcx"))
|
||||
else if (!Q_strcasecmp(link, "tga") || !Q_strcasecmp(link, "png") || !Q_strcasecmp(link, "jpg") || !Q_strcasecmp(link, "jpeg") || !Q_strcasecmp(link, "lmp") || !Q_strcasecmp(link, "pcx")|| !Q_strcasecmp(link, "bmp"))
|
||||
{
|
||||
//FIXME: image replacements are getting in the way here.
|
||||
Q_snprintfz(link, sizeof(link), "\\tiprawimg\\%s\\tip\\(note: image replacement rules are context-dependant, including base path, sub path, extension, or complete replacement via a shader)", name);
|
||||
|
@ -1255,6 +1255,9 @@ fail:
|
|||
return depth+1;
|
||||
}
|
||||
|
||||
//returns the package/'gamedir/foo.pk3' filename to tell the client to download
|
||||
//unfortunately foo.pk3 may contain a 'bar.pk3' and downloading dir/foo.pk3/bar.pk3 won't work
|
||||
//so if loc->search is dir/foo.pk3/bar.pk3 find dir/foo.pk3 instead
|
||||
char *FS_GetPackageDownloadFilename(flocation_t *loc)
|
||||
{
|
||||
searchpath_t *sp, *search;
|
||||
|
@ -1263,11 +1266,11 @@ char *FS_GetPackageDownloadFilename(flocation_t *loc)
|
|||
{
|
||||
for (search = com_searchpaths; search; search = search->next)
|
||||
{
|
||||
if (search != sp && search->handle->GeneratePureCRC)
|
||||
{ //only consider files that have a pure hash. this excludes system paths
|
||||
if (!strncmp(search->purepath, sp->purepath, strlen(search->purepath)))
|
||||
break;
|
||||
}
|
||||
if (search != sp)
|
||||
if (search->handle->GeneratePureCRC) //only consider files that have a pure hash. this excludes system paths
|
||||
if (!strncmp(search->purepath, sp->purepath, strlen(search->purepath)))
|
||||
if (sp->purepath[strlen(search->purepath)] == '/') //also ensures that the path gets shorter, avoiding infinite loops as it fights between base+home dirs.
|
||||
break;
|
||||
}
|
||||
if (search)
|
||||
sp = search;
|
||||
|
@ -1275,7 +1278,7 @@ char *FS_GetPackageDownloadFilename(flocation_t *loc)
|
|||
break;
|
||||
}
|
||||
|
||||
if (sp && strchr(sp->purepath, '/'))
|
||||
if (sp && strchr(sp->purepath, '/')) //never allow any packages that are directly sitting in the basedir.
|
||||
return sp->purepath;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s)
|
|||
int idx;
|
||||
|
||||
mins[0] = mins[1] = 999999;
|
||||
maxs[0] = maxs[1] = -99999;
|
||||
maxs[0] = maxs[1] = -999999;
|
||||
|
||||
tex = s->texinfo;
|
||||
|
||||
|
|
|
@ -608,9 +608,12 @@ void VARGS PR_CB_Free(void *mem)
|
|||
//DP_QC_GETSURFACE
|
||||
static void PF_BuildSurfaceMesh(model_t *model, unsigned int surfnum)
|
||||
{
|
||||
//this function might be called on dedicated servers.
|
||||
#ifdef Q1BSPS
|
||||
void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *cookie);
|
||||
if (model->fromgame == fg_quake)
|
||||
if (model->fromgame == fg_quake || model->fromgame == fg_halflife)
|
||||
ModQ1_Batches_BuildQ1Q2Poly(model, &model->surfaces[surfnum], NULL);
|
||||
#endif
|
||||
//fixme: q3...
|
||||
}
|
||||
// #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
|
||||
|
@ -5852,7 +5855,7 @@ void QCBUILTIN PF_physics_addtorque(pubprogfuncs_t *prinst, struct globalvars_s
|
|||
void PR_Common_Shutdown(pubprogfuncs_t *progs, qboolean errored)
|
||||
{
|
||||
#if defined(SKELETALOBJECTS) || defined(RAGDOLLS)
|
||||
skel_reset(progs);
|
||||
skel_reset(progs->parms->user);
|
||||
#endif
|
||||
PR_fclose_progs(progs);
|
||||
search_close_progs(progs, !errored);
|
||||
|
@ -6221,6 +6224,8 @@ lh_extension_t QSG_Extensions[] = {
|
|||
{"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}, "Provides an easy way to change a user's userinfo from the server."},
|
||||
{"FTE_GFX_QUAKE3SHADERS", 0, NULL, {NULL}, "specifies that the engine has full support for vanilla quake3 shaders"},
|
||||
{"FTE_GFX_REMAPSHADER", 0, NULL, {NULL}, "With the raw power of stuffcmds, the r_remapshader console command is exposed! This mystical command can be used to remap any shader to another. Remapped shaders that specify $diffuse etc in some form will inherit the textures implied by the surface."},
|
||||
// {"FTE_GFX_IQM_HITMESH", 0, NULL, {NULL}, "Supports hitmesh iqm extensions. Also supports geomsets and embedded events."},
|
||||
// {"FTE_GFX_MODELEVENTS", 1, NULL, {"processmodelevents", "getnextmodelevent", "getmodeleventidx"}, "Provides a query for per-animation events in model files, including from progs/foo.mdl.events files."},
|
||||
{"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}, "Allows you to check if a client has too many reliable messages pending."},
|
||||
{"FTE_MEMALLOC", 4, NULL, {"memalloc", "memfree", "memcpy", "memfill8"}, "Allows dynamically allocating memory. Use pointers to access this memory. Memory will not be saved into saved games."},
|
||||
#ifndef NOMEDIA
|
||||
|
|
|
@ -262,10 +262,15 @@ void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_
|
|||
void QCBUILTIN PF_gettaginfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_gettagindex (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
#endif
|
||||
|
||||
void QCBUILTIN PF_processmodelevents (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_getnextmodelevent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_getmodeleventidx (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
|
||||
#if defined(SKELETALOBJECTS) || defined(RAGDOLL)
|
||||
void skel_lookup(pubprogfuncs_t *prinst, int skelidx, framestate_t *out);
|
||||
void skel_dodelete(pubprogfuncs_t *prinst);
|
||||
void skel_reset(pubprogfuncs_t *prinst);
|
||||
void skel_lookup(world_t *prinst, int skelidx, framestate_t *out);
|
||||
void skel_dodelete(world_t *world);
|
||||
void skel_reset(world_t *world);
|
||||
#endif
|
||||
void QCBUILTIN PF_physics_enable(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
void QCBUILTIN PF_physics_addforce(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -60,6 +60,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qi", "..\..\plugins\qi\qi.v
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models", "..\..\plugins\models\models.vcproj", "{E6CDA919-628B-45BF-A5DB-FB55179D6443}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iqm", "..\..\iqm\iqm.vcproj", "{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
D3DDebug|Win32 = D3DDebug|Win32
|
||||
|
@ -689,7 +691,6 @@ Global
|
|||
{74542CA7-48C1-4664-9007-66F751131EA3}.MinGLRelease|Win32.ActiveCfg = Release|Win32
|
||||
{74542CA7-48C1-4664-9007-66F751131EA3}.MinGLRelease|x64.ActiveCfg = Release|Win32
|
||||
{74542CA7-48C1-4664-9007-66F751131EA3}.MRelease|Win32.ActiveCfg = Release|Win32
|
||||
{74542CA7-48C1-4664-9007-66F751131EA3}.MRelease|Win32.Build.0 = Release|Win32
|
||||
{74542CA7-48C1-4664-9007-66F751131EA3}.MRelease|x64.ActiveCfg = Release|Win32
|
||||
{74542CA7-48C1-4664-9007-66F751131EA3}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
|
||||
{74542CA7-48C1-4664-9007-66F751131EA3}.Release Dedicated Server|x64.ActiveCfg = Release|Win32
|
||||
|
@ -805,7 +806,6 @@ Global
|
|||
{ED16B405-BDCD-4EB8-BF70-761964301368}.MinGLRelease|Win32.Build.0 = Release|Win32
|
||||
{ED16B405-BDCD-4EB8-BF70-761964301368}.MinGLRelease|x64.ActiveCfg = Release|Win32
|
||||
{ED16B405-BDCD-4EB8-BF70-761964301368}.MRelease|Win32.ActiveCfg = Release|Win32
|
||||
{ED16B405-BDCD-4EB8-BF70-761964301368}.MRelease|Win32.Build.0 = Release|Win32
|
||||
{ED16B405-BDCD-4EB8-BF70-761964301368}.MRelease|x64.ActiveCfg = Release|Win32
|
||||
{ED16B405-BDCD-4EB8-BF70-761964301368}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
|
||||
{ED16B405-BDCD-4EB8-BF70-761964301368}.Release Dedicated Server|Win32.Build.0 = Release|Win32
|
||||
|
@ -897,7 +897,6 @@ Global
|
|||
{F756A3D2-025A-43D4-9829-4074753B774B}.MinGLRelease|x64.ActiveCfg = Release|x64
|
||||
{F756A3D2-025A-43D4-9829-4074753B774B}.MinGLRelease|x64.Build.0 = Release|x64
|
||||
{F756A3D2-025A-43D4-9829-4074753B774B}.MRelease|Win32.ActiveCfg = Release|Win32
|
||||
{F756A3D2-025A-43D4-9829-4074753B774B}.MRelease|Win32.Build.0 = Release|Win32
|
||||
{F756A3D2-025A-43D4-9829-4074753B774B}.MRelease|x64.ActiveCfg = Release|x64
|
||||
{F756A3D2-025A-43D4-9829-4074753B774B}.MRelease|x64.Build.0 = Release|x64
|
||||
{F756A3D2-025A-43D4-9829-4074753B774B}.Release Dedicated Server|Win32.ActiveCfg = Release|x64
|
||||
|
@ -1011,6 +1010,60 @@ Global
|
|||
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.VkRelease|Win32.Build.0 = Release|Win32
|
||||
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.VkRelease|x64.ActiveCfg = Release|x64
|
||||
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.VkRelease|x64.Build.0 = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DDebug|Win32.ActiveCfg = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DDebug|Win32.Build.0 = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DDebug|x64.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DDebug|x64.Build.0 = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DRelease|Win32.ActiveCfg = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DRelease|Win32.Build.0 = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DRelease|x64.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DRelease|x64.Build.0 = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Debug Dedicated Server|Win32.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Debug Dedicated Server|x64.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Debug Dedicated Server|x64.Build.0 = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Debug|x64.Build.0 = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLDebug|Win32.ActiveCfg = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLDebug|Win32.Build.0 = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLDebug|x64.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLDebug|x64.Build.0 = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLRelease|Win32.ActiveCfg = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLRelease|Win32.Build.0 = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLRelease|x64.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.GLRelease|x64.Build.0 = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MDebug|Win32.ActiveCfg = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MDebug|Win32.Build.0 = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MDebug|x64.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MDebug|x64.Build.0 = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLDebug|Win32.Build.0 = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLDebug|x64.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLDebug|x64.Build.0 = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLRelease|Win32.ActiveCfg = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLRelease|Win32.Build.0 = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLRelease|x64.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MinGLRelease|x64.Build.0 = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MRelease|Win32.ActiveCfg = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MRelease|Win32.Build.0 = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MRelease|x64.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.MRelease|x64.Build.0 = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Release Dedicated Server|Win32.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Release Dedicated Server|x64.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Release Dedicated Server|x64.Build.0 = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Release|Win32.Build.0 = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Release|x64.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Release|x64.Build.0 = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkDebug|Win32.ActiveCfg = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkDebug|Win32.Build.0 = Debug|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkDebug|x64.ActiveCfg = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkDebug|x64.Build.0 = Debug|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkRelease|Win32.ActiveCfg = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkRelease|Win32.Build.0 = Release|Win32
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkRelease|x64.ActiveCfg = Release|x64
|
||||
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkRelease|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -602,6 +602,9 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
|
|||
plskin = sk->qwskin;
|
||||
}
|
||||
}
|
||||
else if (inf->geomset < MAX_GEOMSETS && 0 != inf->geomid)
|
||||
return NULL;
|
||||
|
||||
|
||||
/*hexen2 feature: global skins */
|
||||
if (inf->numskins < e->skinnum && e->skinnum >= r_globalskin_first.ival && e->skinnum < r_globalskin_first.ival+r_globalskin_count.ival)
|
||||
|
|
|
@ -4862,7 +4862,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
{
|
||||
newvals = PR_GetStringOfs(prinst, OFS_PARM2);
|
||||
if (idx >= mod->numentityinfo)
|
||||
Z_ReallocElements(&mod->entityinfo, &mod->numentityinfo, idx+64, sizeof(*mod->entityinfo));
|
||||
Z_ReallocElements((void**)&mod->entityinfo, &mod->numentityinfo, idx+64, sizeof(*mod->entityinfo));
|
||||
mod->entityinfo[idx].keyvals = Z_StrDup(newvals);
|
||||
}
|
||||
else
|
||||
|
@ -6198,7 +6198,7 @@ void CL_Parse_BrushEdit(void)
|
|||
if (id > 0xffff)
|
||||
return;
|
||||
if (id >= mod->numentityinfo)
|
||||
Z_ReallocElements(&mod->entityinfo, &mod->numentityinfo, id+64, sizeof(*mod->entityinfo));
|
||||
Z_ReallocElements((void**)&mod->entityinfo, &mod->numentityinfo, id+64, sizeof(*mod->entityinfo));
|
||||
if (id < mod->numentityinfo)
|
||||
{
|
||||
if (!ignore)
|
||||
|
|
|
@ -396,6 +396,21 @@ int HLMDL_FrameForName(model_t *mod, const char *name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
qboolean HLMDL_GetModelEvent(model_t *model, int animation, int eventidx, float *timestamp, int *eventcode, char **eventdata)
|
||||
{
|
||||
hlmodel_t *mc = Mod_Extradata(model);
|
||||
hlmdl_header_t *h = mc->header;
|
||||
hlmdl_event_t *ev;
|
||||
hlmdl_sequencelist_t *seq = animation + (hlmdl_sequencelist_t*)((char*)h+h->seqindex);
|
||||
if (animation < 0 || animation >= h->numseq || eventidx < 0 || eventidx >= seq->num_events)
|
||||
return false;
|
||||
ev = eventidx + (hlmdl_event_t*)((char*)h+seq->ofs_events);
|
||||
*timestamp = ev->pose / seq->timing;
|
||||
*eventcode = ev->code;
|
||||
*eventdata = ev->data;
|
||||
return true;
|
||||
}
|
||||
|
||||
int HLMDL_BoneForName(model_t *mod, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -52,7 +52,9 @@ void CM_Shutdown(void);
|
|||
void Mod_LoadSpriteShaders(model_t *spr);
|
||||
qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer, size_t fsize);
|
||||
qboolean QDECL Mod_LoadSprite2Model (model_t *mod, void *buffer, size_t fsize);
|
||||
qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsize);
|
||||
#ifdef Q1BSPS
|
||||
static qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsize);
|
||||
#endif
|
||||
#ifdef Q2BSPS
|
||||
qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer, size_t fsize);
|
||||
#endif
|
||||
|
@ -77,18 +79,18 @@ extern cvar_t r_loadlits;
|
|||
extern cvar_t gl_specular;
|
||||
#endif
|
||||
extern cvar_t r_fb_bmodels;
|
||||
mesh_t nullmesh;
|
||||
void Mod_SortShaders(model_t *mod);
|
||||
void Mod_LoadAliasShaders(model_t *mod);
|
||||
|
||||
#ifdef RUNTIMELIGHTING
|
||||
model_t *lightmodel;
|
||||
struct relight_ctx_s *lightcontext;
|
||||
int numlightdata;
|
||||
qboolean writelitfile;
|
||||
static struct relight_ctx_s *lightcontext;
|
||||
static int numlightdata;
|
||||
static qboolean writelitfile;
|
||||
|
||||
long relitsurface;
|
||||
void Mod_UpdateLightmap(int snum)
|
||||
#ifndef MULTITHREAD
|
||||
static void Mod_UpdateLightmap(int snum)
|
||||
{
|
||||
msurface_t *s;
|
||||
if (lightmodel)
|
||||
|
@ -107,6 +109,7 @@ void Mod_UpdateLightmap(int snum)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void Mod_MemList_f(void)
|
||||
{
|
||||
|
@ -261,12 +264,13 @@ static void Mod_BlockTextureColour_f (void)
|
|||
#endif
|
||||
|
||||
|
||||
#if defined(RUNTIMELIGHTING) && defined(MULTITHREAD)
|
||||
void *relightthread[8];
|
||||
unsigned int relightthreads;
|
||||
volatile qboolean wantrelight;
|
||||
#if defined(RUNTIMELIGHTING)
|
||||
#if defined(MULTITHREAD)
|
||||
static void *relightthread[8];
|
||||
static unsigned int relightthreads;
|
||||
static volatile qboolean wantrelight;
|
||||
|
||||
int RelightThread(void *arg)
|
||||
static int RelightThread(void *arg)
|
||||
{
|
||||
int surf;
|
||||
void *threadctx = malloc(lightthreadctxsize);
|
||||
|
@ -287,8 +291,8 @@ int RelightThread(void *arg)
|
|||
free(threadctx);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
void *lightmainthreadctx;
|
||||
#endif
|
||||
static void *lightmainthreadctx;
|
||||
#endif
|
||||
|
||||
void Mod_Think (void)
|
||||
|
@ -707,7 +711,9 @@ void Mod_Init (qboolean initial)
|
|||
Mod_ClearAll(); //shouldn't be needed
|
||||
Mod_Purge(MP_RESET);//shouldn't be needed
|
||||
mod_numknown = 0;
|
||||
#ifdef Q1BSPS
|
||||
Q1BSP_Init();
|
||||
#endif
|
||||
|
||||
Cmd_AddCommand("mod_memlist", Mod_MemList_f);
|
||||
#ifndef SERVERONLY
|
||||
|
@ -758,12 +764,14 @@ void Mod_Init (qboolean initial)
|
|||
Mod_RegisterModelFormatText(NULL, "Doom3 (cm)", "CM", D3_LoadMap_CollisionMap);
|
||||
#endif
|
||||
|
||||
#ifdef Q1BSPS
|
||||
//q1-based formats
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 2PSB Map(bsp)", BSPVERSION_LONG1, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 BSP2 Map(bsp)", BSPVERSION_LONG2, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Half-Life Map (bsp)", 30, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 Map (bsp)", 29, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 Prerelease Map (bsp)", 28, Mod_LoadBrushModel);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1120,7 +1128,7 @@ Mod_LoadModel
|
|||
Loads a model into the cache
|
||||
==================
|
||||
*/
|
||||
void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
|
||||
static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
|
||||
{
|
||||
model_t *mod = ctx;
|
||||
enum mlverbosity_e verbose = a;
|
||||
|
@ -1436,10 +1444,9 @@ static const char *Mod_RemapBuggyTexture(const char *name, const qbyte *data, un
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Mod_FinishTexture(texture_t *tx, const char *loadname, qboolean safetoloadfromwads)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
static void Mod_FinishTexture(texture_t *tx, const char *loadname, qboolean safetoloadfromwads)
|
||||
{
|
||||
extern cvar_t gl_shadeq1_name;
|
||||
char altname[MAX_QPATH];
|
||||
char *star;
|
||||
|
@ -1520,9 +1527,7 @@ void Mod_FinishTexture(texture_t *tx, const char *loadname, qboolean safetoloadf
|
|||
R_BuildLegacyTexnums(tx->shader, origname, loadname, maps, 0, fmt, tx->width, tx->height, tx->mips, tx->palette);
|
||||
}
|
||||
BZ_Free(tx->mips[0]);
|
||||
#endif
|
||||
}
|
||||
#ifndef SERVERONLY
|
||||
static void Mod_LoadMiptex(model_t *loadmodel, texture_t *tx, miptex_t *mt)
|
||||
{
|
||||
unsigned int size =
|
||||
|
@ -1559,7 +1564,7 @@ static void Mod_LoadMiptex(model_t *loadmodel, texture_t *tx, miptex_t *mt)
|
|||
Mod_LoadTextures
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadTextures (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
||||
static qboolean Mod_LoadTextures (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
||||
{
|
||||
int i, j, num, max, altmax;
|
||||
miptex_t *mt;
|
||||
|
@ -2224,7 +2229,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
|
|||
Mod_LoadVisibility
|
||||
=================
|
||||
*/
|
||||
void Mod_LoadVisibility (model_t *loadmodel, qbyte *mod_base, lump_t *l, qbyte *ptr, size_t len)
|
||||
static void Mod_LoadVisibility (model_t *loadmodel, qbyte *mod_base, lump_t *l, qbyte *ptr, size_t len)
|
||||
{
|
||||
if (!ptr)
|
||||
{
|
||||
|
@ -2462,7 +2467,7 @@ qboolean Mod_LoadVertexNormals (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
|||
Mod_LoadSubmodels
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadSubmodels (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean *hexen2map)
|
||||
static qboolean Mod_LoadSubmodels (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean *hexen2map)
|
||||
{
|
||||
dq1model_t *inq;
|
||||
dh2model_t *inh;
|
||||
|
@ -2611,7 +2616,7 @@ qboolean Mod_LoadEdges (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
|
|||
Mod_LoadTexinfo
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadTexinfo (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
||||
static qboolean Mod_LoadTexinfo (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
||||
{
|
||||
texinfo_t *in;
|
||||
mtexinfo_t *out;
|
||||
|
@ -2652,7 +2657,7 @@ qboolean Mod_LoadTexinfo (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
|||
out->texture = r_notexture_mip; // texture not found
|
||||
out->flags = 0;
|
||||
}
|
||||
if (!strncmp(out->texture->name, "scroll", 6) || ((*out->texture->name == '*' || *out->texture->name == '{' || *out->texture->name == '!') && !strncmp(out->texture->name+1, "scroll", 6)))
|
||||
else if (!strncmp(out->texture->name, "scroll", 6) || ((*out->texture->name == '*' || *out->texture->name == '{' || *out->texture->name == '!') && !strncmp(out->texture->name+1, "scroll", 6)))
|
||||
out->flags |= TI_FLOWING;
|
||||
}
|
||||
|
||||
|
@ -2721,7 +2726,7 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s);
|
|||
Mod_LoadFaces
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t *lightlump, qboolean lm)
|
||||
static qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t *lightlump, qboolean lm)
|
||||
{
|
||||
dsface_t *ins;
|
||||
dlface_t *inl;
|
||||
|
@ -3113,7 +3118,7 @@ static void Mod_Batches_BuildModelMeshes(model_t *mod, int maxverts, int maxindi
|
|||
}
|
||||
|
||||
//q1 autoanimates. if the frame is set, it uses the alternate animation.
|
||||
void Mod_UpdateBatchShader_Q1 (struct batch_s *batch)
|
||||
static void Mod_UpdateBatchShader_Q1 (struct batch_s *batch)
|
||||
{
|
||||
texture_t *base = batch->texture;
|
||||
int reletive;
|
||||
|
@ -3144,7 +3149,7 @@ void Mod_UpdateBatchShader_Q1 (struct batch_s *batch)
|
|||
}
|
||||
|
||||
//q2 has direct control over the texture frames used, but typically has the client generate the frame (different flags autogenerate different ranges).
|
||||
void Mod_UpdateBatchShader_Q2 (struct batch_s *batch)
|
||||
static void Mod_UpdateBatchShader_Q2 (struct batch_s *batch)
|
||||
{
|
||||
texture_t *base = batch->texture;
|
||||
int reletive;
|
||||
|
@ -3721,7 +3726,7 @@ static qboolean Mod_LoadNodes (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
|
|||
|
||||
out->firstsurface = LittleLong (in->firstface);
|
||||
out->numsurfaces = LittleLong (in->numfaces);
|
||||
|
||||
|
||||
for (j=0 ; j<2 ; j++)
|
||||
{
|
||||
p = LittleLong (in->children[j]);
|
||||
|
@ -3760,7 +3765,7 @@ static qboolean Mod_LoadNodes (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
|
|||
|
||||
out->firstsurface = (unsigned short)LittleShort (in->firstface);
|
||||
out->numsurfaces = (unsigned short)LittleShort (in->numfaces);
|
||||
|
||||
|
||||
for (j=0 ; j<2 ; j++)
|
||||
{
|
||||
p = LittleShort (in->children[j]);
|
||||
|
@ -3988,13 +3993,13 @@ static qboolean Mod_LoadLeafs (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
|
|||
|
||||
|
||||
//these are used to boost other info sizes
|
||||
int numsuplementryplanes;
|
||||
int numsuplementryclipnodes;
|
||||
void *suplementryclipnodes;
|
||||
void *suplementryplanes;
|
||||
void *crouchhullfile;
|
||||
static int numsuplementryplanes;
|
||||
static int numsuplementryclipnodes;
|
||||
static void *suplementryclipnodes;
|
||||
static void *suplementryplanes;
|
||||
static void *crouchhullfile;
|
||||
|
||||
void Mod_LoadCrouchHull(model_t *loadmodel)
|
||||
static void Mod_LoadCrouchHull(model_t *loadmodel)
|
||||
{
|
||||
int i, h;
|
||||
int numsm;
|
||||
|
@ -4065,7 +4070,7 @@ void Mod_LoadCrouchHull(model_t *loadmodel)
|
|||
Mod_LoadClipnodes
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadClipnodes (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean lm, qboolean hexen2map)
|
||||
static qboolean Mod_LoadClipnodes (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean lm, qboolean hexen2map)
|
||||
{
|
||||
dsclipnode_t *ins;
|
||||
dlclipnode_t *inl;
|
||||
|
@ -4320,7 +4325,7 @@ Mod_MakeHull0
|
|||
Deplicate the drawing hull structure as a clipping hull
|
||||
=================
|
||||
*/
|
||||
void Mod_MakeHull0 (model_t *loadmodel)
|
||||
static void Mod_MakeHull0 (model_t *loadmodel)
|
||||
{
|
||||
mnode_t *in, *child;
|
||||
mclipnode_t *out;
|
||||
|
@ -4452,7 +4457,7 @@ qboolean Mod_LoadSurfedges (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
|||
Mod_LoadPlanes
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadPlanes (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
||||
static qboolean Mod_LoadPlanes (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
||||
{
|
||||
int i, j;
|
||||
mplane_t *out;
|
||||
|
@ -4550,7 +4555,7 @@ static void Q1BSP_StainNode (mnode_t *node, float *parms)
|
|||
}
|
||||
#endif
|
||||
|
||||
void Mod_FixupNodeMinsMaxs (mnode_t *node, mnode_t *parent)
|
||||
static void Mod_FixupNodeMinsMaxs (mnode_t *node, mnode_t *parent)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
|
@ -4733,6 +4738,8 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef Q1BSPS
|
||||
|
||||
struct vispatch_s
|
||||
{
|
||||
void *fileptr;
|
||||
|
@ -4816,7 +4823,7 @@ static void Mod_FindVisPatch(struct vispatch_s *patch, model_t *mod, size_t leaf
|
|||
Mod_LoadBrushModel
|
||||
=================
|
||||
*/
|
||||
qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsize)
|
||||
static qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer, size_t fsize)
|
||||
{
|
||||
struct vispatch_s vispatch;
|
||||
int i, j;
|
||||
|
@ -5109,6 +5116,7 @@ TRACE(("LoadBrushModel %i\n", __LINE__));
|
|||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
|
|
@ -66,8 +66,9 @@ struct doll_s *rag_createdollfromstring(struct model_s *mod, const char *fname,
|
|||
struct world_s;
|
||||
void rag_doallanimations(struct world_s *world);
|
||||
void rag_removedeltaent(lerpents_t *le);
|
||||
void rag_updatedeltaent(entity_t *ent, lerpents_t *le);
|
||||
void rag_updatedeltaent(struct world_s *w, entity_t *ent, lerpents_t *le);
|
||||
void rag_lerpdeltaent(lerpents_t *le, unsigned int bonecount, short *newstate, float frac, short *oldstate);
|
||||
void skel_reset(struct world_s *world);
|
||||
|
||||
typedef struct mesh_s
|
||||
{
|
||||
|
@ -107,7 +108,6 @@ typedef struct mesh_s
|
|||
byte_vec4_t *bonenums;
|
||||
vec4_t *boneweights;
|
||||
} mesh_t;
|
||||
extern mesh_t nullmesh;
|
||||
|
||||
/*
|
||||
batches are generated for each shader/ent as required.
|
||||
|
@ -831,7 +831,7 @@ typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife, fg_new, fg_doom, fg_d
|
|||
#define MFH2_SCARAB (1u<<21) // white transparent particles with little gravity
|
||||
#define MFH2_ACIDBALL (1u<<22) // Green drippy acid shit
|
||||
#define MFH2_BLOODSHOT (1u<<23) // Blood rain shot trail
|
||||
#define MFH2_ROCKET (1u<<31) // spider blood (remapped from MF_ROCKET, to avoid dlight issues)
|
||||
#define MFH2_SPIDERBLOOD (1u<<31) // spider blood (remapped from MF_ROCKET, to avoid dlight issues)
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
|
|
|
@ -1591,10 +1591,10 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
|
|||
front = DotProduct (start, plane->normal) - plane->dist;
|
||||
back = DotProduct (end, plane->normal) - plane->dist;
|
||||
side = front < 0;
|
||||
|
||||
|
||||
if ( (back < 0) == side)
|
||||
return GLRecursiveLightPoint3C (mod, node->children[side], start, end);
|
||||
|
||||
|
||||
frac = front / (front-back);
|
||||
mid[0] = start[0] + (end[0] - start[0])*frac;
|
||||
mid[1] = start[1] + (end[1] - start[1])*frac;
|
||||
|
@ -1604,10 +1604,10 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
|
|||
r = GLRecursiveLightPoint3C (mod, node->children[side], start, mid);
|
||||
if (r && r[0]+r[1]+r[2] >= 0)
|
||||
return r; // hit something
|
||||
|
||||
|
||||
if ( (back < 0) == side )
|
||||
return NULL; // didn't hit anuthing
|
||||
|
||||
|
||||
// check for impact on this node
|
||||
VectorCopy (mid, lightspot);
|
||||
lightplane = plane;
|
||||
|
@ -1626,7 +1626,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
|
|||
if (s < surf->texturemins[0] ||
|
||||
t < surf->texturemins[1])
|
||||
continue;
|
||||
|
||||
|
||||
ds = s - surf->texturemins[0];
|
||||
dt = t - surf->texturemins[1];
|
||||
|
||||
|
|
|
@ -192,7 +192,9 @@ typedef struct
|
|||
char name[32];
|
||||
float timing;
|
||||
int loop;
|
||||
int unknown1[4];
|
||||
int unknown1[2];
|
||||
int num_events;
|
||||
int ofs_events;
|
||||
int numframes;
|
||||
int unknown2[2];
|
||||
int motiontype;
|
||||
|
@ -209,6 +211,14 @@ typedef struct
|
|||
int unknown9[4];
|
||||
} hlmdl_sequencelist_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int pose;
|
||||
int code;
|
||||
int unknown1;
|
||||
char data[64];
|
||||
} hlmdl_event_t;
|
||||
|
||||
/*
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
sequence groups
|
||||
|
@ -289,6 +299,7 @@ int HLMDL_BoneForName(model_t *mod, const char *name);
|
|||
int HLMDL_FrameForName(model_t *mod, const char *name);
|
||||
const char *HLMDL_FrameNameForNum(model_t *model, int surfaceidx, int num);
|
||||
qboolean HLMDL_FrameInfoForNum(model_t *model, int surfaceidx, int num, char **name, int *numframes, float *duration, qboolean *loop);
|
||||
qboolean HLMDL_GetModelEvent(model_t *model, int animation, int eventidx, float *timestamp, int *eventcode, char **eventdata);
|
||||
int HLMDL_GetNumBones(model_t *mod, qboolean tagstoo);
|
||||
int HLMDL_GetBoneParent(model_t *mod, int bonenum);
|
||||
const char *HLMDL_GetBoneName(model_t *mod, int bonenum);
|
||||
|
|
|
@ -1379,7 +1379,10 @@ static int DL_Thread_Work(void *arg)
|
|||
#ifdef NPFTE
|
||||
//the plugin doesn't have a download loop
|
||||
if (dl->notifycomplete)
|
||||
{
|
||||
dl->notifycomplete(dl);
|
||||
dl->notifycomplete = NULL;
|
||||
}
|
||||
if (dl->file)
|
||||
VFS_CLOSE(dl->file);
|
||||
#else
|
||||
|
@ -1452,6 +1455,7 @@ struct dl_download *DL_Create(const char *url)
|
|||
strcpy(newdl->url, url);
|
||||
newdl->poll = DL_Decide;
|
||||
newdl->sizelimit = 0x80000000u; //some sanity limit.
|
||||
newdl->qdownload.method = DL_HTTP;
|
||||
|
||||
if (!newdl->poll(newdl))
|
||||
{
|
||||
|
@ -1488,6 +1492,10 @@ void DL_Close(struct dl_download *dl)
|
|||
if (dl->threadctx)
|
||||
Sys_WaitOnThread(dl->threadctx);
|
||||
#endif
|
||||
if (dl->file && dl->file->Seek)
|
||||
VFS_SEEK(dl->file, 0);
|
||||
if (dl->notifycomplete)
|
||||
dl->notifycomplete(dl);
|
||||
if (dl->abort)
|
||||
dl->abort(dl);
|
||||
if (dl->file)
|
||||
|
@ -1542,7 +1550,6 @@ struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*N
|
|||
if (!cls.download && localfile && !newdl->isquery)
|
||||
{
|
||||
cls.download = &newdl->qdownload;
|
||||
newdl->qdownload.method = DL_HTTP;
|
||||
if (*newdl->localname)
|
||||
Q_strncpyz(newdl->qdownload.localname, newdl->localname, sizeof(newdl->qdownload.localname));
|
||||
else
|
||||
|
@ -1614,10 +1621,6 @@ void HTTP_CL_Think(void)
|
|||
if (!dl->poll(dl))
|
||||
{
|
||||
*link = dl->next;
|
||||
if (dl->file && dl->file->Seek)
|
||||
VFS_SEEK(dl->file, 0);
|
||||
if (dl->notifycomplete)
|
||||
dl->notifycomplete(dl);
|
||||
DL_Close(dl);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -2529,6 +2529,8 @@ int PR_ReallyLoadProgs (progfuncs_t *progfuncs, const char *filename, progstate_
|
|||
|
||||
int stringadjust;
|
||||
|
||||
char *mainstringtable, *newstringtable;
|
||||
|
||||
current_progstate = progstate;
|
||||
|
||||
strcpy(current_progstate->filename, filename);
|
||||
|
@ -2792,6 +2794,9 @@ retry:
|
|||
|
||||
len=sizeof(char)*pr_progs->numstrings;
|
||||
s = PRAddressableExtend(progfuncs, pr_strings, len, 0);
|
||||
|
||||
newstringtable = s;
|
||||
mainstringtable = progfuncs->funcs.stringtable;
|
||||
pr_strings = (char *)s;
|
||||
|
||||
len=sizeof(float)*pr_progs->numglobals;
|
||||
|
|
|
@ -670,6 +670,7 @@ int QCC_PR_IntConstExpr(void);
|
|||
#ifndef COMMONINLINES
|
||||
pbool QCC_PR_CheckImmediate (const char *string);
|
||||
pbool QCC_PR_CheckToken (const char *string);
|
||||
pbool QCC_PR_PeekToken (const char *string);
|
||||
pbool QCC_PR_CheckName (const char *string);
|
||||
void QCC_PR_Expect (const char *string);
|
||||
pbool QCC_PR_CheckKeyword(int keywordenabled, const char *string);
|
||||
|
@ -1073,6 +1074,16 @@ static bool inline QCC_PR_CheckToken (char *string)
|
|||
QCC_PR_Lex ();
|
||||
return true;
|
||||
}
|
||||
static bool inline QCC_PR_PeekToken (char *string)
|
||||
{
|
||||
if (pr_token_type != tt_punct)
|
||||
return false;
|
||||
|
||||
if (STRCMP (string, pr_token))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void inline QCC_PR_Expect (const char *string)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "qcc.h"
|
||||
#include <math.h>
|
||||
|
||||
#define WARN_IMPLICITVARIANTCAST 0
|
||||
|
||||
//FIXME: #define IAMNOTLAZY
|
||||
|
||||
#define SUPPORTINLINE
|
||||
|
@ -191,6 +193,7 @@ void QCC_PR_DiscardRef(QCC_ref_t *ref);
|
|||
QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *type, pbool dowrap);
|
||||
const char *QCC_VarAtOffset(QCC_sref_t ref, unsigned int size);
|
||||
QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit);
|
||||
void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t def, unsigned int flags);
|
||||
|
||||
QCC_statement_t *QCC_Generate_OP_IFNOT(QCC_sref_t e, pbool preserve);
|
||||
QCC_statement_t *QCC_Generate_OP_IF(QCC_sref_t e, pbool preserve);
|
||||
|
@ -5887,60 +5890,8 @@ QCC_sref_t QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
|
|||
if (p)
|
||||
{
|
||||
if (typecmp(e->cast, p))
|
||||
/*if (e->type->type != ev_integer && p->type != ev_function)
|
||||
if (e->type->type != ev_function && p->type != ev_integer)
|
||||
if ( e->type->type != p->type )*/
|
||||
{
|
||||
e = QCC_PR_BuildRef(¶mbuf[arg], REF_GLOBAL, QCC_EvaluateCast(QCC_RefToDef(e, true), p, true), nullsref, p, true);
|
||||
|
||||
#if 0
|
||||
if (p->type == ev_integer && e.cast->type == ev_float) //convert float -> int... is this a constant?
|
||||
e = QCC_PR_Statement(pr_opcodes+OP_CONV_FTOI, e, nullsref, NULL);
|
||||
else if (p->type == ev_float && e.cast->type == ev_integer) //convert float -> int... is this a constant?
|
||||
e = QCC_PR_Statement(pr_opcodes+OP_CONV_ITOF, e, nullsref, NULL);
|
||||
else if ((p->type == ev_function || p->type == ev_field || p->type == ev_string || p->type == ev_pointer || p->type == ev_entity) && QCC_SRef_IsNull(e))
|
||||
{ //you're allowed to use int 0 to pass a null function/field/string/pointer/entity
|
||||
//this is basically because __NULL__ is defined as 0i (int 0)
|
||||
//WARNING: field 0 is actually a valid field, and is commonly modelindex.
|
||||
}
|
||||
else if ((p->type == ev_field || p->type == ev_pointer) && e.cast->type == p->type && (p->aux_type->type == ev_variant || e.cast->aux_type->type == ev_variant || p->aux_type->type == ev_void || e.cast->aux_type->type == ev_void))
|
||||
{ //allow passing variant fields etc (also allow .void or *void as universal/variant field/pointer types)
|
||||
}
|
||||
else if ( (p->type == ev_accessor && p->parentclass->type == e.cast->type)
|
||||
|| (e.cast->type == ev_accessor && e.cast->parentclass->type == p->type))
|
||||
{
|
||||
}
|
||||
else if ((p->type == ev_vector) && QCC_SRef_IsNull(e))
|
||||
{
|
||||
//also allow it for vector types too, but make sure the entire vector is valid.
|
||||
e = QCC_MakeVectorConst(0, 0, 0);
|
||||
}
|
||||
else if (p->type != ev_variant && e.cast->type != ev_variant) //can cast to variant whatever happens
|
||||
{
|
||||
QCC_type_t *inh;
|
||||
for (inh = e.cast->parentclass; inh; inh = inh->parentclass)
|
||||
{
|
||||
if (!typecmp(inh, p))
|
||||
break;
|
||||
}
|
||||
if (!inh)
|
||||
{
|
||||
char typebuf1[1024];
|
||||
char typebuf2[1024];
|
||||
if (flag_laxcasts || (p->type == ev_function && e.cast->type == ev_function))
|
||||
{
|
||||
|
||||
QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch on parm %i: %s should be %s", arg+1, TypeName(e.cast, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2)));
|
||||
QCC_PR_ParsePrintSRef(WARN_LAXCAST, func);
|
||||
}
|
||||
else
|
||||
{
|
||||
QCC_PR_ParseWarning (ERR_TYPEMISMATCHPARM, "type mismatch on parm %i: %s should be %s", arg+1, TypeName(e.cast, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2)));
|
||||
QCC_PR_ParsePrintSRef(ERR_TYPEMISMATCHPARM, func);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
param[arg] = e;
|
||||
|
@ -7053,6 +7004,73 @@ vectorarrayindex:
|
|||
return r;
|
||||
}
|
||||
|
||||
QCC_sref_t QCC_PR_GenerateVector(QCC_sref_t x, QCC_sref_t y, QCC_sref_t z)
|
||||
{
|
||||
QCC_sref_t d;
|
||||
|
||||
if ((x.cast->type != ev_float && x.cast->type != ev_integer) ||
|
||||
(y.cast->type != ev_float && y.cast->type != ev_integer) ||
|
||||
(z.cast->type != ev_float && z.cast->type != ev_integer))
|
||||
{
|
||||
QCC_PR_ParseError(ERR_TYPEMISMATCH, "Argument not a single numeric value in vector constructor");
|
||||
return QCC_MakeVectorConst(0, 0, 0);
|
||||
}
|
||||
|
||||
//return a constant if we can.
|
||||
if (x.sym->constant && y.sym->constant && z.sym->constant)
|
||||
{
|
||||
d = QCC_MakeVectorConst(
|
||||
(x.cast->type==ev_float)?x.sym->symboldata[x.ofs]._float:x.sym->symboldata[x.ofs]._int,
|
||||
(y.cast->type==ev_float)?y.sym->symboldata[y.ofs]._float:y.sym->symboldata[y.ofs]._int,
|
||||
(z.cast->type==ev_float)?z.sym->symboldata[z.ofs]._float:z.sym->symboldata[z.ofs]._int);
|
||||
QCC_FreeTemp(x);
|
||||
QCC_FreeTemp(y);
|
||||
QCC_FreeTemp(z);
|
||||
return d;
|
||||
}
|
||||
if (QCC_SRef_IsNull(y) && QCC_SRef_IsNull(z))
|
||||
{
|
||||
QCC_FreeTemp(y);
|
||||
QCC_FreeTemp(z);
|
||||
return QCC_PR_StatementFlags(pr_opcodes + OP_MUL_VF, QCC_MakeVectorConst(1, 0, 0), QCC_SupplyConversion(x, ev_float, true), NULL, 0);
|
||||
}
|
||||
if (QCC_SRef_IsNull(x) && QCC_SRef_IsNull(z))
|
||||
{
|
||||
QCC_FreeTemp(x);
|
||||
QCC_FreeTemp(z);
|
||||
return QCC_PR_StatementFlags(pr_opcodes + OP_MUL_VF, QCC_MakeVectorConst(0, 1, 0), QCC_SupplyConversion(y, ev_float, true), NULL, 0);
|
||||
}
|
||||
if (QCC_SRef_IsNull(x) && QCC_SRef_IsNull(y))
|
||||
{
|
||||
QCC_FreeTemp(x);
|
||||
QCC_FreeTemp(y);
|
||||
return QCC_PR_StatementFlags(pr_opcodes + OP_MUL_VF, QCC_MakeVectorConst(0, 0, 1), QCC_SupplyConversion(z, ev_float, true), NULL, 0);
|
||||
}
|
||||
|
||||
//pack the variables into a vector
|
||||
d = QCC_GetTemp(type_vector);
|
||||
d.cast = type_float;
|
||||
if (x.cast->type == ev_float)
|
||||
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, x, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
else
|
||||
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, x, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
d.ofs++;
|
||||
if (y.cast->type == ev_float)
|
||||
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, y, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
else
|
||||
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, y, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
d.ofs++;
|
||||
if (z.cast->type == ev_float)
|
||||
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, z, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
else
|
||||
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, z, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
d.ofs++;
|
||||
d.ofs -= 3;
|
||||
d.cast = type_vector;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
PR_ParseValue
|
||||
|
@ -7105,67 +7123,7 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
|
|||
|
||||
QCC_PR_Expect("]");
|
||||
|
||||
if ((x.cast->type != ev_float && x.cast->type != ev_integer) ||
|
||||
(y.cast->type != ev_float && y.cast->type != ev_integer) ||
|
||||
(z.cast->type != ev_float && z.cast->type != ev_integer))
|
||||
{
|
||||
QCC_PR_ParseError(ERR_TYPEMISMATCH, "Argument not a single numeric value in vector constructor");
|
||||
return QCC_DefToRef(refbuf, QCC_MakeVectorConst(0, 0, 0));
|
||||
}
|
||||
|
||||
//return a constant if we can.
|
||||
if (x.sym->constant && y.sym->constant && z.sym->constant)
|
||||
{
|
||||
d = QCC_MakeVectorConst(
|
||||
(x.cast->type==ev_float)?x.sym->symboldata[x.ofs]._float:x.sym->symboldata[x.ofs]._int,
|
||||
(y.cast->type==ev_float)?y.sym->symboldata[y.ofs]._float:y.sym->symboldata[y.ofs]._int,
|
||||
(z.cast->type==ev_float)?z.sym->symboldata[z.ofs]._float:z.sym->symboldata[z.ofs]._int);
|
||||
QCC_FreeTemp(x);
|
||||
QCC_FreeTemp(y);
|
||||
QCC_FreeTemp(z);
|
||||
return QCC_DefToRef(refbuf, d);
|
||||
}
|
||||
if (QCC_SRef_IsNull(y) && QCC_SRef_IsNull(z))
|
||||
{
|
||||
QCC_FreeTemp(y);
|
||||
QCC_FreeTemp(z);
|
||||
return QCC_DefToRef(refbuf, QCC_PR_StatementFlags(pr_opcodes + OP_MUL_VF, QCC_MakeVectorConst(1, 0, 0), QCC_SupplyConversion(x, ev_float, true), NULL, 0));
|
||||
}
|
||||
if (QCC_SRef_IsNull(x) && QCC_SRef_IsNull(z))
|
||||
{
|
||||
QCC_FreeTemp(x);
|
||||
QCC_FreeTemp(z);
|
||||
return QCC_DefToRef(refbuf, QCC_PR_StatementFlags(pr_opcodes + OP_MUL_VF, QCC_MakeVectorConst(0, 1, 0), QCC_SupplyConversion(y, ev_float, true), NULL, 0));
|
||||
}
|
||||
if (QCC_SRef_IsNull(x) && QCC_SRef_IsNull(y))
|
||||
{
|
||||
QCC_FreeTemp(x);
|
||||
QCC_FreeTemp(y);
|
||||
return QCC_DefToRef(refbuf, QCC_PR_StatementFlags(pr_opcodes + OP_MUL_VF, QCC_MakeVectorConst(0, 0, 1), QCC_SupplyConversion(z, ev_float, true), NULL, 0));
|
||||
}
|
||||
|
||||
//pack the variables into a vector
|
||||
d = QCC_GetTemp(type_vector);
|
||||
d.cast = type_float;
|
||||
if (x.cast->type == ev_float)
|
||||
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, x, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
else
|
||||
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, x, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
d.ofs++;
|
||||
if (y.cast->type == ev_float)
|
||||
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, y, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
else
|
||||
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, y, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
d.ofs++;
|
||||
if (z.cast->type == ev_float)
|
||||
QCC_PR_StatementFlags(pr_opcodes + OP_STORE_F, z, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
else
|
||||
QCC_PR_StatementFlags(pr_opcodes+OP_STORE_IF, z, d, NULL, STFL_PRESERVEB|STFL_DISCARDRESULT);
|
||||
d.ofs++;
|
||||
d.ofs -= 3;
|
||||
d.cast = type_vector;
|
||||
|
||||
return QCC_DefToRef(refbuf, d);
|
||||
return QCC_DefToRef(refbuf, QCC_PR_GenerateVector(x,y,z));
|
||||
}
|
||||
|
||||
if (QCC_PR_CheckToken("::"))
|
||||
|
@ -7501,7 +7459,18 @@ QCC_sref_t QCC_EvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool implicit)
|
|||
/*variants can be cast from/to anything without warning, even implicitly. FIXME: size issues*/
|
||||
else if (totype == ev_variant || src.cast->type == ev_variant
|
||||
|| (totype == ev_field && totype == src.cast->type && (tmp->aux_type->type == ev_variant || src.cast->aux_type->type == ev_variant)))
|
||||
{
|
||||
src.cast = cast;
|
||||
|
||||
if (implicit && typecmp_lax(src.cast, cast))
|
||||
{
|
||||
char typea[256];
|
||||
char typeb[256];
|
||||
TypeName(src.cast, typea, sizeof(typea));
|
||||
TypeName(cast, typeb, sizeof(typeb));
|
||||
QCC_PR_ParseWarning(WARN_IMPLICITVARIANTCAST, "Implicit cast from %s to %s", typea, typeb);
|
||||
}
|
||||
}
|
||||
/*these casts are fine when explicit*/
|
||||
else if (
|
||||
/*you may explicitly cast between pointers and ints (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/
|
||||
|
@ -7706,34 +7675,34 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
|
|||
newtype = QCC_PR_ParseType(false, true);
|
||||
if (newtype)
|
||||
{
|
||||
/*if (QCC_PR_Check ("["))
|
||||
{
|
||||
QCC_PR_Expect ("]");
|
||||
QCC_PR_Expect(")");
|
||||
QCC_PR_Expect("{");
|
||||
QCC_PR_Expect ("}");
|
||||
return array;
|
||||
}*/
|
||||
QCC_PR_Expect (")");
|
||||
if (newtype->type == ev_function && pr_token_type == tt_punct && !strcmp(pr_token, "{"))
|
||||
if (QCC_PR_PeekToken("{"))
|
||||
{
|
||||
//save some state of the parent
|
||||
QCC_def_t *firstlocal = pr.local_head.nextlocal;
|
||||
QCC_def_t *lastlocal = pr.local_tail;
|
||||
QCC_function_t *parent = pr_scope;
|
||||
QCC_statement_t *patch;
|
||||
|
||||
//FIXME: make sure gotos/labels/cases/continues/breaks are not broken by this.
|
||||
|
||||
//generate a goto statement around the nested function, so that nothing is hurt.
|
||||
e = nullsref;
|
||||
e.cast = type_float;
|
||||
patch = QCC_Generate_OP_GOTO();
|
||||
e = QCC_MakeIntConst(QCC_PR_ParseImmediateStatements (NULL, newtype, false) - functions);
|
||||
e.cast = newtype;
|
||||
patch->a.ofs = &statements[numstatements] - patch;
|
||||
|
||||
//make sure parent state is restored properly.
|
||||
pr.local_head.nextlocal = firstlocal;
|
||||
pr.local_tail = lastlocal;
|
||||
pr_scope = parent;
|
||||
}
|
||||
else if ((newtype->type == ev_struct || newtype->type == ev_union) && pr_token_type == tt_punct && !strcmp(pr_token, "{"))
|
||||
{
|
||||
//FIXME
|
||||
QCC_PR_ParseError(0, "struct immediates are not supported at this time\n");
|
||||
if (newtype->type == ev_vector)
|
||||
{
|
||||
QCC_sref_t x,y,z;
|
||||
QCC_PR_Expect("{");
|
||||
x = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
|
||||
QCC_PR_Expect(",");
|
||||
y = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
|
||||
QCC_PR_Expect(",");
|
||||
z = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA);
|
||||
QCC_PR_Expect ("}");
|
||||
return QCC_DefToRef(retbuf, QCC_PR_GenerateVector(x,y,z));
|
||||
}
|
||||
else
|
||||
{
|
||||
e = QCC_GetTemp(newtype);
|
||||
QCC_PR_ParseInitializerType(0, NULL, e, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -8612,11 +8581,13 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
|
|||
break;
|
||||
t = t->parentclass;
|
||||
}
|
||||
if (!t && !(source.cast->type == ev_pointer && dest->cast->type == ev_pointer && (source.cast->aux_type->type == ev_void || source.cast->aux_type->type == ev_variant)))
|
||||
if (!t && !(source.cast->type == ev_pointer && dest->cast->type == ev_pointer && (source.cast->aux_type->type == ev_void || source.cast->aux_type->type == ev_variant)) && source.cast->type != ev_variant && dest->cast->type != ev_variant)
|
||||
{ //extra check to allow void*->any*
|
||||
char typea[256];
|
||||
char typeb[256];
|
||||
if ((dest->cast->type == ev_float || dest->cast->type == ev_integer) && (source.cast->type == ev_float || source.cast->type == ev_integer))
|
||||
if (source.cast->type == ev_variant || dest->cast->type == ev_variant)
|
||||
QCC_PR_ParseWarning(WARN_IMPLICITVARIANTCAST, "type mismatch: %s %s to %s %s.%s", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index));
|
||||
else if ((dest->cast->type == ev_float || dest->cast->type == ev_integer) && (source.cast->type == ev_float || source.cast->type == ev_integer))
|
||||
source = QCC_SupplyConversion(source, dest->cast->type, true);
|
||||
else
|
||||
{
|
||||
|
@ -11582,6 +11553,9 @@ void QCC_WriteAsmFunction(QCC_function_t *sc, unsigned int firststatement, QCC_d
|
|||
QCC_type_t *type;
|
||||
char typebuf[512];
|
||||
|
||||
if (sc->parentscope) //don't print dupes.
|
||||
return;
|
||||
|
||||
if (flag_guiannotate)
|
||||
QCC_WriteGUIAsmFunction(sc, firststatement);
|
||||
|
||||
|
@ -13052,6 +13026,7 @@ void QCC_PR_ExpandUnionToFields(QCC_type_t *type, unsigned int *fields)
|
|||
|
||||
#define PIF_WRAP 1 //new initialisation is meant to wrap an existing one.
|
||||
#define PIF_STRONGER 2 //previous initialisation was weak.
|
||||
//basedef can be null, meaning its initialising a temp
|
||||
void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t def, unsigned int flags)
|
||||
{
|
||||
QCC_sref_t tmp;
|
||||
|
@ -13112,7 +13087,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
|
|||
strncpy(fname, QCC_PR_ParseName(), sizeof(fname));
|
||||
|
||||
//if the builtin already exists, just use that dfunction instead
|
||||
if (basedef->initialized)
|
||||
if (basedef && basedef->initialized)
|
||||
{
|
||||
if (*fname)
|
||||
{
|
||||
|
@ -13158,34 +13133,36 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
|
|||
}
|
||||
else
|
||||
{
|
||||
if (flags&PIF_WRAP)
|
||||
if (basedef)
|
||||
{
|
||||
if (!basedef->initialized || !def.sym->symboldata[def.ofs]._int)
|
||||
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "wrapper function does not wrap anything");
|
||||
}
|
||||
else if (basedef->initialized == 1 && !(flags & PIF_STRONGER))
|
||||
{
|
||||
//normally this is an error, but to aid supporting new stuff with old, we convert it into a warning if a vanilla(ish) qc function replaces extension builtins.
|
||||
//the qc function is the one that is used, but there is a warning so you know how to gain efficiency.
|
||||
int bi = -1;
|
||||
if (def.cast->type == ev_function && !arraysize)
|
||||
if (flags&PIF_WRAP)
|
||||
{
|
||||
if (!strcmp(defname, "anglemod") || !strcmp(defname, "crossproduct"))
|
||||
bi = def.sym->symboldata[def.ofs]._int;
|
||||
if (!basedef->initialized || !def.sym->symboldata[def.ofs]._int)
|
||||
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "wrapper function does not wrap anything");
|
||||
}
|
||||
if (bi <= 0 || bi >= numfunctions)
|
||||
bi = 0;
|
||||
else
|
||||
bi = functions[bi].code;
|
||||
if (bi < 0)
|
||||
else if (basedef->initialized == 1 && !(flags & PIF_STRONGER))
|
||||
{
|
||||
QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "%s already declared as a builtin", defname);
|
||||
QCC_PR_ParsePrintSRef(WARN_NOTSTANDARDBEHAVIOUR, def);
|
||||
basedef->initialized = 3;
|
||||
//normally this is an error, but to aid supporting new stuff with old, we convert it into a warning if a vanilla(ish) qc function replaces extension builtins.
|
||||
//the qc function is the one that is used, but there is a warning so you know how to gain efficiency.
|
||||
int bi = -1;
|
||||
if (def.cast->type == ev_function && !arraysize)
|
||||
{
|
||||
if (!strcmp(defname, "anglemod") || !strcmp(defname, "crossproduct"))
|
||||
bi = def.sym->symboldata[def.ofs]._int;
|
||||
}
|
||||
if (bi <= 0 || bi >= numfunctions)
|
||||
bi = 0;
|
||||
else
|
||||
bi = functions[bi].code;
|
||||
if (bi < 0)
|
||||
{
|
||||
QCC_PR_ParseWarning(WARN_NOTSTANDARDBEHAVIOUR, "%s already declared as a builtin", defname);
|
||||
QCC_PR_ParsePrintSRef(WARN_NOTSTANDARDBEHAVIOUR, def);
|
||||
basedef->initialized = 3;
|
||||
}
|
||||
else
|
||||
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "redeclaration of function body");
|
||||
}
|
||||
else
|
||||
QCC_PR_ParseErrorPrintSRef (ERR_REDECLARATION, def, "redeclaration of function body");
|
||||
|
||||
}
|
||||
|
||||
if (pr_scope)
|
||||
|
@ -13213,7 +13190,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
|
|||
f = QCC_PR_ParseImmediateStatements (def.sym, type, flags&PIF_WRAP);
|
||||
|
||||
//allow dupes if its a builtin
|
||||
if (!f->code && basedef->initialized)
|
||||
if (basedef && !f->code && basedef->initialized)
|
||||
{
|
||||
for (i = 1; i < numfunctions; i++)
|
||||
{
|
||||
|
@ -13290,7 +13267,7 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
|
|||
tmp = QCC_EvaluateCast(tmp, type, true);
|
||||
}
|
||||
|
||||
if (!basedef->scope || basedef->constant || basedef->isstatic)
|
||||
if (basedef && (!basedef->scope || basedef->constant || basedef->isstatic))
|
||||
{
|
||||
tmp.sym->referenced = true;
|
||||
if (!tmp.sym->constant)
|
||||
|
@ -13368,6 +13345,17 @@ void QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t d
|
|||
else
|
||||
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_FNC], rhs, def, NULL, STFL_PRESERVEA|STFL_PRESERVEB));
|
||||
}
|
||||
else if (def.cast->type == ev_string)
|
||||
{
|
||||
rhs.cast = def.cast = type_string;
|
||||
if (type->size - i == 1)
|
||||
{
|
||||
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_S], rhs, def, NULL, STFL_PRESERVEB));
|
||||
return;
|
||||
}
|
||||
else
|
||||
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_S], rhs, def, NULL, STFL_PRESERVEA|STFL_PRESERVEB));
|
||||
}
|
||||
else if (def.cast->type == ev_entity)
|
||||
{
|
||||
rhs.cast = def.cast = type_entity;
|
||||
|
|
|
@ -3886,6 +3886,15 @@ pbool QCC_PR_CheckToken (const char *string)
|
|||
return true;
|
||||
}
|
||||
|
||||
pbool QCC_PR_PeekToken (const char *string)
|
||||
{
|
||||
if (pr_token_type != tt_punct)
|
||||
return false;
|
||||
if (STRCMP (string, pr_token))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
pbool QCC_PR_CheckImmediate (const char *string)
|
||||
{
|
||||
if (pr_token_type != tt_immediate)
|
||||
|
|
|
@ -1462,7 +1462,7 @@ pbool QCC_WriteData (int crc)
|
|||
}
|
||||
}
|
||||
*/
|
||||
if (!def->referenced)
|
||||
if (!def->symbolheader->used)
|
||||
{
|
||||
int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED;
|
||||
pr_scope = def->scope;
|
||||
|
@ -1504,7 +1504,7 @@ pbool QCC_WriteData (int crc)
|
|||
if (def->strip || !def->symbolheader->used)
|
||||
{
|
||||
#ifdef DEBUG_DUMP
|
||||
printf("code: %s:%i: strip %s %s@%i;\n", strings+def->s_file, def->s_line, def->type->name, def->name, def->ofs);
|
||||
printf("code: %s:%i: strip %s %s@%i;\n", def->filen, def->s_line, def->type->name, def->name, def->ofs);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
@ -1550,9 +1550,9 @@ pbool QCC_WriteData (int crc)
|
|||
|
||||
#ifdef DEBUG_DUMP
|
||||
if (def->scope)
|
||||
printf("code: %s:%i: strip local %s %s@%i;\n", strings+def->s_file, def->s_line, def->type->name, def->name, def->ofs);
|
||||
printf("code: %s:%i: strip local %s %s@%i;\n", def->filen, def->s_line, def->type->name, def->name, def->ofs);
|
||||
else if (def->constant)
|
||||
printf("code: %s:%i: strip const %s %s@%i;\n", strings+def->s_file, def->s_line, def->type->name, def->name, def->ofs);
|
||||
printf("code: %s:%i: strip const %s %s@%i;\n", def->filen, def->s_line, def->type->name, def->name, def->ofs);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
@ -1590,19 +1590,19 @@ pbool QCC_WriteData (int crc)
|
|||
|
||||
#ifdef DEBUG_DUMP
|
||||
if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_string)
|
||||
printf("code: %s:%i: %s%s%s %s@%i = \"%s\"\n", strings+def->s_file, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, ((unsigned)def->symboldata[def->ofs].string>=(unsigned)strofs)?"???":(strings + def->symboldata[def->ofs].string));
|
||||
printf("code: %s:%i: %s%s%s %s@%i = \"%s\"\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, ((unsigned)def->symboldata[def->ofs].string>=(unsigned)strofs)?"???":(strings + def->symboldata[def->ofs].string));
|
||||
else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_float)
|
||||
printf("code: %s:%i: %s%s%s %s@%i = %g\n", strings+def->s_file, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._float);
|
||||
printf("code: %s:%i: %s%s%s %s@%i = %g\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._float);
|
||||
else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_integer)
|
||||
printf("code: %s:%i: %s%s%s %s@%i = %i\n", strings+def->s_file, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._int);
|
||||
printf("code: %s:%i: %s%s%s %s@%i = %i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._int);
|
||||
else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_vector)
|
||||
printf("code: %s:%i: %s%s%s %s@%i = '%g %g %g'\n", strings+def->s_file, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs].vector[0], def->symboldata[def->ofs].vector[1], def->symboldata[def->ofs].vector[2]);
|
||||
printf("code: %s:%i: %s%s%s %s@%i = '%g %g %g'\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs].vector[0], def->symboldata[def->ofs].vector[1], def->symboldata[def->ofs].vector[2]);
|
||||
else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_function)
|
||||
printf("code: %s:%i: %s%s%s %s@%i = %i(%s)\n", strings+def->s_file, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs].function, def->symboldata[def->ofs].function >= numfunctions?"???":functions[def->symboldata[def->ofs].function].name);
|
||||
printf("code: %s:%i: %s%s%s %s@%i = %i(%s)\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs].function, def->symboldata[def->ofs].function >= numfunctions?"???":functions[def->symboldata[def->ofs].function].name);
|
||||
else if ((dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_field)
|
||||
printf("code: %s:%i: %s%s%s %s@%i = @%i\n", strings+def->s_file, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._int);
|
||||
printf("code: %s:%i: %s%s%s %s@%i = @%i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs, def->symboldata[def->ofs]._int);
|
||||
else
|
||||
printf("code: %s:%i: %s%s%s %s@%i\n", strings+def->s_file, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs);
|
||||
printf("code: %s:%i: %s%s%s %s@%i\n", def->filen, def->s_line, dd->type&DEF_SAVEGLOBAL?"save ":"nosave ", dd->type&DEF_SHARED?"shared ":"", basictypenames[dd->type&~(DEF_SHARED|DEF_SAVEGLOBAL)], strings+dd->s_name, dd->ofs);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -506,9 +506,18 @@ model_t *QDECL SVPR_GetCModel(world_t *w, int modelindex)
|
|||
{
|
||||
if ((unsigned int)modelindex < MAX_PRECACHE_MODELS)
|
||||
{
|
||||
model_t *mod;
|
||||
if (!sv.models[modelindex] && sv.strings.model_precache[modelindex])
|
||||
sv.models[modelindex] = Mod_ForName(Mod_FixName(sv.strings.model_precache[modelindex], sv.modelname), MLV_WARN);
|
||||
return sv.models[modelindex];
|
||||
mod = sv.models[modelindex];
|
||||
if (mod && mod->loadstate != MLS_LOADED)
|
||||
{
|
||||
if (mod->loadstate == MLS_LOADING)
|
||||
COM_WorkerPartialSync(mod, &mod->loadstate, MLS_LOADING);
|
||||
if (mod->loadstate != MLS_LOADED)
|
||||
mod = NULL; //gah, it failed!
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
@ -528,7 +537,7 @@ static void QDECL SVPR_Get_FrameState(world_t *w, wedict_t *ent, framestate_t *f
|
|||
|
||||
#if defined(SKELETALOBJECTS) || defined(RAGDOLL)
|
||||
if (ent->xv->skeletonindex)
|
||||
skel_lookup(w->progs, ent->xv->skeletonindex, fstate);
|
||||
skel_lookup(w, ent->xv->skeletonindex, fstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -10253,6 +10262,9 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
{"skel_delete", PF_skel_delete, 0, 0, 0, 275, D("void(float skel)", "Deletes a skeletal object. The actual delete is delayed, allowing the skeletal object to be deleted in an entity's predraw function yet still be valid by the time the addentity+renderscene builtins need it. Also uninstanciates any ragdoll currently in effect on the skeletal object.")}, // (FTE_CSQC_SKELETONOBJECTS)
|
||||
{"frameforname", PF_frameforname, 0, 0, 0, 276, D("float(float modidx, string framename)", "Looks up a framegroup from a model by name, avoiding the need for hardcoding. Returns -1 on error.")},// (FTE_CSQC_SKELETONOBJECTS)
|
||||
{"frameduration", PF_frameduration, 0, 0, 0, 277, D("float(float modidx, float framenum)", "Retrieves the duration (in seconds) of the specified framegroup.")},// (FTE_CSQC_SKELETONOBJECTS)
|
||||
{"processmodelevents",PF_processmodelevents,0, 0, 0, 0, D("void(float modidx, float framenum, __inout float basetime, float targettime, void(float timestamp, int code, string data) callback)", "Calls a callback for each event that has been reached. Basetime is set to targettime.")},
|
||||
{"getnextmodelevent",PF_getnextmodelevent,0, 0, 0, 0, D("float(float modidx, float framenum, __inout float basetime, float targettime, __out int code, __out string data)", "Reports the next event within a model's animation. Returns a boolean if an event was found between basetime and targettime. Writes to basetime,code,data arguments (if an event was found, basetime is set to the event's time, otherwise to targettime).\nWARNING: this builtin cannot deal with multiple events with the same timestamp (only the first will be reported).")},
|
||||
{"getmodeleventidx",PF_getmodeleventidx,0, 0, 0, 0, D("float(float modidx, float framenum, int eventidx, __out float timestamp, __out int code, __out string data)", "Reports an indexed event within a model's animation. Writes to timestamp,code,data arguments on success. Returns false if the animation/event/model was out of range/invalid. Does not consider looping animations (retry from index 0 if it fails and you know that its a looping animation). This builtin is more annoying to use than getnextmodelevent, but can be made to deal with multiple events with the exact same timestamp.")},
|
||||
|
||||
{"crossproduct", PF_crossproduct, 0, 0, 0, 0, D("#define dotproduct(v1,v2) ((vector)(v1)*(vector)(v2))\nvector(vector v1, vector v2)", "Small helper function to calculate the crossproduct of two vectors.")},
|
||||
|
||||
|
@ -10349,8 +10361,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
{"drawrotsubpic", PF_Fixme, 0, 0, 0, 0, D("void(vector pivot, vector mins, vector maxs, string pic, vector txmin, vector txsize, vector rgb, vector alphaandangles)", "Overcomplicated draw function for over complicated people. Positions follow drawrotpic, while texture coords follow drawsubpic. Due to argument count limitations in builtins, the alpha value and angles are combined into separate fields of a vector (tip: use fteqcc's [alpha, angle] feature.")},
|
||||
|
||||
//330
|
||||
{"getstati", PF_Fixme, 0, 0, 0, 330, D("float(float stnum)", "Retrieves the numerical value of the given EV_INTEGER or EV_ENTITY stat (converted to a float).")},// (EXT_CSQC)
|
||||
{"getstatf", PF_Fixme, 0, 0, 0, 331, D("#define getstatbits getstatf\nfloat(float stnum, optional float firstbit, optional float bitcount)", "Retrieves the numerical value of the given EV_FLOAT stat. If firstbit and bitcount are specified, retrieves the upper bits of the STAT_ITEMS stat.")},// (EXT_CSQC)
|
||||
{"getstati", PF_Fixme, 0, 0, 0, 330, D("#define getstati_punf(stnum) (float)(__variant)getstati(stnum)\nint(float stnum)", "Retrieves the numerical value of the given EV_INTEGER or EV_ENTITY stat (converted to a float).")},// (EXT_CSQC)
|
||||
{"getstatf", PF_Fixme, 0, 0, 0, 331, D("#define getstatbits getstatf\nfloat(float stnum, optional float firstbit, optional float bitcount)", "Retrieves the numerical value of the given EV_FLOAT stat. If firstbit and bitcount are specified, retrieves the upper bits of the STAT_ITEMS stat (converted into a float, so there are no VM dependancies).")},// (EXT_CSQC)
|
||||
{"getstats", PF_Fixme, 0, 0, 0, 332, D("string(float stnum)", "Retrieves the value of the given EV_STRING stat, as a tempstring.\nOlder engines may use 4 consecutive integer stats, with a limit of 15 chars (yes, really. 15.), but "FULLENGINENAME" uses a separate namespace for string stats and has a much higher length limit.")},
|
||||
{"getplayerstat", PF_Fixme, 0, 0, 0, 0, D("__variant(float playernum, float statnum, float stattype)", "Retrieves a specific player's stat, matching the type specified on the server. This builtin is primarily intended for mvd playback where ALL players are known. For EV_ENTITY, world will be returned if the entity is not in the pvs, use type-punning with EV_INTEGER to get the entity number if you just want to see if its set. STAT_ITEMS should be queried as an EV_INTEGER on account of runes and items2 being packed into the upper bits.")},
|
||||
|
||||
|
|
|
@ -421,10 +421,13 @@ typedef struct
|
|||
float animate;
|
||||
qboolean draw:1;
|
||||
qboolean orient:1;
|
||||
qboolean isoffset:1;
|
||||
int orientpeer;
|
||||
|
||||
//ode info
|
||||
int geomshape;
|
||||
float relmatrix[12];
|
||||
float inverserelmatrix[12];
|
||||
vec3_t dimensions;
|
||||
float mass;
|
||||
} rbebodyinfo_t;
|
||||
|
|
|
@ -3240,7 +3240,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
framestate_t fs;
|
||||
fs.skeltype = SKEL_IDENTITY;
|
||||
fs.bonecount = 0;
|
||||
skel_lookup(sv.world.progs, ent->xv->skeletonindex, &fs);
|
||||
skel_lookup(&sv.world, ent->xv->skeletonindex, &fs);
|
||||
if (fs.skeltype == SKEL_RELATIVE && fs.bonecount)
|
||||
{
|
||||
Bones_To_PosQuat4(fs.bonecount, fs.bonestate, AllocateBoneSpace(pack, state->bonecount = fs.bonecount, &state->boneoffset));
|
||||
|
|
|
@ -1135,6 +1135,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
|
|||
{
|
||||
//dpmaster support
|
||||
char response[MAX_UDP_PACKET];
|
||||
char protocolname[MAX_QPATH];
|
||||
|
||||
client_t *cl;
|
||||
int numclients = 0;
|
||||
|
@ -1164,6 +1165,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
|
|||
else
|
||||
gamestatus = "";
|
||||
|
||||
COM_ParseOut(com_protocolname.string, protocolname, sizeof(protocolname));
|
||||
|
||||
resp = response;
|
||||
|
||||
|
@ -1184,7 +1186,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
|
|||
//this is a DP protocol query, so some QW fields are not needed
|
||||
Info_RemoveKey(resp, "maxclients"); //replaced with sv_maxclients
|
||||
Info_RemoveKey(resp, "map"); //replaced with mapname
|
||||
Info_SetValueForKey(resp, "gamename", com_protocolname.string, sizeof(response) - (resp-response));
|
||||
Info_SetValueForKey(resp, "gamename", protocolname, sizeof(response) - (resp-response));
|
||||
Info_SetValueForKey(resp, "modname", FS_GetGamedir(true), sizeof(response) - (resp-response));
|
||||
// Info_SetValueForKey(resp, "gamedir", FS_GetGamedir(true), sizeof(response) - (resp-response));
|
||||
Info_SetValueForKey(resp, "protocol", va("%d", NQ_NETCHAN_VERSION), sizeof(response) - (resp-response));
|
||||
|
|
|
@ -65,7 +65,8 @@ qboolean World_CheckBottom (world_t *world, wedict_t *ent, vec3_t up)
|
|||
sign = (up[a2]>0)?1:-1;
|
||||
|
||||
VectorAdd (ent->v->origin, ent->v->mins, mins);
|
||||
if (world->worldmodel->fromgame == fg_quake)
|
||||
#ifdef Q1BSPS
|
||||
if (world->worldmodel->fromgame == fg_quake || world->worldmodel->fromgame == fg_halflife)
|
||||
{
|
||||
//quake's hulls are weird. sizes are defined as from mins to mins+hullsize. the actual maxs is ignored other than for its size.
|
||||
hull_t *hull;
|
||||
|
@ -75,6 +76,7 @@ qboolean World_CheckBottom (world_t *world, wedict_t *ent, vec3_t up)
|
|||
VectorAdd (maxs, hull->clip_maxs, maxs);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
VectorAdd (ent->v->origin, ent->v->maxs, maxs);
|
||||
|
||||
// if all of the points under the corners are solid world, don't bother
|
||||
|
|
|
@ -2404,6 +2404,7 @@ qboolean SV_Physics (void)
|
|||
int i;
|
||||
qboolean moved = false;
|
||||
int maxtics;
|
||||
double trueframetime = host_frametime;
|
||||
|
||||
//keep gravity tracking the cvar properly
|
||||
movevars.gravity = sv_gravity.value;
|
||||
|
@ -2425,6 +2426,7 @@ qboolean SV_Physics (void)
|
|||
if (host_frametime < sv_maxtic.value && realtime)
|
||||
{
|
||||
// sv.time+=host_frametime;
|
||||
host_frametime = trueframetime;
|
||||
return false; //don't bother with the whole server thing for a bit longer
|
||||
}
|
||||
if (host_frametime > sv_maxtic.value)
|
||||
|
@ -2446,6 +2448,7 @@ qboolean SV_Physics (void)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
host_frametime = trueframetime;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2581,6 +2584,7 @@ qboolean SV_Physics (void)
|
|||
|
||||
sv.world.physicstime += host_frametime;
|
||||
}
|
||||
host_frametime = trueframetime;
|
||||
return moved;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -254,15 +254,20 @@ static qboolean VK_CreateSwapChain(void)
|
|||
|
||||
vk.dopresent(NULL); //make sure they're all pushed through.
|
||||
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.gpu, vk.surface, &fmtcount, NULL));
|
||||
surffmts = malloc(sizeof(VkSurfaceFormatKHR)*fmtcount);
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.gpu, vk.surface, &fmtcount, surffmts));
|
||||
if (!vk.surface)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.gpu, vk.surface, &fmtcount, NULL));
|
||||
surffmts = malloc(sizeof(VkSurfaceFormatKHR)*fmtcount);
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceFormatsKHR(vk.gpu, vk.surface, &fmtcount, surffmts));
|
||||
|
||||
VkAssert(vkGetPhysicalDeviceSurfacePresentModesKHR(vk.gpu, vk.surface, &presentmodes, NULL));
|
||||
presentmode = malloc(sizeof(VkPresentModeKHR)*presentmodes);
|
||||
VkAssert(vkGetPhysicalDeviceSurfacePresentModesKHR(vk.gpu, vk.surface, &presentmodes, presentmode));
|
||||
VkAssert(vkGetPhysicalDeviceSurfacePresentModesKHR(vk.gpu, vk.surface, &presentmodes, NULL));
|
||||
presentmode = malloc(sizeof(VkPresentModeKHR)*presentmodes);
|
||||
VkAssert(vkGetPhysicalDeviceSurfacePresentModesKHR(vk.gpu, vk.surface, &presentmodes, presentmode));
|
||||
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk.gpu, vk.surface, &surfcaps);
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk.gpu, vk.surface, &surfcaps);
|
||||
}
|
||||
|
||||
swapinfo.surface = vk.surface;
|
||||
swapinfo.minImageCount = surfcaps.minImageCount+vk.triplebuffer;
|
||||
|
@ -2110,11 +2115,19 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
|
||||
if (vk.frame) //erk, we already have one...
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
RSpeedRemark();
|
||||
|
||||
VK_FencedCheck();
|
||||
|
||||
if (!vk.surface)
|
||||
{
|
||||
// if (Media_Capturing() != 2)
|
||||
// Cmd_ExecuteString("quit force\n", RESTRICT_LOCAL);
|
||||
return false; //headless...
|
||||
}
|
||||
|
||||
if (!vk.unusedframes)
|
||||
{
|
||||
struct vkframe *newframe = Z_Malloc(sizeof(*vk.frame));
|
||||
|
@ -2745,8 +2758,14 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
|
|||
const char *extensions[8];
|
||||
qboolean nvglsl = false;
|
||||
uint32_t extensions_count = 0;
|
||||
extensions[extensions_count++] = sysextname;
|
||||
extensions[extensions_count++] = VK_KHR_SURFACE_EXTENSION_NAME;
|
||||
qboolean headless = false;
|
||||
if (sysextname)
|
||||
{
|
||||
extensions[extensions_count++] = sysextname;
|
||||
extensions[extensions_count++] = VK_KHR_SURFACE_EXTENSION_NAME;
|
||||
}
|
||||
else
|
||||
headless = true;
|
||||
if (vk_debug.ival)
|
||||
extensions[extensions_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
|
||||
|
||||
|
@ -2877,18 +2896,21 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
|
|||
vkGetPhysicalDeviceProperties(devs[i], &props);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(devs[i], &queue_count, NULL);
|
||||
|
||||
for (j = 0; j < queue_count; j++)
|
||||
if (!headless)
|
||||
{
|
||||
VkBool32 supportsPresent;
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceSupportKHR(devs[i], j, vk.surface, &supportsPresent));
|
||||
if (supportsPresent)
|
||||
break; //okay, this one should be usable
|
||||
}
|
||||
if (j == queue_count)
|
||||
{
|
||||
//no queues can present to that surface, so I guess we can't use that device
|
||||
Con_DPrintf("vulkan: ignoring device %s as it can't present to window\n", props.deviceName);
|
||||
continue;
|
||||
for (j = 0; j < queue_count; j++)
|
||||
{
|
||||
VkBool32 supportsPresent = false;
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceSupportKHR(devs[i], j, vk.surface, &supportsPresent));
|
||||
if (supportsPresent)
|
||||
break; //okay, this one should be usable
|
||||
}
|
||||
if (j == queue_count)
|
||||
{
|
||||
//no queues can present to that surface, so I guess we can't use that device
|
||||
Con_DPrintf("vulkan: ignoring device %s as it can't present to window\n", props.deviceName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vk.gpu)
|
||||
|
@ -3022,8 +3044,11 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
|
|||
{
|
||||
for (i = 0; i < queue_count; i++)
|
||||
{
|
||||
VkBool32 supportsPresent;
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceSupportKHR(vk.gpu, i, vk.surface, &supportsPresent));
|
||||
VkBool32 supportsPresent = false;
|
||||
if (headless)
|
||||
supportsPresent = true; //won't be used anyway.
|
||||
else
|
||||
VkAssert(vkGetPhysicalDeviceSurfaceSupportKHR(vk.gpu, i, vk.surface, &supportsPresent));
|
||||
|
||||
if ((queueprops[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && supportsPresent)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue