Files
MosisVR/Packages/com.omarator.mosissdk/Runtime/KotlinBridge.cs
2026-01-17 08:46:11 +01:00

144 lines
5.0 KiB
C#

using UnityEngine;
using UnityEngine.Rendering;
using System;
using System.Runtime.InteropServices;
public class KotlinBridge : MonoBehaviour
{
static KotlinBridge Instance;
[StructLayout(LayoutKind.Sequential)]
struct NativeCallbacks
{
public IntPtr OnMessage;
public IntPtr OnServiceInitialized;
public IntPtr OnFrameAvailable;
public IntPtr OnBufferReady;
public IntPtr OnTextureReady;
}
delegate void OnMessageDelegate(string message);
delegate void OnServiceInitializedDelegate(bool success);
delegate void OnFrameAvailableDelegate();
delegate void OnBufferReadyDelegate();
delegate void OnTextureReadyDelegate(IntPtr nativeTexturePtr, int width, int height, bool isVulkan);
[DllImport("my_native_lib")]
static extern void SetNativeCallbacks(ref NativeCallbacks callbacks);
[DllImport("my_native_lib")]
public static extern void SendTouchDown(float u, float v);
[DllImport("my_native_lib")]
public static extern void SendTouchMove(float u, float v);
[DllImport("my_native_lib")]
public static extern void SendTouchUp(float u, float v);
[DllImport("my_native_lib")]
static extern IntPtr InitBackend();
[DllImport("my_native_lib")]
static extern IntPtr UpdateTexture();
// Legacy compatibility
[DllImport("my_native_lib")]
static extern IntPtr InitGLAD();
[AOT.MonoPInvokeCallback(typeof(OnMessageDelegate))]
static void OnMessage(string message)
{
// High-speed callback, disabled for performance
// Debug.Log("Native callback: " + message);
}
[AOT.MonoPInvokeCallback(typeof(OnServiceInitializedDelegate))]
static void OnServiceInitialized(bool success)
{
Debug.Log("Service Initialized: " + success);
}
[AOT.MonoPInvokeCallback(typeof(OnFrameAvailableDelegate))]
static void OnFrameAvailable()
{
UnityMainThreadDispatcher.Enqueue(() => {
GL.IssuePluginEvent(UpdateTexture(), 1);
});
}
[AOT.MonoPInvokeCallback(typeof(OnBufferReadyDelegate))]
static void OnBufferReady()
{
Debug.Log("Buffer Ready");
UnityMainThreadDispatcher.Enqueue(() => {
GL.IssuePluginEvent(InitBackend(), 1);
});
}
[AOT.MonoPInvokeCallback(typeof(OnTextureReadyDelegate))]
static void OnTextureReady(IntPtr nativeTexturePtr, int width, int height, bool isVulkan)
{
Debug.Log($"Texture Ready: ptr={nativeTexturePtr}, size={width}x{height}, vulkan={isVulkan}");
UnityMainThreadDispatcher.Enqueue(() => {
var renderer = Instance.GetComponent<Renderer>();
if (renderer == null)
{
Debug.LogError("KotlinBridge: No Renderer component found");
return;
}
// Create external texture with actual dimensions from the service
// Unity handles both OpenGL and Vulkan native textures via CreateExternalTexture
Texture2D texture = Texture2D.CreateExternalTexture(
width,
height,
TextureFormat.RGBA32,
false, // mipChain
false, // linear
nativeTexturePtr
);
if (texture == null)
{
Debug.LogError("KotlinBridge: Failed to create external texture");
return;
}
// Set texture on material (index 2 is the phone screen material)
if (renderer.materials.Length > 2)
{
renderer.materials[2].mainTexture = texture;
Debug.Log($"KotlinBridge: Texture set on material[2], {width}x{height}");
}
else
{
Debug.LogWarning($"KotlinBridge: Not enough materials (have {renderer.materials.Length}, need 3)");
// Fall back to first material if not enough
renderer.material.mainTexture = texture;
}
});
}
void Start()
{
Instance = this;
NativeCallbacks callbacks = new NativeCallbacks();
callbacks.OnMessage = Marshal.GetFunctionPointerForDelegate(new OnMessageDelegate(OnMessage));
callbacks.OnServiceInitialized = Marshal.GetFunctionPointerForDelegate(new OnServiceInitializedDelegate(OnServiceInitialized));
callbacks.OnFrameAvailable = Marshal.GetFunctionPointerForDelegate(new OnFrameAvailableDelegate(OnFrameAvailable));
callbacks.OnBufferReady = Marshal.GetFunctionPointerForDelegate(new OnBufferReadyDelegate(OnBufferReady));
callbacks.OnTextureReady = Marshal.GetFunctionPointerForDelegate(new OnTextureReadyDelegate(OnTextureReady));
SetNativeCallbacks(ref callbacks);
if (Application.platform == RuntimePlatform.Android)
{
using (var ktClass = new AndroidJavaClass("com.omixlab.mosis.unity.MyKotlinPlugin"))
{
ktClass.CallStatic("StartMosisService");
}
}
}
}