diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 680aef1e1..f6324b080 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -1136,7 +1136,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con break; case CG_SETUSERCMDVALUE: //weaponselect, zoomsensitivity. ccs.selected_weapon = VM_LONG(arg[0]); - in_sensitivityscale = VM_FLOAT(arg[1]); + inputfuncs->SetSensitivityScale(VM_FLOAT(arg[1])); break; case CG_GETSERVERCOMMAND: @@ -1360,25 +1360,19 @@ qboolean CG_VideoRestarted(void) void CG_Start (void) { - SCR_SetLoadingStage(0); CG_Stop(); - SCR_BeginLoadingPlaque(); - box_model = worldfuncs->TempBoxModel(vec3_origin, vec3_origin); //just in case. + clientfuncs->SetLoadingState(true); cgvm = vmfuncs->Create("cgame", cvarfuncs->GetFloat("com_gamedirnativecode")?CG_SystemCallsNative:NULL, "vm/cgame", CG_SystemCallsVM); + clientfuncs->SetLoadingState(false); if (cgvm) { //hu... cgame doesn't appear to have a query version call! - SCR_EndLoadingPlaque(); - vmfuncs->Call(cgvm, CG_INIT, ccs.serverMessageNum, ccs.lastServerCommandNum, ccs.playernum); } else - { - SCR_EndLoadingPlaque(); plugfuncs->EndGame("Failed to initialise cgame module\n"); - } } qboolean CG_ConsoleCommand(void) diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index d0a7c3108..1ebd3378c 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -114,6 +114,10 @@ void QDECL Plug_Input_ClearKeyStates(void) { Key_ClearStates(); } +void QDECL Plug_Input_SetSensitivityScale(float scale) +{ + in_sensitivityscale = scale; +} unsigned int QDECL Plug_Input_GetMoveCount(void) { return cl.movesequence; @@ -205,13 +209,16 @@ static qhandle_t QDECL Plug_Draw_LoadImagePic(const char *name) { return Plug_Draw_LoadImage(name, 0, NULL); } - static shader_t *Plug_Draw_ShaderFromId(qhandle_t id) { if (--id >= r_numshaders) return NULL; return r_shaders[id]; } +static void Plug_Draw_UnloadImage(qhandle_t id) +{ + R_UnloadShader(Plug_Draw_ShaderFromId(id)); +} static int QDECL Plug_Draw_ImageSize(qhandle_t image, float *w, float *h) { @@ -367,6 +374,14 @@ static void QDECL Plug_Draw_RedrawScreen(void) SCR_UpdateScreen(); } +static void QDECL Plug_Media_SetState(cin_t *cin, int state) +{ + Media_SetState(cin, state); +} +static int QDECL Plug_Media_GetState(cin_t *cin) +{ + return Media_GetState(cin); +} static qhandle_t Plug_Scene_ModelToId(model_t *mod) { @@ -523,6 +538,13 @@ static void QDECL Plug_LocalSound(const char *soundname, int channel, float volu } +static void QDECL Plug_CL_SetLoadscreenState(qboolean state) +{ + if (state) + SCR_BeginLoadingPlaque(); + else + SCR_EndLoadingPlaque(); +} static int QDECL Plug_CL_GetStats(int pnum, unsigned int *stats, int maxstats) { diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index d0748e6d5..e1b362ac0 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -665,7 +665,7 @@ int UI_Cin_Play(const char *name, int x, int y, int w, int h, unsigned int flags { int idx; qhandle_t mediashader; - //cin_t *cin; + cin_t *cin; for (idx = 0; ; idx++) { if (idx == countof(uicinematics)) @@ -675,13 +675,20 @@ int UI_Cin_Play(const char *name, int x, int y, int w, int h, unsigned int flags break; //this slot is usable } - /*mediashader = R_RegisterCustom(name, SUF_NONE, Shader_DefaultCinematic, va("video/%s", name)); + mediashader = drawfuncs->LoadImageShader(name, va( + "{\n" + "program default2d\n" + "{\n" + "videomap \"video/%s\"\n" + "blendfunc gl_one gl_one_minus_src_alpha\n" + "}\n" + "}\n", name)); if (!mediashader) return -1; //wtf? - cin = R_ShaderGetCinematic(mediashader); + cin = drawfuncs->media.GetCinematic(drawfuncs->ShaderFromId(mediashader)); if (cin) - Media_SetState(cin, CINSTATE_PLAY); - else*/ + drawfuncs->media.SetState(cin, CINSTATE_PLAY); + else return -1; //FAIL! uicinematics[idx].x = x; @@ -719,22 +726,22 @@ int UI_Cin_Run(int idx) if (idx >= 0 && idx < countof(uicinematics)) { shader_t *shader = drawfuncs->ShaderFromId(uicinematics[idx].shaderhandle); - cin_t *cin = R_ShaderGetCinematic(shader); + cin_t *cin = drawfuncs->media.GetCinematic(shader); if (cin) { - switch(Media_GetState(cin)) + switch((cinstates_t)drawfuncs->media.GetState(cin)) { case CINSTATE_INVALID: ret = FMV_IDLE; break; case CINSTATE_PLAY: ret = FMV_PLAY; break; case CINSTATE_LOOP: ret = FMV_PLAY; break; case CINSTATE_PAUSE: ret = FMV_PLAY; break; case CINSTATE_ENDED: - Media_SetState(cin, CINSTATE_FLUSHED); + drawfuncs->media.SetState(cin, CINSTATE_FLUSHED); ret = FMV_EOF; break; case CINSTATE_FLUSHED: //FIXME: roq decoder has no reset method! - Media_Send_Reset(cin); + drawfuncs->media.Reset(cin); ret = FMV_LOOPED; break; } diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index b55f31483..fd7079d2f 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -9,33 +9,18 @@ #ifndef STATIC_Q3 void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats){} //locks/unlocks cheat cvars depending on weather we are allowed them. -//int Cvar_ApplyLatches(int latchflag){return 0;} -unsigned int utf8_decode(int *error, const void *in, char const**out){return 0;} - -void Con_PrintFlags(const char *txt, unsigned int setflags, unsigned int clearflags){} void Con_ClearNotify (void){} unsigned int key_dest_mask; -float in_sensitivityscale; void Sys_Clipboard_PasteText(clipboardtype_t clipboardtype, void (*callback)(void *cb, const char *utf8), void *ctx){}; //calls the callback once the text is available (maybe instantly). utf8 arg may be NULL if the clipboard was unavailable. -void SCR_SetLoadingStage(int stage){} -void SCR_BeginLoadingPlaque (void){} -void SCR_EndLoadingPlaque (void){} +unsigned int utf8_decode(int *error, const void *in, char const**out){return 0;} -void Shader_DefaultCinematic (struct shaderparsestate_s *ps, const char *shortname, const void *args){} -shader_t *R_RegisterCustom (model_t *mod, const char *name, unsigned int usageflags, shader_gen_t *defaultgen, const void *args){return NULL;} -cin_t *R_ShaderGetCinematic(shader_t *s){return NULL;} -void Media_SetState(cin_t *cin, cinstates_t newstate){} -void R_UnloadShader(shader_t *shader){} -cinstates_t Media_GetState(cin_t *cin){return 0;} -void Media_Send_Reset(cin_t *cin){} char *CL_TryingToConnect(void){return NULL;} downloadlist_t *CL_DownloadFailed(const char *name, qdownload_t *qdl, enum dlfailreason_e failreason){return NULL;} qboolean DL_Begun(qdownload_t *dl){return 0;} void CL_DownloadFinished(qdownload_t *dl){} -int Sys_EnumerateFiles (const char *gpath, const char *match, int (QDECL *func)(const char *fname, qofs_t fsize, time_t modtime, void *parm, searchpathfuncs_t *spath), void *parm, searchpathfuncs_t *spath){return 0;} #endif //urm, yeah, this is more than just parse. @@ -632,7 +617,7 @@ void CLQ3_ParseGameState(sizebuf_t *msg) if (!ccs.worldmodel) plugfuncs->EndGame("CGame didn't set a map.\n"); - SCR_EndLoadingPlaque(); + clientfuncs->SetLoadingState(false); ccs.state = ca_active; diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 3749c2dae..2144e3154 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -2752,7 +2752,7 @@ texid_tf Media_UpdateForShader(cin_t *cin) } #endif -void Media_Send_KeyEvent(cin_t *cin, int button, int unicode, int event) +void QDECL Media_Send_KeyEvent(cin_t *cin, int button, int unicode, int event) { if (!cin) cin = R_ShaderGetCinematic(videoshader); @@ -2776,7 +2776,7 @@ void Media_Send_KeyEvent(cin_t *cin, int button, int unicode, int event) else if ((button == K_RIGHTARROW || button == K_KP_RIGHTARROW || button == K_GP_DPAD_RIGHT) && !event) cin->filmstarttime -= (cin->playstate == CINSTATE_PAUSE)?-10:10; } -void Media_Send_MouseMove(cin_t *cin, float x, float y) +void QDECL Media_Send_MouseMove(cin_t *cin, float x, float y) { if (!cin) cin = R_ShaderGetCinematic(videoshader); @@ -2784,7 +2784,7 @@ void Media_Send_MouseMove(cin_t *cin, float x, float y) return; cin->cursormove(cin, x, y); } -void Media_Send_Resize(cin_t *cin, int x, int y) +void QDECL Media_Send_Resize(cin_t *cin, int x, int y) { if (!cin) cin = R_ShaderGetCinematic(videoshader); @@ -2792,7 +2792,7 @@ void Media_Send_Resize(cin_t *cin, int x, int y) return; cin->setsize(cin, x, y); } -void Media_Send_GetSize(cin_t *cin, int *x, int *y, float *aspect) +void QDECL Media_Send_GetSize(cin_t *cin, int *x, int *y, float *aspect) { *x = 0; *y = 0; @@ -2803,7 +2803,7 @@ void Media_Send_GetSize(cin_t *cin, int *x, int *y, float *aspect) return; cin->getsize(cin, x, y, aspect); } -void Media_Send_Reset(cin_t *cin) +void QDECL Media_Send_Reset(cin_t *cin) { if (!cin) return; @@ -2814,7 +2814,7 @@ void Media_Send_Reset(cin_t *cin) if (cin->rewind) cin->rewind(cin); } -void Media_Send_Command(cin_t *cin, const char *command) +void QDECL Media_Send_Command(cin_t *cin, const char *command) { if (!cin) cin = R_ShaderGetCinematic(videoshader); @@ -2823,7 +2823,7 @@ void Media_Send_Command(cin_t *cin, const char *command) else if (cin && !strcmp(command, "cmd:rewind")) Media_Send_Reset(cin); } -const char *Media_Send_GetProperty(cin_t *cin, const char *key) +const char *QDECL Media_Send_GetProperty(cin_t *cin, const char *key) { if (!cin) cin = R_ShaderGetCinematic(videoshader); diff --git a/engine/common/fs.c b/engine/common/fs.c index 4a0f062af..6e6cdd52e 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -6367,7 +6367,11 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL); vidrestart = false; } + + if (Cmd_Exists("ui_restart")) //if we're running a q3 ui, restart it now... + Cbuf_InsertText("ui_restart\n", RESTRICT_LOCAL, false); #endif + if (fs_loadedcommand) { Cbuf_AddText(fs_loadedcommand, RESTRICT_INSECURE); diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 38b4e84fe..764a520d3 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -1156,6 +1156,28 @@ static void QDECL Plug_Net_Close(qhandle_t handle) Plug_Net_Close_Internal(handle); } +void QDECL Plug_FS_EnumerateFiles(enum fs_relative fsroot, const char *match, int (QDECL *callback)(const char *fname, qofs_t fsize, time_t mtime, void *ctx, struct searchpathfuncs_s *package), void *ctx) +{ + if (fsroot == FS_GAME) + COM_EnumerateFiles(match, callback, ctx); + else + { + char base[MAX_OSPATH]; + if (fsroot == FS_ROOT) + { + extern qboolean com_homepathenabled; + if (com_homepathenabled) + Sys_EnumerateFiles(com_homepath, match, callback, ctx, NULL); + Sys_EnumerateFiles(com_gamepath, match, callback, ctx, NULL); + } + else + { + FS_NativePath("", fsroot, base, sizeof(base)); + Sys_EnumerateFiles(base, match, callback, ctx, NULL); + } + } +} + #if defined(HAVE_SERVER) && defined(HAVE_CLIENT) static qboolean QDECL Plug_MapLog_Query(const char *packagename, const char *mapname, float *vals) { @@ -1887,7 +1909,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s FS_Rename, FS_Remove, - COM_EnumerateFiles, + Plug_FS_EnumerateFiles, wildcmp, COM_GetFileExtension, @@ -2007,7 +2029,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s Plug_Draw_LoadImageShader, Plug_Draw_LoadImagePic, Plug_Draw_ShaderFromId, - NULL,//Plug_Draw_UnloadImage, + Plug_Draw_UnloadImage, Plug_Draw_Image, Plug_Draw_Image2dQuad, Plug_Draw_ImageSize, @@ -2024,6 +2046,19 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s Plug_Draw_RedrawScreen, Plug_LocalSound, + + { + R_ShaderGetCinematic, + Plug_Media_SetState, + Plug_Media_GetState, + Media_Send_Reset, + Media_Send_Command, + Media_Send_GetProperty, + Media_Send_MouseMove, + Media_Send_Resize, + Media_Send_GetSize, + Media_Send_KeyEvent, + }, }; if (structsize == sizeof(funcs)) return &funcs; @@ -2086,6 +2121,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s #endif Plug_CL_ClearState, + Plug_CL_SetLoadscreenState, Plug_CL_UpdateGameTime, }; if (structsize == sizeof(funcs)) @@ -2110,6 +2146,7 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s Plug_Input_IsKeyDown, Plug_Input_ClearKeyStates, + Plug_Input_SetSensitivityScale, Plug_Input_GetMoveCount, Plug_Input_GetMoveEntry, diff --git a/engine/common/q3common.c b/engine/common/q3common.c index 2d6d37080..56d01c4ba 100644 --- a/engine/common/q3common.c +++ b/engine/common/q3common.c @@ -206,7 +206,6 @@ void VM_fcloseall (int owner) typedef struct { char *initialbuffer; char *buffer; - char *dir; int found; int bufferleft; int skip; @@ -243,6 +242,8 @@ static int QDECL IfFound(const char *match, qofs_t size, time_t modtime, void *a static int QDECL VMEnumMods(const char *match, qofs_t size, time_t modtime, void *args, searchpathfuncs_t *spath) { + const int continuesearch = true; + const int abortsearch = false; char *check; char desc[1024]; int newlen; @@ -253,19 +254,19 @@ static int QDECL VMEnumMods(const char *match, qofs_t size, time_t modtime, void newlen = strlen(match)+1; if (newlen <= 2) - return true; + return continuesearch; //make sure match is a directory if (match[newlen-2] != '/') - return true; + return continuesearch; if (!Q_strcasecmp(match, "baseq3/")) - return true; //we don't want baseq3. FIXME: should be any basedir, rather than hardcoded. + return continuesearch; //we don't want baseq3. FIXME: should be any basedir, rather than hardcoded. foundone = false; - Sys_EnumerateFiles(va("%s%s/", ((vmsearch_t *)args)->dir, match), "*.pk3", IfFound, &foundone, spath); + fsfuncs->EnumerateFiles(FS_ROOT, va("%s/*.pk3", match), IfFound, &foundone); if (foundone == false) - return true; //we only count directories with a pk3 file + return continuesearch; //we only count directories with a pk3 file Q_strncpyz(desc, match, sizeof(desc)); f = fsfuncs->OpenVFS(va("%sdescription.txt", match), "rb", FS_ROOT); @@ -286,13 +287,13 @@ static int QDECL VMEnumMods(const char *match, qofs_t size, time_t modtime, void desclen = strlen(desc)+1; if (newlen+desclen+5 > ((vmsearch_t *)args)->bufferleft) - return false; //too many files for the buffer + return abortsearch; //too many files for the buffer check = ((vmsearch_t *)args)->initialbuffer; while(check < ((vmsearch_t *)args)->buffer) { if (!Q_strcasecmp(check, match)) - return true; //we found this one already + return continuesearch; //we found this one already check += strlen(check)+1; check += strlen(check)+1; } @@ -308,7 +309,7 @@ static int QDECL VMEnumMods(const char *match, qofs_t size, time_t modtime, void ((vmsearch_t *)args)->bufferleft-=desclen; ((vmsearch_t *)args)->found++; - return true; + return continuesearch; } int VM_GetFileList(const char *path, const char *ext, char *output, int buffersize) @@ -320,18 +321,13 @@ int VM_GetFileList(const char *path, const char *ext, char *output, int buffersi vms.found=0; if (!strcmp(path, "$modlist")) { - cvar_t *fs_basedir = cvarfuncs->GetNVFDG("fs_basedir", NULL, 0, NULL, NULL); - cvar_t *fs_homedir = cvarfuncs->GetNVFDG("fs_homedir", NULL, 0, NULL, NULL); vms.skip=0; - if (fs_basedir && *fs_basedir->string) - Sys_EnumerateFiles((vms.dir=fs_basedir->string), "*", VMEnumMods, &vms, NULL); - if (fs_homedir && *fs_homedir->string) - Sys_EnumerateFiles((vms.dir=fs_homedir->string), "*", VMEnumMods, &vms, NULL); + fsfuncs->EnumerateFiles(FS_ROOT, "*", VMEnumMods, &vms); } else if (*(char *)ext == '.' || *(char *)ext == '/') - fsfuncs->EnumerateFiles(va("%s/*%s", path, ext), VMEnum, &vms); + fsfuncs->EnumerateFiles(FS_GAME, va("%s/*%s", path, ext), VMEnum, &vms); else - fsfuncs->EnumerateFiles(va("%s/*.%s", path, ext), VMEnum, &vms); + fsfuncs->EnumerateFiles(FS_GAME, va("%s/*.%s", path, ext), VMEnum, &vms); return vms.found; } diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 69df68289..4a8b63539 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -8186,7 +8186,7 @@ void Shader_NeedReload(qboolean rescanfs) shader_reload_needed = true; } -cin_t *R_ShaderGetCinematic(shader_t *s) +cin_t *QDECL R_ShaderGetCinematic(shader_t *s) { #ifdef HAVE_MEDIA_DECODER int j; diff --git a/plugins/openxr.c b/plugins/openxr.c index 71a7ba563..76fa05b93 100644 --- a/plugins/openxr.c +++ b/plugins/openxr.c @@ -1335,7 +1335,7 @@ static void XR_SetupInputs_Instance(void) h = 0; if (fsfuncs) - fsfuncs->EnumerateFiles("oxr_*.binds", XR_BindProfileFile, &h); + fsfuncs->EnumerateFiles(FS_GAME, "oxr_*.binds", XR_BindProfileFile, &h); if (!h) //no user bindings defined, use fallbacks. probably this needs to be per-mod. { for (h = 0; h < countof(xr_knownprofiles); h++) diff --git a/plugins/plugin.h b/plugins/plugin.h index 95daedb41..fbf2deac2 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -311,6 +311,7 @@ typedef struct //q1 client/network info F(void, GetPredInfo, (int seat, vec3_t outvel)); F(void, ClearClientState, (void)); //called at the start of map changes. + F(void, SetLoadingState, (qboolean newstate)); //Change the client's loading screen state. F(void, UpdateGameTime, (double)); //tells the client an updated snapshot time for interpolation/timedrift. #define plugclientfuncs_name "Client" } plugclientfuncs_t; @@ -334,6 +335,7 @@ typedef struct //for menu-like stuff F(qboolean, IsKeyDown, (int keycode)); F(void, ClearKeyStates, (void)); //forget any keys that are still held. + F(void, SetSensitivityScale,(float newsensitivityscale)); //this is a temporary sensitivity thing. F(unsigned int, GetMoveCount, (void)); F(usercmd_t*, GetMoveEntry, (unsigned int move)); //GetMoveEntry(GetMoveCount()) gives you the partial entry. forgotten entries return NULL. @@ -405,6 +407,23 @@ typedef struct //for huds and menus alike F(void, RedrawScreen, (void)); //redraws the entire screen and presents it. for loading screen type things. F(void, LocalSound, (const char *soundname, int channel, float volume)); + + struct + { + //basic media poking + F(struct cin_s *, GetCinematic, (struct shader_s *s)); + F(void, SetState, (struct cin_s *cin, int newstate)); + F(int, GetState, (struct cin_s *cin)); + F(void, Reset, (struct cin_s *cin)); + + //complex media poking (web browser stuff) + F(void, Command, (struct cin_s *cin, const char *command)); + F(const char *, GetProperty, (struct cin_s *cin, const char *key)); + F(void, MouseMove, (struct cin_s *cin, float x, float y)); + F(void, Resize, (struct cin_s *cin, int x, int y)); + F(void, GetSize, (struct cin_s *cin, int *x, int *y, float *aspect)); + F(void, KeyEvent, (struct cin_s *cin, int button, int unicode, int event)); + } media; #define plug2dfuncs_name "2D" } plug2dfuncs_t; @@ -507,7 +526,7 @@ typedef struct //for plugins that need to read/write files... F(qboolean, Rename, (const char *oldf, const char *newf, enum fs_relative relativeto)); F(qboolean, Remove, (const char *fname, enum fs_relative relativeto)); - F(void, EnumerateFiles, (const char *match, int (QDECL *callback)(const char *fname, qofs_t fsize, time_t mtime, void *ctx, struct searchpathfuncs_s *package), void *ctx)); + F(void, EnumerateFiles, (enum fs_relative fsroot, const char *match, int (QDECL *callback)(const char *fname, qofs_t fsize, time_t mtime, void *ctx, struct searchpathfuncs_s *package), void *ctx)); //helpers F(int, WildCmp, (const char *wild, const char *string));