Files
VR-WuKong/Packages/PICO Unity Integration SDK-3.3.2-20251111/Runtime/Scripts/OpenXRFeatures/OpenXRExtensions.cs
2025-11-13 17:40:28 +08:00

352 lines
14 KiB
C#

#if PICO_OPENXR_SDK
using System.Collections.Generic;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
using Object = System.Object;
using UnityEngine.XR.OpenXR.Features.Interactions;
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using AOT;
using Unity.XR.PXR;
using UnityEngine.XR;
#if UNITY_EDITOR
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
using UnityEditor;
using UnityEditor.XR.OpenXR.Features;
#endif
#if AR_FOUNDATION_5||AR_FOUNDATION_6
using UnityEngine.XR.ARSubsystems;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
#if UNITY_EDITOR
public class ExtensionsConfig
{
public const string OpenXrExtensionList = "XR_FB_composition_layer_alpha_blend " +
"XR_FB_triangle_mesh " +
"XR_KHR_composition_layer_color_scale_bias " +
"XR_KHR_composition_layer_cylinder " +
"XR_KHR_composition_layer_equirect2 " +
"XR_KHR_composition_layer_cube " +
"XR_BD_composition_layer_eac " +
"XR_BD_composition_layer_fisheye " +
"XR_BD_composition_layer_blurred_quad " +
"XR_KHR_android_surface_swapchain " +
"XR_BD_composition_layer_color_matrix " +
"XR_BD_composition_layer_settings " +
"XR_KHR_composition_layer_depth ";
}
[OpenXRFeature(UiName = "PICO OpenXR Features",
Desc = "PICO XR Features for OpenXR.",
Company = "PICO",
Priority = 100,
Version = PXR_Constants.SDKVersion,
BuildTargetGroups = new[] { BuildTargetGroup.Android },
OpenxrExtensionStrings = ExtensionsConfig.OpenXrExtensionList,
FeatureId = featureId
)]
#endif
public class OpenXRExtensions : OpenXRFeature
{
public const string featureId = "com.unity.openxr.pico.features";
public const string PXR_PLATFORM_DLL = "PxrPlatform";
private static ulong xrInstance = 0ul;
private static ulong xrSession = 0ul;
public static event Action<ulong> SenseDataUpdated;
public static event Action SpatialAnchorDataUpdated;
public static event Action SceneAnchorDataUpdated;
public static event Action<PxrEventSenseDataProviderStateChanged> SenseDataProviderStateChanged;
public static event Action<List<PxrSpatialMeshInfo>> SpatialMeshDataUpdated;
static bool isCoroutineRunning = false;
protected override bool OnInstanceCreate(ulong instance)
{
Debug.Log($"[PICOOpenXRExtensions] OnInstanceCreate: {instance}");
xrInstance = instance;
xrSession = 0ul;
PICO_OnInstanceCreate(instance);
return true;
}
protected override void OnSessionCreate(ulong xrSessionId)
{
Debug.Log($"[PICOOpenXRExtensions] OnSessionCreate: {xrSessionId}");
xrSession = xrSessionId;
PICO_OnSessionCreate(xrSessionId);
PXR_Plugin.System.UPxr_SetXrEventDataBufferCallBack(XrEventDataBufferFunction);
}
public static int GetReferenceSpaceBoundsRect(XrReferenceSpaceType referenceSpace, ref XrExtent2Df extent2D)
{
return PICO_xrGetReferenceSpaceBoundsRect(
xrSession, referenceSpace, ref extent2D);
}
public static XrReferenceSpaceType[] EnumerateReferenceSpaces()
{
UInt32 Output = 0;
XrReferenceSpaceType[] outSpaces = null;
PICO_xrEnumerateReferenceSpaces(xrSession, 0, ref Output, outSpaces);
if (Output <= 0)
{
return null;
}
outSpaces = new XrReferenceSpaceType[Output];
PICO_xrEnumerateReferenceSpaces(xrSession, Output, ref Output, outSpaces);
return outSpaces;
}
[MonoPInvokeCallback(typeof(XrEventDataBufferCallBack))]
static void XrEventDataBufferFunction(ref XrEventDataBuffer eventDB)
{
int status, action;
Debug.Log($"XrEventDataBufferFunction eventType={eventDB.type}");
switch (eventDB.type)
{
case XrStructureType.XR_TYPE_EVENT_DATA_SENSE_DATA_PROVIDER_STATE_CHANGED:
{
if (SenseDataProviderStateChanged != null)
{
PxrEventSenseDataProviderStateChanged data = new PxrEventSenseDataProviderStateChanged()
{
providerHandle = BitConverter.ToUInt64(eventDB.data, 0),
newState = (PxrSenseDataProviderState)BitConverter.ToInt32(eventDB.data, 8),
};
SenseDataProviderStateChanged(data);
}
break;
}
case XrStructureType.XR_TYPE_EVENT_KEY_EVENT:
{
if (PXR_Plugin.System.RecenterSuccess != null)
{
PXR_Plugin.System.RecenterSuccess();
}
break;
}
case XrStructureType.XR_TYPE_EVENT_DATA_SENSE_DATA_UPDATED:
{
ulong providerHandle = BitConverter.ToUInt64(eventDB.data, 0);
PLog.i("EventDataFunction",$"providerHandle ={providerHandle}");
if (SenseDataUpdated != null)
{
SenseDataUpdated(providerHandle);
}
if (providerHandle == PXR_Plugin.MixedReality.UPxr_GetSenseDataProviderHandle(PxrSenseDataProviderType.SpatialAnchor))
{
if (SpatialAnchorDataUpdated != null)
{
SpatialAnchorDataUpdated();
}
}
if (providerHandle == PXR_Plugin.MixedReality.UPxr_GetSenseDataProviderHandle(PxrSenseDataProviderType.SceneCapture))
{
if (SceneAnchorDataUpdated != null)
{
SceneAnchorDataUpdated();
}
}
if (providerHandle == PXR_Plugin.MixedReality.UPxr_GetSpatialMeshProviderHandle())
{
if (!isCoroutineRunning)
{
QuerySpatialMeshAnchor();
}
}
break;
}
}
}
static async void QuerySpatialMeshAnchor()
{
isCoroutineRunning = true;
var task = await PXR_MixedReality.QueryMeshAnchorAsync();
isCoroutineRunning = false;
var (result, meshInfos) = task;
for (int i = 0; i < meshInfos.Count; i++)
{
switch (meshInfos[i].state)
{
case MeshChangeState.Added:
case MeshChangeState.Updated:
{
PXR_Plugin.MixedReality.UPxr_AddOrUpdateMesh(meshInfos[i]);
}
break;
case MeshChangeState.Removed:
{
PXR_Plugin.MixedReality.UPxr_RemoveMesh(meshInfos[i].uuid);
}
break;
case MeshChangeState.Unchanged:
{
break;
}
}
}
if (result == PxrResult.SUCCESS)
{
SpatialMeshDataUpdated?.Invoke(meshInfos);
}
}
protected override void OnInstanceDestroy(ulong xrInstance)
{
Debug.Log($"[PICOOpenXRExtensions] OnInstanceDestroy: {xrInstance}");
base.OnInstanceDestroy(xrInstance);
xrInstance = 0ul;
PICO_OnInstanceDestroy(xrInstance);
}
protected override IntPtr HookGetInstanceProcAddr(IntPtr func)
{
Debug.Log($"[PICOOpenXRExtensions] HookGetInstanceProcAddr: {func}");
return PICO_HookCreateInstance(func);
}
protected override void OnAppSpaceChange(ulong xrSpace)
{
Debug.Log($"[PICOOpenXRExtensions] OnAppSpaceChange: {xrSpace}");
PICO_OnAppSpaceChange(xrSpace);
}
protected override void OnSystemChange(ulong xrSystem)
{
Debug.Log($"[PICOOpenXRExtensions] OnSystemChange: {xrSystem}");
PICO_OnSystemChange(xrSystem);
}
protected override void OnSessionStateChange(int oldState, int newState)
{
Debug.Log($"[PICOOpenXRExtensions] OnSessionStateChange: {oldState} -> {newState}");
}
protected override void OnSessionBegin(ulong xrSessionId)
{
Debug.Log($"[PICOOpenXRExtensions] OnSessionBegin: {xrSessionId}");
}
protected override void OnSessionEnd(ulong xrSessionId)
{
Debug.Log($"[PICOOpenXRExtensions] OnSessionEnd: {xrSessionId}");
}
protected override void OnSessionExiting(ulong xrSessionId)
{
Debug.Log($"[PICOOpenXRExtensions] OnSessionExiting: {xrSessionId}");
}
protected override void OnSessionDestroy(ulong xrSessionId)
{
Debug.Log($"[PICOOpenXRExtensions] OnSessionDestroy: {xrSessionId}");
xrSession = 0ul;
PICO_OnSessionDestroy(xrSessionId);
}
public static float GetLocationHeight()
{
float height = 0;
PICO_GetLocationHeight( ref height);
return height;
}
#if AR_FOUNDATION_5||AR_FOUNDATION_6
public bool isSessionSubsystem=false;
private static List<XRSessionSubsystemDescriptor> sessionSubsystemDescriptors = new List<XRSessionSubsystemDescriptor>();
protected override void OnSubsystemCreate()
{
base.OnSubsystemCreate();
if (isSessionSubsystem)
{
CreateSubsystem<XRSessionSubsystemDescriptor, XRSessionSubsystem>(sessionSubsystemDescriptors, PXR_SessionSubsystem.k_SubsystemId);
}
}
protected override void OnSubsystemStart()
{
if (isSessionSubsystem)
{
StartSubsystem<XRSessionSubsystem>();
}
}
protected override void OnSubsystemStop()
{
if (isSessionSubsystem)
{
StopSubsystem<XRSessionSubsystem>();
}
}
protected override void OnSubsystemDestroy()
{
if (isSessionSubsystem)
{
DestroySubsystem<XRSessionSubsystem>();
}
}
#endif
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr PICO_HookCreateInstance(IntPtr func);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnInstanceCreate(UInt64 xrInstance);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnInstanceDestroy(UInt64 xrInstance);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnSessionCreate(UInt64 xrSession);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnAppSpaceChange(UInt64 xrSpace);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnSessionStateChange(int oldState, int newState);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnSessionBegin(UInt64 xrSession);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnSessionEnd(UInt64 xrSession);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnSessionExiting(UInt64 xrSession);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnSessionDestroy(UInt64 xrSession);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PICO_OnSystemChange(UInt64 xrSystemId);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int PICO_xrEnumerateReferenceSpaces(ulong xrSession, UInt32 CountInput, ref UInt32 CountOutput,
XrReferenceSpaceType[] Spaces);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int PICO_xrGetReferenceSpaceBoundsRect(ulong xrSession, XrReferenceSpaceType referenceSpace,
ref XrExtent2Df extent2D);
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, EntryPoint = "PICO_SetMarkMode", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetMarkMode();
[DllImport(PXR_Plugin.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int PICO_GetLocationHeight(ref float delaY);
}
}
#endif