From f2601b7de354da76d4304c9d2ef62679eba10ab4 Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Wed, 14 Jan 2026 13:47:34 -0800 Subject: [PATCH 01/10] Fix permission issues related to gaze-based foveated rendering --- com.valvesoftware.openxr.utils/CHANGELOG.md | 4 ++ .../ValveOpenXRFoveatedRenderingBuildHooks.cs | 58 ------------------- .../ValveOpenXRFoveatedRenderingFeature.cs | 30 ++++++---- com.valvesoftware.openxr.utils/package.json | 2 +- 4 files changed, 23 insertions(+), 71 deletions(-) diff --git a/com.valvesoftware.openxr.utils/CHANGELOG.md b/com.valvesoftware.openxr.utils/CHANGELOG.md index 297d976..a845b4b 100644 --- a/com.valvesoftware.openxr.utils/CHANGELOG.md +++ b/com.valvesoftware.openxr.utils/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.0.2] - 2026-01-14 +### Fixed +- Fixed app permissions preventing gaze-based foveated rendering from being enabled. + ## [1.0.1] - 2026-01-12 ### Updating Frame Controller Interaction Path ### Added diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs index b9c5aff..da1e222 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs @@ -24,63 +24,5 @@ protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBui builder.SetBootConfigValue("xr-meta-enabled", "1"); #endif } - - protected override ManifestRequirement ProvideManifestRequirementExt() - { - var elementsToRemove = new List() - { - }; - - var elementsToAdd = new List() - { - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-feature" }, - Attributes = new Dictionary - { - { "name", "oculus.software.eye_tracking" }, - { "required", "true" } - } - }, - - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-permission" }, - Attributes = new Dictionary - { - { "name", "com.oculus.permission.EYE_TRACKING" } - } - }, - - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-permission" }, - Attributes = new Dictionary - { - { "name", "android.permission.EYE_TRACKING" } - - } - }, - - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-permission" }, - Attributes = new Dictionary - { - { "name", "android.permission.EYE_TRACKING_FINE" } - } - } - }; - - return new ManifestRequirement - { - SupportedXRLoaders = new HashSet() - { - typeof(OpenXRLoader) - }, - NewElements = elementsToAdd, - RemoveElements = elementsToRemove - }; - } } } \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs index c068ff2..c85e7b3 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs @@ -154,10 +154,10 @@ public bool eyeTrackedFoveation #else NativeMethods.MetaSetFoveationEyeTracked(_xrSession, value); #endif -#endif +#endif } } - + public bool GetFoveationEyeTrackedCenter(ref Vector2 leftEye, ref Vector2 rightEye) { if (_xrGetFoveationEyeTrackedStateMETA == null) @@ -169,7 +169,7 @@ public bool GetFoveationEyeTrackedCenter(ref Vector2 leftEye, ref Vector2 rightE { return false; } - + XrFoveationEyeTrackedStateMETA eyeTrackedState = new XrFoveationEyeTrackedStateMETA{type = XrStructureType.XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META}; XrResult result = _xrGetFoveationEyeTrackedStateMETA(_xrSession, ref eyeTrackedState); @@ -182,7 +182,7 @@ public bool GetFoveationEyeTrackedCenter(ref Vector2 leftEye, ref Vector2 rightE rightEye.Set(eyeTrackedState.foveationCenter[1].X, eyeTrackedState.foveationCenter[1].Y); return true; } - + #if UNITY_EDITOR protected override void GetValidationChecks(List results, BuildTargetGroup target) { @@ -238,14 +238,17 @@ protected override void GetValidationChecks(List r fixItMessage = "Enable Unity's Foveated Rendering feature" }); #endif - } -#endif + } +#endif protected override void OnSessionCreate(ulong xrSession) { _xrSession = xrSession; + + // Work around for Lepton not knowing about eye-tracking related permissions. + NativeMethods.Internal_SetHasEyeTrackingPermissions(true); } - + protected override void OnSessionStateChange(int oldState, int newState) { if (oldState == (int)XrSessionState.XR_SESSION_STATE_VISIBLE && @@ -258,7 +261,7 @@ protected override void OnSessionStateChange(int oldState, int newState) } } } - + #region OpenXR Plugin DLL Imports and Dependencies internal static class NativeMethods @@ -277,8 +280,11 @@ internal static class NativeMethods [DllImport("UnityOpenXR", EntryPoint = "MetaGetFoveationEyeTracked")] internal static extern void MetaGetFoveationEyeTracked(out bool isEyeTracked); + + [DllImport("UnityOpenXR", EntryPoint = "OculusFoveation_SetHasEyeTrackingPermissions")] + internal static extern void Internal_SetHasEyeTrackingPermissions([MarshalAs(UnmanagedType.I1)] bool value); } - + [StructLayout(LayoutKind.Sequential)] private struct XrFoveationEyeTrackedStateMETA { @@ -288,7 +294,7 @@ private struct XrFoveationEyeTrackedStateMETA public XrVector2f[] foveationCenter; public XrFoveationEyeTrackedStateFlagsMETA flags; } - + [Flags] private enum XrFoveationEyeTrackedStateFlagsMETA { @@ -296,7 +302,7 @@ private enum XrFoveationEyeTrackedStateFlagsMETA } #endregion - + #if UNITY_EDITOR internal class ValveOpenXRFoveatedRenderingFeatureEditorWindow : EditorWindow { @@ -332,7 +338,7 @@ internal enum XrSessionState XR_SESSION_STATE_EXITING = 8, XR_SESSION_STATE_MAX_ENUM = 0x7FFFFFFF } - + internal enum FoveatedRenderingLevel { Off = 0, diff --git a/com.valvesoftware.openxr.utils/package.json b/com.valvesoftware.openxr.utils/package.json index 38af848..b4ec618 100644 --- a/com.valvesoftware.openxr.utils/package.json +++ b/com.valvesoftware.openxr.utils/package.json @@ -1,7 +1,7 @@ { "name": "com.valvesoftware.openxr.utils", "displayName": "Valve OpenXR Utilities", - "version": "1.0.1", + "version": "1.0.2", "description": "The Valve OpenXR Utilities package provides support for OpenXR projects and their access to Unity's OpenXR functionality.", "dependencies": { "com.unity.xr.openxr": "1.10.0", From 09aef700b875f966fb421218862bc1b08f2547f1 Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:29:12 -0800 Subject: [PATCH 02/10] Fix permission issues related to gaze-based foveated rendering (#2) --- com.valvesoftware.openxr.utils/CHANGELOG.md | 4 ++ .../ValveOpenXRFoveatedRenderingBuildHooks.cs | 58 ------------------- .../ValveOpenXRFoveatedRenderingFeature.cs | 30 ++++++---- com.valvesoftware.openxr.utils/package.json | 2 +- 4 files changed, 23 insertions(+), 71 deletions(-) diff --git a/com.valvesoftware.openxr.utils/CHANGELOG.md b/com.valvesoftware.openxr.utils/CHANGELOG.md index 297d976..a845b4b 100644 --- a/com.valvesoftware.openxr.utils/CHANGELOG.md +++ b/com.valvesoftware.openxr.utils/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.0.2] - 2026-01-14 +### Fixed +- Fixed app permissions preventing gaze-based foveated rendering from being enabled. + ## [1.0.1] - 2026-01-12 ### Updating Frame Controller Interaction Path ### Added diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs index b9c5aff..da1e222 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs @@ -24,63 +24,5 @@ protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBui builder.SetBootConfigValue("xr-meta-enabled", "1"); #endif } - - protected override ManifestRequirement ProvideManifestRequirementExt() - { - var elementsToRemove = new List() - { - }; - - var elementsToAdd = new List() - { - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-feature" }, - Attributes = new Dictionary - { - { "name", "oculus.software.eye_tracking" }, - { "required", "true" } - } - }, - - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-permission" }, - Attributes = new Dictionary - { - { "name", "com.oculus.permission.EYE_TRACKING" } - } - }, - - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-permission" }, - Attributes = new Dictionary - { - { "name", "android.permission.EYE_TRACKING" } - - } - }, - - new ManifestElement() - { - ElementPath = new List { "manifest", "uses-permission" }, - Attributes = new Dictionary - { - { "name", "android.permission.EYE_TRACKING_FINE" } - } - } - }; - - return new ManifestRequirement - { - SupportedXRLoaders = new HashSet() - { - typeof(OpenXRLoader) - }, - NewElements = elementsToAdd, - RemoveElements = elementsToRemove - }; - } } } \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs index c068ff2..c85e7b3 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs @@ -154,10 +154,10 @@ public bool eyeTrackedFoveation #else NativeMethods.MetaSetFoveationEyeTracked(_xrSession, value); #endif -#endif +#endif } } - + public bool GetFoveationEyeTrackedCenter(ref Vector2 leftEye, ref Vector2 rightEye) { if (_xrGetFoveationEyeTrackedStateMETA == null) @@ -169,7 +169,7 @@ public bool GetFoveationEyeTrackedCenter(ref Vector2 leftEye, ref Vector2 rightE { return false; } - + XrFoveationEyeTrackedStateMETA eyeTrackedState = new XrFoveationEyeTrackedStateMETA{type = XrStructureType.XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META}; XrResult result = _xrGetFoveationEyeTrackedStateMETA(_xrSession, ref eyeTrackedState); @@ -182,7 +182,7 @@ public bool GetFoveationEyeTrackedCenter(ref Vector2 leftEye, ref Vector2 rightE rightEye.Set(eyeTrackedState.foveationCenter[1].X, eyeTrackedState.foveationCenter[1].Y); return true; } - + #if UNITY_EDITOR protected override void GetValidationChecks(List results, BuildTargetGroup target) { @@ -238,14 +238,17 @@ protected override void GetValidationChecks(List r fixItMessage = "Enable Unity's Foveated Rendering feature" }); #endif - } -#endif + } +#endif protected override void OnSessionCreate(ulong xrSession) { _xrSession = xrSession; + + // Work around for Lepton not knowing about eye-tracking related permissions. + NativeMethods.Internal_SetHasEyeTrackingPermissions(true); } - + protected override void OnSessionStateChange(int oldState, int newState) { if (oldState == (int)XrSessionState.XR_SESSION_STATE_VISIBLE && @@ -258,7 +261,7 @@ protected override void OnSessionStateChange(int oldState, int newState) } } } - + #region OpenXR Plugin DLL Imports and Dependencies internal static class NativeMethods @@ -277,8 +280,11 @@ internal static class NativeMethods [DllImport("UnityOpenXR", EntryPoint = "MetaGetFoveationEyeTracked")] internal static extern void MetaGetFoveationEyeTracked(out bool isEyeTracked); + + [DllImport("UnityOpenXR", EntryPoint = "OculusFoveation_SetHasEyeTrackingPermissions")] + internal static extern void Internal_SetHasEyeTrackingPermissions([MarshalAs(UnmanagedType.I1)] bool value); } - + [StructLayout(LayoutKind.Sequential)] private struct XrFoveationEyeTrackedStateMETA { @@ -288,7 +294,7 @@ private struct XrFoveationEyeTrackedStateMETA public XrVector2f[] foveationCenter; public XrFoveationEyeTrackedStateFlagsMETA flags; } - + [Flags] private enum XrFoveationEyeTrackedStateFlagsMETA { @@ -296,7 +302,7 @@ private enum XrFoveationEyeTrackedStateFlagsMETA } #endregion - + #if UNITY_EDITOR internal class ValveOpenXRFoveatedRenderingFeatureEditorWindow : EditorWindow { @@ -332,7 +338,7 @@ internal enum XrSessionState XR_SESSION_STATE_EXITING = 8, XR_SESSION_STATE_MAX_ENUM = 0x7FFFFFFF } - + internal enum FoveatedRenderingLevel { Off = 0, diff --git a/com.valvesoftware.openxr.utils/package.json b/com.valvesoftware.openxr.utils/package.json index 38af848..b4ec618 100644 --- a/com.valvesoftware.openxr.utils/package.json +++ b/com.valvesoftware.openxr.utils/package.json @@ -1,7 +1,7 @@ { "name": "com.valvesoftware.openxr.utils", "displayName": "Valve OpenXR Utilities", - "version": "1.0.1", + "version": "1.0.2", "description": "The Valve OpenXR Utilities package provides support for OpenXR projects and their access to Unity's OpenXR functionality.", "dependencies": { "com.unity.xr.openxr": "1.10.0", From 1eaf6516322dbefbc9ac69bc0b4936a6e8cdf28f Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:01:48 -0800 Subject: [PATCH 03/10] System info sample --- com.valvesoftware.openxr.utils/CHANGELOG.md | 5 + .../Documentation~/index.md | 11 + .../ValveOpenXRFoveatedRenderingBuildHooks.cs | 3 - ...lveOpenXRRenderRegionsFeatureBuildHooks.cs | 10 + .../ValveOpenXRRenderRegionsFeatureEditor.cs | 8 +- .../Features/ValveOpenXRSupportBuildHooks.cs | 16 +- .../ValveOpenXRSupportFeatureEditor.cs | 3 +- .../ValveOpenXRFoveatedRenderingFeature.cs | 35 +- .../ValveOpenXRLeptonValidationFeature.cs | 7 +- .../ValveOpenXRRenderRegionsFeature.cs | 244 +-- .../Features/ValveOpenXRSupportFeature.cs | 374 ++-- .../Runtime/Valve.OpenXR.Utils.asmdef | 71 +- .../Samples~/SystemInfo.meta | 8 + .../Samples~/SystemInfo/README.md | 9 + .../Samples~/SystemInfo/README.md.meta | 7 + .../Samples~/SystemInfo/Scenes.meta | 8 + .../SystemInfo/Scenes/SystemInfoExample.unity | 1831 +++++++++++++++++ .../Scenes/SystemInfoExample.unity.meta | 7 + .../Samples~/SystemInfo/Scripts.meta | 8 + .../SystemInfo/Scripts/SteamFrameCheck.cs | 43 + .../Scripts/SteamFrameCheck.cs.meta | 2 + .../Scripts/SteamFrameCheckSimple.cs | 23 + .../Scripts/SteamFrameCheckSimple.cs.meta | 2 + .../Scripts/SystemInfoExample.asmdef | 17 + .../Scripts/SystemInfoExample.asmdef.meta | 7 + .../SystemInfo/Scripts/SystemInfoFeature.cs | 187 ++ .../Scripts/SystemInfoFeature.cs.meta | 2 + .../Samples~/SystemInfo/UI.meta | 8 + .../Samples~/SystemInfo/UI/checkmark.png | Bin 0 -> 863 bytes .../Samples~/SystemInfo/UI/checkmark.png.meta | 130 ++ .../Samples~/SystemInfo/UI/question_mark.png | Bin 0 -> 754 bytes .../SystemInfo/UI/question_mark.png.meta | 130 ++ .../Samples~/SystemInfo/UI/red_x.png | Bin 0 -> 655 bytes .../Samples~/SystemInfo/UI/red_x.png.meta | 130 ++ com.valvesoftware.openxr.utils/package.json | 7 +- 35 files changed, 2992 insertions(+), 361 deletions(-) create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/checkmark.png create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/checkmark.png.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/question_mark.png create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/question_mark.png.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/red_x.png create mode 100644 com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/red_x.png.meta diff --git a/com.valvesoftware.openxr.utils/CHANGELOG.md b/com.valvesoftware.openxr.utils/CHANGELOG.md index a845b4b..683f895 100644 --- a/com.valvesoftware.openxr.utils/CHANGELOG.md +++ b/com.valvesoftware.openxr.utils/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [1.0.3] - 2026-02-12 +### Added +- System info sample for checking device is Steam Frame +- Minor fixes/additions to documentation and OpenXR feature validation rules. + ## [1.0.2] - 2026-01-14 ### Fixed - Fixed app permissions preventing gaze-based foveated rendering from being enabled. diff --git a/com.valvesoftware.openxr.utils/Documentation~/index.md b/com.valvesoftware.openxr.utils/Documentation~/index.md index 78b9539..8b3b3d8 100644 --- a/com.valvesoftware.openxr.utils/Documentation~/index.md +++ b/com.valvesoftware.openxr.utils/Documentation~/index.md @@ -44,6 +44,17 @@ git@github.com:ValveSoftware/Unity.git?path=com.valvesoftware.openxr.utils | :--- | :--- | | **Steam Frame Controller** | Interaction profile for Steam Frame controllers. | +## Samples + +| **Name** | **Description** | **Requirements** +| :--- | :--- | :--- | +| **Refresh Rate** | Queries and displays the current display refresh rate. | Valve Utils Refresh Rate OpenXR Feature | +| **System Info** | Queries whether the device is Steam Frame using OpenXR's system info. | Unity 2022.3, Unity OpenXR Plugin v1.9.1 | + +## Limitations + +* Foveated rendering on Steam Frame under Unity 2022.3 may not render correctly when MSAA is enabled. + ## Support For bugs or features requests, open up a new issue if you don't see it addressed in the existing / closed issues. diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs index da1e222..1520feb 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using Unity.XR.Management.AndroidManifest.Editor; using UnityEditor.Build.Reporting; using UnityEditor.XR.OpenXR.Features; -using UnityEngine.XR.OpenXR; namespace Valve.OpenXR.Utils.Editor { diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureBuildHooks.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureBuildHooks.cs index 1102c6d..a4bdf68 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureBuildHooks.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureBuildHooks.cs @@ -3,6 +3,7 @@ using UnityEditor.Build.Reporting; using UnityEditor.XR.OpenXR.Features; using UnityEngine; +using UnityEngine.XR.OpenXR; namespace Valve.OpenXR.Utils.Editor { @@ -16,6 +17,7 @@ internal class ValveOpenXRRenderRegionsFeatureBuildHooks : OpenXRFeatureBuildHoo protected override void OnPreprocessBuildExt(BuildReport report) { + ApplySettingsOverride(); } protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBuilder builder) @@ -43,5 +45,13 @@ protected override void OnPostGenerateGradleAndroidProjectExt(string path) protected override void OnPostprocessBuildExt(BuildReport report) { } + + private void ApplySettingsOverride() + { + var openXrSettings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android); + var target = EditorUtils.GetFeatureAsset(); + target.ApplySettingsOverride(openXrSettings); + AssetDatabase.SaveAssetIfDirty(openXrSettings); + } } } diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureEditor.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureEditor.cs index 879f1fa..fcd3195 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureEditor.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRRenderRegionsFeatureEditor.cs @@ -46,14 +46,8 @@ public override void OnInspectorGUI() OpenXRSettings androidOpenXRSettings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android); var serializedOpenXrSettings = new SerializedObject(androidOpenXRSettings); - - androidOpenXRSettings.symmetricProjection = symmetricProjection.boolValue; -#if UNITY_6000_1_OR_NEWER - androidOpenXRSettings.multiviewRenderRegionsOptimizationMode = (OpenXRSettings.MultiviewRenderRegionsOptimizationMode)multiviewRenderRegionsOptimizationMode.intValue; -#endif + ((ValveOpenXRRenderRegionsFeature)target).ApplySettingsOverride(androidOpenXRSettings); serializedOpenXrSettings.ApplyModifiedProperties(); - - EditorGUIUtility.labelWidth = 0.0f; } } } diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportBuildHooks.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportBuildHooks.cs index 2e1a0f5..87ce5a0 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportBuildHooks.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportBuildHooks.cs @@ -1,7 +1,9 @@ using System; +using UnityEditor; using UnityEditor.Build.Reporting; using UnityEditor.XR.OpenXR.Features; using UnityEngine; +using UnityEngine.XR.OpenXR; namespace Valve.OpenXR.Utils.Editor { @@ -15,7 +17,11 @@ internal class ValveOpenXRSupportBuildHooks : OpenXRFeatureBuildHooks protected override void OnPostGenerateGradleAndroidProjectExt(string path) {} protected override void OnPostprocessBuildExt(BuildReport report) {} - protected override void OnPreprocessBuildExt(BuildReport report) {} + + protected override void OnPreprocessBuildExt(BuildReport report) + { + ApplySettingsOverride(); + } protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBuilder builder) { @@ -29,5 +35,13 @@ protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBui builder.SetBootConfigValue(kLateLatchingSupported, item.lateLatchingMode ? "1" : "0"); builder.SetBootConfigValue(kLateLatchingDebug, item.lateLatchingDebug ? "1" : "0"); } + + private void ApplySettingsOverride() + { + var openXrSettings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android); + var target = EditorUtils.GetFeatureAsset(); + target.ApplySettingsOverride(openXrSettings); + AssetDatabase.SaveAssetIfDirty(openXrSettings); + } } } \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportFeatureEditor.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportFeatureEditor.cs index 1e1efca..b2c1733 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportFeatureEditor.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRSupportFeatureEditor.cs @@ -31,11 +31,12 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(lateLatchingModeProp, s_lateLatchingModeLabel); EditorGUILayout.PropertyField(lateLatchingDebugProp, s_lateLatchingDebugLabel); EditorGUIUtility.labelWidth = 0.0f; + serializedObject.ApplyModifiedProperties(); OpenXRSettings androidOpenXRSettings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android); var serializedOpenXrSettings = new SerializedObject(androidOpenXRSettings); - androidOpenXRSettings.optimizeBufferDiscards = optimizeBufferDiscardsProp.boolValue; + ((ValveOpenXRSupportFeature)target).ApplySettingsOverride(androidOpenXRSettings); serializedOpenXrSettings.ApplyModifiedProperties(); } } diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs index c85e7b3..1b7a1b8 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs @@ -184,9 +184,11 @@ public bool GetFoveationEyeTrackedCenter(ref Vector2 leftEye, ref Vector2 rightE } #if UNITY_EDITOR - protected override void GetValidationChecks(List results, BuildTargetGroup target) + protected override void GetValidationChecks(List rules, BuildTargetGroup targetGroup) { - results.Add(new ValidationRule(this) + base.GetValidationChecks(rules, targetGroup); + + rules.Add(new ValidationRule(this) { message = "This feature is only supported on Vulkan graphics API.", error = true, @@ -211,14 +213,37 @@ protected override void GetValidationChecks(List r fixItMessage = "Set Vulkan as Graphics API" }); +#if UNITY_2023_2_OR_NEWER + rules.Add(new ValidationRule(this) + { + message = "This feature requires the foveated rendering API set to SRP foveation.", + error = true, + checkPredicate = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (settings) + { + return settings.foveatedRenderingApi == OpenXRSettings.BackendFovationApi.SRPFoveation; + } + return true; + }, + fixIt = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + settings.foveatedRenderingApi = OpenXRSettings.BackendFovationApi.SRPFoveation; + }, + fixItAutomatic = true, + fixItMessage = "Set SPR foveation as the foveated rendering API." + }); +#endif #if UNITY_6000_0_OR_NEWER - results.Add(new ValidationRule(this) + rules.Add(new ValidationRule(this) { message = "Unity Foveated Rendering feature must be enabled.", error = true, checkPredicate = () => { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(target); + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); if (settings == null) return false; @@ -227,7 +252,7 @@ protected override void GetValidationChecks(List r }, fixIt = () => { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(target); + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); if (settings != null) { var foveationFeature = settings.GetFeature(); diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs index 05709c4..db8f680 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs @@ -1,12 +1,7 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using UnityEngine; using UnityEngine.XR.OpenXR.Features; using UnityEngine.XR.OpenXR.Features.MetaQuestSupport; using UnityEngine.XR.OpenXR; -using UnityEngine.XR.OpenXR.NativeTypes; #if UNITY_EDITOR using UnityEditor; using UnityEditor.XR.OpenXR.Features; @@ -37,6 +32,8 @@ public class ValveOpenXRLeptonValidationFeature : OpenXRFeature #if UNITY_EDITOR protected override void GetValidationChecks(List rules, BuildTargetGroup targetGroup) { + base.GetValidationChecks(rules, targetGroup); + var highestMinAndroidApiLevel = AndroidSdkVersions.AndroidApiLevel30; rules.Add(new ValidationRule(this) { diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRRenderRegionsFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRRenderRegionsFeature.cs index 1097f37..fb1c97c 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRRenderRegionsFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRRenderRegionsFeature.cs @@ -1,5 +1,5 @@ - using System; +using System.Collections.Generic; using System.Runtime.CompilerServices; using UnityEngine; using UnityEngine.Rendering; @@ -103,144 +103,146 @@ private bool SettingsUseVulkan() return true; } + internal void ApplySettingsOverride(OpenXRSettings openXrSettings) + { + openXrSettings.symmetricProjection = symmetricProjection; +#if UNITY_6000_1_OR_NEWER + openXrSettings.multiviewRenderRegionsOptimizationMode = multiviewRenderRegionsOptimizationMode; +#endif + } - private ValidationRule[] CreateValidationRules(BuildTargetGroup targetGroup) => - - new ValidationRule[] - { - // OptimizeMultiviewRenderRegions (aka MVPVV) only supported on Unity 6.1 onwards + protected override void GetValidationChecks(List rules, BuildTargetGroup targetGroup) + { + base.GetValidationChecks(rules, targetGroup); + #if UNITY_6000_1_OR_NEWER - new ValidationRule(this) + rules.Add(new ValidationRule(this) + { + // OptimizeMultiviewRenderRegions (aka MVPVV) only supported on Unity 6.1 onwards + message = "Multiview Render Regions Optimizations Mode requires symmetric projection setting turned on.", + checkPredicate = () => + { + if (multiviewRenderRegionsOptimizationMode != OpenXRSettings.MultiviewRenderRegionsOptimizationMode.None) { - message = "Multiview Render Regions Optimizations Mode requires symmetric projection setting turned on.", - checkPredicate = () => - { - if (multiviewRenderRegionsOptimizationMode != OpenXRSettings.MultiviewRenderRegionsOptimizationMode.None) - { - return symmetricProjection; - } - return true; - }, - error = true, - fixIt = () => - { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); - var feature = settings.GetFeature(); - feature.symmetricProjection = true; - } - }, + return symmetricProjection; + } + return true; + }, + error = true, + fixIt = () => + { + symmetricProjection = true; + } + }); - new ValidationRule(this) + rules.Add(new ValidationRule(this) + { + message = "Multiview Render Regions Optimizations Mode requires Render Mode set to \"Single Pass Instanced / Multi-view\".", + checkPredicate = () => + { + if (multiviewRenderRegionsOptimizationMode != OpenXRSettings.MultiviewRenderRegionsOptimizationMode.None) { - message = "Multiview Render Regions Optimizations Mode requires Render Mode set to \"Single Pass Instanced / Multi-view\".", - checkPredicate = () => - { - if (multiviewRenderRegionsOptimizationMode != OpenXRSettings.MultiviewRenderRegionsOptimizationMode.None) - { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); - return (settings.renderMode == OpenXRSettings.RenderMode.SinglePassInstanced); - } - return true; - }, - error = true, - fixIt = () => - { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); - settings.renderMode = OpenXRSettings.RenderMode.SinglePassInstanced; - } - }, + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + return (settings.renderMode == OpenXRSettings.RenderMode.SinglePassInstanced); + } + return true; + }, + error = true, + fixIt = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + settings.renderMode = OpenXRSettings.RenderMode.SinglePassInstanced; + } + }); - new ValidationRule(this) + rules.Add(new ValidationRule(this) + { + message = "Multiview Render Regions Optimizations Mode needs the Vulkan Graphics API to be the default Graphics API to work at runtime.", + helpText = "The Multiview Render Regions Optimizations Mode feature only works with the Vulkan Graphics API, which needs to be set as the first Graphics API to be loaded at application startup. Choosing other Graphics API may require to switch to Vulkan and restart the application.", + checkPredicate = () => + { + if (multiviewRenderRegionsOptimizationMode != OpenXRSettings.MultiviewRenderRegionsOptimizationMode.None) { - message = "Multiview Render Regions Optimizations Mode needs the Vulkan Graphics API to be the default Graphics API to work at runtime.", - helpText = "The Multiview Render Regions Optimizations Mode feature only works with the Vulkan Graphics API, which needs to be set as the first Graphics API to be loaded at application startup. Choosing other Graphics API may require to switch to Vulkan and restart the application.", - checkPredicate = () => - { - if (multiviewRenderRegionsOptimizationMode != OpenXRSettings.MultiviewRenderRegionsOptimizationMode.None) - { - var graphicsApis = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android); - return graphicsApis[0] == GraphicsDeviceType.Vulkan; - } - return true; - }, - error = false - }, + var graphicsApis = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android); + return graphicsApis[0] == GraphicsDeviceType.Vulkan; + } + return true; + }, + error = false + }); - new ValidationRule(this) - { - message = "Multiview Render Regions Optimizations - All Passes mode is only supported on Unity 6.2+ versions", - checkPredicate = () => - { + rules.Add(new ValidationRule(this) + { + message = "Multiview Render Regions Optimizations - All Passes mode is only supported on Unity 6.2+ versions", + checkPredicate = () => + { #if !UNITY_6000_2_OR_NEWER - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); - if (settings.multiviewRenderRegionsOptimizationMode == OpenXRSettings.MultiviewRenderRegionsOptimizationMode.AllPasses) - return false; + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (settings.multiviewRenderRegionsOptimizationMode == OpenXRSettings.MultiviewRenderRegionsOptimizationMode.AllPasses) + return false; #endif - return true; - }, - error = true, - fixIt = () => - { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); - var feature = settings.GetFeature(); - feature.multiviewRenderRegionsOptimizationMode = OpenXRSettings.MultiviewRenderRegionsOptimizationMode.FinalPass; - }, - fixItAutomatic = true, - fixItMessage = "Set Multiview Render Regions Optimization Mode to Final Pass." - }, - + return true; + }, + error = true, + fixIt = () => + { + multiviewRenderRegionsOptimizationMode = OpenXRSettings.MultiviewRenderRegionsOptimizationMode.FinalPass; + }, + fixItAutomatic = true, + fixItMessage = "Set Multiview Render Regions Optimization Mode to Final Pass." + }); #endif #if UNITY_ANDROID - new ValidationRule(this) + rules.Add(new ValidationRule(this) + { + message = "Symmetric Projection is only supported on Vulkan graphics API", + checkPredicate = () => + { + if (symmetricProjection && !SettingsUseVulkan()) { - message = "Symmetric Projection is only supported on Vulkan graphics API", - checkPredicate = () => - { - if (symmetricProjection && !SettingsUseVulkan()) - { - return false; - } - return true; - }, - fixIt = () => - { - PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new[] { GraphicsDeviceType.Vulkan }); - }, - fixItAutomatic = true, - fixItMessage = "Set Vulkan as Graphics API" - }, + return false; + } + return true; + }, + fixIt = () => + { + PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new[] { GraphicsDeviceType.Vulkan }); + }, + fixItAutomatic = true, + fixItMessage = "Set Vulkan as Graphics API" + }); - new ValidationRule(this) - { - message = "Symmetric Projection is only supported when using Multi-view", - checkPredicate = () => - { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); - if (null == settings) - return false; + rules.Add(new ValidationRule(this) + { + message = "Symmetric Projection is only supported when using Multi-view", + checkPredicate = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (null == settings) + return false; - if (symmetricProjection && (settings.renderMode != OpenXRSettings.RenderMode.SinglePassInstanced)) - { - return false; - } - return true; - }, - fixIt = () => - { - var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); - if (null != settings) - { - settings.renderMode = OpenXRSettings.RenderMode.SinglePassInstanced; - } - }, - error = true, - fixItAutomatic = true, - fixItMessage = "Set Render Mode to Multi-view" - }, + if (symmetricProjection && (settings.renderMode != OpenXRSettings.RenderMode.SinglePassInstanced)) + { + return false; + } + return true; + }, + fixIt = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (null != settings) + { + settings.renderMode = OpenXRSettings.RenderMode.SinglePassInstanced; + } + }, + error = true, + fixItAutomatic = true, + fixItMessage = "Set Render Mode to Multi-view" + }); #endif - }; + } internal class ValveOpenXRRenderRegionsFeatureEditorWindow : EditorWindow { diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs index c9efdf5..d824406 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs @@ -1,184 +1,190 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using UnityEngine; -using UnityEngine.XR.OpenXR.Features; -using UnityEngine.XR.OpenXR.Features.MetaQuestSupport; -using UnityEngine.XR.OpenXR; -using UnityEngine.XR.OpenXR.NativeTypes; -#if UNITY_EDITOR -using UnityEditor; -using UnityEditor.XR.OpenXR.Features; -#endif - -namespace Valve.OpenXR.Utils -{ - /// - /// Enables the Valve OpenXR Loader support. - /// -#if UNITY_EDITOR - [OpenXRFeature(UiName = "Valve Utils: Settings for Unity's Rendering", - Desc = "Settings for OpenXR Rendering.", - Company = "Valve Software", - DocumentationLink = "https://github.com/ValveSoftware/Unity/blob/main/com.valvesoftware.openxr.utils/Documentation~/index.md#open-xr-features", - OpenxrExtensionStrings = "", - Version = "0.1.0", - BuildTargetGroups = new[] { BuildTargetGroup.Android }, - FeatureId = featureId - )] -#endif - public class ValveOpenXRSupportFeature : OpenXRFeature - { - public const string featureId = "com.valvesoftware.openxr.utils.support"; - - [SerializeField] - [Tooltip("Optimization that allows 4x MSAA textures to be memoryless on Vulkan")] - internal bool optimizeBufferDiscards; - - [SerializeField] - [Tooltip("Vulkan only")] - internal bool lateLatchingMode; - - [SerializeField] - [Tooltip("Vulkan only")] - internal bool lateLatchingDebug; - - private ulong _xrInstance; - private ulong _xrSession; - - private ulong XrInstance => _xrInstance; - private ulong XrSession => _xrSession; - - private delegate XrResult GetInstanceProcAddrDelegate(ulong instance, string name, ref IntPtr procAddr); - private GetInstanceProcAddrDelegate _getInstanceProcAddr; - - private System.Type[] incompatibleFeatureTypes = { typeof(MetaQuestFeature) }; - - internal static ValveOpenXRSupportFeature Instance - { - get - { - OpenXRSettings settings = OpenXRSettings.ActiveBuildTargetInstance; - var features = new List(); - return settings.GetFeatures(features) > 0 ? features.First() : null; - } - } - - #region "Public OpenXR Support" - - public static bool HasOpenXRInstance() { return Instance.XrInstance != 0; } - public static ulong GetOpenXRInstance() { return Instance.XrInstance; } - public static event InstanceCreated OnInstanceCreated; - public static event InstanceDestroyed OnInstanceDestroyed; - - public static bool HasSession() { return Instance.XrSession != 0; } - public static ulong GetSession() { return Instance.XrSession; } - public static event SessionCreated OnSessionCreated; - public static event SessionDestroyed OnSessionDestroyed; - - public static T GetOpenXrInstanceProc(string procName) - { - var instanceProc = GetOpenXrInstanceProc(procName); - - return instanceProc != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(instanceProc) : default; - } - - public static IntPtr GetOpenXrInstanceProc(string procName) - { - return Instance.GetOpenXrInstanceProcInternal(procName); - } - - #endregion - - protected override bool OnInstanceCreate(ulong xrInstance) - { - _xrInstance = xrInstance; - OnInstanceCreated?.Invoke(xrInstance); - return true; - } - - protected override void OnInstanceDestroy(ulong xrInstance) - { - OnInstanceDestroyed?.Invoke(xrInstance); - _xrInstance = 0; - } - - protected override void OnSessionCreate(ulong xrSession) - { - _xrSession = xrSession; - OnSessionCreated?.Invoke(_xrSession); - } - - protected override void OnSessionDestroy(ulong xrSession) - { - OnSessionDestroyed?.Invoke(_xrSession); - _xrSession = 0; - } - - private IntPtr GetOpenXrInstanceProcInternal(string procName) - { - if (_getInstanceProcAddr == null) - { - if (xrGetInstanceProcAddr == IntPtr.Zero) - { - Debug.LogWarning($"Unity's OpenXR GetInstance function accessor is invalid!"); - return IntPtr.Zero; - } - - _getInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(xrGetInstanceProcAddr); - } - - IntPtr procAddr = IntPtr.Zero; - - if (_getInstanceProcAddr != null) - { - XrResult result = _getInstanceProcAddr(_xrInstance, procName, ref procAddr); - - if (result < 0) - { - Debug.LogWarning($"Failed to find OpenXR instance function '{procName}'"); - return IntPtr.Zero; - } - } - - return procAddr; - } - - -#if UNITY_EDITOR - protected override void GetValidationChecks(List rules, BuildTargetGroup targetGroup) - { - rules.Add(new ValidationRule(this) - { - message = "Late latching is only supported on Vulkan graphics API.", - error = true, - checkPredicate = () => (!lateLatchingMode && !lateLatchingDebug) || EditorUtils.UsesVulkan(BuildTarget.Android), - fixIt = () => - { - PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new[] { UnityEngine.Rendering.GraphicsDeviceType.Vulkan }); - }, - fixItAutomatic = true, - fixItMessage = "Set Vulkan as Graphics API" - }); - } -#endif - } - - internal enum XrStructureType - { - XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META = 1000200001, - } - - [StructLayout(LayoutKind.Sequential)] - public struct XrVector2f - { - public float X; - public float Y; - }; - - public delegate void InstanceCreated(ulong instance); - public delegate void InstanceDestroyed(ulong instance); - public delegate void SessionCreated(ulong session); - public delegate void SessionDestroyed(ulong session); -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.XR.OpenXR.Features; +using UnityEngine.XR.OpenXR.Features.MetaQuestSupport; +using UnityEngine.XR.OpenXR; +using UnityEngine.XR.OpenXR.NativeTypes; +#if UNITY_EDITOR +using UnityEditor; +using UnityEditor.XR.OpenXR.Features; +#endif + +namespace Valve.OpenXR.Utils +{ + /// + /// Enables the Valve OpenXR Loader support. + /// +#if UNITY_EDITOR + [OpenXRFeature(UiName = "Valve Utils: Settings for Unity's Rendering", + Desc = "Settings for OpenXR Rendering.", + Company = "Valve Software", + DocumentationLink = "https://github.com/ValveSoftware/Unity/blob/main/com.valvesoftware.openxr.utils/Documentation~/index.md#open-xr-features", + OpenxrExtensionStrings = "", + Version = "0.1.0", + BuildTargetGroups = new[] { BuildTargetGroup.Android }, + FeatureId = featureId + )] +#endif + public class ValveOpenXRSupportFeature : OpenXRFeature + { + public const string featureId = "com.valvesoftware.openxr.utils.support"; + + [SerializeField] + [Tooltip("Optimization that allows 4x MSAA textures to be memoryless on Vulkan")] + internal bool optimizeBufferDiscards; + + [SerializeField] + [Tooltip("Vulkan only")] + internal bool lateLatchingMode; + + [SerializeField] + [Tooltip("Vulkan only")] + internal bool lateLatchingDebug; + + private ulong _xrInstance; + private ulong _xrSession; + + private ulong XrInstance => _xrInstance; + private ulong XrSession => _xrSession; + + private delegate XrResult GetInstanceProcAddrDelegate(ulong instance, string name, ref IntPtr procAddr); + private GetInstanceProcAddrDelegate _getInstanceProcAddr; + + private System.Type[] incompatibleFeatureTypes = { typeof(MetaQuestFeature) }; + + internal static ValveOpenXRSupportFeature Instance + { + get + { + OpenXRSettings settings = OpenXRSettings.ActiveBuildTargetInstance; + var features = new List(); + return settings.GetFeatures(features) > 0 ? features.First() : null; + } + } + + #region "Public OpenXR Support" + + public static bool HasOpenXRInstance() { return Instance.XrInstance != 0; } + public static ulong GetOpenXRInstance() { return Instance.XrInstance; } + public static event InstanceCreated OnInstanceCreated; + public static event InstanceDestroyed OnInstanceDestroyed; + + public static bool HasSession() { return Instance.XrSession != 0; } + public static ulong GetSession() { return Instance.XrSession; } + public static event SessionCreated OnSessionCreated; + public static event SessionDestroyed OnSessionDestroyed; + + public static T GetOpenXrInstanceProc(string procName) + { + var instanceProc = GetOpenXrInstanceProc(procName); + + return instanceProc != IntPtr.Zero ? Marshal.GetDelegateForFunctionPointer(instanceProc) : default; + } + + public static IntPtr GetOpenXrInstanceProc(string procName) + { + return Instance.GetOpenXrInstanceProcInternal(procName); + } + + #endregion + + protected override bool OnInstanceCreate(ulong xrInstance) + { + _xrInstance = xrInstance; + OnInstanceCreated?.Invoke(xrInstance); + return true; + } + + protected override void OnInstanceDestroy(ulong xrInstance) + { + OnInstanceDestroyed?.Invoke(xrInstance); + _xrInstance = 0; + } + + protected override void OnSessionCreate(ulong xrSession) + { + _xrSession = xrSession; + OnSessionCreated?.Invoke(_xrSession); + } + + protected override void OnSessionDestroy(ulong xrSession) + { + OnSessionDestroyed?.Invoke(_xrSession); + _xrSession = 0; + } + + private IntPtr GetOpenXrInstanceProcInternal(string procName) + { + if (_getInstanceProcAddr == null) + { + if (xrGetInstanceProcAddr == IntPtr.Zero) + { + Debug.LogWarning($"Unity's OpenXR GetInstance function accessor is invalid!"); + return IntPtr.Zero; + } + + _getInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(xrGetInstanceProcAddr); + } + + IntPtr procAddr = IntPtr.Zero; + + if (_getInstanceProcAddr != null) + { + XrResult result = _getInstanceProcAddr(_xrInstance, procName, ref procAddr); + + if (result < 0) + { + Debug.LogWarning($"Failed to find OpenXR instance function '{procName}'"); + return IntPtr.Zero; + } + } + + return procAddr; + } + + +#if UNITY_EDITOR + + internal void ApplySettingsOverride(OpenXRSettings openXrSettings) + { + openXrSettings.optimizeBufferDiscards = optimizeBufferDiscards; + } + + protected override void GetValidationChecks(List rules, BuildTargetGroup targetGroup) + { + rules.Add(new ValidationRule(this) + { + message = "Late latching is only supported on Vulkan graphics API.", + error = true, + checkPredicate = () => (!lateLatchingMode && !lateLatchingDebug) || EditorUtils.UsesVulkan(BuildTarget.Android), + fixIt = () => + { + PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new[] { UnityEngine.Rendering.GraphicsDeviceType.Vulkan }); + }, + fixItAutomatic = true, + fixItMessage = "Set Vulkan as Graphics API" + }); + } +#endif + } + + internal enum XrStructureType + { + XR_TYPE_FOVEATION_EYE_TRACKED_STATE_META = 1000200001, + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrVector2f + { + public float X; + public float Y; + }; + + public delegate void InstanceCreated(ulong instance); + public delegate void InstanceDestroyed(ulong instance); + public delegate void SessionCreated(ulong session); + public delegate void SessionDestroyed(ulong session); +} diff --git a/com.valvesoftware.openxr.utils/Runtime/Valve.OpenXR.Utils.asmdef b/com.valvesoftware.openxr.utils/Runtime/Valve.OpenXR.Utils.asmdef index 6a660b9..ec16d5f 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Valve.OpenXR.Utils.asmdef +++ b/com.valvesoftware.openxr.utils/Runtime/Valve.OpenXR.Utils.asmdef @@ -1,34 +1,39 @@ -{ - "name": "Valve.OpenXR.Utils", - "rootNamespace": "", - "references": [ - "Unity.XR.OpenXR", - "Unity.InputSystem", - "Unity.XR.OpenXR.Features.MetaQuestSupport" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [ - { - "name": "com.unity.xr.openxr", - "expression": "1.9.0", - "define": "UNITY_OPENXR_1_9_0" - }, - { - "name": "Unity", - "expression": "6000.0.0", - "define": "USE_XR_DISPLAY_FOVEATION_API" - }, - { - "name": "Unity", - "expression": "[2022.2,6000.0.0)", - "define": "USE_LEGACY_BOOT_CONFIG" - } - ], - "noEngineReferences": false +{ + "name": "Valve.OpenXR.Utils", + "rootNamespace": "", + "references": [ + "Unity.XR.OpenXR", + "Unity.InputSystem", + "Unity.XR.OpenXR.Features.MetaQuestSupport" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.xr.openxr", + "expression": "1.9.0", + "define": "UNITY_OPENXR_1_9_0" + }, + { + "name": "com.unity.xr.openxr", + "expression": "1.5.3", + "define": "UNITY_OPENXR_1_5_3" + }, + { + "name": "Unity", + "expression": "6000.0.0", + "define": "USE_XR_DISPLAY_FOVEATION_API" + }, + { + "name": "Unity", + "expression": "[2022.2,6000.0.0)", + "define": "USE_LEGACY_BOOT_CONFIG" + } + ], + "noEngineReferences": false } \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo.meta new file mode 100644 index 0000000..c9e35c5 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b30c301a3e8b551459afeb8ca98798c7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md new file mode 100644 index 0000000..07c1e47 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md @@ -0,0 +1,9 @@ +# System Info Sample + +This sample demonstrates how to request the headset name from OpenXR and verify the app is running on Steam Frame. + +## Usage + +* Import sample from the Package Manager +* Enable the OpenXR feature in ProjectSettings -> OpenXR (Valve Utils: System Info Sample) +* See the SystemInfoExample scene and SteamFrameCheckSimple script for more details. diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md.meta new file mode 100644 index 0000000..3aaadbe --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 208f7ec4e6ff7e1408676caa2c8e1d69 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes.meta new file mode 100644 index 0000000..71e479d --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 02e2875f9fbef05448a564b116658db6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity new file mode 100644 index 0000000..6da2863 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity @@ -0,0 +1,1831 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 2100000, guid: a2294966a3496b64bb53aecaaf29eb8f, type: 2} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &48142790 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 48142791} + - component: {fileID: 48142794} + - component: {fileID: 48142793} + - component: {fileID: 48142792} + m_Layer: 0 + m_Name: Back Wall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 2147483647 + m_IsActive: 1 +--- !u!4 &48142791 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 48142790} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.70710677, z: 0.70710677, w: 0} + m_LocalPosition: {x: 0, y: 0.5, z: 3.5} + m_LocalScale: {x: 3, y: 0.05, z: 2} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1278933305} + m_LocalEulerAnglesHint: {x: -90, y: 90, z: 90} +--- !u!65 &48142792 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 48142790} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &48142793 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 48142790} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &48142794 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 48142790} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &83273604 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 83273605} + m_Layer: 0 + m_Name: CheckmarkStates + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &83273605 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 83273604} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 423886535} + - {fileID: 904846746} + - {fileID: 944053464} + m_Father: {fileID: 1449709195} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &423886534 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 423886535} + - component: {fileID: 423886537} + - component: {fileID: 423886536} + m_Layer: 0 + m_Name: Unknown + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &423886535 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 423886534} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 83273605} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -97.50001, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &423886536 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 423886534} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 2100000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: c53c1530f23d0ca40b6dd3704f90b27b, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &423886537 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 423886534} + m_CullTransparentMesh: 1 +--- !u!1 &588475809 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 588475810} + m_Layer: 0 + m_Name: Camera Offset + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &588475810 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 588475809} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1.1176, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1981365428} + m_Father: {fileID: 1609452151} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &589018149 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 589018150} + m_Layer: 0 + m_Name: HeadsetCheckSimple + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &589018150 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 589018149} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.1097, y: 1.24929, z: 3.475} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &613266701 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 613266702} + - component: {fileID: 613266705} + - component: {fileID: 613266704} + - component: {fileID: 613266703} + m_Layer: 0 + m_Name: Ground + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 2147483647 + m_IsActive: 1 +--- !u!4 &613266702 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 613266701} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0.5, z: 1.5} + m_LocalScale: {x: 3, y: 0.05, z: 4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1278933305} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &613266703 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 613266701} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &613266704 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 613266701} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &613266705 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 613266701} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &866492117 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 866492118} + - component: {fileID: 866492121} + - component: {fileID: 866492120} + - component: {fileID: 866492119} + m_Layer: 0 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &866492118 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 866492117} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.001, y: 0.001, z: 0.001} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1338222086} + m_Father: {fileID: 2122847252} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 300, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &866492119 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 866492117} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.GraphicRaycaster + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &866492120 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 866492117} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.CanvasScaler + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 1 +--- !u!223 &866492121 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 866492117} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 0 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!1 &877268222 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 877268223} + - component: {fileID: 877268226} + - component: {fileID: 877268225} + - component: {fileID: 877268224} + m_Layer: 0 + m_Name: Left Wall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 2147483647 + m_IsActive: 1 +--- !u!4 &877268223 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 877268222} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0.7071068, w: 0.7071068} + m_LocalPosition: {x: -1.5, y: 0.5, z: 1.5} + m_LocalScale: {x: 2, y: 0.05, z: 4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1278933305} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 90} +--- !u!65 &877268224 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 877268222} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &877268225 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 877268222} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &877268226 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 877268222} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &904846745 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 904846746} + - component: {fileID: 904846748} + - component: {fileID: 904846747} + m_Layer: 0 + m_Name: Yes + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &904846746 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 904846745} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 83273605} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -97.50001, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &904846747 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 904846745} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 2100000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3} + m_Color: {r: 0, g: 1, b: 0.26161647, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 0394812c1255f9841bc62c1d431407f8, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &904846748 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 904846745} + m_CullTransparentMesh: 1 +--- !u!1 &944053463 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 944053464} + - component: {fileID: 944053466} + - component: {fileID: 944053465} + m_Layer: 0 + m_Name: No + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &944053464 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 944053463} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 83273605} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -97.50001, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &944053465 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 944053463} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 2100000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3} + m_Color: {r: 1, g: 0.026519261, b: 0, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 429d013bf9bc6154abdc550badf59e91, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &944053466 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 944053463} + m_CullTransparentMesh: 1 +--- !u!1 &1110656103 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1110656104} + - component: {fileID: 1110656107} + - component: {fileID: 1110656106} + - component: {fileID: 1110656105} + m_Layer: 0 + m_Name: Right Wall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 2147483647 + m_IsActive: 1 +--- !u!4 &1110656104 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1110656103} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0.7071068, w: 0.7071068} + m_LocalPosition: {x: 1.5, y: 0.5, z: 1.5} + m_LocalScale: {x: 2, y: 0.05, z: 4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1278933305} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 90} +--- !u!65 &1110656105 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1110656103} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &1110656106 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1110656103} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1110656107 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1110656103} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1235526238 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1235526239} + - component: {fileID: 1235526240} + - component: {fileID: 1235526241} + m_Layer: 0 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1235526239 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1235526238} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1449709195} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 15, y: -15} + m_SizeDelta: {x: 30, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1235526240 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1235526238} + m_CullTransparentMesh: 1 +--- !u!114 &1235526241 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1235526238} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 0.4716981, g: 0.4716981, b: 0.4716981, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &1278933304 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1278933305} + m_Layer: 0 + m_Name: Environment + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1278933305 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1278933304} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 613266702} + - {fileID: 1110656104} + - {fileID: 877268223} + - {fileID: 48142791} + - {fileID: 2031574506} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1338222085 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1338222086} + - component: {fileID: 1338222088} + - component: {fileID: 1338222087} + m_Layer: 0 + m_Name: MainPanel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1338222086 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1338222085} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1449709195} + m_Father: {fileID: 866492118} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1338222087 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1338222085} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0, b: 0, a: 0.9372549} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1338222088 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1338222085} + m_CullTransparentMesh: 1 +--- !u!1 &1449709193 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1449709195} + - component: {fileID: 1449709194} + m_Layer: 0 + m_Name: Toggle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1449709194 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1449709193} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Toggle + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 0 + m_TargetGraphic: {fileID: 1235526241} + toggleTransition: 1 + graphic: {fileID: 0} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_IsOn: 0 +--- !u!224 &1449709195 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1449709193} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1235526239} + - {fileID: 1901400940} + - {fileID: 83273605} + m_Father: {fileID: 1338222086} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 225, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1609452148 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1609452151} + - component: {fileID: 1609452150} + - component: {fileID: 1609452149} + m_Layer: 0 + m_Name: XR Origin (VR) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1609452149 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1609452148} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 017c5e3933235514c9520e1dace2a4b2, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.XR.Interaction.Toolkit::UnityEngine.XR.Interaction.Toolkit.Inputs.InputActionManager + m_ActionAssets: + - {fileID: -944628639613478452, guid: c348712bda248c246b8c49b3db54643f, type: 3} +--- !u!114 &1609452150 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1609452148} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e0cb9aa70a22847b5925ee5f067c10a9, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.XR.CoreUtils::Unity.XR.CoreUtils.XROrigin + m_Camera: {fileID: 1981365432} + m_OriginBaseGameObject: {fileID: 1609452148} + m_CameraFloorOffsetObject: {fileID: 588475809} + m_RequestedTrackingOriginMode: 0 + m_CameraYOffset: 1.1176 +--- !u!4 &1609452151 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1609452148} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0.5987, z: 0.4069} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 588475810} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1901400939 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1901400940} + - component: {fileID: 1901400942} + - component: {fileID: 1901400941} + m_Layer: 0 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1901400940 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1901400939} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1449709195} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 15, y: -0.5} + m_SizeDelta: {x: -40, y: -3} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1901400941 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1901400939} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Text + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 24 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 2 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Is Steam Frame? +--- !u!222 &1901400942 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1901400939} + m_CullTransparentMesh: 1 +--- !u!1 &1981365427 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1981365428} + - component: {fileID: 1981365432} + - component: {fileID: 1981365431} + - component: {fileID: 1981365430} + - component: {fileID: 1981365429} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1981365428 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981365427} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.336} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 588475810} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1981365429 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981365427} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalCameraData + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 + m_Version: 2 +--- !u!114 &1981365430 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981365427} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c2fadf230d1919748a9aa21d40f74619, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.InputSystem::UnityEngine.InputSystem.XR.TrackedPoseDriver + m_TrackingType: 0 + m_UpdateType: 0 + m_IgnoreTrackingState: 0 + m_PositionInput: + m_UseReference: 0 + m_Action: + m_Name: Position + m_Type: 0 + m_ExpectedControlType: Vector3 + m_Id: fd26b093-ee40-45a1-bc6f-a74712ef2bb6 + m_Processors: + m_Interactions: + m_SingletonActionBindings: + - m_Name: + m_Id: 686f9d92-cdd3-4c23-83cf-870f4ed41899 + m_Path: /centerEyePosition + m_Interactions: + m_Processors: + m_Groups: + m_Action: Position + m_Flags: 0 + - m_Name: + m_Id: 8273fcdb-70fa-4f5a-b0a1-90eed0f1482d + m_Path: /devicePosition + m_Interactions: + m_Processors: + m_Groups: + m_Action: Position + m_Flags: 0 + m_Flags: 0 + m_Reference: {fileID: 0} + m_RotationInput: + m_UseReference: 0 + m_Action: + m_Name: Rotation + m_Type: 0 + m_ExpectedControlType: Quaternion + m_Id: d2662bb4-e953-490f-a8c0-1f8c0e5af3da + m_Processors: + m_Interactions: + m_SingletonActionBindings: + - m_Name: + m_Id: 5641c0f9-2ec8-40bc-8dcb-c8e0cc789089 + m_Path: /centerEyeRotation + m_Interactions: + m_Processors: + m_Groups: + m_Action: Rotation + m_Flags: 0 + - m_Name: + m_Id: fbb2edd2-e20d-42c4-9f31-aab63502b901 + m_Path: /deviceRotation + m_Interactions: + m_Processors: + m_Groups: + m_Action: Rotation + m_Flags: 0 + m_Flags: 0 + m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: Tracking State + m_Type: 0 + m_ExpectedControlType: Integer + m_Id: 479df8de-6f57-4be8-9c72-ed4657f0255f + m_Processors: + m_Interactions: + m_SingletonActionBindings: + - m_Name: + m_Id: af6bda2b-e1a9-4261-90cf-f0f89c979731 + m_Path: /trackingState + m_Interactions: + m_Processors: + m_Groups: + m_Action: Tracking State + m_Flags: 0 + m_Flags: 0 + m_Reference: {fileID: 0} + m_PositionAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: c254c082-f1e5-4e90-bc47-4cc9e5dde146 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_RotationAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: cc05427e-eeb7-482d-a0da-a9684a430699 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 +--- !u!81 &1981365431 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981365427} + m_Enabled: 1 +--- !u!20 &1981365432 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981365427} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.01 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!1 &2031574505 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2031574506} + - component: {fileID: 2031574509} + - component: {fileID: 2031574508} + - component: {fileID: 2031574507} + m_Layer: 0 + m_Name: Front Wall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 2147483647 + m_IsActive: 1 +--- !u!4 &2031574506 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2031574505} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0.70710677, z: 0.70710677, w: 0} + m_LocalPosition: {x: 0, y: 0.5, z: -0.5} + m_LocalScale: {x: 3, y: 0.05, z: 2} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1278933305} + m_LocalEulerAnglesHint: {x: -90, y: 90, z: 90} +--- !u!65 &2031574507 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2031574505} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &2031574508 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2031574505} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &2031574509 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2031574505} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &2122847250 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2122847252} + - component: {fileID: 2122847251} + m_Layer: 0 + m_Name: 'HeadsetCheckUI ' + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2122847251 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2122847250} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 427e93331a51cd04d9bedd4418ac0e3f, type: 3} + m_Name: + m_EditorClassIdentifier: SystemInfoExample::FrameCheck + _states: + - {fileID: 423886534} + - {fileID: 904846745} + - {fileID: 944053463} +--- !u!4 &2122847252 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2122847250} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.5, z: 1.5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 866492118} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 1609452151} + - {fileID: 1278933305} + - {fileID: 589018150} + - {fileID: 2122847252} diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity.meta new file mode 100644 index 0000000..873390e --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scenes/SystemInfoExample.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c0f2b840826d186499da92cf3746aef9 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts.meta new file mode 100644 index 0000000..41fd6ad --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 396994d8721992d4e997d4c934b29d96 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs new file mode 100644 index 0000000..ea44d5d --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs @@ -0,0 +1,43 @@ +using UnityEngine; +using Valve.OpenXR.Utils; + +public class SteamFrameCheck : MonoBehaviour +{ + enum CheckState { Unknown, Yes, No } + + [SerializeField] + private GameObject[] _states; + + private bool _firstTime = true; + + private void Awake() + { + SetToggleState(CheckState.Unknown); + } + + private void Update() + { + if (_firstTime) + { + if (SystemInfoFeature.IsInitialized()) + { + bool isRunningOnFrame = SystemInfoFeature.IsRunnginOnSteamFrame(); + SetToggleState(isRunningOnFrame ? CheckState.Yes : CheckState.No); + _firstTime = false; + } + } + } + + private void SetToggleState(CheckState state) + { + var stateIndex = (int)state; + + if (stateIndex < _states.Length) + { + for (int i = 0; i < _states.Length; i++) + { + _states[i].gameObject.SetActive(i == stateIndex); + } + } + } +} diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs.meta new file mode 100644 index 0000000..3718e68 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheck.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 427e93331a51cd04d9bedd4418ac0e3f \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs new file mode 100644 index 0000000..acdd501 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs @@ -0,0 +1,23 @@ +using System.Collections; +using UnityEngine; +using Valve.OpenXR.Utils; + +public class SteamFrameCheckSimple : MonoBehaviour +{ + private IEnumerator Start() + { + bool done = false; + + while (!done) + { + if (SystemInfoFeature.IsInitialized()) + { + bool isRunningOnFrame = SystemInfoFeature.IsRunnginOnSteamFrame(); + Debug.Log($"Is running on Steam Frame? {(isRunningOnFrame?"y":"n")}"); + done = true; + } + + yield return null; + } + } +} diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs.meta new file mode 100644 index 0000000..25df8f7 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SteamFrameCheckSimple.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 83cdcc9730a145f4c98cceb85f27b1d9 diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef new file mode 100644 index 0000000..966644e --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef @@ -0,0 +1,17 @@ +{ + "name": "SystemInfoExample", + "rootNamespace": "", + "references": [ + "GUID:4920cda478a7ad9418e70a29fd7c1eae", + "GUID:4847341ff46394e83bb78fbd0652937e" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef.meta new file mode 100644 index 0000000..884b154 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoExample.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 723953874d47e0b42ba0a0b2eecdc3b7 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs new file mode 100644 index 0000000..c209839 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine.XR.OpenXR.Features; +using UnityEngine.XR.OpenXR; + +namespace Valve.OpenXR.Utils +{ + #if UNITY_EDITOR + [UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "Valve Utils: System Info Sample", + Desc = "Support for querying the system info.", + Company = "Valve Software", + DocumentationLink = "https://github.com/ValveSoftware/Unity/blob/main/com.valvesoftware.openxr.utils/Documentation~/index.md#open-xr-features", + Version = "0.1.0", + BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.Android }, + OpenxrExtensionStrings = "", + FeatureId = featureId)] + #endif + public class SystemInfoFeature : OpenXRFeature + { + public const string featureId = "com.valvesoftware.openxr.utils.sysinfo"; + + private ulong _xrInstance; + private ulong _xrSystemId; + private PFN_xrGetSystemProperties _xrGetSystemProperties; + + private static SystemInfoFeature Instance => OpenXRSettings.ActiveBuildTargetInstance.GetFeature(); + + protected override bool OnInstanceCreate(ulong xrInstance) + { + _xrInstance = xrInstance; + _xrGetSystemProperties = ValveOpenXRSupportFeature.GetOpenXrInstanceProc("xrGetSystemProperties"); + return base.OnInstanceCreate(xrInstance); + } + + protected override void OnSystemChange(ulong xrSystem) + { + _xrSystemId = xrSystem; + base.OnSystemChange(xrSystem); + } + +#if UNITY_EDITOR + protected override void OnEnabledChange() + { + if (enabled) + { + var supportFeature = OpenXRSettings.ActiveBuildTargetInstance.GetFeature(); + supportFeature.enabled = true; + } + } + + protected override void GetValidationChecks(List results, BuildTargetGroup target) + { + results.Add(new ValidationRule(this) + { + message = "Valve Utils rendering feature must be enabled.", + error = true, + checkPredicate = () => + { + var supportFeature = OpenXRSettings.ActiveBuildTargetInstance.GetFeature(); + return supportFeature.enabled; + }, + fixIt = () => + { + var supportFeature = OpenXRSettings.ActiveBuildTargetInstance.GetFeature(); + supportFeature.enabled = true; + }, + fixItAutomatic = true, + fixItMessage = "Enable Valve Utils rendering feature" + }); + } +#endif + + public static bool IsInitialized() + { + return Instance.IsInitializedInternal(); + } + + public static bool IsRunnginOnSteamFrame() + { + string steamVRFamilyKey = "SteamVR/OpenXR"; + string steamVRDriverKey = "cv"; + + return Instance.DoesHeadsetMatch(steamVRFamilyKey, steamVRDriverKey); + } + + public static string GetHeadsetName() + { + return Instance.GetHeadsetNameFromOpenXR(); + } + + private string GetHeadsetNameFromOpenXR() + { + string systemName = null; + + if (_xrInstance != 0 && _xrSystemId != 0 && _xrGetSystemProperties != null) + { + XrSystemProperties properties = new XrSystemProperties + { + type = XrStructureType.XR_TYPE_SYSTEM_PROPERTIES + }; + + _xrGetSystemProperties(_xrInstance, _xrSystemId, ref properties); + + systemName = properties.systemName; + } + + return systemName; + } + + private bool DoesHeadsetMatch(string familyKey, string driverKey) + { + string headsetName = GetHeadsetName(); + + Debug.Log($"DoesHeadsetMatch - {headsetName}"); + + if (!string.IsNullOrEmpty(headsetName)) + { + string pattern = @"^(?[^:]+)\s*:\s*(?.+)$"; + Match match = Regex.Match(headsetName, pattern); + + if (match.Success) + { + string family = match.Groups["family"].Value.Trim(); + string driver = match.Groups["driver"].Value.Trim(); + + return family.Equals(familyKey, StringComparison.OrdinalIgnoreCase) && + driver.Equals(driverKey, StringComparison.OrdinalIgnoreCase); + } + } + + return false; + } + + private bool IsInitializedInternal() + { + return enabled && _xrInstance != 0 && _xrSystemId != 0 && _xrGetSystemProperties != null; + } + + #region OpenXR Structures + + public enum XrStructureType : uint + { + XR_TYPE_SYSTEM_PROPERTIES = 5, + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrSystemProperties + + { + private const int XR_MAX_SYSTEM_NAME_SIZE = 256; + public XrStructureType type; + public IntPtr next; + public ulong systemId; // XrSystemId + public uint vendorId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = XR_MAX_SYSTEM_NAME_SIZE)] + public string systemName; + public XrSystemGraphicsProperties graphicsProperties; + public XrSystemTrackingProperties trackingProperties; + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrSystemGraphicsProperties + { + public uint maxSwapchainImageHeight; + public uint maxSwapchainImageWidth; + public uint maxLayerCount; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct XrSystemTrackingProperties + { + public uint orientationTracking; + public uint positionTracking; + }; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrGetSystemProperties(ulong instance, ulong systemId, ref XrSystemProperties properties); + + #endregion + } +} \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs.meta new file mode 100644 index 0000000..55024a4 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/Scripts/SystemInfoFeature.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 92d72486042652b4394a9029d7523d89 \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI.meta b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI.meta new file mode 100644 index 0000000..431b4d7 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 664c85acf07cee04f82f468e9e6e3f3d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/checkmark.png b/com.valvesoftware.openxr.utils/Samples~/SystemInfo/UI/checkmark.png new file mode 100644 index 0000000000000000000000000000000000000000..734a0a209dd38edfd1c00e93a4650fb44dfa05aa GIT binary patch literal 863 zcmV-l1EBngP)zt1(ApdQ6wKkO2h|^5W`$r=i|f9U1!(X z*_kuv>~X*E^Si&#u$Q}YZV1yf%);hVKXj*|A(61w) zRbQd6v}4jx!xue3tM;K*+B0Dd=w}I_RUef$wX6aCBq6kFXKC9#VRr^7TqJp;6kw_}%j3I8<) zeVhooq4DkKfW8yE)N=egZs6V?p=t2F2nUnhHve1 z<}0|B3A#NNx&(iBc##h}oY{Qer*2Oy^jTc%@?x7Onc3>TPgUGM`FI9bA}(0R#tCM& zyYGALOEHf^JdMjeT)2+6#?4%ce-fZtwO`B+b3BEM2^JW}`o_%XbbjA=+adJFKo{Ub z!bOJh9=p;ITk`#U8~iGVm{m#Lij%IJ|ToW(7_PG znpo&)_%PF-T&jM+K$5S_$hps_g+UXQ{-u=>@aKhL<2xnS>qzwBKw)6j@0gbb+63;$ zH-(|6F+VG`2|NSe7J~kPC#D421fGc_Qw%+iC#MwJ1RlVTQv|($1x27u;Mw>&GxRSk zEDEi{93zi`9NomC(#A1iE`Ci69mb2LZ7sv2_$?9iHeN1mY8xKI*#yv4r7azW$8jza zTE}ap4P7PfM}Hj~O79+(?v8Wf-@n{1>HMH>Q|Vokr2P?WU55wh(`29vfq3>hX7hv%nDW zf%N(TTm!cI!p{KTJ;2o}0XKoQ^@7`h+f4vh>l3iA7JNDIFr{%R#oRfdV1parRt$1=PnlC;w@IAV->(`bN-9$D(SNYXCLV6jPXNt&?K zyEBqbN?I?eSJJxJ)yx3xmilbQ7*lLAEJ>Rz^>LbC)z+uNR9}Er815+0G zIFJbm&jQaKcYh)zJO_+A;P*qq`+zYAd<^Ig1>XjIbigNp&7t7Cv2Qpi_ZwS7!S_@C zbldbE*cb|4z}@+b1AU?3J-}xNd=%&j1&?sI@XvrXLEx1DryTGnKwC(72K!lmMW}Ng z3ovMbmw5%JTgvl7E}AXG3N2sz9ELKHKANXK{}L@*wRcuW8y2@`+_$3!5aFcAoUOadYZ zlYnqz1Q1>r0fbE(Lpg*^Cx&ten-hle2%9qu~08dJF z$~yp4rIQ2Ig@4t@4~liBhU5&@r}eB@NHco?3j+WdV=9C(J7b^85OYKTfN8#x5#|g5 zTtI*Pf6zE$gpGR`p8>+Ae`1vp!lpgd%@AR8T71YDVN+p9ZUDR}7Xow_=r$7o2gL$g z0I&69t61k?7qOSxLksH7XId-rl9;}>f;6VLM_+pZGKMY}{ws5#GV*63LFw&c9`Y_@ Date: Mon, 23 Feb 2026 14:33:19 -0800 Subject: [PATCH 04/10] Fix standalone support for system info example --- .../Runtime/Features/ValveOpenXRSupportFeature.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs index d824406..e141f95 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRSupportFeature.cs @@ -24,7 +24,7 @@ namespace Valve.OpenXR.Utils DocumentationLink = "https://github.com/ValveSoftware/Unity/blob/main/com.valvesoftware.openxr.utils/Documentation~/index.md#open-xr-features", OpenxrExtensionStrings = "", Version = "0.1.0", - BuildTargetGroups = new[] { BuildTargetGroup.Android }, + BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.Android }, FeatureId = featureId )] #endif @@ -150,11 +150,14 @@ private IntPtr GetOpenXrInstanceProcInternal(string procName) internal void ApplySettingsOverride(OpenXRSettings openXrSettings) { +#if UNITY_ANDROID openXrSettings.optimizeBufferDiscards = optimizeBufferDiscards; +#endif } protected override void GetValidationChecks(List rules, BuildTargetGroup targetGroup) { +#if UNITY_ANDROID rules.Add(new ValidationRule(this) { message = "Late latching is only supported on Vulkan graphics API.", @@ -167,6 +170,7 @@ protected override void GetValidationChecks(List rules, BuildTar fixItAutomatic = true, fixItMessage = "Set Vulkan as Graphics API" }); +#endif } #endif } From e489cab1417903dbd782ecc9cd5817c86adfa196 Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:11:39 -0800 Subject: [PATCH 05/10] Add render model sample --- com.valvesoftware.openxr.utils/CHANGELOG.md | 4 + .../Documentation~/index.md | 1 + .../Samples~/RenderModels.meta | 8 + .../Samples~/RenderModels/README.md | 11 + .../Samples~/RenderModels/README.md.meta | 7 + .../RenderModels/RenderModelLoader.cs | 195 ++++ .../RenderModels/RenderModelLoader.cs.meta | 2 + .../RenderModels/RenderModelSample.unity | 997 ++++++++++++++++++ .../RenderModels/RenderModelSample.unity.meta | 7 + ...e.OpenXR.Utils.Samples.RenderModels.asmdef | 23 + ...nXR.Utils.Samples.RenderModels.asmdef.meta | 7 + .../ValveRenderModelFeature-Interop.cs | 298 ++++++ .../ValveRenderModelFeature-Interop.cs.meta | 2 + .../RenderModels/ValveRenderModelFeature.cs | 444 ++++++++ .../ValveRenderModelFeature.cs.meta | 2 + com.valvesoftware.openxr.utils/package.json | 7 +- 16 files changed, 2014 insertions(+), 1 deletion(-) create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs.meta create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs create mode 100644 com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs.meta diff --git a/com.valvesoftware.openxr.utils/CHANGELOG.md b/com.valvesoftware.openxr.utils/CHANGELOG.md index 683f895..bff38dc 100644 --- a/com.valvesoftware.openxr.utils/CHANGELOG.md +++ b/com.valvesoftware.openxr.utils/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.0.4] - 2026-03-03 +### Added +- OpenXR render model sample. + ## [1.0.3] - 2026-02-12 ### Added - System info sample for checking device is Steam Frame diff --git a/com.valvesoftware.openxr.utils/Documentation~/index.md b/com.valvesoftware.openxr.utils/Documentation~/index.md index 8b3b3d8..97b1a44 100644 --- a/com.valvesoftware.openxr.utils/Documentation~/index.md +++ b/com.valvesoftware.openxr.utils/Documentation~/index.md @@ -50,6 +50,7 @@ git@github.com:ValveSoftware/Unity.git?path=com.valvesoftware.openxr.utils | :--- | :--- | :--- | | **Refresh Rate** | Queries and displays the current display refresh rate. | Valve Utils Refresh Rate OpenXR Feature | | **System Info** | Queries whether the device is Steam Frame using OpenXR's system info. | Unity 2022.3, Unity OpenXR Plugin v1.9.1 | +| **Render Model** | Displays the Steam Frame controller render models obtained from the OpenXR runtime. | Unity 6.0, Unity OpenXR Plugin v1.9.1 | ## Limitations diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels.meta b/com.valvesoftware.openxr.utils/Samples~/RenderModels.meta new file mode 100644 index 0000000..6be8e1c --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7591a98e3ab99b2499fafa489bfd0954 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md b/com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md new file mode 100644 index 0000000..ac7431f --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md @@ -0,0 +1,11 @@ +# Render Model Sample + +This sample demonstrates how to retrieve XR controller render models from the OpenXR runtime and animate and display them. + +## Usage + +* Import sample from the Package Manager +* Enable the OpenXR feature in ProjectSettings -> OpenXR (Valve Utils: Render Model Sample) +* Fix any project validation errors (will insure glTFast is installed and required shaders are preloaded). +* Build and run the example scene. +* See the RenderModelLoader MonoBehaviour in the example scene for placement details (ie: initial rotation needed) \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md.meta b/com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md.meta new file mode 100644 index 0000000..4995109 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2e136ece87ace3649be98a2acf8122db +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs new file mode 100644 index 0000000..01298e6 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs @@ -0,0 +1,195 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +#if UNITY_GLTFAST +using System.Threading.Tasks; +using GLTFast; +#endif +using UnityEngine; +using UnityEngine.XR; +using UnityEngine.XR.OpenXR; + +public class RenderModelLoader : MonoBehaviour +{ + private enum Handedness { Left, Right } + [SerializeField] private Handedness controllerHand; + + private ulong renderModelHandle; + private List animNodes; + private List animNodeStates; + private Coroutine modelLoadCoroutine; + private ValveRenderModelFeature feature; + + private void Awake() + { + feature = OpenXRSettings.Instance.GetFeature(); + if (feature ==null) + { + Debug.LogError("RenderModelFeature not found or not enabled - disabling RenderModelLoader."); + enabled = false; + } + } + + private void Update() + { + // Load the render model once the input device has connected. + if (modelLoadCoroutine == null) + { + if (IsTrackedControllerConnected(controllerHand)) + { + modelLoadCoroutine = StartCoroutine(LoadModelAsync()); + } + return; + } + + UpdateAnimations(); + } + + private IEnumerator LoadModelAsync() + { + // Load the binary data for the render model + ulong renderModelAssetHandle; + List animNodeNames; + byte[] assetBytes; + if (!feature.GetRenderModelAssetData(controllerHand == Handedness.Left, + out renderModelHandle, + out renderModelAssetHandle, + out animNodeNames, + out assetBytes)) + { + Debug.LogError("Failed to retrieve glTF data from runtime."); + yield break; + } + +#if UNITY_GLTFAST + // Import GLTF binary data and instantiate hierarchy under this transform + var gltf = new GltfImport(); + Task task = gltf.Load(assetBytes); + yield return new WaitUntil(() => task.IsCompleted); + if (!task.Result) + { + Debug.LogError($"glTF import error (code: = {task.Result}"); + yield break; + } + task = gltf.InstantiateMainSceneAsync(transform); + yield return new WaitUntil(() => task.IsCompleted); + if (!task.Result) + { + Debug.LogError($"glTF scene instantiation error (code: {task.Result})."); + yield break; + } + + // Adjust for SteamVR authoring + if (transform.childCount > 0) + { + var child = transform.GetChild(0); + AdjustModelBasis(child.transform); + } +#endif + + // Setup animation state data to use for updating render model animatable nodes + int animStateCount = animNodeNames.Count; + animNodeStates = Enumerable.Range(0, animStateCount) + .Select(_ => new ValveRenderModelFeature.ModelNodeState()) + .ToList(); + + // Find the animatable nodes in the game object hierarchy base on the list of object names provided by OpenXR + // Store them in a list so their transforms can up updated when render model nodes' state changes. + animNodes = new List(); + foreach (var name in animNodeNames) + { + var child = FindChildRecursive(transform, name); + if (child) + { + animNodes.Add(child); + } + } + + // Free up the resources used for the glhf transmission data now that the model's hierarchy has been created. + if (renderModelAssetHandle != 0) + { + if (!feature.DestroyRenderModel(renderModelAssetHandle)) + { + Debug.LogError("[RenderModelLoader] Error destroying temporary render model."); + yield break; + } + } + } + + private void UpdateAnimations() + { + // Get the poses from OpenXR and update the transforms of those that are visible. + if (renderModelHandle == 0) return; + if (animNodeStates == null) return; + + if (feature.GetRenderModelStates(renderModelHandle, ref animNodeStates)) + { + for (int i = 0; i < animNodeStates.Count; ++i) + { + var state = animNodeStates[i]; + var node = animNodes[i]; + + node.gameObject.SetActive(state.Visible); + if (state.Visible) + { + AdjustLocalAnimUpdate(ref state.Position, ref state.Rotation); + node.SetLocalPositionAndRotation(state.Position, state.Rotation); + } + } + } + } + + private static bool IsTrackedControllerConnected(Handedness handedness) + { + var inputDevices = new List(); + InputDevices.GetDevices(inputDevices); + InputDeviceCharacteristics desiredCharacteristics = + InputDeviceCharacteristics.Controller | + (handedness == Handedness.Left ? InputDeviceCharacteristics.Left : InputDeviceCharacteristics.Right); + + foreach (var inputDevice in inputDevices) + { + if ((inputDevice.characteristics & desiredCharacteristics) == desiredCharacteristics && + inputDevice.TryGetFeatureValue(CommonUsages.isTracked, out bool isTracked) && + isTracked) + { + return true; + } + } + return false; + } + + private static Transform FindChildRecursive(Transform parent, string name) + { + if (parent.name == name) + { + return parent; + } + + for (int i = 0; i < parent.childCount; i++) + { + Transform result = FindChildRecursive(parent.GetChild(i), name); + if (result != null) + { + return result; + } + } + + return null; + } + + private static void AdjustModelBasis(Transform transform) + { + // Adjust for facing direction of SteamVR model authoring + transform.localRotation *= Quaternion.Euler(0, 180, 0); + } + + private static void AdjustLocalAnimUpdate(ref Vector3 position, ref Quaternion rotation) + { + // Compensate for RH -> LH reflection (GLTF -> Unity) and original model basis change + position.x = -position.x; + position.z = -position.z; + rotation.x = -rotation.x; + rotation.z = -rotation.z; + } +} diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs.meta b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs.meta new file mode 100644 index 0000000..762abeb --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0358dc4049417e94c9697b6b93c5cb32 \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity new file mode 100644 index 0000000..7ab3d43 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity @@ -0,0 +1,997 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &203844586 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 203844589} + - component: {fileID: 203844588} + - component: {fileID: 203844587} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &203844587 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203844586} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Version: 4 + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_LightLayerMask: 1 + m_RenderingLayers: 1 + m_CustomShadowLayers: 0 + m_ShadowLayerMask: 1 + m_ShadowRenderingLayers: 1 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 +--- !u!108 &203844588 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203844586} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 0.8392157, g: 0.89568436, b: 1, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 2 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &203844589 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 203844586} + serializedVersion: 2 + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &688780007 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 688780008} + - component: {fileID: 688780011} + - component: {fileID: 688780010} + - component: {fileID: 688780009} + m_Layer: 0 + m_Name: Ground + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &688780008 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 688780007} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.05, y: -0.5, z: 0} + m_LocalScale: {x: 25, y: 0.05, z: 25} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &688780009 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 688780007} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &688780010 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 688780007} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 2 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &688780011 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 688780007} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &704318476 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 704318477} + - component: {fileID: 704318478} + m_Layer: 0 + m_Name: Right Controller Visual + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &704318477 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704318476} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1864849695} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &704318478 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 704318476} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0358dc4049417e94c9697b6b93c5cb32, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::RenderModelLoader + controllerHand: 1 +--- !u!1 &945056201 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 945056202} + - component: {fileID: 945056206} + - component: {fileID: 945056205} + - component: {fileID: 945056204} + - component: {fileID: 945056203} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &945056202 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945056201} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.336} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1247386272} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &945056203 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945056201} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalCameraData + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + m_Quality: 3 + m_FrameInfluence: 0.1 + m_JitterScale: 1 + m_MipBias: 0 + m_VarianceClampScale: 0.9 + m_ContrastAdaptiveSharpening: 0 +--- !u!114 &945056204 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945056201} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c2fadf230d1919748a9aa21d40f74619, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.InputSystem::UnityEngine.InputSystem.XR.TrackedPoseDriver + m_TrackingType: 0 + m_UpdateType: 0 + m_IgnoreTrackingState: 0 + m_PositionInput: + m_UseReference: 0 + m_Action: + m_Name: Position + m_Type: 0 + m_ExpectedControlType: Vector3 + m_Id: fd26b093-ee40-45a1-bc6f-a74712ef2bb6 + m_Processors: + m_Interactions: + m_SingletonActionBindings: + - m_Name: + m_Id: 686f9d92-cdd3-4c23-83cf-870f4ed41899 + m_Path: /centerEyePosition + m_Interactions: + m_Processors: + m_Groups: + m_Action: Position + m_Flags: 0 + - m_Name: + m_Id: 8273fcdb-70fa-4f5a-b0a1-90eed0f1482d + m_Path: /devicePosition + m_Interactions: + m_Processors: + m_Groups: + m_Action: Position + m_Flags: 0 + m_Flags: 0 + m_Reference: {fileID: 0} + m_RotationInput: + m_UseReference: 0 + m_Action: + m_Name: Rotation + m_Type: 0 + m_ExpectedControlType: Quaternion + m_Id: d2662bb4-e953-490f-a8c0-1f8c0e5af3da + m_Processors: + m_Interactions: + m_SingletonActionBindings: + - m_Name: + m_Id: 5641c0f9-2ec8-40bc-8dcb-c8e0cc789089 + m_Path: /centerEyeRotation + m_Interactions: + m_Processors: + m_Groups: + m_Action: Rotation + m_Flags: 0 + - m_Name: + m_Id: fbb2edd2-e20d-42c4-9f31-aab63502b901 + m_Path: /deviceRotation + m_Interactions: + m_Processors: + m_Groups: + m_Action: Rotation + m_Flags: 0 + m_Flags: 0 + m_Reference: {fileID: 0} + m_TrackingStateInput: + m_UseReference: 0 + m_Action: + m_Name: Tracking State + m_Type: 0 + m_ExpectedControlType: Integer + m_Id: 479df8de-6f57-4be8-9c72-ed4657f0255f + m_Processors: + m_Interactions: + m_SingletonActionBindings: + - m_Name: + m_Id: af6bda2b-e1a9-4261-90cf-f0f89c979731 + m_Path: /trackingState + m_Interactions: + m_Processors: + m_Groups: + m_Action: Tracking State + m_Flags: 0 + m_Flags: 0 + m_Reference: {fileID: 0} + m_PositionAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: c254c082-f1e5-4e90-bc47-4cc9e5dde146 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_RotationAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: cc05427e-eeb7-482d-a0da-a9684a430699 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 +--- !u!81 &945056205 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945056201} + m_Enabled: 1 +--- !u!20 &945056206 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 945056201} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.01 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!1 &1228838798 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1228838799} + - component: {fileID: 1228838800} + m_Layer: 0 + m_Name: Left Controller + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1228838799 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1228838798} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1328898454} + m_Father: {fileID: 1247386272} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1228838800 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1228838798} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c2fadf230d1919748a9aa21d40f74619, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackingType: 0 + m_UpdateType: 0 + m_IgnoreTrackingState: 0 + m_PositionInput: + m_UseReference: 1 + m_Action: + m_Name: Position + m_Type: 0 + m_ExpectedControlType: Vector3 + m_Id: cd22b81e-c39a-4170-bdbf-33b5a06ea86f + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: -2024308242397127297, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_RotationInput: + m_UseReference: 1 + m_Action: + m_Name: Rotation + m_Type: 0 + m_ExpectedControlType: Quaternion + m_Id: 04fa80c1-7876-441c-8416-c5ea3caea5c4 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 8248158260566104461, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_TrackingStateInput: + m_UseReference: 1 + m_Action: + m_Name: Tracking State + m_Type: 0 + m_ExpectedControlType: Integer + m_Id: fdcc0d62-5cd0-4fcc-8c3a-c07cf6230b7d + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 684395432459739428, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_PositionAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: ddb05e9d-4218-401c-a7a8-003424f4b4fa + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_RotationAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: de98cdb6-b2c4-4d67-af3c-9c8bd60b295a + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 +--- !u!1 &1247386271 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1247386272} + m_Layer: 0 + m_Name: Camera Offset + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1247386272 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1247386271} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1.1176, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 945056202} + - {fileID: 1228838799} + - {fileID: 1864849695} + m_Father: {fileID: 1317914603} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1317914600 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1317914603} + - component: {fileID: 1317914602} + - component: {fileID: 1317914601} + m_Layer: 0 + m_Name: XR Origin (VR) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1317914601 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1317914600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 017c5e3933235514c9520e1dace2a4b2, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.XR.Interaction.Toolkit::UnityEngine.XR.Interaction.Toolkit.Inputs.InputActionManager + m_ActionAssets: + - {fileID: -944628639613478452, guid: c348712bda248c246b8c49b3db54643f, type: 3} +--- !u!114 &1317914602 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1317914600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e0cb9aa70a22847b5925ee5f067c10a9, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.XR.CoreUtils::Unity.XR.CoreUtils.XROrigin + m_Camera: {fileID: 945056206} + m_OriginBaseGameObject: {fileID: 1317914600} + m_CameraFloorOffsetObject: {fileID: 1247386271} + m_RequestedTrackingOriginMode: 0 + m_CameraYOffset: 1.1176 +--- !u!4 &1317914603 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1317914600} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1247386272} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1328898453 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1328898454} + - component: {fileID: 1328898455} + m_Layer: 0 + m_Name: Left Controller Visual + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1328898454 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328898453} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1228838799} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1328898455 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1328898453} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0358dc4049417e94c9697b6b93c5cb32, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::RenderModelLoader + controllerHand: 0 +--- !u!1 &1864849694 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1864849695} + - component: {fileID: 1864849696} + m_Layer: 0 + m_Name: Right Controller + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1864849695 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1864849694} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 704318477} + m_Father: {fileID: 1247386272} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1864849696 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1864849694} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c2fadf230d1919748a9aa21d40f74619, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackingType: 0 + m_UpdateType: 0 + m_IgnoreTrackingState: 0 + m_PositionInput: + m_UseReference: 1 + m_Action: + m_Name: Position + m_Type: 0 + m_ExpectedControlType: Vector3 + m_Id: c21ad7d3-c46f-48ad-99da-097df39312cc + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: -3326005586356538449, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_RotationInput: + m_UseReference: 1 + m_Action: + m_Name: Rotation + m_Type: 0 + m_ExpectedControlType: Quaternion + m_Id: 69f091ba-e646-4189-9296-d68870a4d922 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 5101698808175986029, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_TrackingStateInput: + m_UseReference: 1 + m_Action: + m_Name: Tracking State + m_Type: 0 + m_ExpectedControlType: Integer + m_Id: 05873c58-6d6f-4aea-8e06-78c4544c58dc + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: -1277054153949319361, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_PositionAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: e0c62bbd-29f9-48af-967b-21babef9a6a4 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_RotationAction: + m_Name: + m_Type: 0 + m_ExpectedControlType: + m_Id: 303ef588-e0d6-494e-9ceb-2d2edc0eb8e5 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 1317914603} + - {fileID: 203844589} + - {fileID: 688780008} diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity.meta b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity.meta new file mode 100644 index 0000000..0117c39 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelSample.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bce2c43cccf175142927c69962b62512 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef b/com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef new file mode 100644 index 0000000..b2918ed --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef @@ -0,0 +1,23 @@ +{ + "name": "Valve.OpenXR.Utils.Samples.RenderModels", + "rootNamespace": "", + "references": [ + "GUID:4847341ff46394e83bb78fbd0652937e", + "GUID:a42927d1d4a3b4cda9b076a7adecb9cc" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [ + { + "name": "com.unity.cloud.gltfast", + "expression": "6", + "define": "UNITY_GLTFAST" + } + ], + "noEngineReferences": false +} \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef.meta b/com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef.meta new file mode 100644 index 0000000..6c254de --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/Valve.OpenXR.Utils.Samples.RenderModels.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fe1b8d930a46c524f8fac60b11389af8 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs new file mode 100644 index 0000000..b9317f9 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs @@ -0,0 +1,298 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +using UnityEngine; +using UnityEngine.XR.OpenXR.Features; +using UnityEngine.XR.OpenXR.NativeTypes; + +public partial class ValveRenderModelFeature : OpenXRFeature +{ + private delegate XrResult GetInstanceProcAddrDelegate(ulong instance, string name, ref IntPtr procAddr); + private GetInstanceProcAddrDelegate _getInstanceProcAddr; + + private T GetOpenXrInstanceProc(string procName) + { + if (_getInstanceProcAddr == null) + { + if (xrGetInstanceProcAddr == IntPtr.Zero) + { + Debug.LogWarning($"Unity's OpenXR GetInstance function accessor is invalid!"); + return default; + } + + _getInstanceProcAddr = Marshal.GetDelegateForFunctionPointer(xrGetInstanceProcAddr); + } + + IntPtr resultProcAddr = IntPtr.Zero; + + if (_getInstanceProcAddr != null) + { + XrResult result = _getInstanceProcAddr(_xrInstance, procName, ref resultProcAddr); + + if (result < 0 || resultProcAddr == IntPtr.Zero) + { + Debug.LogWarning($"Failed to find OpenXR instance function '{procName} (result: {result}, instance: {_xrInstance}).'"); + return default; + } + } + + return Marshal.GetDelegateForFunctionPointer(resultProcAddr); + } + + private bool XrSucceeded(int xrResult) + { + return xrResult == 0; + } + + private static long ToXrTime(double seconds) + { + return (long)(seconds * 1_000_000_000.0); + } + + #region OpenXR Structures + + public enum XrStructureType : uint + { + XR_TYPE_RENDER_MODEL_ASSET_CREATE_INFO_EXT = 1000300006, + XR_TYPE_RENDER_MODEL_ASSET_DATA_GET_INFO_EXT = 1000300007, + XR_TYPE_RENDER_MODEL_ASSET_DATA_EXT = 1000300008, + XR_TYPE_RENDER_MODEL_CREATE_INFO_EXT = 1000300000, + XR_TYPE_RENDER_MODEL_PROPERTIES_GET_INFO_EXT = 1000300001, + XR_TYPE_RENDER_MODEL_PROPERTIES_EXT = 1000300002, + XR_TYPE_RENDER_MODEL_STATE_EXT = 1000300005, + XR_TYPE_RENDER_MODEL_ASSET_PROPERTIES_GET_INFO_EXT = 1000300009, + XR_TYPE_RENDER_MODEL_ASSET_PROPERTIES_EXT = 1000300010, + XR_TYPE_RENDER_MODEL_STATE_GET_INFO_EXT = 1000300004, + XR_TYPE_INTERACTION_RENDER_MODEL_IDS_ENUMERATE_INFO_EXT = 1000301000, + XR_TYPE_INTERACTION_RENDER_MODEL_SUBACTION_PATH_INFO_EXT = 1000301001, + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrPath + { + public ulong Value; + + public static implicit operator ulong(XrPath p) => p.Value; + public static implicit operator XrPath(ulong v) => new XrPath { Value = v }; + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrInteractionRenderModelIdsEnumerateInfoEXT + { + public XrStructureType type; + public IntPtr next; + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrRenderModelPropertiesGetInfoEXT + { + public XrStructureType type; + public IntPtr next; + } + + // 16-byte UUID + [StructLayout(LayoutKind.Sequential)] + public struct XrUuidEXT + { + private const int XR_UUID_SIZE = 16; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = XR_UUID_SIZE)] + public byte[] bytes; + + public bool IsValid => bytes != null && bytes.Length == XR_UUID_SIZE; + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrRenderModelPropertiesEXT + { + public XrStructureType type; + public IntPtr next; + public XrUuidEXT assetId; + public uint animatableNodeCount; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct XrRenderModelAssetNodePropertiesEXT + { + private const int XR_MAX_RENDER_MODEL_ASSET_NODE_NAME_SIZE_EXT = 64; + + // Placeholder for inline char[64] + private byte _dummy; + + public static int stride => XR_MAX_RENDER_MODEL_ASSET_NODE_NAME_SIZE_EXT; + + public static IntPtr Allocate(int nodeCount) + { + int size = nodeCount * XR_MAX_RENDER_MODEL_ASSET_NODE_NAME_SIZE_EXT; + IntPtr ptr = Marshal.AllocHGlobal(size); + + // Zero memory + Span zero = stackalloc byte[XR_MAX_RENDER_MODEL_ASSET_NODE_NAME_SIZE_EXT]; + for (int i = 0; i < nodeCount; i++) + Marshal.Copy(zero.ToArray(), 0, ptr + i * zero.Length, zero.Length); + + return ptr; + } + + public static void Free(IntPtr ptr) + { + if (ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + } + } + + public static string HandleToUtf8String(IntPtr structPtr, int maxLen = XR_MAX_RENDER_MODEL_ASSET_NODE_NAME_SIZE_EXT) + { + byte[] buffer = new byte[maxLen]; + Marshal.Copy(structPtr, buffer, 0, maxLen); + + int len = Array.IndexOf(buffer, (byte)0); + if (len < 0) len = maxLen; + + return Encoding.UTF8.GetString(buffer, 0, len); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrRenderModelAssetPropertiesGetInfoEXT + { + public XrStructureType type; + public IntPtr next; + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrRenderModelAssetPropertiesEXT + { + public XrStructureType type; + public IntPtr next; + public uint nodePropertyCount; + public IntPtr nodeProperties; // XrRenderModelAssetNodePropertiesEXT* + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrRenderModelNodeStateEXT + { + public XrPosef nodePose; + public uint isVisible; + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrRenderModelStateEXT + { + public XrStructureType type; + public IntPtr next; + public uint nodeStateCount; + public IntPtr nodeStates; // XrRenderModelNodeStateEXT* + } + + [StructLayout(LayoutKind.Sequential)] + private struct XrRenderModelAssetCreateInfoEXT + { + public XrStructureType type; + public IntPtr next; + public XrUuidEXT cacheId; // uuid to request asset + } + + [StructLayout(LayoutKind.Sequential)] + public struct XrRenderModelCreateInfoEXT + { + public XrStructureType type; + public IntPtr next; + public XrRenderModelIdEXT renderModelId; + public uint gltfExtensionCount; + public IntPtr gltfExtensions; // const char* const* + } + + [StructLayout(LayoutKind.Sequential)] + private struct XrRenderModelAssetDataGetInfoEXT + { + public XrStructureType type; + public IntPtr next; + } + + [StructLayout(LayoutKind.Sequential)] + private struct XrInteractionRenderModelSubactionPathInfoEXT + { + public XrStructureType type; + public IntPtr next; + } + + [StructLayout(LayoutKind.Sequential)] + private struct XrRenderModelStateGetInfoEXT + { + public XrStructureType type; + public IntPtr next; + public long displayTime; + } + + [StructLayout(LayoutKind.Sequential)] + private struct XrRenderModelAssetDataEXT + { + public XrStructureType type; + public IntPtr next; + public uint bufferCapacityInput; + public uint bufferCountOutput; + public IntPtr buffer; // void* to GLB data + } + + [StructLayout(LayoutKind.Sequential)] + public readonly struct XrRenderModelIdEXT : IEquatable + { + private readonly ulong _value; + public ulong Value => _value; + public XrRenderModelIdEXT(ulong value) { _value = value; } + public static implicit operator ulong(XrRenderModelIdEXT id) { return id._value; } + public static implicit operator XrRenderModelIdEXT(ulong value) { return new XrRenderModelIdEXT(value); } + public override bool Equals(object obj) { if (obj is XrRenderModelIdEXT other) { return Equals(other); } return false; } + public bool Equals(XrRenderModelIdEXT other) { return _value == other._value; } + public override int GetHashCode() { return _value.GetHashCode(); } + public static bool operator ==(XrRenderModelIdEXT left, XrRenderModelIdEXT right) { return left.Equals(right); } + public static bool operator !=(XrRenderModelIdEXT left, XrRenderModelIdEXT right) { return !(left == right); } + } + + #endregion + + #region OpenXR Functions + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrCreateRenderModelEXT(ulong session, ref XrRenderModelCreateInfoEXT createInfo, out ulong renderModel); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrGetRenderModelPropertiesEXT(ulong renderModel, ref XrRenderModelPropertiesGetInfoEXT info, ref XrRenderModelPropertiesEXT properties); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrCreateRenderModelAssetEXT(ulong session, ref XrRenderModelAssetCreateInfoEXT createInfo, out ulong asset /* XrRenderModelAssetEXT* */); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrGetRenderModelAssetDataEXT(ulong asset, ref XrRenderModelAssetDataGetInfoEXT getInfo, out XrRenderModelAssetDataEXT buffer); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrGetRenderModelAssetPropertiesEXT(ulong asset, ref XrRenderModelAssetPropertiesGetInfoEXT getInfo, ref XrRenderModelAssetPropertiesEXT properties); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrDestroyRenderModelAssetEXT(ulong asset); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrDestroyRenderModelEXT(ulong renderModel); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrGetRenderModelStateEXT(ulong renderModel, ref XrRenderModelStateGetInfoEXT getInfo, ref XrRenderModelStateEXT state); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int PFN_xrGetPredictedDisplayTime(ulong session, int viewConfigurationType, out long predictedDisplayTime); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrEnumerateInteractionRenderModelIdsEXT (ulong session, ref XrInteractionRenderModelIdsEnumerateInfoEXT enumerateInfo, uint renderModelIdCapacityInput, out uint renderModelIdCountOutput, [Out] XrRenderModelIdEXT[] renderModelIds); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int PFN_xrEnumerateRenderModelSubactionPathsEXT( + ulong renderModel, + ref XrInteractionRenderModelSubactionPathInfoEXT info, + uint pathCapacityInput, + out uint pathCountOutput, + IntPtr paths // pointer to pre-allocated unmanaged array of XrPath + ); + + #endregion +} diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs.meta b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs.meta new file mode 100644 index 0000000..6282238 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature-Interop.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 0b77f4e31e8cd5e42b9a024ecda0ac70 \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs new file mode 100644 index 0000000..1cf3993 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs @@ -0,0 +1,444 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +#if UNITY_EDITOR +using UnityEditor; +using UnityEditor.XR.OpenXR.Features; +using UnityEditor.PackageManager; +#endif +using UnityEngine; +using UnityEngine.XR.OpenXR.Features; +using Object = UnityEngine.Object; + +#if UNITY_EDITOR +[OpenXRFeature(UiName = "Valve Utils: Render Model Sample", + Desc = "Support for OpenXR render models", + Company = "Valve", + Version = "0.1.0", + BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.Android }, + FeatureId = "com.valve.openxr.feature.render_models", + OpenxrExtensionStrings = "XR_EXT_render_model XR_EXT_interaction_render_model XR_EXT_uuid" +)] +#endif +public partial class ValveRenderModelFeature : OpenXRFeature +{ + private ulong _xrInstance; + private ulong _xrSession; + + // From XR_EXT_render_model + private PFN_xrCreateRenderModelEXT _xrCreateRenderModelEXT; + private PFN_xrGetRenderModelPropertiesEXT _xrGetRenderModelPropertiesEXT; + private PFN_xrCreateRenderModelAssetEXT _xrCreateRenderModelAssetEXT; + private PFN_xrGetRenderModelAssetDataEXT _xrGetRenderModelAssetDataEXT; + private PFN_xrGetRenderModelAssetPropertiesEXT _xrGetRenderModelAssetPropertiesEXT; + private PFN_xrDestroyRenderModelAssetEXT _xrDestroyRenderModelAssetEXT; + private PFN_xrDestroyRenderModelEXT _xrDestroyRenderModelEXT; + private PFN_xrGetPredictedDisplayTime _xrGetPredictedDisplayTime; + private PFN_xrGetRenderModelStateEXT _xrGetRenderModelStateEXT; + // From XR_EXT_interaction_render_model + private PFN_xrEnumerateInteractionRenderModelIdsEXT _xrEnumerateInteractionRenderModelIdsEXT; + private PFN_xrEnumerateRenderModelSubactionPathsEXT _xrEnumerateRenderModelSubactionPathsEXT; + + public class ModelNodeState + { + public Vector3 Position; + public Quaternion Rotation; + public bool Visible; + } + + public bool GetRenderModelAssetData( + bool isLeftHand, + out ulong renderModelHandle, + out ulong renderModelAssetHandle, + out List animatableNodeNames, + out byte[] renderModelAssetBytes) + { + renderModelHandle = 0; + renderModelAssetHandle = 0; + animatableNodeNames = null; + renderModelAssetBytes = null; + + // Enumerate the render models and search for one with the desired model path + var modelPath = $"/user/hand/{(isLeftHand ? "left" : "right")}"; + XrRenderModelIdEXT renderModelId = FindRenderModelByPath(modelPath); + if (renderModelId == 0) + { + Debug.LogError($"No render model found for path: {modelPath}"); + return false; + } + + if (!CreateRenderModel(renderModelId, ref renderModelHandle)) + { + return false; + } + XrUuidEXT assetId = default(XrUuidEXT); + if (!GetRenderModelAssetId(renderModelHandle, ref assetId)) + { + return false; + } + + if (!CreateRenderModelAsset(assetId, ref renderModelAssetHandle)) + { + return false; + } + + LoadAssetData(renderModelAssetHandle, out renderModelAssetBytes); + var animatableNodeCount = GetAnimatableNodeCount(renderModelHandle); + animatableNodeNames = GetAnimatableNodeNames(renderModelAssetHandle, animatableNodeCount); + return true; + } + + public bool GetRenderModelStates(ulong renderModel, ref List nodeStates) + { + Debug.Assert(renderModel != 0); + + XrRenderModelNodeStateEXT[] states = new XrRenderModelNodeStateEXT[nodeStates.Count]; + GCHandle hStates = GCHandle.Alloc(states, GCHandleType.Pinned); + + try + { + var renderModelState = new XrRenderModelStateEXT + { + type = XrStructureType.XR_TYPE_RENDER_MODEL_STATE_EXT, + nodeStateCount = (uint)nodeStates.Count, + nodeStates = hStates.AddrOfPinnedObject() + }; + + var stateGetInfo = new XrRenderModelStateGetInfoEXT + { + type = XrStructureType.XR_TYPE_RENDER_MODEL_STATE_GET_INFO_EXT, + displayTime = ToXrTime(Time.time) + }; + + if (!XrSucceeded(_xrGetRenderModelStateEXT(renderModel, ref stateGetInfo, ref renderModelState))) + { + Debug.LogError($"_xrGetRenderModelStateEXT failed!"); + return false; + } + + for (var i = 0; i < states.Length; ++i) + { + nodeStates[i].Visible = states[i].isVisible != 0; + nodeStates[i].Position = states[i].nodePose.Position.AsVector3(); + nodeStates[i].Rotation = states[i].nodePose.Orientation.AsQuaternion(); + } + } + finally + { + hStates.Free(); + } + + return true; + } + + public bool DestroyRenderModel(ulong asset) + { + if (!XrSucceeded(_xrDestroyRenderModelAssetEXT(asset))) + { + Debug.LogError($"xrDestroyRenderModelAssetEXT failed!"); + return false; + } + + return true; + } + + + #region "OpenXRFeature overrides" + + protected override bool OnInstanceCreate(ulong xrInstance) + { + _xrInstance = xrInstance; + + if (xrGetInstanceProcAddr == IntPtr.Zero) + { + Debug.LogError("[RenderModelFeature] xrGetInstanceProcAddr is null."); + return false; + } + + _xrGetRenderModelPropertiesEXT = GetOpenXrInstanceProc("xrGetRenderModelPropertiesEXT"); + _xrCreateRenderModelEXT = GetOpenXrInstanceProc("xrCreateRenderModelEXT"); + _xrCreateRenderModelAssetEXT = GetOpenXrInstanceProc("xrCreateRenderModelAssetEXT"); + _xrGetRenderModelAssetDataEXT = GetOpenXrInstanceProc("xrGetRenderModelAssetDataEXT"); + _xrGetRenderModelAssetPropertiesEXT = GetOpenXrInstanceProc("xrGetRenderModelAssetPropertiesEXT"); + _xrDestroyRenderModelAssetEXT = GetOpenXrInstanceProc("xrDestroyRenderModelAssetEXT"); + _xrDestroyRenderModelEXT = GetOpenXrInstanceProc("xrDestroyRenderModelEXT"); + _xrGetRenderModelStateEXT = GetOpenXrInstanceProc("xrGetRenderModelStateEXT"); + _xrEnumerateInteractionRenderModelIdsEXT = GetOpenXrInstanceProc("xrEnumerateInteractionRenderModelIdsEXT"); + _xrEnumerateRenderModelSubactionPathsEXT = GetOpenXrInstanceProc("xrEnumerateRenderModelSubactionPathsEXT"); + + return true; + } + + protected override void OnSessionCreate(ulong session) + { + _xrSession = session; + } + +#if UNITY_EDITOR + protected override void GetValidationChecks(List results, BuildTargetGroup target) + { + const string gltfPackageName = "com.unity.cloud.gltfast"; + string[] requiredAssetFilenames = new[] { "glTF-pbrMetallicRoughness.shadergraph" }; + +#if !UNITY_GLTFAST + results.Add(new ValidationRule(this) + { + message = "This feature requires the GLTFast package to be installed.", + error = true, + checkPredicate = () => false, + fixIt = () => + { + Client.Add("com.unity.cloud.gltfast"); + }, + fixItAutomatic = true, + fixItMessage = "Install the Unity GLTFast package." + }); +#else + // Preloading shaders as indicated in Unity glTFast docs + // https://docs.unity3d.com/Packages/com.unity.cloud.gltfast@6.0/manual/ProjectSetup.html + // Automating the process here for Steam Frame under XR Project Validation rules for convenience. + results.Add(new ValidationRule(this) + { + message = "GLTFast needs to preload expected shaders/variants to avoid being stripped out of builds.", + error = false, + checkPredicate = () => + { + var preloaded = PlayerSettings.GetPreloadedAssets() ?? Array.Empty(); + var preloadedGLTFFiles = preloaded + .Select(a => AssetDatabase.GetAssetPath(a)) + .Where(p => !string.IsNullOrEmpty(p)) + .Where(p => p.StartsWith($"Packages/{gltfPackageName}")) + .Select(Path.GetFileName) + .ToList(); + + // Find any missing required assets + foreach (var filename in requiredAssetFilenames) + { + if (!preloadedGLTFFiles.Contains(filename)) + { + return false; + } + } + return true; + }, + fixIt = () => + { + var packageFolder = Path.GetFullPath($"Packages/{gltfPackageName}"); + var preloaded = PlayerSettings.GetPreloadedAssets().ToHashSet(); + foreach (var filename in requiredAssetFilenames) + { + var files = Directory.GetFiles(packageFolder, filename, SearchOption.AllDirectories); + foreach (var file in files) + { + var path = Path.Combine("Packages", gltfPackageName, file.Remove(0, packageFolder.Length+1)); + var asset = AssetDatabase.LoadMainAssetAtPath(path); + preloaded.Add(asset); + } + } + PlayerSettings.SetPreloadedAssets(preloaded.Where(p => p).ToArray()); + }, + fixItAutomatic = true, + fixItMessage = "Add top level shaders to preloaded assets." + }); +#endif + } +#endif + +#endregion + + private ulong RenderModelIdToHandle(ulong session, XrRenderModelIdEXT modelId) + { + var createInfo = new XrRenderModelCreateInfoEXT + { + type = XrStructureType.XR_TYPE_RENDER_MODEL_CREATE_INFO_EXT, + renderModelId = modelId, + gltfExtensionCount = 0, + gltfExtensions = IntPtr.Zero, + }; + + if (!XrSucceeded(_xrCreateRenderModelEXT(session, ref createInfo, out var hRenderModel))) + { + Debug.LogError($"Failed to create render model handle!"); + return 0; + } + + return hRenderModel; + } + + private bool CreateRenderModel(XrRenderModelIdEXT renderModelId, ref ulong handle) + { + Debug.Assert(_xrSession != 0); + + var createInfo = new XrRenderModelCreateInfoEXT + { + type = XrStructureType.XR_TYPE_RENDER_MODEL_CREATE_INFO_EXT, + renderModelId = renderModelId, + gltfExtensionCount = 0, + gltfExtensions = IntPtr.Zero + }; + + if (!XrSucceeded(_xrCreateRenderModelEXT(_xrSession, ref createInfo, out ulong renderModel))) + { + Debug.LogError($"CreateRenderModelEXT failed!"); + return false; + } + + handle = renderModel; + return true; + } + + private bool GetRenderModelAssetId(ulong hRenderModel, ref XrUuidEXT renderModelId) + { + var propGetInfo = new XrRenderModelPropertiesGetInfoEXT { type = XrStructureType.XR_TYPE_RENDER_MODEL_PROPERTIES_GET_INFO_EXT }; + var props = new XrRenderModelPropertiesEXT { type = XrStructureType.XR_TYPE_RENDER_MODEL_PROPERTIES_EXT }; + + if (!XrSucceeded(_xrGetRenderModelPropertiesEXT(hRenderModel, ref propGetInfo, ref props))) + { + Debug.LogError($"xrGetRenderModelPropertiesEXT failed!"); + return false; + } + + renderModelId = props.assetId; + return true; + } + + private int GetAnimatableNodeCount(ulong hRenderModel) + { + var propGetInfo = new XrRenderModelPropertiesGetInfoEXT { type = XrStructureType.XR_TYPE_RENDER_MODEL_PROPERTIES_GET_INFO_EXT }; + var props = new XrRenderModelPropertiesEXT { type = XrStructureType.XR_TYPE_RENDER_MODEL_PROPERTIES_EXT }; + + if (!XrSucceeded(_xrGetRenderModelPropertiesEXT(hRenderModel, ref propGetInfo, ref props))) + { + Debug.LogError($"xrGetRenderModelPropertiesEXT failed!"); + return -1; + } + + return (int)props.animatableNodeCount; + } + + private bool CreateRenderModelAsset(XrUuidEXT assetId, ref ulong hAsset) + { + Debug.Assert(_xrSession != 0); + + var assetCreate = new XrRenderModelAssetCreateInfoEXT + { + type = XrStructureType.XR_TYPE_RENDER_MODEL_ASSET_CREATE_INFO_EXT, + cacheId = assetId + }; + + if (!XrSucceeded(_xrCreateRenderModelAssetEXT(_xrSession, ref assetCreate, out ulong asset))) + { + Debug.LogError($"_xrCreateRenderModelAssetEXT failed!"); + return false; + } + + hAsset = asset; + return true; + } + + private void LoadAssetData(ulong hAsset, out byte[] gltfData) + { + gltfData = null; + + // Two-call idiom to get model buffer size + var assetGetInfo = new XrRenderModelAssetDataGetInfoEXT { type = XrStructureType.XR_TYPE_RENDER_MODEL_ASSET_DATA_GET_INFO_EXT }; + var assetData = new XrRenderModelAssetDataEXT + { + type = XrStructureType.XR_TYPE_RENDER_MODEL_ASSET_DATA_EXT, + bufferCapacityInput = 0, + bufferCountOutput = 0, + buffer = IntPtr.Zero + }; + + _xrGetRenderModelAssetDataEXT(hAsset, ref assetGetInfo, out assetData ); + + gltfData = new byte[assetData.bufferCountOutput]; + var handle = GCHandle.Alloc(gltfData, GCHandleType.Pinned); + assetData.bufferCapacityInput = assetData.bufferCountOutput; + assetData.buffer = handle.AddrOfPinnedObject(); + + _xrGetRenderModelAssetDataEXT(hAsset, ref assetGetInfo, out assetData); + handle.Free(); + } + + private XrRenderModelIdEXT FindRenderModelByPath(string path) + { + Debug.Assert(_xrSession != 0); + Debug.Assert(_xrEnumerateInteractionRenderModelIdsEXT != null); + + var info = new XrInteractionRenderModelIdsEnumerateInfoEXT { type = XrStructureType.XR_TYPE_INTERACTION_RENDER_MODEL_IDS_ENUMERATE_INFO_EXT }; + _xrEnumerateInteractionRenderModelIdsEXT(_xrSession, ref info, 0, out var count, null); + var ids = new XrRenderModelIdEXT[count]; + _xrEnumerateInteractionRenderModelIdsEXT(_xrSession, ref info, count, out count, ids); + + var subActionPathInfo = new XrInteractionRenderModelSubactionPathInfoEXT { type = XrStructureType.XR_TYPE_INTERACTION_RENDER_MODEL_SUBACTION_PATH_INFO_EXT }; + foreach (var id in ids) + { + ulong renderModel = RenderModelIdToHandle(_xrSession, id); + _xrEnumerateRenderModelSubactionPathsEXT(renderModel, ref subActionPathInfo, 0, out var pathCount, IntPtr.Zero); + var xrPaths = new XrPath[pathCount]; + GCHandle hXrPaths = GCHandle.Alloc(xrPaths, GCHandleType.Pinned); + try + { + IntPtr xrPathsPtr = hXrPaths.AddrOfPinnedObject(); + _xrEnumerateRenderModelSubactionPathsEXT(renderModel, ref subActionPathInfo, (uint)xrPaths.Length, out pathCount, xrPathsPtr); + if (xrPaths.Any(p => PathToString(p.Value).Equals(path))) + { + return id; + } + } + finally + { + hXrPaths.Free(); + } + } + + Debug.LogWarning("[RenderModelLoader] No render models found."); + return 0; + } + + private List GetAnimatableNodeNames(ulong asset, int nodeCount) + { + if (asset == 0 || nodeCount <= 0) + { + Debug.LogError($"GetanimatableNodeNames - bad input args!"); + return new List(); + } + + IntPtr nodeArrayPtr = XrRenderModelAssetNodePropertiesEXT.Allocate(nodeCount); + + var list = new List(nodeCount); + + try + { + var getInfo = new XrRenderModelAssetPropertiesGetInfoEXT { type = XrStructureType.XR_TYPE_RENDER_MODEL_ASSET_PROPERTIES_GET_INFO_EXT }; + var assetProps = new XrRenderModelAssetPropertiesEXT + { + type = XrStructureType.XR_TYPE_RENDER_MODEL_ASSET_PROPERTIES_EXT, + nodePropertyCount = (uint)nodeCount, + nodeProperties = nodeArrayPtr + }; + + if (!XrSucceeded(_xrGetRenderModelAssetPropertiesEXT(asset, ref getInfo, ref assetProps))) + { + Debug.LogError($"xrGetRenderModelAssetPropertiesEXT failed!"); + return list; + } + + // Convert names to strings + for (int i = 0; i < nodeCount; i++) + { + IntPtr elemPtr = IntPtr.Add(nodeArrayPtr, i * XrRenderModelAssetNodePropertiesEXT.stride); + list.Add(XrRenderModelAssetNodePropertiesEXT.HandleToUtf8String(elemPtr)); + } + } + finally + { + XrRenderModelAssetNodePropertiesEXT.Free(nodeArrayPtr); + } + + return list; + } +} diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs.meta b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs.meta new file mode 100644 index 0000000..3e5b508 --- /dev/null +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 95f309fdc0607444ea36f89da2c4b55c \ No newline at end of file diff --git a/com.valvesoftware.openxr.utils/package.json b/com.valvesoftware.openxr.utils/package.json index 3f273d3..adc5fcd 100644 --- a/com.valvesoftware.openxr.utils/package.json +++ b/com.valvesoftware.openxr.utils/package.json @@ -1,7 +1,7 @@ { "name": "com.valvesoftware.openxr.utils", "displayName": "Valve OpenXR Utilities", - "version": "1.0.3", + "version": "1.0.4", "description": "The Valve OpenXR Utilities package provides support for OpenXR projects and their access to Unity's OpenXR functionality.", "dependencies": { "com.unity.xr.openxr": "1.10.0", @@ -29,6 +29,11 @@ "displayName": "System Info", "description": "Demonstrates how to request the headset name from OpenXR and verify the app is running on Steam Frame.", "path": "Samples~/SystemInfo" + }, + { + "displayName": "Render Model", + "description": "Retrieves XR controller render models from the OpenXR runtime and display and animates them on screen.", + "path": "Samples~/RenderModels" } ] } \ No newline at end of file From 41ca1855174652d288af94a1b83ef76e34b5d4af Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:55:21 -0700 Subject: [PATCH 06/10] Fixed settings to better support foveated rendering with VK_KHR_depth_stencil_resolve (#7) --- com.valvesoftware.openxr.utils/CHANGELOG.md | 4 +++ .../ValveOpenXRFoveatedRenderingBuildHooks.cs | 1 + .../ValveOpenXRFoveatedRenderingFeature.cs | 28 +++++++++++++++++++ com.valvesoftware.openxr.utils/package.json | 2 +- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/com.valvesoftware.openxr.utils/CHANGELOG.md b/com.valvesoftware.openxr.utils/CHANGELOG.md index bff38dc..5f270e3 100644 --- a/com.valvesoftware.openxr.utils/CHANGELOG.md +++ b/com.valvesoftware.openxr.utils/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.0.5] - 2026-04-27 +### Fixed +- Fixed settings to better support foveated rendering with VK_KHR_depth_stencil_resolve + ## [1.0.4] - 2026-03-03 ### Added - OpenXR render model sample. diff --git a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs index 1520feb..d4c74ef 100644 --- a/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs +++ b/com.valvesoftware.openxr.utils/Editor/Features/ValveOpenXRFoveatedRenderingBuildHooks.cs @@ -17,6 +17,7 @@ protected override void OnProcessBootConfigExt(BuildReport report, BootConfigBui { #if !USE_LEGACY_BOOT_CONFIG builder.SetBootConfigValue("xr-vulkan-extension-fragment-density-map-enabled", "1"); + builder.SetBootConfigValue("xr-hide-memoryless-render-texture", "1"); #else builder.SetBootConfigValue("xr-meta-enabled", "1"); #endif diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs index 1b7a1b8..53c3fcb 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs @@ -262,6 +262,34 @@ protected override void GetValidationChecks(List r fixItAutomatic = true, fixItMessage = "Enable Unity's Foveated Rendering feature" }); +#endif +#if UNITY_6000_3_OR_NEWER + rules.Add(new ValidationRule(this) + { + message = "Optimize Buffer Discards must be enabled.", + error = true, + checkPredicate = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (settings == null) + return false; + + var supportFeature = settings.GetFeature(); + return supportFeature.enabled && supportFeature.optimizeBufferDiscards; + }, + fixIt = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (settings != null) + { + var supportFeature = settings.GetFeature(); + supportFeature.enabled = true; + supportFeature.optimizeBufferDiscards = true; + } + }, + fixItAutomatic = true, + fixItMessage = "Enable Optimize Buffer Discards" + }); #endif } #endif diff --git a/com.valvesoftware.openxr.utils/package.json b/com.valvesoftware.openxr.utils/package.json index adc5fcd..99b44b7 100644 --- a/com.valvesoftware.openxr.utils/package.json +++ b/com.valvesoftware.openxr.utils/package.json @@ -1,7 +1,7 @@ { "name": "com.valvesoftware.openxr.utils", "displayName": "Valve OpenXR Utilities", - "version": "1.0.4", + "version": "1.0.5", "description": "The Valve OpenXR Utilities package provides support for OpenXR projects and their access to Unity's OpenXR functionality.", "dependencies": { "com.unity.xr.openxr": "1.10.0", From a1a3ad73c1a35f3ebbbf41d38d88ea606ba1d37c Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Tue, 12 May 2026 12:09:18 -0700 Subject: [PATCH 07/10] Update min OpenXR plugin version to 1.13.0 for foveated rendering to avoid instability with Unity 2022.3 (#8) --- com.valvesoftware.openxr.utils/Documentation~/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.valvesoftware.openxr.utils/Documentation~/index.md b/com.valvesoftware.openxr.utils/Documentation~/index.md index 97b1a44..d14de4c 100644 --- a/com.valvesoftware.openxr.utils/Documentation~/index.md +++ b/com.valvesoftware.openxr.utils/Documentation~/index.md @@ -33,7 +33,7 @@ git@github.com:ValveSoftware/Unity.git?path=com.valvesoftware.openxr.utils | **Name** | **Description** | **Requirements** | :--- | :--- | :--- | | **Settings for Unity's Rendering** | OpenXR rendering settings | Unity 2022.3, Unity OpenXR Plugin v1.9.1 | -| **Settings for Unity's Foveated Rendering** | Settings for enabling foveated rendering on startup. | Unity 2022.3, Unity OpenXR Plugin v1.9.1, Vulkan, URP | +| **Settings for Unity's Foveated Rendering** | Settings for enabling foveated rendering on startup. | Unity 2022.3, Unity OpenXR Plugin v1.13.0, Vulkan, URP | | **Settings for Unity's Render Regions** | Settings for symmetric projection and per-view viewports and render areas. | Unity 6.1, Unity OpenXR Plugin v1.14.1, Vulkan, Multi-view | | **Lepton Validation** | Project validation rules for Lepton-enabled projects | Unity 2022.3 | | **Refresh Rate** | Access to the OpenXR refresh rate display extension. | Unity 2022.3, Unity OpenXR Plugin v1.9.1 | From 255678bbfc02a2418b3a9c1050e577d8a1b5b8f4 Mon Sep 17 00:00:00 2001 From: Keith Bradner <198704+keithbradner@users.noreply.github.com> Date: Wed, 27 May 2026 11:31:49 -0700 Subject: [PATCH 08/10] Forcing refresh of project validation window after the validation feature is enabled/disabled. --- .../Features/ValveOpenXRLeptonValidationFeature.cs | 8 ++++++++ .../Samples~/RenderModels/ValveRenderModelFeature.cs | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs index db8f680..0578421 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRLeptonValidationFeature.cs @@ -124,6 +124,14 @@ protected override void GetValidationChecks(List rules, BuildTar fixItMessage = "Disable incompatible features." }); } + + protected override void OnEnabledChange() + { + base.OnEnabledChange(); + + // Force a refresh of the Project Validation window + EditorApplication.delayCall += EditorUtility.RequestScriptReload; + } #endif } } diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs index 1cf3993..a11f35c 100644 --- a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs @@ -177,6 +177,16 @@ protected override void OnSessionCreate(ulong session) } #if UNITY_EDITOR + + + protected override void OnEnabledChange() + { + base.OnEnabledChange(); + + // Force a refresh of the Project Validation window + EditorApplication.delayCall += EditorUtility.RequestScriptReload; + } + protected override void GetValidationChecks(List results, BuildTargetGroup target) { const string gltfPackageName = "com.unity.cloud.gltfast"; From 28c3b8d9a4ecd7a128906e11c398944d3c8524dc Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Wed, 1 Jul 2026 10:41:21 -0700 Subject: [PATCH 09/10] render model sample - more sync friendly (#10) --- com.valvesoftware.openxr.utils/CHANGELOG.md | 4 ++ .../RenderModels/RenderModelLoader.cs | 38 ++++++++++++++----- .../RenderModels/ValveRenderModelFeature.cs | 20 +++++++--- com.valvesoftware.openxr.utils/package.json | 2 +- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/com.valvesoftware.openxr.utils/CHANGELOG.md b/com.valvesoftware.openxr.utils/CHANGELOG.md index 5f270e3..2440733 100644 --- a/com.valvesoftware.openxr.utils/CHANGELOG.md +++ b/com.valvesoftware.openxr.utils/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.0.6] - 2026-06-30 +### Fixed +- Render model sample - added explicit api for checking when model data is available, minor refactoring for readability. + ## [1.0.5] - 2026-04-27 ### Fixed - Fixed settings to better support foveated rendering with VK_KHR_depth_stencil_resolve diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs index 01298e6..ff26cdf 100644 --- a/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/RenderModelLoader.cs @@ -19,6 +19,11 @@ private enum Handedness { Left, Right } private List animNodeStates; private Coroutine modelLoadCoroutine; private ValveRenderModelFeature feature; + private float lastModelCheckTime; + private bool loadingComplete = false; + + private bool IsLoaded() => loadingComplete; + private bool IsLoading() => modelLoadCoroutine != null; private void Awake() { @@ -32,19 +37,29 @@ private void Awake() private void Update() { - // Load the render model once the input device has connected. - if (modelLoadCoroutine == null) + TryToLoadIfNeeded(); + UpdateAnimations(); + } + + private void TryToLoadIfNeeded() + { + const float kRenderModelCheckInterval = 0.25f; + if (IsLoaded()) return; + if (IsLoading()) return; + if (!feature) return; + if (Time.time - lastModelCheckTime < kRenderModelCheckInterval) return; + + bool ready = IsTrackedControllerConnected(controllerHand) && + feature.IsRenderModelAvailable(controllerHand == Handedness.Left); + + lastModelCheckTime = Time.time; + + if (ready) { - if (IsTrackedControllerConnected(controllerHand)) - { - modelLoadCoroutine = StartCoroutine(LoadModelAsync()); - } - return; + modelLoadCoroutine = StartCoroutine(LoadModelAsync()); } - - UpdateAnimations(); } - + private IEnumerator LoadModelAsync() { // Load the binary data for the render model @@ -114,11 +129,14 @@ private IEnumerator LoadModelAsync() yield break; } } + + loadingComplete = true; } private void UpdateAnimations() { // Get the poses from OpenXR and update the transforms of those that are visible. + if (!IsLoaded()) return; if (renderModelHandle == 0) return; if (animNodeStates == null) return; diff --git a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs index a11f35c..10f6491 100644 --- a/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs +++ b/com.valvesoftware.openxr.utils/Samples~/RenderModels/ValveRenderModelFeature.cs @@ -48,6 +48,11 @@ public class ModelNodeState public bool Visible; } + public bool IsRenderModelAvailable(bool isLeftHand) + { + return GetRenderModelId(isLeftHand) != 0; + } + public bool GetRenderModelAssetData( bool isLeftHand, out ulong renderModelHandle, @@ -60,12 +65,10 @@ public bool GetRenderModelAssetData( animatableNodeNames = null; renderModelAssetBytes = null; - // Enumerate the render models and search for one with the desired model path - var modelPath = $"/user/hand/{(isLeftHand ? "left" : "right")}"; - XrRenderModelIdEXT renderModelId = FindRenderModelByPath(modelPath); + XrRenderModelIdEXT renderModelId = GetRenderModelId(isLeftHand); if (renderModelId == 0) { - Debug.LogError($"No render model found for path: {modelPath}"); + Debug.LogError($"No render model available for {(isLeftHand ? "left" : "right")} hand"); return false; } @@ -258,6 +261,13 @@ protected override void GetValidationChecks(List r #endregion + private XrRenderModelIdEXT GetRenderModelId(bool isLeftHand) + { + // Enumerate the render models and search for one with the desired model path + var modelPath = $"/user/hand/{(isLeftHand ? "left" : "right")}"; + return FindRenderModelByPath(modelPath); + } + private ulong RenderModelIdToHandle(ulong session, XrRenderModelIdEXT modelId) { var createInfo = new XrRenderModelCreateInfoEXT @@ -405,7 +415,7 @@ private XrRenderModelIdEXT FindRenderModelByPath(string path) } } - Debug.LogWarning("[RenderModelLoader] No render models found."); + Debug.LogWarning($"[RenderModelLoader] No render models currently available for {path}"); return 0; } diff --git a/com.valvesoftware.openxr.utils/package.json b/com.valvesoftware.openxr.utils/package.json index 99b44b7..2ebbe92 100644 --- a/com.valvesoftware.openxr.utils/package.json +++ b/com.valvesoftware.openxr.utils/package.json @@ -1,7 +1,7 @@ { "name": "com.valvesoftware.openxr.utils", "displayName": "Valve OpenXR Utilities", - "version": "1.0.5", + "version": "1.0.6", "description": "The Valve OpenXR Utilities package provides support for OpenXR projects and their access to Unity's OpenXR functionality.", "dependencies": { "com.unity.xr.openxr": "1.10.0", From b933e9322ff1ebd60914e90f6496314dc7044dfb Mon Sep 17 00:00:00 2001 From: Mike Baldwin <7369476+ropemonkey@users.noreply.github.com> Date: Fri, 24 Jul 2026 00:18:28 -0700 Subject: [PATCH 10/10] Added more foveation rendering related project validation rules (#13) --- com.valvesoftware.openxr.utils/CHANGELOG.md | 4 ++ .../ValveOpenXRFoveatedRenderingFeature.cs | 39 +++++++++++++++++++ com.valvesoftware.openxr.utils/package.json | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/com.valvesoftware.openxr.utils/CHANGELOG.md b/com.valvesoftware.openxr.utils/CHANGELOG.md index 2440733..7785a8a 100644 --- a/com.valvesoftware.openxr.utils/CHANGELOG.md +++ b/com.valvesoftware.openxr.utils/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [1.0.7] - 2026-07-24 +### Added +- Added project validation warnings if settings that potentially interfere with foveated rendering are enabled. + ## [1.0.6] - 2026-06-30 ### Fixed - Render model sample - added explicit api for checking when model data is available, minor refactoring for readability. diff --git a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs index 53c3fcb..a0cbe32 100644 --- a/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs +++ b/com.valvesoftware.openxr.utils/Runtime/Features/ValveOpenXRFoveatedRenderingFeature.cs @@ -291,6 +291,45 @@ protected override void GetValidationChecks(List r fixItMessage = "Enable Optimize Buffer Discards" }); #endif + rules.Add(new ValidationRule(this) + { + message = "Depth submission may cause issues with Foveated Rendering.", + error = false, + checkPredicate = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (settings == null) + return false; + + return settings.depthSubmissionMode == OpenXRSettings.DepthSubmissionMode.None; + }, + fixIt = () => + { + var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(targetGroup); + if (settings != null) + { + settings.depthSubmissionMode = OpenXRSettings.DepthSubmissionMode.None; + } + }, + fixItAutomatic = true, + fixItMessage = "Disable Depth Submission Mode" + }); + + rules.Add(new ValidationRule(this) + { + message = "Graphics Jobs may cause issues with Foveated Rendering.", + error = false, + checkPredicate = () => + { + return PlayerSettings.graphicsJobs == false; + }, + fixIt = () => + { + PlayerSettings.graphicsJobs = false; + }, + fixItAutomatic = true, + fixItMessage = "Disable Graphics Jobs" + }); } #endif diff --git a/com.valvesoftware.openxr.utils/package.json b/com.valvesoftware.openxr.utils/package.json index 2ebbe92..fc7a1ee 100644 --- a/com.valvesoftware.openxr.utils/package.json +++ b/com.valvesoftware.openxr.utils/package.json @@ -1,7 +1,7 @@ { "name": "com.valvesoftware.openxr.utils", "displayName": "Valve OpenXR Utilities", - "version": "1.0.6", + "version": "1.0.7", "description": "The Valve OpenXR Utilities package provides support for OpenXR projects and their access to Unity's OpenXR functionality.", "dependencies": { "com.unity.xr.openxr": "1.10.0",