diff --git a/Assets/Scripts/CallbackHandler.cs b/Assets/Scripts/CallbackHandler.cs index 14cc8a5..322d82f 100644 --- a/Assets/Scripts/CallbackHandler.cs +++ b/Assets/Scripts/CallbackHandler.cs @@ -8,9 +8,9 @@ public abstract class CallbackHandler private GCHandle selfHandle; private GCHandle callbacksHandle; - public IntPtr CallbacksPtr => callbacksHandle.AddrOfPinnedObject(); + public IntPtr ContextPtr => GCHandle.ToIntPtr(selfHandle); - protected IntPtr TargetPtr => GCHandle.ToIntPtr(selfHandle); + public IntPtr CallbacksPtr => callbacksHandle.AddrOfPinnedObject(); protected CallbackHandler() { diff --git a/Assets/Scripts/Modules/GameModule.Interop.cs b/Assets/Scripts/Modules/GameModule.Interop.cs index b74731f..9cfc4ea 100644 --- a/Assets/Scripts/Modules/GameModule.Interop.cs +++ b/Assets/Scripts/Modules/GameModule.Interop.cs @@ -12,8 +12,6 @@ public partial class GameModule : CallbackHandler { var callbacks = new Callbacks { - target = TargetPtr, - SetEntityModel = CreateCallback(Callback_GameSetEntityModel), SetEntityTransform = CreateCallback(Callback_GameSetEntityTransform), RemoveEntity = CreateCallback(Callback_GameRemoveEntity), @@ -30,8 +28,6 @@ public partial class GameModule : CallbackHandler [StructLayout(LayoutKind.Sequential, Pack = 0)] private class Callbacks { - public IntPtr target; - public IntPtr SetEntityModel; public IntPtr SetEntityTransform; public IntPtr RemoveEntity; diff --git a/Assets/Scripts/Modules/RenderModule.Interop.cs b/Assets/Scripts/Modules/RenderModule.Interop.cs index 10e61d6..d403939 100644 --- a/Assets/Scripts/Modules/RenderModule.Interop.cs +++ b/Assets/Scripts/Modules/RenderModule.Interop.cs @@ -12,8 +12,6 @@ public partial class RenderModule: CallbackHandler { var callbacks = new Callbacks { - target = TargetPtr, - UploadAliasModel = CreateCallback(Callback_UploadAliasModel), UploadBrushModel = CreateCallback(Callback_UploadBrushModel), UploadWorldModel = CreateCallback(Callback_UploadWorldModel), @@ -32,8 +30,6 @@ public partial class RenderModule: CallbackHandler [StructLayout(LayoutKind.Sequential, Pack = 0)] private class Callbacks { - public IntPtr target; - public IntPtr UploadAliasModel; public IntPtr UploadBrushModel; public IntPtr UploadWorldModel; diff --git a/Assets/Scripts/Modules/SystemModule.Interop.cs b/Assets/Scripts/Modules/SystemModule.Interop.cs index a899ff1..d13bec2 100644 --- a/Assets/Scripts/Modules/SystemModule.Interop.cs +++ b/Assets/Scripts/Modules/SystemModule.Interop.cs @@ -8,8 +8,6 @@ public partial class SystemModule: CallbackHandler { var callbacks = new Callbacks { - target = TargetPtr, - SysPrint = CreateCallback(Callback_SysPrint), SysError = CreateCallback(Callback_SysError), SysQuit = CreateCallback(Callback_SysQuit), @@ -34,8 +32,6 @@ public partial class SystemModule: CallbackHandler [StructLayout(LayoutKind.Sequential, Pack = 0)] private class Callbacks { - public IntPtr target; - public IntPtr SysPrint; public IntPtr SysError; public IntPtr SysQuit; diff --git a/Assets/Scripts/UniQuake.Interop.cs b/Assets/Scripts/UniQuake.Interop.cs index fe3ec1f..5dc79da 100644 --- a/Assets/Scripts/UniQuake.Interop.cs +++ b/Assets/Scripts/UniQuake.Interop.cs @@ -18,7 +18,7 @@ public partial class UniQuake private IntPtr libraryHandle; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void UniQuake_InitFunc(IntPtr parms, IntPtr sysCalls, IntPtr glCalls, IntPtr gameCalls); + private delegate void UniQuake_InitFunc(IntPtr parms); private UniQuake_InitFunc UniQuake_Init; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -33,6 +33,12 @@ public partial class UniQuake private delegate void UniQuake_SetFmodSystemFunc(IntPtr fmodSystem, int playerNumber = 0); private UniQuake_SetFmodSystemFunc UniQuake_SetFmodSystem; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void UniQuake_SetCallbacksFunc(IntPtr context, IntPtr callbacks); + private UniQuake_SetCallbacksFunc UniQuake_SetSysCallbacks; + private UniQuake_SetCallbacksFunc UniQuake_SetRenderCallbacks; + private UniQuake_SetCallbacksFunc UniQuake_SetGameCallbacks; + private void LoadLibrary() { string dllFile = Path.Combine(Application.dataPath, DllPath); @@ -51,10 +57,13 @@ public partial class UniQuake throw new DllNotFoundException($"Failed to load UniQuake library from path: {dllFile}, last error = {Marshal.GetLastWin32Error()}"); } - UniQuake_Init = LoadLibraryFunction("UniQuake_Init"); - UniQuake_Update = LoadLibraryFunction("UniQuake_Update"); - UniQuake_Shutdown = LoadLibraryFunction("UniQuake_Shutdown"); - UniQuake_SetFmodSystem = LoadLibraryFunction("UniQuake_SetFmodSystem"); + UniQuake_Init = LoadLibraryFunction(nameof(UniQuake_Init)); + UniQuake_Update = LoadLibraryFunction(nameof(UniQuake_Update)); + UniQuake_Shutdown = LoadLibraryFunction(nameof(UniQuake_Shutdown)); + UniQuake_SetFmodSystem = LoadLibraryFunction(nameof(UniQuake_SetFmodSystem)); + UniQuake_SetSysCallbacks = LoadLibraryFunction(nameof(UniQuake_SetSysCallbacks)); + UniQuake_SetRenderCallbacks = LoadLibraryFunction(nameof(UniQuake_SetRenderCallbacks)); + UniQuake_SetGameCallbacks = LoadLibraryFunction(nameof(UniQuake_SetGameCallbacks)); } private TDelegate LoadLibraryFunction(string functionName) diff --git a/Assets/Scripts/UniQuake.cs b/Assets/Scripts/UniQuake.cs index 7e34167..f7cd791 100644 --- a/Assets/Scripts/UniQuake.cs +++ b/Assets/Scripts/UniQuake.cs @@ -102,8 +102,11 @@ public partial class UniQuake: MonoBehaviour try { UniQuake_SetFmodSystem(AudioManager.Instance.FmodSystem.handle); - UniQuake_Init(quakeParms.ToNativePtr(), - systemModule.CallbacksPtr, renderModule.CallbacksPtr, gameModule.CallbacksPtr); + UniQuake_SetSysCallbacks(systemModule.ContextPtr, systemModule.CallbacksPtr); + UniQuake_SetRenderCallbacks(renderModule.ContextPtr, renderModule.CallbacksPtr); + UniQuake_SetGameCallbacks(gameModule.ContextPtr, gameModule.CallbacksPtr); + + UniQuake_Init(quakeParms.ToNativePtr()); initialized = true; } diff --git a/engine/UniQuake/game_uniquake.c b/engine/UniQuake/game_uniquake.c index 0f057f9..f7aa738 100644 --- a/engine/UniQuake/game_uniquake.c +++ b/engine/UniQuake/game_uniquake.c @@ -4,38 +4,43 @@ typedef struct unity_gamecalls_s { - void *target; - - void(*SetEntityModel)(void *target, int entityNum, const char *modelName); - void(*SetEntityTransform)(void *target, int entityNum, vec3_t origin, vec3_t angles); - void(*RemoveEntity)(void *target, int entityNum); - void(*UpdateEntityAnimation)(void *target, int entityNum, int pose1, int pose2, float blend); - void(*SetEntitySkin)(void *target, int entityNum, int skinNum); + void(*SetEntityModel)(void *context, int entityNum, const char *modelName); + void(*SetEntityTransform)(void *context, int entityNum, vec3_t origin, vec3_t angles); + void(*RemoveEntity)(void *context, int entityNum); + void(*UpdateEntityAnimation)(void *context, int entityNum, int pose1, int pose2, float blend); + void(*SetEntitySkin)(void *context, int entityNum, int skinNum); } unity_gamecalls_t; -const unity_gamecalls_t *unity_gamecalls; +static void *unity_context; +static const unity_gamecalls_t *unity_gamecalls; + +UNIQUAKE_API void UniQuake_SetGameCallbacks(void *context, const unity_gamecalls_t *callbacks) +{ + unity_context = context; + unity_gamecalls = callbacks; +} void UQ_Game_SetEntityModel(int entityNum, const char *modelName) { - unity_gamecalls->SetEntityModel(unity_gamecalls->target, entityNum, modelName); + unity_gamecalls->SetEntityModel(unity_context, entityNum, modelName); } void UQ_Game_SetEntityTransform(int entityNum, vec3_t origin, vec3_t angles) { - unity_gamecalls->SetEntityTransform(unity_gamecalls->target, entityNum, origin, angles); + unity_gamecalls->SetEntityTransform(unity_context, entityNum, origin, angles); } void UQ_Game_RemoveEntity(int entityNum) { - unity_gamecalls->RemoveEntity(unity_gamecalls->target, entityNum); + unity_gamecalls->RemoveEntity(unity_context, entityNum); } void UQ_Game_UpdateEntityAnimation(int entityNum, int pose1, int pose2, float blend) { - unity_gamecalls->UpdateEntityAnimation(unity_gamecalls->target, entityNum, pose1, pose2, blend); + unity_gamecalls->UpdateEntityAnimation(unity_context, entityNum, pose1, pose2, blend); } void UQ_Game_SetEntitySkin(int entityNum, int skinNum) { - unity_gamecalls->SetEntitySkin(unity_gamecalls->target, entityNum, skinNum); + unity_gamecalls->SetEntitySkin(unity_context, entityNum, skinNum); } diff --git a/engine/UniQuake/gl_uniquake.c b/engine/UniQuake/gl_uniquake.c index ddea92e..e777104 100644 --- a/engine/UniQuake/gl_uniquake.c +++ b/engine/UniQuake/gl_uniquake.c @@ -5,47 +5,52 @@ typedef struct unity_glcalls_s { - void *target; - - int(*UploadAliasModel)(void *target, const char *name, aliashdr_t *aliashdr, aliasframetype_t frametype, maliasframedesc_t *frames, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts); - int(*UploadBrushModel)(void *target, qmodel_t *model); - int(*UploadWorldModel)(void *target, qmodel_t *model); - qboolean(*UploadTexture)(void *target, gltexture_t *texture, unsigned *data, GLuint *texnum); - qboolean(*UploadLightmap)(void *target, int lmap, byte *data); - void(*SetupView)(void *target, vec3_t origin, vec3_t angles, mleaf_t *viewLeaf); + int(*UploadAliasModel)(void *context, const char *name, aliashdr_t *aliashdr, aliasframetype_t frametype, maliasframedesc_t *frames, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts); + int(*UploadBrushModel)(void *context, qmodel_t *model); + int(*UploadWorldModel)(void *context, qmodel_t *model); + qboolean(*UploadTexture)(void *context, gltexture_t *texture, unsigned *data, GLuint *texnum); + qboolean(*UploadLightmap)(void *context, int lmap, byte *data); + void(*SetupView)(void *context, vec3_t origin, vec3_t angles, mleaf_t *viewLeaf); } unity_glcalls_t; -const unity_glcalls_t *unity_glcalls; +static void *unity_context; +static const unity_glcalls_t *unity_glcalls; + +UNIQUAKE_API void UniQuake_SetRenderCallbacks(void *context, const unity_glcalls_t *callbacks) +{ + unity_context = context; + unity_glcalls = callbacks; +} int UQ_GL_UploadAliasModel(qmodel_t *model, aliashdr_t *aliashdr, aliasframetype_t frametype, trivertx_t **poseVerts, mtriangle_t *triangles, stvert_t *stVerts) { // C# doesn't really understand this idea of a variable-length embedded array of structs, // so we pass along the pointer to the first frame struct which allows us to manually marshal the entire array. - return unity_glcalls->UploadAliasModel(unity_glcalls->target, model->name, aliashdr, frametype, &aliashdr->frames[0], poseVerts, triangles, stVerts); + return unity_glcalls->UploadAliasModel(unity_context, model->name, aliashdr, frametype, &aliashdr->frames[0], poseVerts, triangles, stVerts); } int UQ_GL_UploadBrushModel(qmodel_t *model) { - return unity_glcalls->UploadBrushModel(unity_glcalls->target, model); + return unity_glcalls->UploadBrushModel(unity_context, model); } int UQ_GL_UploadWorldModel(qmodel_t *model) { - return unity_glcalls->UploadWorldModel(unity_glcalls->target, model); + return unity_glcalls->UploadWorldModel(unity_context, model); } qboolean UQ_GL_UploadTexture(gltexture_t *texture, unsigned *data) { // Allow UniQuake to either sync up its internal texture reference number, or assign a new one. - return unity_glcalls->UploadTexture(unity_glcalls->target, texture, data, &texture->texnum); + return unity_glcalls->UploadTexture(unity_context, texture, data, &texture->texnum); } qboolean UQ_GL_UploadLightmap(int lmap, byte *data) { - return unity_glcalls->UploadLightmap(unity_glcalls->target, lmap, data); + return unity_glcalls->UploadLightmap(unity_context, lmap, data); } void UQ_GL_SetupView(vec3_t origin, vec3_t angles, mleaf_t *viewLeaf) { - unity_glcalls->SetupView(unity_glcalls->target, origin, angles, viewLeaf); + unity_glcalls->SetupView(unity_context, origin, angles, viewLeaf); } diff --git a/engine/UniQuake/sys_uniquake.c b/engine/UniQuake/sys_uniquake.c index ce55f0f..119987f 100644 --- a/engine/UniQuake/sys_uniquake.c +++ b/engine/UniQuake/sys_uniquake.c @@ -8,24 +8,29 @@ cvar_t sys_throttle = { "sys_throttle", "0.02", CVAR_ARCHIVE }; typedef struct unity_syscalls_s { - void *target; - - void(*SysPrint)(void *target, const char *msg); - void(*SysError)(void *target, const char *msg); - void(*SysQuit)(void *target); - double(*SysDoubleTime)(void *target); - - int(*SysFileOpenRead)(void *target, const char *path, int *hndl); - int(*SysFileOpenWrite)(void *target, const char *path); - void(*SysFileClose)(void *target, int handle); - void(*SysFileSeek)(void *target, int handle, int position); - int(*SysFileRead)(void *target, int handle, void *dest, int count); - int(*SysFileWrite)(void *target, int handle, const void *data, int count); - int(*SysFileTime)(void *target, const char *path); - qboolean(*SysMkDir)(void *target, const char *path); + void(*SysPrint)(void *context, const char *msg); + void(*SysError)(void *context, const char *msg); + void(*SysQuit)(void *context); + double(*SysDoubleTime)(void *context); + + int(*SysFileOpenRead)(void *context, const char *path, int *hndl); + int(*SysFileOpenWrite)(void *context, const char *path); + void(*SysFileClose)(void *context, int handle); + void(*SysFileSeek)(void *context, int handle, int position); + int(*SysFileRead)(void *context, int handle, void *dest, int count); + int(*SysFileWrite)(void *context, int handle, const void *data, int count); + int(*SysFileTime)(void *context, const char *path); + qboolean(*SysMkDir)(void *context, const char *path); } unity_syscalls_t; -const unity_syscalls_t *unity_syscalls; +static void *unity_context; +static const unity_syscalls_t *unity_syscalls; + +UNIQUAKE_API void UniQuake_SetSysCallbacks(void *context, const unity_syscalls_t *callbacks) +{ + unity_context = context; + unity_syscalls = callbacks; +} void Sys_Error(const char *error, ...) { @@ -36,7 +41,7 @@ void Sys_Error(const char *error, ...) q_vsnprintf(text, sizeof(text), error, argptr); va_end(argptr); - unity_syscalls->SysError(unity_syscalls->target, text); + unity_syscalls->SysError(unity_context, text); } void Sys_Printf(const char *fmt, ...) @@ -48,57 +53,57 @@ void Sys_Printf(const char *fmt, ...) q_vsnprintf(text, sizeof(text), fmt, argptr); va_end(argptr); - unity_syscalls->SysPrint(unity_syscalls->target, text); + unity_syscalls->SysPrint(unity_context, text); } void Sys_Quit(void) { - unity_syscalls->SysQuit(unity_syscalls->target); + unity_syscalls->SysQuit(unity_context); } double Sys_DoubleTime(void) { - return unity_syscalls->SysDoubleTime(unity_syscalls->target); + return unity_syscalls->SysDoubleTime(unity_context); } int Sys_FileOpenRead(const char *path, int *hndl) { - return unity_syscalls->SysFileOpenRead(unity_syscalls->target, path, hndl); + return unity_syscalls->SysFileOpenRead(unity_context, path, hndl); } int Sys_FileOpenWrite(const char *path) { - return unity_syscalls->SysFileOpenWrite(unity_syscalls->target, path); + return unity_syscalls->SysFileOpenWrite(unity_context, path); } void Sys_FileClose(int handle) { - unity_syscalls->SysFileClose(unity_syscalls->target, handle); + unity_syscalls->SysFileClose(unity_context, handle); } void Sys_FileSeek(int handle, int position) { - unity_syscalls->SysFileSeek(unity_syscalls->target, handle, position); + unity_syscalls->SysFileSeek(unity_context, handle, position); } int Sys_FileRead(int handle, void *dest, int count) { - return unity_syscalls->SysFileRead(unity_syscalls->target, handle, dest, count); + return unity_syscalls->SysFileRead(unity_context, handle, dest, count); } int Sys_FileWrite(int handle, const void *data, int count) { - return unity_syscalls->SysFileWrite(unity_syscalls->target, handle, data, count); + return unity_syscalls->SysFileWrite(unity_context, handle, data, count); } int Sys_FileTime(const char *path) { - return unity_syscalls->SysFileTime(unity_syscalls->target, path); + return unity_syscalls->SysFileTime(unity_context, path); } void Sys_mkdir(const char *path) { - if (!unity_syscalls->SysMkDir(unity_syscalls->target, path)) + if (!unity_syscalls->SysMkDir(unity_context, path)) Sys_Error("Unable to create directory %s", path); } diff --git a/engine/UniQuake/uniquake.c b/engine/UniQuake/uniquake.c index b69f71c..4f66def 100644 --- a/engine/UniQuake/uniquake.c +++ b/engine/UniQuake/uniquake.c @@ -14,14 +14,10 @@ UNIQUAKE_API void UniQuake_SetFmodSystem(FMOD_SYSTEM *system, int playernumber) } #endif -UNIQUAKE_API void UniQuake_Init(quakeparms_t *parms, const unity_syscalls_t *syscalls, const unity_glcalls_t *glcalls, const unity_gamecalls_t *gamecalls) +UNIQUAKE_API void UniQuake_Init(quakeparms_t *parms) { host_parms = parms; - unity_syscalls = syscalls; - unity_glcalls = glcalls; - unity_gamecalls = gamecalls; - COM_InitArgv(parms->argc, parms->argv); parms->argc = com_argc; parms->argv = com_argv; diff --git a/engine/UniQuake/uniquake.h b/engine/UniQuake/uniquake.h index 28a1929..b979d15 100644 --- a/engine/UniQuake/uniquake.h +++ b/engine/UniQuake/uniquake.h @@ -8,12 +8,3 @@ #else #define UNIQUAKE_API __declspec(dllimport) #endif - -typedef struct unity_syscalls_s unity_syscalls_t; -extern const unity_syscalls_t *unity_syscalls; - -typedef struct unity_glcalls_s unity_glcalls_t; -extern const unity_glcalls_t *unity_glcalls; - -typedef struct unity_gamecalls_s unity_gamecalls_t; -extern const unity_gamecalls_t *unity_gamecalls;