using System; using System.Runtime.InteropServices; using AOT; using UnityEngine; public partial class RenderModule: CallbackHandler { private const int MaxAliasFrames = 256; // Should match MAXALIASFRAMES private void BuildCallbacks() { var callbacks = new Callbacks { target = TargetPtr, UploadAliasModel = CreateCallback(Callback_UploadAliasModel), UploadBrushModel = CreateCallback(Callback_UploadBrushModel), UploadTexture = CreateCallback(Callback_UploadTexture), }; RegisterCallbacks(callbacks); } /// /// This matches unity_modcalls_t from mod_uniquake.c in native code. /// [StructLayout(LayoutKind.Sequential, Pack = 0)] private class Callbacks { public IntPtr target; public IntPtr UploadAliasModel; public IntPtr UploadBrushModel; public IntPtr UploadTexture; } [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] private delegate int UploadAliasModelCallback(IntPtr target, [MarshalAs(UnmanagedType.LPStr)] string name, QAliasHeader header, QAliasFrameType frameType, IntPtr frames, [MarshalAs(UnmanagedType.LPArray, SizeConst = MaxAliasFrames)] IntPtr[] poseVerts, IntPtr triangles, IntPtr stVerts); [MonoPInvokeCallback(typeof(UploadAliasModelCallback))] private static int Callback_UploadAliasModel(IntPtr target, string name, QAliasHeader header, QAliasFrameType frameType, IntPtr frames, IntPtr[] poseVerts, IntPtr triangles, IntPtr stVerts) { if (header == null) { Debug.LogWarning($"Uploading invalid alias model, name = {name}"); return 0; } if (header.numFrames > MaxAliasFrames) header.numFrames = MaxAliasFrames; if (frames != IntPtr.Zero) header.frames = frames.ToStructArray(header.numFrames); header.numPoses = 0; for (int i = 0; i < header.numFrames; ++i) { header.numPoses += header.frames[i].numPoses; } var poseVertices = new QTriVertex[header.numPoses][]; for (int i = 0; i < header.numPoses; ++i) { poseVertices[i] = poseVerts[i].ToStructArray(header.numVerts); } var glTextures = new QGLTexture[QConstants.MaxSkins][]; var fbTextures = new QGLTexture[QConstants.MaxSkins][]; for (int i = 0; i < QConstants.MaxSkins; ++i) { glTextures[i] = header.glTextures[i * 4].ToStructArray(4); fbTextures[i] = header.fbTextures[i * 4].ToStructArray(4); } return GetSelf(target).UploadAliasModel( name, header, frameType, poseVertices, triangles.ToStructArray(header.numTriangles), stVerts.ToStructArray(header.numVerts), glTextures, fbTextures); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int UploadBrushModelCallback(IntPtr target, QModel model); [MonoPInvokeCallback(typeof(UploadBrushModelCallback))] private static int Callback_UploadBrushModel(IntPtr target, QModel model) { if (model == null || model.type != QModelType.Brush) return -1; var surfaces = model.surfaces.ToStructArray(model.numSurfaces); return GetSelf(target).UploadBrushModel(model, surfaces); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool UploadTextureCallback(IntPtr target, QGLTexture texture, IntPtr data, ref uint texNum); [MonoPInvokeCallback(typeof(UploadTextureCallback))] private static bool Callback_UploadTexture(IntPtr target, QGLTexture texture, IntPtr data, ref uint texNum) { byte[] dataBytes = new byte[texture.width * texture.height * 4]; // 32 bits per pixel Marshal.Copy(data, dataBytes, 0, dataBytes.Length); return GetSelf(target).UploadTexture(texture, dataBytes, ref texNum); } }