Init
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51e35b2149654cc5b668f78d0f52bba6
|
||||
timeCreated: 1738739439
|
||||
@@ -0,0 +1,133 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.Collections;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.NativeTypes;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
public enum SystemDisplayFrequency
|
||||
{
|
||||
Default,
|
||||
RefreshRate72 = 72,
|
||||
RefreshRate90 = 90,
|
||||
RefreshRate120 = 120,
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "OpenXR Display Refresh Rate",
|
||||
Hidden = false,
|
||||
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = PXR_Constants.SDKVersion,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class DisplayRefreshRateFeature : OpenXRFeatureBase
|
||||
{
|
||||
public const string featureId = "com.pico.openxr.feature.refreshrate";
|
||||
public const string extensionString = "XR_FB_display_refresh_rate";
|
||||
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled(extensionString);
|
||||
|
||||
public override string GetExtensionString()
|
||||
{
|
||||
return extensionString;
|
||||
}
|
||||
|
||||
public override void SessionCreate(ulong xrSessionId)
|
||||
{
|
||||
PXR_OpenXRProjectSetting projectConfig = PXR_OpenXRProjectSetting.GetProjectConfig();
|
||||
if (projectConfig.displayFrequency != SystemDisplayFrequency.Default)
|
||||
{
|
||||
SetDisplayRefreshRate(projectConfig.displayFrequency);
|
||||
}
|
||||
}
|
||||
public static bool SetDisplayRefreshRate(SystemDisplayFrequency DisplayFrequency)
|
||||
{
|
||||
PLog.e(extensionString,$"SetDisplayRefreshRate:{DisplayFrequency}");
|
||||
float rate = 0;
|
||||
switch (DisplayFrequency)
|
||||
{
|
||||
case SystemDisplayFrequency.Default:
|
||||
return true;
|
||||
case SystemDisplayFrequency.RefreshRate72:
|
||||
rate = 72;
|
||||
break;
|
||||
case SystemDisplayFrequency.RefreshRate90:
|
||||
rate = 90;
|
||||
break;
|
||||
case SystemDisplayFrequency.RefreshRate120:
|
||||
rate = 120;
|
||||
break;
|
||||
}
|
||||
|
||||
return SetDisplayRefreshRate(rate);
|
||||
}
|
||||
|
||||
public static bool GetDisplayRefreshRate(ref float displayRefreshRate)
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Pxr_GetDisplayRefreshRate(ref displayRefreshRate) == (int)XrResult.Success;
|
||||
}
|
||||
|
||||
public static bool SetDisplayRefreshRate(float displayRefreshRate)
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Pxr_SetDisplayRefreshRate(displayRefreshRate) == (int)XrResult.Success;
|
||||
}
|
||||
[Obsolete("Please use GetDisplayFrequenciesAvailable")]
|
||||
public static int GetDisplayRefreshRateCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
[Obsolete("Please use GetDisplayFrequenciesAvailable")]
|
||||
public static bool TryGetSupportedDisplayRefreshRates(
|
||||
Allocator allocator, out NativeArray<float> refreshRates)
|
||||
{
|
||||
refreshRates = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static float[] GetDisplayFrequenciesAvailable()
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
float[] configArray = { 0 };
|
||||
int configCount = 0;
|
||||
IntPtr configHandle = IntPtr.Zero;
|
||||
bool ret = false;
|
||||
ret = Pxr_GetDisplayRefreshRatesAvailable(ref configCount, ref configHandle);
|
||||
if (ret)
|
||||
{
|
||||
configArray = new float[configCount];
|
||||
Marshal.Copy(configHandle, configArray, 0, configCount);
|
||||
}
|
||||
|
||||
return configArray;
|
||||
}
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_GetDisplayRefreshRate(ref float displayRefreshRate);
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_SetDisplayRefreshRate(float refreshRate);
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool Pxr_GetDisplayRefreshRatesAvailable(ref int configCount, ref IntPtr configArray);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f13a1b00c8524d6495757293c2324596
|
||||
timeCreated: 1738739475
|
||||
@@ -0,0 +1,156 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using Unity.XR.OpenXR.Features.PICOSupport;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
|
||||
[OpenXRFeature(UiName = "OpenXR Foveation",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
OpenxrExtensionStrings = extensionList,
|
||||
Company = "PICO",
|
||||
Version = PXR_Constants.SDKVersion,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
|
||||
|
||||
public class FoveationFeature : OpenXRFeatureBase
|
||||
{
|
||||
public const string extensionList = "XR_FB_foveation " +
|
||||
"XR_FB_foveation_configuration " +
|
||||
"XR_FB_foveation_vulkan " +
|
||||
"XR_META_foveation_eye_tracked " +
|
||||
"XR_META_vulkan_swapchain_create_info " +
|
||||
"XR_FB_swapchain_update_state ";
|
||||
|
||||
public const string featureId = "com.pico.openxr.feature.foveation";
|
||||
private static string TAG = "FoveationFeature";
|
||||
public enum FoveatedRenderingLevel
|
||||
{
|
||||
Off = 0,
|
||||
Low = 1,
|
||||
Medium = 2,
|
||||
High = 3
|
||||
}
|
||||
public enum FoveatedRenderingMode
|
||||
{
|
||||
FixedFoveatedRendering = 0,
|
||||
EyeTrackedFoveatedRendering = 1
|
||||
}
|
||||
|
||||
private static UInt32 _foveatedRenderingLevel = 0;
|
||||
private static UInt32 _useDynamicFoveation = 0;
|
||||
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled("XR_FB_foveation");
|
||||
public override string GetExtensionString()
|
||||
{
|
||||
return extensionList;
|
||||
}
|
||||
|
||||
public override void SessionCreate(ulong xrSessionId)
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
PXR_OpenXRProjectSetting projectConfig = PXR_OpenXRProjectSetting.GetProjectConfig();
|
||||
if (projectConfig.foveationEnable)
|
||||
{
|
||||
PICO_setFoveationEyeTracked(projectConfig.foveatedRenderingMode ==
|
||||
FoveatedRenderingMode.EyeTrackedFoveatedRendering);
|
||||
foveatedRenderingLevel = projectConfig.foveatedRenderingLevel;
|
||||
}
|
||||
}
|
||||
public static FoveatedRenderingLevel foveatedRenderingLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return FoveatedRenderingLevel.Off;
|
||||
}
|
||||
UInt32 level;
|
||||
FBGetFoveationLevel(out level);
|
||||
PLog.i(TAG,$" foveatedRenderingLevel get if level= {level}");
|
||||
return (FoveatedRenderingLevel)level;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
PLog.e(TAG,$" foveatedRenderingLevel set if value= {value}");
|
||||
_foveatedRenderingLevel = (UInt32)value;
|
||||
FBSetFoveationLevel(xrSession, _foveatedRenderingLevel, 0.0f, _useDynamicFoveation);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool useDynamicFoveatedRendering
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
UInt32 dynamic;
|
||||
FBGetFoveationLevel(out dynamic);
|
||||
return dynamic != 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
if (value)
|
||||
_useDynamicFoveation = 1;
|
||||
else
|
||||
_useDynamicFoveation = 0;
|
||||
FBSetFoveationLevel(xrSession, _foveatedRenderingLevel, 0.0f, _useDynamicFoveation);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool supportsFoveationEyeTracked
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool supported=false;
|
||||
Pxr_GetEyeTrackingFoveationRenderingSupported(ref supported);
|
||||
return supported;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region OpenXR Plugin DLL Imports
|
||||
|
||||
[DllImport("UnityOpenXR", EntryPoint = "FBSetFoveationLevel")]
|
||||
private static extern void FBSetFoveationLevel(UInt64 session, UInt32 level, float verticalOffset, UInt32 dynamic);
|
||||
|
||||
[DllImport("UnityOpenXR", EntryPoint = "FBGetFoveationLevel")]
|
||||
private static extern void FBGetFoveationLevel(out UInt32 level);
|
||||
|
||||
[DllImport("UnityOpenXR", EntryPoint = "FBGetFoveationDynamic")]
|
||||
private static extern void FBGetFoveationDynamic(out UInt32 dynamic);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool Pxr_GetEyeTrackingFoveationRenderingSupported(ref bool supported);
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void PICO_setFoveationEyeTracked(bool value);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7137a47eb739c7a4485f1395871a6d68
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,128 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.XR.CoreUtils;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
public class LayerBase : MonoBehaviour
|
||||
{
|
||||
public static int ID = 0;
|
||||
private Transform overlayTransform;
|
||||
private Camera xrRig;
|
||||
|
||||
private Vector3 modelTranslations;
|
||||
private Quaternion modelRotations;
|
||||
private Vector3 modelScales ;
|
||||
private XROrigin cameraRig;
|
||||
private XROrigin lastcameraRig;
|
||||
public bool isXROriginChange = false;
|
||||
private float offsetY = 0;
|
||||
bool isUpdateOffsetY= false;
|
||||
private Vector3 cameraPosOri;
|
||||
private TrackingOriginModeFlags lastTrackingOriginMod = TrackingOriginModeFlags.Unknown;
|
||||
public void Awake()
|
||||
{
|
||||
ID++;
|
||||
lastcameraRig=cameraRig=FindActiveXROrigin();
|
||||
overlayTransform = GetComponent<Transform>();
|
||||
PXR_Plugin.System.RecenterSuccess+=()=>
|
||||
{
|
||||
isUpdateOffsetY = true;
|
||||
};
|
||||
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
if (overlayTransform != null)
|
||||
{
|
||||
MeshRenderer render = overlayTransform.GetComponent<MeshRenderer>();
|
||||
if (render != null)
|
||||
{
|
||||
render.enabled = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
XROrigin FindActiveXROrigin()
|
||||
{
|
||||
XROrigin[] xrOrigins = FindObjectsOfType<XROrigin>();
|
||||
foreach (XROrigin xrOrigin in xrOrigins)
|
||||
{
|
||||
if (xrOrigin.gameObject.activeInHierarchy)
|
||||
{
|
||||
return xrOrigin;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
ID--;
|
||||
}
|
||||
|
||||
public void UpdateCoords(bool isCreate = false)
|
||||
{
|
||||
if (isXROriginChange)
|
||||
{
|
||||
cameraRig=FindActiveXROrigin();
|
||||
isUpdateOffsetY=cameraRig!= lastcameraRig;
|
||||
lastcameraRig = cameraRig;
|
||||
}
|
||||
|
||||
if (isCreate)
|
||||
{
|
||||
cameraPosOri=cameraRig.transform.position;
|
||||
}
|
||||
if (isCreate||cameraRig.CurrentTrackingOriginMode != lastTrackingOriginMod ||isUpdateOffsetY)
|
||||
{
|
||||
|
||||
if (cameraRig.CurrentTrackingOriginMode == TrackingOriginModeFlags.Floor)
|
||||
{
|
||||
offsetY= cameraRig.Camera.transform.position.y;
|
||||
}
|
||||
Debug.Log("CurrentTrackingOriginMode:"+cameraRig.CurrentTrackingOriginMode+" offsetY:"+offsetY);
|
||||
isUpdateOffsetY=false;
|
||||
lastTrackingOriginMod = cameraRig.CurrentTrackingOriginMode;
|
||||
}
|
||||
|
||||
|
||||
var worldInsightModel = GetTransformMatrixForPassthrough(overlayTransform.localToWorldMatrix);
|
||||
modelTranslations=worldInsightModel.GetPosition();
|
||||
modelRotations = worldInsightModel.rotation;
|
||||
modelScales = overlayTransform.lossyScale;
|
||||
}
|
||||
|
||||
private Matrix4x4 GetTransformMatrixForPassthrough(Matrix4x4 worldFromObj)
|
||||
{
|
||||
Matrix4x4 trackingSpaceFromWorld =
|
||||
(cameraRig != null) ? cameraRig.CameraFloorOffsetObject.transform.worldToLocalMatrix : Matrix4x4.identity;
|
||||
|
||||
return trackingSpaceFromWorld * worldFromObj;
|
||||
}
|
||||
public void GetCurrentTransform(ref GeometryInstanceTransform geometryInstanceTransform)
|
||||
{
|
||||
geometryInstanceTransform.pose.position.x = modelTranslations.x;
|
||||
geometryInstanceTransform.pose.position.y = modelTranslations.y-offsetY+ (cameraRig.CurrentTrackingOriginMode == TrackingOriginModeFlags.Floor
|
||||
? (cameraRig.transform.position.y - cameraPosOri.y)
|
||||
: 0);
|
||||
geometryInstanceTransform.pose.position.z = -modelTranslations.z;
|
||||
geometryInstanceTransform.pose.orientation.x = -modelRotations.x;
|
||||
geometryInstanceTransform.pose.orientation.y = -modelRotations.y;
|
||||
geometryInstanceTransform.pose.orientation.z = modelRotations.z;
|
||||
geometryInstanceTransform.pose.orientation.w = modelRotations.w;
|
||||
|
||||
geometryInstanceTransform.scale.x = modelScales.x;
|
||||
geometryInstanceTransform.scale.y = modelScales.y;
|
||||
geometryInstanceTransform.scale.z = 1;
|
||||
|
||||
geometryInstanceTransform.isFloor = cameraRig.CurrentTrackingOriginMode == TrackingOriginModeFlags.Floor;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d95410458cc9bf46a74d78dcba2294f
|
||||
timeCreated: 1695197751
|
||||
@@ -0,0 +1,54 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "OpenXR Composition Layer Secure Content",
|
||||
Hidden = false,
|
||||
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = PXR_Constants.SDKVersion,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class LayerSecureContentFeature : OpenXRFeatureBase
|
||||
{
|
||||
public const string featureId = "com.pico.openxr.feature.LayerSecureContent";
|
||||
public const string extensionString = "XR_FB_composition_layer_secure_content";
|
||||
|
||||
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled(extensionString);
|
||||
|
||||
public override string GetExtensionString()
|
||||
{
|
||||
return extensionString;
|
||||
}
|
||||
public override void SessionCreate(ulong xrSessionId)
|
||||
{
|
||||
PXR_OpenXRProjectSetting projectConfig = PXR_OpenXRProjectSetting.GetProjectConfig();
|
||||
if (projectConfig.useContentProtect)
|
||||
{
|
||||
SetSecureContentFlag(projectConfig.contentProtectFlags);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetSecureContentFlag(SecureContentFlag flag)
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SetSecureContentFlag((int)flag);
|
||||
}
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void SetSecureContentFlag(int state);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9496d215cb181c64c9cde2f724356e20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
public abstract class OpenXRFeatureBase : OpenXRFeature
|
||||
{
|
||||
protected static ulong xrInstance = 0ul;
|
||||
protected static ulong xrSession = 0ul;
|
||||
protected override bool OnInstanceCreate(ulong instance)
|
||||
{
|
||||
xrInstance = instance;
|
||||
xrSession = 0ul;
|
||||
InstanceCreate(instance);
|
||||
return true;
|
||||
}
|
||||
protected override void OnSessionCreate(ulong xrSessionId)
|
||||
{
|
||||
xrSession = xrSessionId;
|
||||
base.OnSessionCreate(xrSessionId);
|
||||
SessionCreate(xrSessionId);
|
||||
}
|
||||
public bool isExtensionEnabled(string extensionUrl)
|
||||
{
|
||||
string[] exts = extensionUrl.Split(' ');
|
||||
if (exts.Length > 0)
|
||||
{
|
||||
foreach (var _ext in exts)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_ext) && !OpenXRRuntime.IsExtensionEnabled(_ext))
|
||||
{
|
||||
PLog.e("OpenXRFeatureBase", _ext + " is not enabled");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(extensionUrl) && !OpenXRRuntime.IsExtensionEnabled(extensionUrl))
|
||||
{
|
||||
PLog.e("OpenXRFeatureBase", extensionUrl + " is not enabled");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void InstanceCreate(ulong instance) {}
|
||||
|
||||
public virtual void SessionCreate(ulong xrSessionId) {}
|
||||
public abstract string GetExtensionString();
|
||||
#if UNITY_EDITOR
|
||||
protected override void GetValidationChecks(List<ValidationRule> rules, BuildTargetGroup targetGroup)
|
||||
{
|
||||
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup);
|
||||
rules.Add(new ValidationRule(this)
|
||||
{
|
||||
message = "No PICO OpenXR Features selected.",
|
||||
checkPredicate = () =>
|
||||
{
|
||||
if (null == settings)
|
||||
return false;
|
||||
|
||||
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
|
||||
{
|
||||
if (feature is OpenXRExtensions)
|
||||
{
|
||||
return feature.enabled;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
fixIt = () =>
|
||||
{
|
||||
if (null == settings)
|
||||
return ;
|
||||
var openXRExtensions = settings.GetFeature<OpenXRExtensions>();
|
||||
if (openXRExtensions != null)
|
||||
{
|
||||
openXRExtensions.enabled = true;
|
||||
}
|
||||
},
|
||||
error = true
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03de18223d234dd4914b78bf7b2ad088
|
||||
timeCreated: 1738739629
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7a3b25af74c35240b11ce66fc7614ef
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,251 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEngine;
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
using UnityEngine.XR.ARSubsystems;
|
||||
#endif
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
public enum XrBodyJointSetBD
|
||||
{
|
||||
XR_BODY_JOINT_SET_DEFAULT_BD = 0, //default joint set XR_BODY_JOINT_SET_BODY_STAR_WITHOUT_ARM_BD
|
||||
XR_BODY_JOINT_SET_BODY_START_WITHOUT_ARM_BD = 1,
|
||||
XR_BODY_JOINT_SET_BODY_FULL_STAR_BD = 2
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "PICO Body Tracking",
|
||||
Hidden = false,
|
||||
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = PXR_Constants.SDKVersion,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
|
||||
public class BodyTrackingFeature : OpenXRFeatureBase
|
||||
{
|
||||
public const string featureId = "com.pico.openxr.feature.PICO_BodyTracking";
|
||||
public const string extensionString = "XR_BD_body_tracking XR_PICO_body_tracking2";
|
||||
|
||||
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_BD_body_tracking");
|
||||
|
||||
public override string GetExtensionString()
|
||||
{
|
||||
return extensionString;
|
||||
}
|
||||
|
||||
[Obsolete("Please use StartBodyTracking(BodyJointSet JointSet, BodyTrackingBoneLength boneLength)")]
|
||||
public static bool StartBodyTracking(XrBodyJointSetBD Mode)
|
||||
{
|
||||
if (!isEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BodyTrackingBoneLength boneLength=new BodyTrackingBoneLength();
|
||||
|
||||
return StartBodyTracking((BodyJointSet)Mode, boneLength)==0;
|
||||
}
|
||||
/// <summary>Starts body tracking.</summary>
|
||||
/// <param name="mode">Specifies the body tracking mode (default or high-accuracy).</param>
|
||||
/// <param name="boneLength">Specifies lengths (unit: cm) for the bones of the avatar, which is only available for the `BTM_FULL_BODY_HIGH` mode.
|
||||
/// Bones that are not set lengths for will use the default values.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// - `0`: success
|
||||
/// - `1`: failure
|
||||
/// </returns>
|
||||
public static int StartBodyTracking(BodyJointSet JointSet, BodyTrackingBoneLength boneLength)
|
||||
{
|
||||
if (!isEnable)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
BodyTrackingStartInfo startInfo = new BodyTrackingStartInfo();
|
||||
startInfo.jointSet = JointSet;
|
||||
startInfo.BoneLength = boneLength;
|
||||
|
||||
return Pxr_StartBodyTracking(ref startInfo);
|
||||
}
|
||||
/// <summary>Launches the PICO Motion Tracker app to perform calibration.
|
||||
/// - For PICO Motion Tracker (Beta), the user needs to follow the instructions on the home of the PICO Motion Tracker app to complete calibration.
|
||||
/// - For PICO Motion Tracker (Official), "single-glance calibration" will be performed. When a user has a glance at the PICO Motion Tracker on their lower legs, calibration is completed.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// - `0`: success
|
||||
/// - `1`: failure
|
||||
/// </returns>
|
||||
public static int StartMotionTrackerCalibApp()
|
||||
{
|
||||
if (!isEnable)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return Pxr_StartBodyTrackingCalibApp();
|
||||
}
|
||||
|
||||
public static bool IsBodyTrackingSupported()
|
||||
{
|
||||
if (!isEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool supported=false;
|
||||
Pxr_GetBodyTrackingSupported(ref supported);
|
||||
return supported;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data about the poses of body joints.
|
||||
/// </summary>
|
||||
/// <param name="predictTime">Reserved parameter, pass `0`.</param>
|
||||
/// <param name="bodyTrackerResult">Contains the data about the poses of body joints, including position, action, and more.</param>
|
||||
[Obsolete("Please use GetBodyTrackingData",true)]
|
||||
public static bool GetBodyTrackingPose(ref BodyTrackerResult bodyTrackerResult)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/// <summary>Stops body tracking.</summary>
|
||||
/// <returns>
|
||||
/// - `0`: success
|
||||
/// - `1`: failure
|
||||
/// </returns>
|
||||
public static int StopBodyTracking()
|
||||
{
|
||||
return Pxr_StopBodyTracking();
|
||||
}
|
||||
[Obsolete("Please use StopBodyTracking")]
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (!isEnable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StopBodyTracking();
|
||||
}
|
||||
|
||||
[Obsolete("Please use StartMotionTrackerCalibApp")]
|
||||
public static void OpenFitnessBandCalibrationAPP()
|
||||
{
|
||||
StartMotionTrackerCalibApp();
|
||||
}
|
||||
|
||||
/// <summary>Gets body tracking data.</summary>
|
||||
/// <param name="getInfo"> Specifies the display time and the data filtering flags.
|
||||
/// For the display time, for example, when it is set to 0.1 second, it means predicting the pose of the tracked node 0.1 seconds ahead.
|
||||
/// </param>
|
||||
/// <param name="data">Returns the array of data for all tracked nodes.</param>
|
||||
/// <returns>
|
||||
/// - `0`: success
|
||||
/// - `1`: failure
|
||||
/// </returns>
|
||||
public unsafe static int GetBodyTrackingData(ref BodyTrackingGetDataInfo getInfo, ref BodyTrackingData data)
|
||||
{
|
||||
if (!isEnable)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int val = -1;
|
||||
{
|
||||
val = Pxr_GetBodyTrackingData(ref getInfo, ref data);
|
||||
for (int i = 0; i < (int)BodyTrackerRole.ROLE_NUM; i++)
|
||||
{
|
||||
data.roleDatas[i].localPose.PosZ = -data.roleDatas[i].localPose.PosZ;
|
||||
data.roleDatas[i].localPose.RotQz = -data.roleDatas[i].localPose.RotQz;
|
||||
data.roleDatas[i].localPose.RotQw = -data.roleDatas[i].localPose.RotQw;
|
||||
data.roleDatas[i].velo[3] = -data.roleDatas[i].velo[3];
|
||||
data.roleDatas[i].acce[3] = -data.roleDatas[i].acce[3];
|
||||
data.roleDatas[i].wvelo[3] = -data.roleDatas[i].wvelo[3];
|
||||
data.roleDatas[i].wacce[3] = -data.roleDatas[i].wacce[3];
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
/// <summary>Gets the state of PICO Motion Tracker and, if any, the reason for an exception.</summary>
|
||||
/// <param name="isTracking">Indicates whether the PICO Motion Tracker is tracking normally:
|
||||
/// - `true`: is tracking
|
||||
/// - `false`: tracking lost
|
||||
/// </param>
|
||||
/// <param name="state">Returns the information about body tracking state.</param>
|
||||
/// <returns>
|
||||
/// - `0`: success
|
||||
/// - `1`: failure
|
||||
/// </returns>
|
||||
public static int GetBodyTrackingState(ref bool isTracking, ref BodyTrackingStatus state)
|
||||
{
|
||||
int val = -1;
|
||||
{
|
||||
val = Pxr_GetBodyTrackingState(ref isTracking, ref state);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
public bool isBodyTracking=false;
|
||||
static List<XRHumanBodySubsystemDescriptor> s_HumanBodyDescriptors = new List<XRHumanBodySubsystemDescriptor>();
|
||||
protected override void OnSubsystemCreate()
|
||||
{
|
||||
base.OnSubsystemCreate();
|
||||
if (isBodyTracking)
|
||||
{
|
||||
CreateSubsystem<XRHumanBodySubsystemDescriptor, XRHumanBodySubsystem>(
|
||||
s_HumanBodyDescriptors,
|
||||
PXR_HumanBodySubsystem.k_SubsystemId);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
protected override void OnSubsystemStart()
|
||||
{
|
||||
if (isBodyTracking)
|
||||
{
|
||||
StartSubsystem<XRHumanBodySubsystem>();
|
||||
}
|
||||
}
|
||||
protected override void OnSubsystemStop()
|
||||
{
|
||||
if (isBodyTracking)
|
||||
{
|
||||
StopSubsystem<XRHumanBodySubsystem>();
|
||||
}
|
||||
}
|
||||
protected override void OnSubsystemDestroy()
|
||||
{
|
||||
if (isBodyTracking)
|
||||
{
|
||||
DestroySubsystem<XRHumanBodySubsystem>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_StartBodyTrackingCalibApp();
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_GetBodyTrackingSupported(ref bool supported);
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_StartBodyTracking(ref BodyTrackingStartInfo startInfo);
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_StopBodyTracking();
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_GetBodyTrackingState(ref bool isTracking, ref BodyTrackingStatus state);
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int Pxr_GetBodyTrackingData(ref BodyTrackingGetDataInfo getInfo, ref BodyTrackingData data);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa772d31a64f93d49bd62d49064fee41
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "PICO Scene Capture",
|
||||
Hidden = false,
|
||||
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = "1.0.0",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class PICOSceneCapture: OpenXRFeature
|
||||
{
|
||||
public const string featureId = "com.pico.openxr.feature.scenecapture";
|
||||
public const string extensionString = "XR_PICO_scene_capture XR_PICO_spatial_sensing XR_EXT_future";
|
||||
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_PICO_scene_capture");
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
base.OnSessionCreate(xrSession);
|
||||
PXR_Plugin.MixedReality.UPxr_CreateSceneCaptureSenseDataProvider();
|
||||
}
|
||||
|
||||
protected override void OnSessionExiting(ulong xrSession)
|
||||
{
|
||||
PXR_MixedReality.GetSenseDataProviderState(PxrSenseDataProviderType.SceneCapture, out var providerState);
|
||||
if (providerState == PxrSenseDataProviderState.Running)
|
||||
{
|
||||
PXR_MixedReality.StopSenseDataProvider(PxrSenseDataProviderType.SceneCapture);
|
||||
}
|
||||
|
||||
PXR_Plugin.MixedReality.UPxr_DestroySenseDataProvider(
|
||||
PXR_Plugin.MixedReality.UPxr_GetSenseDataProviderHandle(PxrSenseDataProviderType.SceneCapture));
|
||||
|
||||
base.OnSessionExiting(xrSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0b5403262c64d5888bf5672e1e1f3bb
|
||||
timeCreated: 1721806849
|
||||
@@ -0,0 +1,96 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
using UnityEngine.XR.ARSubsystems;
|
||||
#endif
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "PICO Spatial Anchor",
|
||||
Hidden = false,
|
||||
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = "1.0.0",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class PICOSpatialAnchor: OpenXRFeature
|
||||
{
|
||||
public const string featureId = "com.pico.openxr.feature.spatialanchor";
|
||||
public const string extensionString = "XR_PICO_spatial_anchor XR_PICO_spatial_sensing XR_EXT_future";
|
||||
|
||||
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_PICO_spatial_anchor");
|
||||
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
base.OnSessionCreate(xrSession);
|
||||
PXR_Plugin.MixedReality.UPxr_CreateSpatialAnchorSenseDataProvider();
|
||||
}
|
||||
protected override void OnSessionExiting(ulong xrSession)
|
||||
{
|
||||
PXR_MixedReality.GetSenseDataProviderState(PxrSenseDataProviderType.SpatialAnchor, out var providerState);
|
||||
if (providerState == PxrSenseDataProviderState.Running)
|
||||
{
|
||||
PXR_MixedReality.StopSenseDataProvider(PxrSenseDataProviderType.SpatialAnchor);
|
||||
}
|
||||
|
||||
PXR_Plugin.MixedReality.UPxr_DestroySenseDataProvider(
|
||||
PXR_Plugin.MixedReality.UPxr_GetSenseDataProviderHandle(PxrSenseDataProviderType.SpatialAnchor));
|
||||
|
||||
base.OnSessionExiting(xrSession);
|
||||
}
|
||||
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
public bool isAnchorSubsystem=false;
|
||||
static List<XRAnchorSubsystemDescriptor> anchorSubsystemDescriptors = new List<XRAnchorSubsystemDescriptor>();
|
||||
protected override void OnSubsystemCreate()
|
||||
{
|
||||
base.OnSubsystemCreate();
|
||||
if (isAnchorSubsystem)
|
||||
{
|
||||
CreateSubsystem<XRAnchorSubsystemDescriptor, XRAnchorSubsystem>(
|
||||
anchorSubsystemDescriptors,
|
||||
PXR_AnchorSubsystem.k_SubsystemId);
|
||||
}
|
||||
|
||||
}
|
||||
protected override void OnSubsystemStart()
|
||||
{
|
||||
if (isAnchorSubsystem)
|
||||
{
|
||||
StartSubsystem<XRAnchorSubsystem>();
|
||||
}
|
||||
}
|
||||
protected override void OnSubsystemStop()
|
||||
{
|
||||
if (isAnchorSubsystem)
|
||||
{
|
||||
StopSubsystem<XRAnchorSubsystem>();
|
||||
}
|
||||
}
|
||||
protected override void OnSubsystemDestroy()
|
||||
{
|
||||
if (isAnchorSubsystem)
|
||||
{
|
||||
DestroySubsystem<XRAnchorSubsystem>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8b7731b990240c0b289e41fb880787b
|
||||
timeCreated: 1721806849
|
||||
@@ -0,0 +1,72 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
// using Unity.XR.CoreUtils;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "PICO Spatial Mesh",
|
||||
Hidden = false,
|
||||
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = "1.0.0",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class PICOSpatialMesh: OpenXRFeature
|
||||
{
|
||||
public const string featureId = "com.pico.openxr.feature.spatialmesh";
|
||||
public const string extensionString = "XR_PICO_spatial_mesh XR_PICO_spatial_sensing XR_EXT_future";
|
||||
private static List<XRMeshSubsystemDescriptor> meshSubsystemDescriptors = new List<XRMeshSubsystemDescriptor>();
|
||||
|
||||
public PxrMeshLod LOD;
|
||||
|
||||
private XRMeshSubsystem subsystem;
|
||||
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_PICO_spatial_mesh");
|
||||
protected override void OnSubsystemCreate()
|
||||
{
|
||||
base.OnSubsystemCreate();
|
||||
PXR_Plugin.Pxr_SetMeshLOD(Convert.ToUInt16(LOD));
|
||||
|
||||
}
|
||||
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
base.OnSessionCreate(xrSession);
|
||||
CreateSubsystem<XRMeshSubsystemDescriptor, XRMeshSubsystem>(meshSubsystemDescriptors, "PICO Mesh");
|
||||
}
|
||||
|
||||
protected override void OnSubsystemStop()
|
||||
{
|
||||
base.OnSubsystemStop();
|
||||
StopSubsystem<XRMeshSubsystem>();
|
||||
|
||||
}
|
||||
|
||||
protected override void OnSubsystemDestroy()
|
||||
{
|
||||
base.OnSubsystemDestroy();
|
||||
PXR_Plugin.MixedReality.UPxr_DisposeMesh();
|
||||
DestroySubsystem<XRMeshSubsystem>();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1248416ce414cd0a788c5240bec5766
|
||||
timeCreated: 1721806849
|
||||
@@ -0,0 +1,541 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Unity.XR.CoreUtils;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
using UnityEngine.XR.ARSubsystems;
|
||||
#endif
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.NativeTypes;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "OpenXR Passthrough",
|
||||
Hidden = false,
|
||||
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = PXR_Constants.SDKVersion,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class PassthroughFeature : OpenXRFeatureBase
|
||||
{
|
||||
public const string featureId = "com.pico.openxr.feature.passthrough";
|
||||
public const string extensionString = "XR_FB_passthrough";
|
||||
public const int XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB = 256;
|
||||
private static byte[] colorData;
|
||||
private static uint Size = 0;
|
||||
private static bool isInit = false;
|
||||
private static bool isPause = false;
|
||||
private static int _enableVideoSeeThrough=-1;
|
||||
public static event Action<bool> EnableVideoSeeThroughAction;
|
||||
private static bool isRefreshRecenterSpace = false;
|
||||
public static bool isExtensionEnable => OpenXRRuntime.IsExtensionEnabled(extensionString);
|
||||
[HideInInspector]
|
||||
public static bool EnableVideoSeeThrough
|
||||
{
|
||||
get => _enableVideoSeeThrough==1;
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
if (_enableVideoSeeThrough != 1)
|
||||
{
|
||||
_enableVideoSeeThrough = 1;
|
||||
EnableSeeThroughManual(value);
|
||||
|
||||
if (EnableVideoSeeThroughAction != null)
|
||||
{
|
||||
EnableVideoSeeThroughAction(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_enableVideoSeeThrough == 1)
|
||||
{
|
||||
_enableVideoSeeThrough = 0;
|
||||
EnableSeeThroughManual(value);
|
||||
|
||||
if (EnableVideoSeeThroughAction != null)
|
||||
{
|
||||
EnableVideoSeeThroughAction(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected override void OnSessionBegin(ulong xrSessionId)
|
||||
{
|
||||
if (!isRefreshRecenterSpace)
|
||||
{
|
||||
OpenXRSettings.RefreshRecenterSpace();
|
||||
isRefreshRecenterSpace = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetExtensionString()
|
||||
{
|
||||
return extensionString;
|
||||
}
|
||||
|
||||
public static void PassthroughStart()
|
||||
{
|
||||
passthroughStart();
|
||||
isPause = false;
|
||||
}
|
||||
|
||||
public static void PassthroughPause()
|
||||
{
|
||||
passthroughPause();
|
||||
isPause = true;
|
||||
}
|
||||
|
||||
//This interface has been changed to a private interface.
|
||||
//Please use the EnableVideoSeeThrough .
|
||||
private static bool EnableSeeThroughManual(bool value)
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isInit)
|
||||
{
|
||||
isInit = initializePassthrough();
|
||||
}
|
||||
|
||||
if (value)
|
||||
{
|
||||
createFullScreenLayer();
|
||||
if (!isPause)
|
||||
{
|
||||
passthroughStart();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
passthroughPause();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Destroy()
|
||||
{
|
||||
if (!isExtensionEnable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Passthrough_Destroy();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
private static void AllocateColorMapData(uint size)
|
||||
{
|
||||
if (colorData != null && size != colorData.Length)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
if (colorData == null)
|
||||
{
|
||||
colorData = new byte[size];
|
||||
}
|
||||
}
|
||||
|
||||
private static void Clear()
|
||||
{
|
||||
if (colorData != null)
|
||||
{
|
||||
colorData = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteVector3ToColorMap(int colorIndex, ref Vector3 color)
|
||||
{
|
||||
for (int c = 0; c < 3; c++)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(color[c]);
|
||||
Buffer.BlockCopy(bytes, 0, colorData, colorIndex * 12 + c * 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteFloatToColorMap(int index, float value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
Buffer.BlockCopy(bytes, 0, colorData, index * sizeof(float), sizeof(float));
|
||||
}
|
||||
|
||||
private static void WriteColorToColorMap(int colorIndex, ref Color color)
|
||||
{
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(color[c]);
|
||||
Buffer.BlockCopy(bytes, 0, colorData, colorIndex * 16 + c * 4, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static unsafe void SetBrightnessContrastSaturation(ref PassthroughStyle style, float brightness = 0.0f,
|
||||
float contrast = 0.0f, float saturation = 0.0f)
|
||||
{
|
||||
style.enableColorMap = true;
|
||||
style.TextureColorMapType = PassthroughColorMapType.BrightnessContrastSaturation;
|
||||
Size = 3 * sizeof(float);
|
||||
AllocateColorMapData(Size);
|
||||
WriteFloatToColorMap(0, brightness);
|
||||
|
||||
WriteFloatToColorMap(1, contrast);
|
||||
|
||||
WriteFloatToColorMap(2, saturation);
|
||||
fixed (byte* p = colorData)
|
||||
{
|
||||
style.TextureColorMapData = (IntPtr)p;
|
||||
}
|
||||
|
||||
style.TextureColorMapDataSize = Size;
|
||||
StringBuilder str = new StringBuilder();
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
str.Append(colorData[i]);
|
||||
}
|
||||
|
||||
Debug.Log("SetPassthroughStyle SetBrightnessContrastSaturation colorData:" + str);
|
||||
}
|
||||
|
||||
public static unsafe void SetColorMapbyMonoToMono(ref PassthroughStyle style, int[] values)
|
||||
{
|
||||
if (values.Length != XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB)
|
||||
throw new ArgumentException("Must provide exactly 256 values");
|
||||
style.enableColorMap = true;
|
||||
style.TextureColorMapType = PassthroughColorMapType.MonoToMono;
|
||||
Size = XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB * 4;
|
||||
AllocateColorMapData(Size);
|
||||
Buffer.BlockCopy(values, 0, colorData, 0, (int)Size);
|
||||
|
||||
fixed (byte* p = colorData)
|
||||
{
|
||||
style.TextureColorMapData = (IntPtr)p;
|
||||
}
|
||||
|
||||
style.TextureColorMapDataSize = Size;
|
||||
}
|
||||
|
||||
public static unsafe void SetColorMapbyMonoToRgba(ref PassthroughStyle style, Color[] values)
|
||||
{
|
||||
if (values.Length != XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB)
|
||||
throw new ArgumentException("Must provide exactly 256 colors");
|
||||
|
||||
style.TextureColorMapType = PassthroughColorMapType.MonoToRgba;
|
||||
style.enableColorMap = true;
|
||||
Size = XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB * 4 * 4;
|
||||
|
||||
AllocateColorMapData(Size);
|
||||
|
||||
for (int i = 0; i < XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB; i++)
|
||||
{
|
||||
WriteColorToColorMap(i, ref values[i]);
|
||||
}
|
||||
|
||||
fixed (byte* p = colorData)
|
||||
{
|
||||
style.TextureColorMapData = (IntPtr)p;
|
||||
}
|
||||
|
||||
style.TextureColorMapDataSize = Size;
|
||||
}
|
||||
|
||||
public static _PassthroughStyle ToPassthroughStyle(PassthroughStyle c)
|
||||
{
|
||||
_PassthroughStyle mPassthroughStyle = new _PassthroughStyle();
|
||||
mPassthroughStyle.enableEdgeColor = (uint)(c.enableEdgeColor ? 1 : 0);
|
||||
mPassthroughStyle.enableColorMap = (uint)(c.enableColorMap ? 1 : 0);
|
||||
mPassthroughStyle.TextureOpacityFactor = c.TextureOpacityFactor;
|
||||
mPassthroughStyle.TextureColorMapType = c.TextureColorMapType;
|
||||
mPassthroughStyle.TextureColorMapDataSize = c.TextureColorMapDataSize;
|
||||
mPassthroughStyle.TextureColorMapData = c.TextureColorMapData;
|
||||
mPassthroughStyle.EdgeColor = new Colorf()
|
||||
{ r = c.EdgeColor.r, g = c.EdgeColor.g, b = c.EdgeColor.b, a = c.EdgeColor.a };
|
||||
return mPassthroughStyle;
|
||||
}
|
||||
|
||||
public static void SetPassthroughStyle(PassthroughStyle style)
|
||||
{
|
||||
setPassthroughStyle(ToPassthroughStyle(style));
|
||||
}
|
||||
|
||||
public static bool IsPassthroughSupported()
|
||||
{
|
||||
return isPassthroughSupported();
|
||||
}
|
||||
|
||||
|
||||
public static unsafe bool CreateTriangleMesh(int id, Vector3[] vertices, int[] triangles,
|
||||
GeometryInstanceTransform transform)
|
||||
{
|
||||
if (vertices == null || triangles == null || vertices.Length == 0 || triangles.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isInit)
|
||||
{
|
||||
isInit = initializePassthrough();
|
||||
}
|
||||
|
||||
int vertexCount = vertices.Length;
|
||||
int triangleCount = triangles.Length;
|
||||
|
||||
Size = (uint)vertexCount * 3 * 4;
|
||||
|
||||
AllocateColorMapData(Size);
|
||||
|
||||
for (int i = 0; i < vertexCount; i++)
|
||||
{
|
||||
WriteVector3ToColorMap(i, ref vertices[i]);
|
||||
}
|
||||
|
||||
IntPtr vertexDataPtr = IntPtr.Zero;
|
||||
|
||||
fixed (byte* p = colorData)
|
||||
{
|
||||
vertexDataPtr = (IntPtr)p;
|
||||
}
|
||||
|
||||
StringBuilder str = new StringBuilder();
|
||||
for (int i = 0; i < 3 * 4; i++)
|
||||
{
|
||||
str.Append(colorData[i]);
|
||||
}
|
||||
|
||||
Debug.Log("CreateTriangleMesh vertexDataPtr colorData:" + str);
|
||||
str.Clear();
|
||||
|
||||
Size = (uint)triangleCount * 4;
|
||||
AllocateColorMapData(Size);
|
||||
Buffer.BlockCopy(triangles, 0, colorData, 0, (int)Size);
|
||||
IntPtr triangleDataPtr = IntPtr.Zero;
|
||||
fixed (byte* p = colorData)
|
||||
{
|
||||
triangleDataPtr = (IntPtr)p;
|
||||
}
|
||||
|
||||
for (int i = 0; i < colorData.Length; i++)
|
||||
{
|
||||
str.Append(colorData[i]);
|
||||
}
|
||||
|
||||
// Debug.Log("CreateTriangleMesh triangleDataPtr colorData:" + str);
|
||||
//
|
||||
// Debug.Log("CreateTriangleMesh vertexDataPtr=" + vertexDataPtr + " vertexCount=" + vertexCount);
|
||||
// Debug.Log("CreateTriangleMesh triangleDataPtr=" + triangleDataPtr + " triangleCount=" + triangleCount);
|
||||
|
||||
XrResult result =
|
||||
createTriangleMesh(id, vertexDataPtr, vertexCount, triangleDataPtr, triangleCount, transform);
|
||||
Clear();
|
||||
if (result == XrResult.Success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void UpdateMeshTransform(int id, GeometryInstanceTransform transform)
|
||||
{
|
||||
updatePassthroughMeshTransform(id, transform);
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// Validation Rules for ARCameraFeature.
|
||||
/// </summary>
|
||||
protected override void GetValidationChecks(List<ValidationRule> rules, BuildTargetGroup targetGroup)
|
||||
{
|
||||
var AdditionalRules = new ValidationRule[]
|
||||
{
|
||||
new ValidationRule(this)
|
||||
{
|
||||
message = "Passthrough requires Camera clear flags set to solid color with alpha value zero.",
|
||||
checkPredicate = () =>
|
||||
{
|
||||
|
||||
var xrOrigin = FindObjectsOfType<XROrigin>();
|
||||
|
||||
if (xrOrigin != null && xrOrigin.Length > 0)
|
||||
{
|
||||
if (!xrOrigin[0].enabled) return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var camera = xrOrigin[0].Camera;
|
||||
if (camera == null) return true;
|
||||
|
||||
return camera.clearFlags == CameraClearFlags.SolidColor && Mathf.Approximately(camera.backgroundColor.a, 0);
|
||||
},
|
||||
fixItAutomatic = true,
|
||||
fixItMessage = "Set your XR Origin camera's Clear Flags to solid color with alpha value zero.",
|
||||
fixIt = () =>
|
||||
{
|
||||
var xrOrigin = FindObjectsOfType<XROrigin>();
|
||||
if (xrOrigin!=null&&xrOrigin.Length>0)
|
||||
{
|
||||
if (xrOrigin[0].enabled)
|
||||
{
|
||||
var camera = xrOrigin[0].Camera;
|
||||
if (camera != null )
|
||||
{
|
||||
camera.clearFlags = CameraClearFlags.SolidColor;
|
||||
Color clearColor = camera.backgroundColor;
|
||||
clearColor.a = 0;
|
||||
camera.backgroundColor = clearColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
error = false
|
||||
}
|
||||
};
|
||||
|
||||
rules.AddRange(AdditionalRules);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
public bool isCameraSubsystem=false;
|
||||
static List<XRCameraSubsystemDescriptor> s_CameraDescriptors = new List<XRCameraSubsystemDescriptor>();
|
||||
protected override void OnSubsystemCreate()
|
||||
{
|
||||
base.OnSubsystemCreate();
|
||||
if (isCameraSubsystem)
|
||||
{
|
||||
CreateSubsystem<XRCameraSubsystemDescriptor, XRCameraSubsystem>(
|
||||
s_CameraDescriptors,
|
||||
PXR_CameraSubsystem.k_SubsystemId);
|
||||
}
|
||||
|
||||
}
|
||||
protected override void OnSubsystemStart()
|
||||
{
|
||||
if (isCameraSubsystem)
|
||||
{
|
||||
StartSubsystem<XRCameraSubsystem>();
|
||||
}
|
||||
}
|
||||
protected override void OnSubsystemStop()
|
||||
{
|
||||
if (isCameraSubsystem)
|
||||
{
|
||||
StopSubsystem<XRCameraSubsystem>();
|
||||
}
|
||||
}
|
||||
protected override void OnSubsystemDestroy()
|
||||
{
|
||||
if (isCameraSubsystem)
|
||||
{
|
||||
DestroySubsystem<XRCameraSubsystem>();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
protected override void OnSessionStateChange(int oldState, int newState)
|
||||
{
|
||||
base.OnSessionStateChange(oldState, newState);
|
||||
if (newState == 1)
|
||||
{
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
if (isCameraSubsystem)
|
||||
{
|
||||
StopSubsystem<XRCameraSubsystem>();
|
||||
}else{
|
||||
if (_enableVideoSeeThrough!=-1)
|
||||
{
|
||||
EnableSeeThroughManual(false);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (_enableVideoSeeThrough!=-1)
|
||||
{
|
||||
EnableSeeThroughManual(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (newState == 5)
|
||||
{
|
||||
#if AR_FOUNDATION_5||AR_FOUNDATION_6
|
||||
if (isCameraSubsystem)
|
||||
{
|
||||
StartSubsystem<XRCameraSubsystem>();
|
||||
}else{
|
||||
if (_enableVideoSeeThrough!=-1)
|
||||
{
|
||||
EnableSeeThroughManual(EnableVideoSeeThrough);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (_enableVideoSeeThrough!=-1)
|
||||
{
|
||||
EnableSeeThroughManual(EnableVideoSeeThrough);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_InitializePassthrough", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool initializePassthrough();
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_CreateFullScreenLayer", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool createFullScreenLayer();
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_PassthroughStart", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void passthroughStart();
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_PassthroughPause", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void passthroughPause();
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_SetPassthroughStyle", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void setPassthroughStyle(_PassthroughStyle style);
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_IsPassthroughSupported", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool isPassthroughSupported();
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_Passthrough_Destroy", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void Passthrough_Destroy();
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_CreateTriangleMesh", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern XrResult createTriangleMesh(int id, IntPtr vertices, int vertexCount, IntPtr triangles,
|
||||
int triangleCount, GeometryInstanceTransform transform);
|
||||
|
||||
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, EntryPoint = "PICO_UpdatePassthroughMeshTransform",
|
||||
CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void updatePassthroughMeshTransform(int id, GeometryInstanceTransform transform);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25fd7afe1de6d1545bfb5621a8e3aad5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,86 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System;
|
||||
using Unity.XR.PXR;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.XR.OpenXR.Features.PICOSupport
|
||||
{
|
||||
public class PassthroughLayerFeature : LayerBase
|
||||
{
|
||||
private int id = 0;
|
||||
private Vector3[] vertices;
|
||||
private int[] triangles;
|
||||
private Mesh mesh;
|
||||
private bool isPassthroughSupported = false;
|
||||
private bool isCreateTriangleMesh = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
id = ID;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
MeshFilter meshFilter = this.gameObject.GetComponent<MeshFilter>();
|
||||
if (meshFilter == null)
|
||||
{
|
||||
Debug.LogError("Passthrough GameObject does not have a mesh component.");
|
||||
return;
|
||||
}
|
||||
|
||||
mesh = meshFilter.sharedMesh;
|
||||
vertices = mesh.vertices;
|
||||
triangles = mesh.triangles;
|
||||
isPassthroughSupported = PassthroughFeature.IsPassthroughSupported();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (isPassthroughSupported && !isCreateTriangleMesh)
|
||||
{
|
||||
GeometryInstanceTransform Transform = new GeometryInstanceTransform();
|
||||
UpdateCoords(true);
|
||||
GetCurrentTransform(ref Transform);
|
||||
isCreateTriangleMesh = PassthroughFeature.CreateTriangleMesh(id, vertices, triangles, Transform);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
Camera.onPostRender += OnPostRenderCallBack;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Camera.onPostRender -= OnPostRenderCallBack;
|
||||
}
|
||||
|
||||
|
||||
private void OnPostRenderCallBack(Camera cam)
|
||||
{
|
||||
GeometryInstanceTransform Transform = new GeometryInstanceTransform();
|
||||
UpdateCoords();
|
||||
GetCurrentTransform(ref Transform);
|
||||
PassthroughFeature.UpdateMeshTransform(id, Transform);
|
||||
}
|
||||
|
||||
void OnApplicationPause(bool pause)
|
||||
{
|
||||
if (isCreateTriangleMesh)
|
||||
{
|
||||
if (pause)
|
||||
{
|
||||
PassthroughFeature.PassthroughPause();
|
||||
}
|
||||
else
|
||||
{
|
||||
PassthroughFeature.PassthroughStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d56a853c0545c25418b6e768fdff0d71
|
||||
timeCreated: 1694522562
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd592918e6931274a8da93e7707e25b1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,742 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.XR.OpenXR.Features.Interactions
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of PICO TouchControllers interaction profiles in OpenXR.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "PICO4 Touch Controller Profile",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
Desc = "Allows for mapping input to the PICO4 Touch Controller interaction profile.",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = "1.0.0",
|
||||
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class PICO4ControllerProfile : OpenXRInteractionFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.unity.openxr.feature.input.PICO4touch";
|
||||
|
||||
/// <summary>
|
||||
/// An Input System device based on the hand interaction profile in the PICO Touch Controller</a>.
|
||||
/// </summary>
|
||||
[Preserve, InputControlLayout(displayName = "PICO4 Touch Controller (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" })]
|
||||
public class PICO4TouchController : XRControllerWithRumble
|
||||
{
|
||||
/// <summary>
|
||||
/// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents the <see cref="PICO4TouchControllerProfile.thumbstick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary2DAxis", "Joystick" }, usage = "Primary2DAxis")]
|
||||
public Vector2Control thumbstick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="PICO4TouchControllerProfile.squeezeValue"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripAxis", "squeeze" }, usage = "Grip")]
|
||||
public AxisControl grip { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.squeezeClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripButton", "squeezeClicked" }, usage = "GripButton")]
|
||||
public ButtonControl gripPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.menu"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary", "menuButton" }, usage = "Menu")]
|
||||
public ButtonControl menu { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.system"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "systemButton" }, usage = "system")]
|
||||
public ButtonControl system { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.buttonA"/> <see cref="PICO4TouchControllerProfile.buttonX"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "A", "X", "buttonA", "buttonX" }, usage = "PrimaryButton")]
|
||||
public ButtonControl primaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.buttonATouch"/> <see cref="PICO4TouchControllerProfile.buttonYTouch"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "ATouched", "XTouched", "ATouch", "XTouch", "buttonATouched", "buttonXTouched" }, usage = "PrimaryTouch")]
|
||||
public ButtonControl primaryTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.buttonB"/> <see cref="PICO4TouchControllerProfile.buttonY"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "B", "Y", "buttonB", "buttonY" }, usage = "SecondaryButton")]
|
||||
public ButtonControl secondaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.buttonBTouch"/> <see cref="PICO4TouchControllerProfile.buttonYTouch"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "BTouched", "YTouched", "BTouch", "YTouch", "buttonBTouched", "buttonYTouched" }, usage = "SecondaryTouch")]
|
||||
public ButtonControl secondaryTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="PICO4TouchControllerProfile.trigger"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Trigger")]
|
||||
public AxisControl trigger { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.triggerClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexButton", "indexTouched", "triggerbutton" }, usage = "TriggerButton")]
|
||||
public ButtonControl triggerPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.triggerTouch"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexTouch", "indexNearTouched" }, usage = "TriggerTouch")]
|
||||
public ButtonControl triggerTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.thumbstickClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadPressed", "thumbstickClick", "joystickClicked" }, usage = "Primary2DAxisClick")]
|
||||
public ButtonControl thumbstickClicked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4TouchControllerProfile.thumbstickTouch"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadTouched", "thumbstickTouch", "joystickTouched" }, usage = "Primary2DAxisTouch")]
|
||||
public ButtonControl thumbstickTouched { get; private set; }
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICO4TouchControllerProfile.grip"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICO4TouchControllerProfile.aim"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "aimPose", usage = "Pointer")]
|
||||
public PoseControl pointer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28, usage = "IsTracked")]
|
||||
new public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for backwards compatibility with the XRSDK layouts. This represents the bit flag set to indicate what data is valid. This value is equivalent to mapping devicePose/trackingState.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 32, usage = "TrackingState")]
|
||||
new public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the device position. For the PICO Touch device, this is both the grip and the pointer position. This value is equivalent to mapping devicePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 36, noisy = true, alias = "gripPosition")]
|
||||
new public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the PICO Touch device, this is both the grip and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 48, noisy = true, alias = "gripOrientation")]
|
||||
new public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for back compatibility with the XRSDK layouts. This is the pointer position. This value is equivalent to mapping pointerPose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 96)]
|
||||
public Vector3Control pointerPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pointer rotation. This value is equivalent to mapping pointerPose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 108, alias = "pointerOrientation")]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="HapticControl"/> that represents the <see cref="PICO4TouchControllerProfile.haptic"/> binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Haptic")]
|
||||
public HapticControl haptic { get; private set; }
|
||||
|
||||
[Preserve, InputControl(usage = "BatteryLevel")]
|
||||
public AxisControl batteryLevel { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal call used to assign controls to the the correct element.
|
||||
/// </summary>
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
thumbstick = GetChildControl<Vector2Control>("thumbstick");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
triggerTouched = GetChildControl<ButtonControl>("triggerTouched");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
primaryButton = GetChildControl<ButtonControl>("primaryButton");
|
||||
primaryTouched = GetChildControl<ButtonControl>("primaryTouched");
|
||||
secondaryButton = GetChildControl<ButtonControl>("secondaryButton");
|
||||
secondaryTouched = GetChildControl<ButtonControl>("secondaryTouched");
|
||||
thumbstickClicked = GetChildControl<ButtonControl>("thumbstickClicked");
|
||||
thumbstickTouched = GetChildControl<ButtonControl>("thumbstickTouched");
|
||||
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
pointer = GetChildControl<PoseControl>("pointer");
|
||||
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
|
||||
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
|
||||
|
||||
haptic = GetChildControl<HapticControl>("haptic");
|
||||
batteryLevel = GetChildControl<AxisControl>("BatteryLevel");
|
||||
}
|
||||
}
|
||||
|
||||
public const string profile = "/interaction_profiles/bytedance/pico4_controller";
|
||||
|
||||
// Available Bindings
|
||||
// Left Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/x/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonX = "/input/x/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/x/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonXTouch = "/input/x/touch";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/y/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonY = "/input/y/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/y/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonYTouch = "/input/y/touch";
|
||||
|
||||
// Right Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/a/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonA = "/input/a/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/a/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonATouch = "/input/a/touch";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '..."/input/b/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonB = "/input/b/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/b/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonBTouch = "/input/b/touch";
|
||||
|
||||
// Both Hands
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string menu = "/input/menu/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.(may not be available for application use)
|
||||
/// </summary>
|
||||
public const string system = "/input/system/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerClick = "/input/trigger/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string trigger = "/input/trigger/value";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/trigger/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerTouch = "/input/trigger/touch";
|
||||
/// <summary>
|
||||
/// Constant for a Vector2 interaction binding '.../input/thumbstick' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstick = "/input/thumbstick";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/thumbstick/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickClick = "/input/thumbstick/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/thumbstick/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickTouch = "/input/thumbstick/touch";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeClick = "/input/squeeze/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/squeeze/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeValue = "/input/squeeze/value";
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string grip = "/input/grip/pose";
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string aim = "/input/aim/pose";
|
||||
/// <summary>
|
||||
/// Constant for a haptic interaction binding '.../output/haptic' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string haptic = "/output/haptic";
|
||||
|
||||
public const string batteryLevel = "/input/battery/value";
|
||||
|
||||
private const string kDeviceLocalizedName = "PICO4 Touch Controller OpenXR";
|
||||
|
||||
/// <summary>
|
||||
/// The OpenXR Extension string. This extension defines the interaction profile for PICO Neo3 and PICO 4 Controllers.
|
||||
/// /// </summary>
|
||||
public const string extensionString = "XR_BD_controller_interaction";
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RegisterLayout(typeof(PICO4TouchController),
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RemoveLayout(nameof(PICO4TouchController));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "PICO4TouchController",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "PICO",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left),
|
||||
userPath = UserPaths.leftHand
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right),
|
||||
userPath = UserPaths.rightHand
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
// Grip
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "grip",
|
||||
localizedName = "Grip",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Grip"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeValue,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Grip Pressed
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "gripPressed",
|
||||
localizedName = "Grip Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"GripButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//A / X Press
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primaryButton",
|
||||
localizedName = "Primary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonX,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonA,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//A / X Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primaryTouched",
|
||||
localizedName = "Primary Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonXTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonATouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//B / Y Press
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "secondaryButton",
|
||||
localizedName = "Secondary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"SecondaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonY,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonB,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//B / Y Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "secondaryTouched",
|
||||
localizedName = "Secondary Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"SecondaryTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonYTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonBTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
// Menu
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "menu",
|
||||
localizedName = "Menu",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Menu"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = menu,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
}
|
||||
}
|
||||
},
|
||||
// System
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "system",
|
||||
localizedName = "system",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"System"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = system,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "trigger",
|
||||
localizedName = "Trigger",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Trigger"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = trigger,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger Pressed
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerPressed",
|
||||
localizedName = "Trigger Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Trigger Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerTouched",
|
||||
localizedName = "Trigger Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Joystick
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstick",
|
||||
localizedName = "Thumbstick",
|
||||
type = ActionType.Axis2D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxis"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Thumbstick Clicked
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickClicked",
|
||||
localizedName = "Thumbstick Clicked",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisClick"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Thumbstick Touched
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickTouched",
|
||||
localizedName = "Thumbstick Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Device Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicePose",
|
||||
localizedName = "Device Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = grip,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Pointer Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "pointer",
|
||||
localizedName = "Pointer Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Pointer"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = aim,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "batteryLevel",
|
||||
localizedName = "BatteryLevel",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"BatteryLevel"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = batteryLevel,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Haptics
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "haptic",
|
||||
localizedName = "Haptic Output",
|
||||
type = ActionType.Vibrate,
|
||||
usages = new List<string>() { "Haptic" },
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = haptic,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
protected override string GetDeviceLayoutName()
|
||||
{
|
||||
return nameof(PICO4TouchController);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fc69ec2fe7250b429391581208e2fbe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,743 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.XR.OpenXR.Features.Interactions
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of PICO TouchControllers interaction profiles in OpenXR.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "PICO4 Ultra Touch Controller Profile",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
Desc = "Allows for mapping input to the PICO4 Ultra Touch Controller interaction profile.",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = "1.0.0",
|
||||
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class PICO4UltraControllerProfile : OpenXRInteractionFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.unity.openxr.feature.input.PICO4Ultratouch";
|
||||
|
||||
/// <summary>
|
||||
/// An Input System device based on the hand interaction profile in the PICO Touch Controller</a>.
|
||||
/// </summary>
|
||||
[Preserve, InputControlLayout(displayName = "PICO4 Ultra Touch Controller (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" })]
|
||||
public class PICO4UltraController : XRControllerWithRumble
|
||||
{
|
||||
/// <summary>
|
||||
/// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents the <see cref="PICO4UltraControllerProfile.thumbstick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary2DAxis", "Joystick" }, usage = "Primary2DAxis")]
|
||||
public Vector2Control thumbstick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="PICO4UltraControllerProfile.squeezeValue"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripAxis", "squeeze" }, usage = "Grip")]
|
||||
public AxisControl grip { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.squeezeClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripButton", "squeezeClicked" }, usage = "GripButton")]
|
||||
public ButtonControl gripPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.menu"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary", "menuButton" }, usage = "Menu")]
|
||||
public ButtonControl menu { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.system"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "systemButton" }, usage = "system")]
|
||||
public ButtonControl system { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.buttonA"/> <see cref="PICO4UltraControllerProfile.buttonX"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "A", "X", "buttonA", "buttonX" }, usage = "PrimaryButton")]
|
||||
public ButtonControl primaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.buttonATouch"/> <see cref="PICO4UltraControllerProfile.buttonYTouch"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "ATouched", "XTouched", "ATouch", "XTouch", "buttonATouched", "buttonXTouched" }, usage = "PrimaryTouch")]
|
||||
public ButtonControl primaryTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.buttonB"/> <see cref="PICO4UltraControllerProfile.buttonY"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "B", "Y", "buttonB", "buttonY" }, usage = "SecondaryButton")]
|
||||
public ButtonControl secondaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.buttonBTouch"/> <see cref="PICO4UltraControllerProfile.buttonYTouch"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "BTouched", "YTouched", "BTouch", "YTouch", "buttonBTouched", "buttonYTouched" }, usage = "SecondaryTouch")]
|
||||
public ButtonControl secondaryTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="PICO4UltraControllerProfile.trigger"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Trigger")]
|
||||
public AxisControl trigger { get; private set; }
|
||||
|
||||
[Preserve, InputControl(usage = "BatteryLevel")]
|
||||
public AxisControl batteryLevel { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.triggerClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexButton", "indexTouched", "triggerbutton" }, usage = "TriggerButton")]
|
||||
public ButtonControl triggerPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.triggerTouch"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexTouch", "indexNearTouched" }, usage = "TriggerTouch")]
|
||||
public ButtonControl triggerTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.thumbstickClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadPressed", "thumbstickClick", "joystickClicked" }, usage = "Primary2DAxisClick")]
|
||||
public ButtonControl thumbstickClicked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICO4UltraControllerProfile.thumbstickTouch"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadTouched", "thumbstickTouch", "joystickTouched" }, usage = "Primary2DAxisTouch")]
|
||||
public ButtonControl thumbstickTouched { get; private set; }
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICO4UltraControllerProfile.grip"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICO4UltraControllerProfile.aim"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "aimPose", usage = "Pointer")]
|
||||
public PoseControl pointer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28, usage = "IsTracked")]
|
||||
new public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for backwards compatibility with the XRSDK layouts. This represents the bit flag set to indicate what data is valid. This value is equivalent to mapping devicePose/trackingState.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 32, usage = "TrackingState")]
|
||||
new public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the device position. For the PICO Touch device, this is both the grip and the pointer position. This value is equivalent to mapping devicePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 36, noisy = true, alias = "gripPosition")]
|
||||
new public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the PICO Touch device, this is both the grip and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 48, noisy = true, alias = "gripOrientation")]
|
||||
new public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for back compatibility with the XRSDK layouts. This is the pointer position. This value is equivalent to mapping pointerPose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 96)]
|
||||
public Vector3Control pointerPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pointer rotation. This value is equivalent to mapping pointerPose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 108, alias = "pointerOrientation")]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="HapticControl"/> that represents the <see cref="PICO4UltraControllerProfile.haptic"/> binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Haptic")]
|
||||
public HapticControl haptic { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal call used to assign controls to the the correct element.
|
||||
/// </summary>
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
thumbstick = GetChildControl<Vector2Control>("thumbstick");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
triggerTouched = GetChildControl<ButtonControl>("triggerTouched");
|
||||
batteryLevel = GetChildControl<AxisControl>("BatteryLevel");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
primaryButton = GetChildControl<ButtonControl>("primaryButton");
|
||||
primaryTouched = GetChildControl<ButtonControl>("primaryTouched");
|
||||
secondaryButton = GetChildControl<ButtonControl>("secondaryButton");
|
||||
secondaryTouched = GetChildControl<ButtonControl>("secondaryTouched");
|
||||
thumbstickClicked = GetChildControl<ButtonControl>("thumbstickClicked");
|
||||
thumbstickTouched = GetChildControl<ButtonControl>("thumbstickTouched");
|
||||
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
pointer = GetChildControl<PoseControl>("pointer");
|
||||
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
|
||||
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
|
||||
|
||||
haptic = GetChildControl<HapticControl>("haptic");
|
||||
}
|
||||
}
|
||||
|
||||
public const string profile = "/interaction_profiles/bytedance/pico4s_controller";
|
||||
|
||||
// Available Bindings
|
||||
// Left Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/x/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonX = "/input/x/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/x/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonXTouch = "/input/x/touch";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/y/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonY = "/input/y/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/y/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonYTouch = "/input/y/touch";
|
||||
|
||||
// Right Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/a/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonA = "/input/a/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/a/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonATouch = "/input/a/touch";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '..."/input/b/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonB = "/input/b/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/b/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonBTouch = "/input/b/touch";
|
||||
|
||||
// Both Hands
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string menu = "/input/menu/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.(may not be available for application use)
|
||||
/// </summary>
|
||||
public const string system = "/input/system/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerClick = "/input/trigger/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string trigger = "/input/trigger/value";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/trigger/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerTouch = "/input/trigger/touch";
|
||||
/// <summary>
|
||||
/// Constant for a Vector2 interaction binding '.../input/thumbstick' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstick = "/input/thumbstick";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/thumbstick/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickClick = "/input/thumbstick/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/thumbstick/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickTouch = "/input/thumbstick/touch";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeClick = "/input/squeeze/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/squeeze/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeValue = "/input/squeeze/value";
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string grip = "/input/grip/pose";
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string aim = "/input/aim/pose";
|
||||
/// <summary>
|
||||
/// Constant for a haptic interaction binding '.../output/haptic' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string haptic = "/output/haptic";
|
||||
|
||||
public const string batteryLevel = "/input/battery/value";
|
||||
|
||||
private const string kDeviceLocalizedName = "PICO4 Ultra Touch Controller OpenXR";
|
||||
|
||||
/// <summary>
|
||||
/// The OpenXR Extension string. This extension defines the interaction profile for PICO Neo3 and PICO 4 Controllers.
|
||||
/// /// </summary>
|
||||
public const string extensionString = "XR_BD_controller_interaction";
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RegisterLayout(typeof(PICO4UltraController),
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RemoveLayout(nameof(PICO4UltraController));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "PICO4UltraController",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "PICO",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left),
|
||||
userPath = UserPaths.leftHand
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right),
|
||||
userPath = UserPaths.rightHand
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
// Grip
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "grip",
|
||||
localizedName = "Grip",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Grip"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeValue,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Grip Pressed
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "gripPressed",
|
||||
localizedName = "Grip Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"GripButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//A / X Press
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primaryButton",
|
||||
localizedName = "Primary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonX,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonA,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//A / X Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primaryTouched",
|
||||
localizedName = "Primary Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonXTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonATouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//B / Y Press
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "secondaryButton",
|
||||
localizedName = "Secondary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"SecondaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonY,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonB,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//B / Y Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "secondaryTouched",
|
||||
localizedName = "Secondary Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"SecondaryTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonYTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonBTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
// Menu
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "menu",
|
||||
localizedName = "Menu",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Menu"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = menu,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
}
|
||||
}
|
||||
},
|
||||
// System
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "system",
|
||||
localizedName = "system",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"System"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = system,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "trigger",
|
||||
localizedName = "Trigger",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Trigger"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = trigger,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger Pressed
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerPressed",
|
||||
localizedName = "Trigger Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Trigger Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerTouched",
|
||||
localizedName = "Trigger Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Joystick
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstick",
|
||||
localizedName = "Thumbstick",
|
||||
type = ActionType.Axis2D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxis"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Thumbstick Clicked
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickClicked",
|
||||
localizedName = "Thumbstick Clicked",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisClick"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Thumbstick Touched
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickTouched",
|
||||
localizedName = "Thumbstick Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Device Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicePose",
|
||||
localizedName = "Device Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = grip,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Pointer Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "pointer",
|
||||
localizedName = "Pointer Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Pointer"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = aim,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "batteryLevel",
|
||||
localizedName = "BatteryLevel",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"BatteryLevel"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = batteryLevel,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Haptics
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "haptic",
|
||||
localizedName = "Haptic Output",
|
||||
type = ActionType.Vibrate,
|
||||
usages = new List<string>() { "Haptic" },
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = haptic,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
protected override string GetDeviceLayoutName()
|
||||
{
|
||||
return nameof(PICO4UltraController);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4891747df4d5e714f9fec69b98639e2c
|
||||
timeCreated: 1712037227
|
||||
@@ -0,0 +1,496 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.XR.OpenXR.Features.Interactions
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of PICO TouchControllers interaction profiles in OpenXR.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "PICOG3 Touch Controller Profile",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
Desc = "Allows for mapping input to the PICOG3 Touch Controller interaction profile.",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = "1.0.0",
|
||||
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class PICOG3ControllerProfile : OpenXRInteractionFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.unity.openxr.feature.input.PICOG3touch";
|
||||
|
||||
/// <summary>
|
||||
/// An Input System device based on the hand interaction profile in the PICO Touch Controller</a>.
|
||||
/// </summary>
|
||||
[Preserve,
|
||||
InputControlLayout(displayName = "PICOG3 Touch Controller (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" })]
|
||||
public class PICOG3TouchController : XRControllerWithRumble
|
||||
{
|
||||
/// <summary>
|
||||
/// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents the <see cref="PICOG3TouchControllerProfile.thumbstick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary2DAxis", "Joystick" }, usage = "Primary2DAxis")]
|
||||
public Vector2Control thumbstick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICOG3TouchControllerProfile.menu"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary", "menuButton" }, usage = "Menu")]
|
||||
public ButtonControl menu { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICOG3TouchControllerProfile.system"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "systemButton" }, usage = "system")]
|
||||
public ButtonControl system { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="PICOG3TouchControllerProfile.trigger"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Trigger")]
|
||||
public AxisControl trigger { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICOG3TouchControllerProfile.triggerClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve,
|
||||
InputControl(aliases = new[] { "indexButton", "indexTouched", "triggerbutton" }, usage = "TriggerButton")]
|
||||
public ButtonControl triggerPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICOG3TouchControllerProfile.thumbstickClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve,
|
||||
InputControl(aliases = new[] { "JoystickOrPadPressed", "thumbstickClick", "joystickClicked" },
|
||||
usage = "Primary2DAxisClick")]
|
||||
public ButtonControl thumbstickClicked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents information from the <see cref="HTCViveControllerProfile.trackpad"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary2DAxis", "touchpadaxes", "touchpad" }, usage = "Primary2DAxis")]
|
||||
public Vector2Control trackpad { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents information from the <see cref="HTCViveControllerProfile.trackpadClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "joystickorpadpressed", "touchpadpressed" }, usage = "Primary2DAxisClick")]
|
||||
public ButtonControl trackpadClicked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICOG3TouchControllerProfile.grip"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICOG3TouchControllerProfile.aim"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "aimPose", usage = "Pointer")]
|
||||
public PoseControl pointer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28, usage = "IsTracked")]
|
||||
new public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for backwards compatibility with the XRSDK layouts. This represents the bit flag set to indicate what data is valid. This value is equivalent to mapping devicePose/trackingState.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 32, usage = "TrackingState")]
|
||||
new public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the device position. For the PICO Touch device, this is both the grip and the pointer position. This value is equivalent to mapping devicePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 36, noisy = true, alias = "gripPosition")]
|
||||
new public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the PICO Touch device, this is both the grip and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 48, noisy = true, alias = "gripOrientation")]
|
||||
new public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for back compatibility with the XRSDK layouts. This is the pointer position. This value is equivalent to mapping pointerPose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 96)]
|
||||
public Vector3Control pointerPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pointer rotation. This value is equivalent to mapping pointerPose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 108, alias = "pointerOrientation")]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
|
||||
[Preserve, InputControl(usage = "BatteryLevel")]
|
||||
public AxisControl batteryLevel { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal call used to assign controls to the the correct element.
|
||||
/// </summary>
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
thumbstick = GetChildControl<Vector2Control>("thumbstick");
|
||||
// trigger = GetChildControl<AxisControl>("trigger");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
trackpad = GetChildControl<Vector2Control>("trackpad");
|
||||
trackpadClicked = GetChildControl<ButtonControl>("trackpadClicked");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
thumbstickClicked = GetChildControl<ButtonControl>("thumbstickClicked");
|
||||
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
pointer = GetChildControl<PoseControl>("pointer");
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
|
||||
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
|
||||
batteryLevel = GetChildControl<AxisControl>("BatteryLevel");
|
||||
}
|
||||
}
|
||||
|
||||
public const string profile = "/interaction_profiles/bytedance/pico_g3_controller";
|
||||
|
||||
// Available Bindings
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/thumbstick/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickClick = "/input/thumbstick/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a Vector2 interaction binding '.../input/thumbstick' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstick = "/input/thumbstick";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerClick = "/input/trigger/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string trigger = "/input/trigger/value";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string aim = "/input/aim/pose";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string menu = "/input/menu/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.(may not be available for application use)
|
||||
/// </summary>
|
||||
public const string system = "/input/system/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a Vector2 interaction binding '.../input/trackpad' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string trackpad = "/input/trackpad";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/trackpad/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string trackpadClick = "/input/trackpad/click";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string grip = "/input/grip/pose";
|
||||
|
||||
public const string batteryLevel = "/input/battery/value";
|
||||
|
||||
private const string kDeviceLocalizedName = "PICOG3 Touch Controller OpenXR";
|
||||
|
||||
/// <summary>
|
||||
/// The OpenXR Extension string. This extension defines the interaction profile for PICO Neo3 and PICO 4 Controllers.
|
||||
/// /// </summary>
|
||||
public const string extensionString = "XR_BD_controller_interaction";
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RegisterLayout(typeof(PICOG3TouchController),
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RemoveLayout(nameof(PICOG3TouchController));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "PICOG3TouchController",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "PICO",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left),
|
||||
userPath = UserPaths.leftHand
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right),
|
||||
userPath = UserPaths.rightHand
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "trigger",
|
||||
localizedName = "Trigger",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Trigger"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = trigger,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Menu
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "menu",
|
||||
localizedName = "Menu",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Menu"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = menu,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// System
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "system",
|
||||
localizedName = "system",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"System"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = system,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger Pressed
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerPressed",
|
||||
localizedName = "Trigger Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Joystick
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstick",
|
||||
localizedName = "Thumbstick",
|
||||
type = ActionType.Axis2D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxis"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Thumbstick Clicked
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickClicked",
|
||||
localizedName = "Thumbstick Clicked",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisClick"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "trackpad",
|
||||
localizedName = "Trackpad",
|
||||
type = ActionType.Axis2D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxis"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = trackpad,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "trackpadClicked",
|
||||
localizedName = "Trackpad Clicked",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisClick"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = trackpadClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Device Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicePose",
|
||||
localizedName = "Device Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = grip,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "batteryLevel",
|
||||
localizedName = "BatteryLevel",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"BatteryLevel"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = batteryLevel,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Pointer Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "pointer",
|
||||
localizedName = "Pointer Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Pointer"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = aim,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
protected override string GetDeviceLayoutName()
|
||||
{
|
||||
return nameof(PICOG3TouchController);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db9703b1b47dbc048be32403e18dcd7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,738 @@
|
||||
#if PICO_OPENXR_SDK
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.XR.OpenXR.Features.Interactions
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of PICO TouchControllers interaction profiles in OpenXR.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "PICO Neo3 Touch Controller Profile",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
Company = "PICO",
|
||||
Desc = "Allows for mapping input to the PICO Neo3 Touch Controller interaction profile.",
|
||||
OpenxrExtensionStrings = extensionString,
|
||||
Version = "1.0.0",
|
||||
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class PICONeo3ControllerProfile : OpenXRInteractionFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.unity.openxr.feature.input.PICONeo3touch";
|
||||
|
||||
/// <summary>
|
||||
/// An Input System device based on the hand interaction profile in the PICO Touch Controller</a>.
|
||||
/// </summary>
|
||||
[Preserve, InputControlLayout(displayName = "PICO Neo3 Touch Controller (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" })]
|
||||
public class PICONeo3Controller : XRControllerWithRumble
|
||||
{
|
||||
/// <summary>
|
||||
/// A [Vector2Control](xref:UnityEngine.InputSystem.Controls.Vector2Control) that represents the <see cref="PICONeo3TouchControllerProfile.thumbstick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary2DAxis", "Joystick" }, usage = "Primary2DAxis")]
|
||||
public Vector2Control thumbstick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="PICONeo3TouchControllerProfile.squeezeValue"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripAxis", "squeeze" }, usage = "Grip")]
|
||||
public AxisControl grip { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.squeezeClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripButton", "squeezeClicked" }, usage = "GripButton")]
|
||||
public ButtonControl gripPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.menu"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary", "menuButton" }, usage = "Menu")]
|
||||
public ButtonControl menu { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.system"/> OpenXR bindings.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "systemButton" }, usage = "system")]
|
||||
public ButtonControl system { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.buttonA"/> <see cref="PICONeo3TouchControllerProfile.buttonX"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "A", "X", "buttonA", "buttonX" }, usage = "PrimaryButton")]
|
||||
public ButtonControl primaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.buttonATouch"/> <see cref="PICONeo3TouchControllerProfile.buttonYTouch"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "ATouched", "XTouched", "ATouch", "XTouch", "buttonATouched", "buttonXTouched" }, usage = "PrimaryTouch")]
|
||||
public ButtonControl primaryTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.buttonB"/> <see cref="PICONeo3TouchControllerProfile.buttonY"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "B", "Y", "buttonB", "buttonY" }, usage = "SecondaryButton")]
|
||||
public ButtonControl secondaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.buttonBTouch"/> <see cref="PICONeo3TouchControllerProfile.buttonYTouch"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "BTouched", "YTouched", "BTouch", "YTouch", "buttonBTouched", "buttonYTouched" }, usage = "SecondaryTouch")]
|
||||
public ButtonControl secondaryTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [AxisControl](xref:UnityEngine.InputSystem.Controls.AxisControl) that represents the <see cref="PICONeo3TouchControllerProfile.trigger"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Trigger")]
|
||||
public AxisControl trigger { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.triggerClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexButton", "indexTouched", "triggerbutton" }, usage = "TriggerButton")]
|
||||
public ButtonControl triggerPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.triggerTouch"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "indexTouch", "indexNearTouched" }, usage = "TriggerTouch")]
|
||||
public ButtonControl triggerTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.thumbstickClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadPressed", "thumbstickClick", "joystickClicked" }, usage = "Primary2DAxisClick")]
|
||||
public ButtonControl thumbstickClicked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) that represents the <see cref="PICONeo3TouchControllerProfile.thumbstickTouch"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "JoystickOrPadTouched", "thumbstickTouch", "joystickTouched" }, usage = "Primary2DAxisTouch")]
|
||||
public ButtonControl thumbstickTouched { get; private set; }
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICONeo3TouchControllerProfile.grip"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, aliases = new[] { "device", "gripPose" }, usage = "Device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> that represents the <see cref="PICONeo3TouchControllerProfile.aim"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "aimPose", usage = "Pointer")]
|
||||
public PoseControl pointer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [ButtonControl](xref:UnityEngine.InputSystem.Controls.ButtonControl) required for backwards compatibility with the XRSDK layouts. This represents the overall tracking state of the device. This value is equivalent to mapping devicePose/isTracked.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28, usage = "IsTracked")]
|
||||
new public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [IntegerControl](xref:UnityEngine.InputSystem.Controls.IntegerControl) required for backwards compatibility with the XRSDK layouts. This represents the bit flag set to indicate what data is valid. This value is equivalent to mapping devicePose/trackingState.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 32, usage = "TrackingState")]
|
||||
new public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for backwards compatibility with the XRSDK layouts. This is the device position. For the PICO Touch device, this is both the grip and the pointer position. This value is equivalent to mapping devicePose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 36, noisy = true, alias = "gripPosition")]
|
||||
new public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the device orientation. For the PICO Touch device, this is both the grip and the pointer rotation. This value is equivalent to mapping devicePose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 48, noisy = true, alias = "gripOrientation")]
|
||||
new public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [Vector3Control](xref:UnityEngine.InputSystem.Controls.Vector3Control) required for back compatibility with the XRSDK layouts. This is the pointer position. This value is equivalent to mapping pointerPose/position.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 96)]
|
||||
public Vector3Control pointerPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A [QuaternionControl](xref:UnityEngine.InputSystem.Controls.QuaternionControl) required for backwards compatibility with the XRSDK layouts. This is the pointer rotation. This value is equivalent to mapping pointerPose/rotation.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 108, alias = "pointerOrientation")]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="HapticControl"/> that represents the <see cref="PICONeo3TouchControllerProfile.haptic"/> binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Haptic")]
|
||||
public HapticControl haptic { get; private set; }
|
||||
[Preserve, InputControl(usage = "BatteryLevel")]
|
||||
public AxisControl batteryLevel { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal call used to assign controls to the the correct element.
|
||||
/// </summary>
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
thumbstick = GetChildControl<Vector2Control>("thumbstick");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
triggerTouched = GetChildControl<ButtonControl>("triggerTouched");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
primaryButton = GetChildControl<ButtonControl>("primaryButton");
|
||||
primaryTouched = GetChildControl<ButtonControl>("primaryTouched");
|
||||
secondaryButton = GetChildControl<ButtonControl>("secondaryButton");
|
||||
secondaryTouched = GetChildControl<ButtonControl>("secondaryTouched");
|
||||
thumbstickClicked = GetChildControl<ButtonControl>("thumbstickClicked");
|
||||
thumbstickTouched = GetChildControl<ButtonControl>("thumbstickTouched");
|
||||
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
pointer = GetChildControl<PoseControl>("pointer");
|
||||
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
|
||||
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
|
||||
batteryLevel = GetChildControl<AxisControl>("BatteryLevel");
|
||||
haptic = GetChildControl<HapticControl>("haptic");
|
||||
}
|
||||
}
|
||||
|
||||
public const string profile = "/interaction_profiles/bytedance/pico_neo3_controller";
|
||||
|
||||
// Available Bindings
|
||||
// Left Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/x/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonX = "/input/x/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/x/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonXTouch = "/input/x/touch";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/y/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonY = "/input/y/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/y/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.leftHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonYTouch = "/input/y/touch";
|
||||
|
||||
// Right Hand Only
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/a/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonA = "/input/a/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/a/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonATouch = "/input/a/touch";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '..."/input/b/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonB = "/input/b/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/b/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs. This binding is only available for the <see cref="OpenXRInteractionFeature.UserPaths.rightHand"/> user path.
|
||||
/// </summary>
|
||||
public const string buttonBTouch = "/input/b/touch";
|
||||
|
||||
// Both Hands
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/menu/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string menu = "/input/menu/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/system/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.(may not be available for application use)
|
||||
/// </summary>
|
||||
public const string system = "/input/system/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerClick = "/input/trigger/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string trigger = "/input/trigger/value";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/trigger/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerTouch = "/input/trigger/touch";
|
||||
/// <summary>
|
||||
/// Constant for a Vector2 interaction binding '.../input/thumbstick' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstick = "/input/thumbstick";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/thumbstick/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickClick = "/input/thumbstick/click";
|
||||
/// <summary>
|
||||
/// Constant for a boolean interaction binding '.../input/thumbstick/touch' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickTouch = "/input/thumbstick/touch";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeClick = "/input/squeeze/click";
|
||||
/// <summary>
|
||||
/// Constant for a float interaction binding '.../input/squeeze/value' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeValue = "/input/squeeze/value";
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string grip = "/input/grip/pose";
|
||||
/// <summary>
|
||||
/// Constant for a pose interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string aim = "/input/aim/pose";
|
||||
/// <summary>
|
||||
/// Constant for a haptic interaction binding '.../output/haptic' OpenXR Input Binding. Used by input subsystem to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string haptic = "/output/haptic";
|
||||
public const string batteryLevel = "/input/battery/value";
|
||||
|
||||
private const string kDeviceLocalizedName = "PICO Neo3 Touch Controller OpenXR";
|
||||
|
||||
/// <summary>
|
||||
/// The OpenXR Extension string. This extension defines the interaction profile for PICO Neo3 and PICO 4 Controllers.
|
||||
/// /// </summary>
|
||||
public const string extensionString = "XR_BD_controller_interaction";
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RegisterLayout(typeof(PICONeo3Controller),
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RemoveLayout(nameof(PICONeo3Controller));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "PICONeo3controller",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "PICO",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left),
|
||||
userPath = UserPaths.leftHand
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right),
|
||||
userPath = UserPaths.rightHand
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
// Grip
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "grip",
|
||||
localizedName = "Grip",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Grip"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeValue,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Grip Pressed
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "gripPressed",
|
||||
localizedName = "Grip Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"GripButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//A / X Press
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primaryButton",
|
||||
localizedName = "Primary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonX,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonA,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//A / X Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primaryTouched",
|
||||
localizedName = "Primary Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonXTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonATouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//B / Y Press
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "secondaryButton",
|
||||
localizedName = "Secondary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"SecondaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonY,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonB,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
//B / Y Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "secondaryTouched",
|
||||
localizedName = "Secondary Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"SecondaryTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonYTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = buttonBTouch,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
// Menu
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "menu",
|
||||
localizedName = "Menu",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Menu"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = menu,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// System
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "system",
|
||||
localizedName = "system",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"System"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = system,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "trigger",
|
||||
localizedName = "Trigger",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Trigger"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = trigger,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Trigger Pressed
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerPressed",
|
||||
localizedName = "Trigger Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Trigger Touch
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerTouched",
|
||||
localizedName = "Trigger Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Joystick
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstick",
|
||||
localizedName = "Thumbstick",
|
||||
type = ActionType.Axis2D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxis"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Thumbstick Clicked
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickClicked",
|
||||
localizedName = "Thumbstick Clicked",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisClick"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
//Thumbstick Touched
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickTouched",
|
||||
localizedName = "Thumbstick Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Device Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicePose",
|
||||
localizedName = "Device Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = grip,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Pointer Pose
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "pointer",
|
||||
localizedName = "Pointer Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Pointer"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = aim,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "batteryLevel",
|
||||
localizedName = "BatteryLevel",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"BatteryLevel"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = batteryLevel,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
// Haptics
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "haptic",
|
||||
localizedName = "Haptic Output",
|
||||
type = ActionType.Vibrate,
|
||||
usages = new List<string>() { "Haptic" },
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = haptic,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
protected override string GetDeviceLayoutName()
|
||||
{
|
||||
return nameof(PICONeo3Controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50d1481d756df2e4093342229c33de82
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,352 @@
|
||||
#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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7410d1eba61186c43a9ff128c59f364c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,129 @@
|
||||
#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;
|
||||
|
||||
|
||||
#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
|
||||
[OpenXRFeature(UiName = "PICO XR Support",
|
||||
Desc = "Necessary to deploy an PICO compatible app.",
|
||||
Company = "PICO",
|
||||
Version = PXR_Constants.SDKVersion,
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Android },
|
||||
CustomRuntimeLoaderBuildTargets = new[] { BuildTarget.Android },
|
||||
OpenxrExtensionStrings = OpenXrExtensionList,
|
||||
FeatureId = featureId
|
||||
)]
|
||||
#endif
|
||||
public class PICOFeature : OpenXRFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.unity.openxr.feature.pico";
|
||||
public const string OpenXrExtensionList = "XR_PICO_controller_interaction "+"XR_PICO_view_state";
|
||||
public bool isPicoSupport = false;
|
||||
public static Action<bool> onAppFocusedAction;
|
||||
|
||||
protected override void OnSessionStateChange(int oldState, int newState)
|
||||
{
|
||||
Debug.Log($"[PICOOpenXRExtensions] OnSessionStateChange: {oldState} -> {newState}");
|
||||
if (onAppFocusedAction != null)
|
||||
{
|
||||
onAppFocusedAction(newState == 5);
|
||||
}
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
|
||||
protected override void GetValidationChecks(List<ValidationRule> rules, BuildTargetGroup targetGroup)
|
||||
{
|
||||
OpenXRSettings settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
|
||||
|
||||
|
||||
var AdditionalRules = new ValidationRule[]
|
||||
{
|
||||
new ValidationRule(this)
|
||||
{
|
||||
message = "Only the PICO Touch Interaction Profile is supported right now.",
|
||||
checkPredicate = () =>
|
||||
{
|
||||
if (null == settings)
|
||||
return false;
|
||||
|
||||
bool touchFeatureEnabled = false;
|
||||
bool otherInteractionFeatureEnabled = false;
|
||||
|
||||
foreach (var feature in settings.GetFeatures<OpenXRInteractionFeature>())
|
||||
{
|
||||
if (feature.enabled)
|
||||
{
|
||||
if ((feature is PICONeo3ControllerProfile) ||
|
||||
(feature is PICO4UltraControllerProfile) || (feature is PICO4ControllerProfile) ||
|
||||
(feature is EyeGazeInteraction) || (feature is HandInteractionProfile) ||
|
||||
(feature is PalmPoseInteraction) || (feature is PICOG3ControllerProfile))
|
||||
touchFeatureEnabled = true;
|
||||
else
|
||||
otherInteractionFeatureEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return touchFeatureEnabled && !otherInteractionFeatureEnabled;
|
||||
},
|
||||
fixIt = () =>
|
||||
{
|
||||
if (null == settings)
|
||||
return;
|
||||
|
||||
foreach (var feature in settings.GetFeatures<OpenXRInteractionFeature>())
|
||||
{
|
||||
feature.enabled = ((feature is PICO4UltraControllerProfile) || (feature is PICO4ControllerProfile));
|
||||
}
|
||||
},
|
||||
error = true,
|
||||
}
|
||||
};
|
||||
|
||||
rules.AddRange(AdditionalRules);
|
||||
}
|
||||
|
||||
internal class PICOFeatureEditorWindow : EditorWindow
|
||||
{
|
||||
private Object feature;
|
||||
private Editor featureEditor;
|
||||
|
||||
public static EditorWindow Create(Object feature)
|
||||
{
|
||||
var window = EditorWindow.GetWindow<PICOFeatureEditorWindow>(true, "PICO Feature Configuration", true);
|
||||
window.feature = feature;
|
||||
window.featureEditor = Editor.CreateEditor((UnityEngine.Object)feature);
|
||||
return window;
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
featureEditor.OnInspectorGUI();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9b76292af5e4e389c642703b656f3b6
|
||||
timeCreated: 1737536725
|
||||
Reference in New Issue
Block a user