This commit is contained in:
2025-11-13 17:40:28 +08:00
parent 962ab49609
commit 10156da245
5503 changed files with 805282 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: af2e07e443067b947ba9416c54fd673f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c4a172f3ddf65b643aee5a7bdd3e5015
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eac9288513d6ab14fbb83c358e066e68
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using Unity.XR.CoreUtils.Capabilities;
using UnityEngine;
using Unity.XR.PXR;
#if UNITY_EDITOR
using UnityEditor;
#endif
class PXR_OpenXR_SDKCapability : CapabilityProfile, ICapabilityModifier
{
static CapabilityDictionary m_CurrentCapabilities = new CapabilityDictionary();
public bool TryGetCapabilityValue(string capabilityKey, out bool capabilityValue)
{
return m_CurrentCapabilities.TryGetValue(capabilityKey, out capabilityValue);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 37f17ef263b31984bbb562a0f1f1918f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
using Unity.XR.CoreUtils.Capabilities;
using UnityEngine;
using Unity.XR.PXR;
#if UNITY_EDITOR
using UnityEditor;
#endif
class PXR_SDKCapability : CapabilityProfile, ICapabilityModifier
{
static CapabilityDictionary m_CurrentCapabilities = new CapabilityDictionary();
public bool TryGetCapabilityValue(string capabilityKey, out bool capabilityValue)
{
return m_CurrentCapabilities.TryGetValue(capabilityKey, out capabilityValue);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2b340d6b5858d6439e4b03f2c397afa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7ce500e2a00603a46a6aed7bd3f4385a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
#if UNITY_EDITOR
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Unity.XR.PXR.Debugger
{
[InitializeOnLoad]
public class PXR_PicoDebuggerSetup
{
static PXR_PicoDebuggerSetup()
{
EditorApplication.update += Init_PXR_PicoDebuggerSetup;
}
static void Init_PXR_PicoDebuggerSetup()
{
string currentPanelPath = $"{PXR_DebuggerConst.sdkPackageName}Assets/Debugger/Prefabs/DebuggerPanel.prefab";
string targetPanelPath = "Assets/Resources/PXR_DebuggerPanel.prefab";
string currentEntryPath = $"{PXR_DebuggerConst.sdkPackageName}Assets/Debugger/Prefabs/PICODebugger.prefab";
string targetEntryPath = "Assets/Resources/PXR_PICODebugger.prefab";
if(!File.Exists(targetEntryPath)){
if (!Directory.Exists("Assets/Resources"))
{
AssetDatabase.CreateFolder("Assets", "Resources");
}
if (AssetDatabase.LoadAssetAtPath<GameObject>(currentEntryPath) == null)
{
Debug.LogError("Prefab not found at path: " + currentEntryPath);
}
AssetDatabase.CopyAsset(currentEntryPath, targetEntryPath);
AssetDatabase.SaveAssets();
}
if(!File.Exists(targetPanelPath)){
if (!Directory.Exists("Assets/Resources"))
{
AssetDatabase.CreateFolder("Assets", "Resources");
}
if (AssetDatabase.LoadAssetAtPath<GameObject>(currentPanelPath) == null)
{
Debug.LogError("Prefab not found at path: " + currentPanelPath);
}
AssetDatabase.CopyAsset(currentPanelPath, targetPanelPath);
AssetDatabase.SaveAssets();
}
// EditorApplication.update -= Init_PXR_PicoDebuggerSetup;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c809738d124f34369b66513743555f59
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,109 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using System;
namespace Unity.XR.PXR.Debugger
{
// Generate a setting item in the editor project settings screen
static class SettingToolEditor
{
[SettingsProvider]
public static SettingsProvider CreateMyCustomSettingsProvider()
{
var config = PXR_PicoDebuggerSO.Instance;
var provider = new SettingsProvider("Project/PICO Debugger", SettingsScope.Project)
{
label = "PICO Debugger",
activateHandler = (obj, rootElement) =>
{
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>($"{PXR_Utils.sdkPackageName}Assets/Debugger/UI/PICODebuggerPanel.uxml");
var rootVisualElement = visualTree.Instantiate();
rootElement.Add(rootVisualElement);
var isOpenToggle = rootVisualElement.Q<Toggle>("IsOpen");
var debuggerlaucherButtonDropdown = rootVisualElement.Q<DropdownField>("DebuggerLaucherButton");
var startPositionDropdown = rootVisualElement.Q<DropdownField>("StartPosition");
var maxInfoCountSlider = rootVisualElement.Q<Slider>("MaxInfoCount");
var rulerClearButtonDropdown = rootVisualElement.Q<DropdownField>("RulerClearButton");
isOpenToggle.value = config.isOpen;
isOpenToggle.RegisterValueChangedCallback(evt =>
{
config.isOpen = evt.newValue;
EditorUtility.SetDirty(config); // Mark as dirty to save the changes
if(config.isOpen){
PXR_AppLog.PXR_OnEvent($"{PXR_AppLog.strPICODebugger}", PXR_AppLog.strPICODebugger_Enable,"enable");
}
});
debuggerlaucherButtonDropdown.choices = Enum.GetNames(typeof(LauncherButton)).ToList();
debuggerlaucherButtonDropdown.choices = Enum.GetNames(typeof(LauncherButton)).Where(name => name != config.rulerClearButton.ToString()).ToList();
debuggerlaucherButtonDropdown.index = (int)config.debuggerLauncherButton;
debuggerlaucherButtonDropdown.RegisterValueChangedCallback(evt =>
{
config.debuggerLauncherButton = (LauncherButton)Enum.Parse(typeof(LauncherButton), evt.newValue);
rulerClearButtonDropdown.choices = Enum.GetNames(typeof(LauncherButton)).Where(name => name != config.debuggerLauncherButton.ToString()).ToList();
EditorUtility.SetDirty(config);
PXR_AppLog.PXR_OnEvent($"{PXR_AppLog.strPICODebugger}", PXR_AppLog.strPICODebugger_LauncherButton,$"{config.debuggerLauncherButton}");
});
startPositionDropdown.choices = Enum.GetNames(typeof(StartPosiion)).ToList();
startPositionDropdown.index = (int)config.startPosition;
startPositionDropdown.RegisterValueChangedCallback(evt =>
{
config.startPosition = (StartPosiion)Enum.Parse(typeof(StartPosiion), evt.newValue);
EditorUtility.SetDirty(config);
PXR_AppLog.PXR_OnEvent($"{PXR_AppLog.strPICODebugger}",$"{PXR_AppLog.strPICODebugger_InitialPosition}",$"{config.startPosition}");
});
// var isFollowingToggle = rootVisualElement.Q<Toggle>("isFollowing");
// var isFollowingProperty = settings.FindProperty("isFollowing");
// var isLookAtCameraToggle = rootVisualElement.Q<Toggle>("isLookAtCamera");
// var isLookAtCameraProperty = settings.FindProperty("isLookAtCamera");
maxInfoCountSlider.value = config.maxInfoCount;
maxInfoCountSlider.RegisterValueChangedCallback(evt =>
{
config.maxInfoCount = Mathf.RoundToInt(evt.newValue);
EditorUtility.SetDirty(config);
PXR_AppLog.PXR_OnEvent($"{PXR_AppLog.strPICODebugger}",$"{PXR_AppLog.strPICODebugger_MaxLogCount}", $"{config.maxInfoCount}");
});
rulerClearButtonDropdown.choices = Enum.GetNames(typeof(LauncherButton)).Where(name => name != config.debuggerLauncherButton.ToString()).ToList();
rulerClearButtonDropdown.index = (int)config.rulerClearButton;
rulerClearButtonDropdown.RegisterValueChangedCallback(evt =>
{
config.rulerClearButton = (LauncherButton)Enum.Parse(typeof(LauncherButton), evt.newValue);
debuggerlaucherButtonDropdown.choices = Enum.GetNames(typeof(LauncherButton)).Where(name => name != config.rulerClearButton.ToString()).ToList();
EditorUtility.SetDirty(config);
PXR_AppLog.PXR_OnEvent($"{PXR_AppLog.strPICODebugger}",$"{PXR_AppLog.strPICODebugger_RulerResetButton}", $"{config.rulerClearButton}");
});
AssetDatabase.Refresh();
},
keywords = new HashSet<string>(new[] { "PICO", "Debugger Tool" })
};
return provider;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16a4fd861d5a241dd806c0390ca67f73
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,107 @@
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(PXR_ARCameraEffectManager))]
public class PXR_ARCameraEffectManagerEditor : Editor
{
public override void OnInspectorGUI()
{
PXR_ARCameraEffectManager manager = (PXR_ARCameraEffectManager)target;
PXR_ProjectSetting projectConfig = PXR_ProjectSetting.GetProjectConfig();
var guiContent = new GUIContent();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
// camera effect
guiContent.text = "Camera Effect";
manager.enableCameraEffect = EditorGUILayout.Toggle(guiContent, manager.enableCameraEffect);
EditorGUILayout.EndHorizontal();
if (manager.enableCameraEffect)
{
EditorGUI.indentLevel++;
guiContent.text = "Colortemp";
manager.colortempValue = EditorGUILayout.Slider(guiContent, manager.colortempValue, -50, 50);
guiContent.text = "Brightness";
manager.brightnessValue = EditorGUILayout.Slider(guiContent, manager.brightnessValue, -50, 50);
guiContent.text = "Saturation";
manager.saturationValue = EditorGUILayout.Slider(guiContent, manager.saturationValue, -50, 50);
guiContent.text = "Contrast";
manager.contrastValue = EditorGUILayout.Slider(guiContent, manager.contrastValue, -50, 50);
EditorGUILayout.LabelField("LUT");
var textureControlRect = EditorGUILayout.GetControlRect(GUILayout.Width(100), GUILayout.Height(100));
manager.lutTex1 = (Texture2D)EditorGUI.ObjectField(new Rect(textureControlRect.x, textureControlRect.y, 100, textureControlRect.height), manager.lutTex1, typeof(Texture), false);
ValidateTexture(manager.lutTex1);
manager.lutTex2 = (Texture2D)EditorGUI.ObjectField(new Rect(textureControlRect.x + textureControlRect.width, textureControlRect.y, textureControlRect.width, textureControlRect.height), manager.lutTex2, typeof(Texture), false);
ValidateTexture(manager.lutTex2);
manager.lutTex3 = (Texture2D)EditorGUI.ObjectField(new Rect(textureControlRect.x + 2*textureControlRect.width, textureControlRect.y, textureControlRect.width, textureControlRect.height), manager.lutTex3, typeof(Texture), false);
ValidateTexture(manager.lutTex3);
manager.lutTex4 = (Texture2D)EditorGUI.ObjectField(new Rect(textureControlRect.x + 3 * textureControlRect.width, textureControlRect.y, textureControlRect.width, textureControlRect.height), manager.lutTex4, typeof(Texture), false);
ValidateTexture(manager.lutTex4);
manager.lutTex5 = (Texture2D)EditorGUI.ObjectField(new Rect(textureControlRect.x + 4 * textureControlRect.width, textureControlRect.y, textureControlRect.width, textureControlRect.height), manager.lutTex5, typeof(Texture), false);
ValidateTexture(manager.lutTex5);
EditorGUI.indentLevel--;
}
Camera camera = manager.gameObject.GetComponent<Camera>();
if (camera)
{
camera.clearFlags = CameraClearFlags.SolidColor;
camera.backgroundColor = new Color(0, 0, 0, 0);
}
if (GUI.changed)
{
EditorUtility.SetDirty(projectConfig);
EditorUtility.SetDirty(manager);
}
serializedObject.ApplyModifiedProperties();
if (GUI.changed)
{
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
}
}
private static void ValidateTexture(Texture2D lutTex)
{
if (lutTex != null)
{
// Validate texture format
if (lutTex.format != TextureFormat.RGBA32)
{
Debug.LogError("Unsupported texture format! Please provide a texture in RGBA32 format.");
lutTex = null; // Reset texture if format is incorrect
}
// Validate texture size
if (lutTex.width > 512 || lutTex.height > 512)
{
Debug.LogError("The texture size must not exceed 512x512 pixels!");
lutTex = null; // Reset texture if size is incorrect
}
// Set read/write flag
if (!lutTex.isReadable)
{
string assetPath = AssetDatabase.GetAssetPath(lutTex);
TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (importer != null)
{
importer.isReadable = true;
AssetDatabase.ImportAsset(assetPath);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1e9fbaf94f2922449415352deff41f0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,306 @@
using LitJson;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEditor;
using UnityEngine;
namespace Unity.XR.PXR
{
public class PXR_AppLog
{
public static string APPName = "PICO_UnitySDK";
public static int APPID = 722442;
public static int productLineID = 843;
public static string strXRSDK = "unity_xr_sdk";
public static string strOpenXRSDK = "unity_openxr_sdk";
#region Portal
public static string strPortal = "portal"; // param
public static string strPortal_Enter = "enter";
public static string strPortal_Configs_Open = "configs_open";
public static string strPortal_Configs_RequiredPICOXRPluginApplied = "configs_required_picoxr_plugin_applied";
public static string strPortal_Configs_RequiredBuildTargetAndroidApplied = "configs_required_build_target_android_applied";
public static string strPortal_Configs_RequiredAndroidSdkVersionsApplied = "configs_required_android_api_level29_applied";
public static string strPortal_Configs_ToApplyAllApplied = "configs_to_apply_all_applied";
public static string strPortal_Configs_ProjectValidation = "configs_project_validation";
public static string strPortal_Configs_OpenPICOXRProjectSetting = "configs_open_picoxr_project_setting";
public static string strPortal_Tools_Open = "tools_open";
public static string strPortal_Tools_ProjectValidation_Documentation = "tools_project_validation_documentation";
public static string strPortal_Tools_ProjectValidation_Open = "tools_project_validation_open";
public static string strPortal_Tools_BuildingBlocks = "tools_building_blocks_documentation";
public static string strPortal_Tools_PICOXRToolkitMR = "tools_picoxr_toolkit_mr_documentation";
public static string strPortal_Tools_XRProfilingToolkit = "tools_xr_profiling_toolkit_documentation";
public static string strPortal_Tools_PICODeveloperCenter = "tools_pico_developer_center_documentation";
public static string strPortal_Tools_Emulator = "tools_emulator_documentation";
public static string strPortal_Tools_MoreDeveloperTools = "tools_more_developer_tools_documentation";
public static string strPortal_Sample_Open = "samples_open";
public static string strPortal_Samples_MixedRealitySample_Documentation = "samples_mixed_reality_sample_documentation";
public static string strPortal_Samples_MixedRealitySample_GitHub = "samples_mixed_reality_sample_github";
public static string strPortal_Samples_InteractionSample_Documentation = "samples_interaction_sample_documentation";
public static string strPortal_Samples_InteractionSample_GitHub = "samples_interaction_sample_github";
public static string strPortal_Samples_MotionTrackerSample_Documentation = "samples_motion_tracker_sample_documentation";
public static string strPortal_Samples_MotionTrackerSample_GitHub = "samples_motion_tracker_sample_github";
public static string strPortal_Samples_PlatformServicesSample_Documentation = "samples_platform_services_sample_documentation";
public static string strPortal_Samples_PlatformServicesSample_GitHub = "samples_platform_services_sample_github";
public static string strPortal_Samples_SpatialAudioSample_Documentation = "samples_spatial_audio_sample_documentation";
public static string strPortal_Samples_SpatialAudioSample_GitHub = "samples_spatial_audio_sample_github";
public static string strPortal_Samples_ARFoundationSample_Documentation = "samples_arfoundation_sample_documentation";
public static string strPortal_Samples_ARFoundationSample_GitHub = "samples_arfoundation_sample_github";
public static string strPortal_Samples_AdaptiveResolutionSample_Documentation = "samples_adaptive_resolution_sample_documentation";
public static string strPortal_Samples_AdaptiveResolutionSample_GitHub = "samples_adaptive_resolution_sample_github";
public static string strPortal_Samples_ToonWorldSample_Documentation = "samples_toon_world_sample_documentation";
public static string strPortal_Samples_ToonWorldSample_GitHub = "samples_toon_world_sample_github";
public static string strPortal_Samples_MicroWarSample_Documentation = "samples_micro_war_sample_documentation";
public static string strPortal_Samples_MicroWarSample_GitHub = "samples_micro_war_sample_github";
public static string strPortal_Samples_PICOAvatarSample_Documentation = "samples_pico_avatar_sample_documentation";
public static string strPortal_Samples_PICOAvatarSample_GitHub = "samples_pico_avatar_sample_github";
public static string strPortal_Samples_URPFork_Documentation = "samples_urp_fork_documentation";
public static string strPortal_Samples_URPFork_GitHub = "samples_urp_fork_github";
public static string strPortal_About_Open = "about_open";
public static string strPortal_About_Documentation = "about_documentation";
public static string strPortal_About_Installation = "about_installation";
#endregion
#region ProjectValidation
public static string strProjectValidation = "project_validation"; // param
public static string strProjectValidation_AndroidAPIMinSdkVersion = "android_api_min_sdk_version";
public static string strProjectValidation_ARM64 = "arm64";
public static string strProjectValidation_OneMainCamera = "one_main_camera";
public static string strProjectValidation_OneAudioListener = "one_audio_listener";
public static string strProjectValidation_BuildTargetPlatformAndroid = "build_target_platform_android";
public static string strProjectValidation_PICOXRPlugin = "picoxr_plugin";
public static string strProjectValidation_GraphicsAPIOrderForAndroid = "graphics_api_order_for_android";
public static string strProjectValidation_Unity2022NoDevelopmentBuild = "unity2022_no_development_build";
public static string strProjectValidation_Unity2022114URPLinearMSAA4OpenglesCrash = "unity2022114_urp_linear_msaa4_opengles_crash";
public static string strProjectValidation_AddPXRManager = "add_pxr_manager";
public static string strProjectValidation_ETFRUseOpenGLES3 = "etfr_use_opengles3";
public static string strProjectValidation_FTUnsafeCode = "ft_unsafe_code";
public static string strProjectValidation_URPNoHDR = "urp_no_hdr";
public static string strProjectValidation_URPGraphicsQuality = "urp_graphics_quality";
public static string strProjectValidation_MRARM64 = "mr_arm64";
public static string strProjectValidation_OneXROrigin = "one_xr_origin";
public static string strProjectValidation_ProjectKeystore = "project_keystore";
public static string strProjectValidation_ProjectKey = "project_key";
public static string strProjectValidation_UIOrientationLandscapeLeft = "ui_orientation_landscape_left";
public static string strProjectValidation_UseActivity = "use_activity";
public static string strProjectValidation_TargetAPILevelAuto = "target_api_level_auto";
public static string strProjectValidation_InstallLocationAuto = "install_location_auto";
public static string strProjectValidation_ContactOffset001 = "context_offset_001";
public static string strProjectValidation_SleepThreshold0005 = "sleep_threshold_0005";
public static string strProjectValidation_SolverIteration8 = "solver_iteration8";
public static string strProjectValidation_MaximumPixelLights = "maximum_pixel_lights";
public static string strProjectValidation_TextureQualitytoFullRes = "texture_quality_to_full_res";
public static string strProjectValidation_AnisotropicFiltering = "anisotropic_filtering";
public static string strProjectValidation_ETC2 = "etc2";
public static string strProjectValidation_ColorSpaceLinear = "color_space_linear";
public static string strProjectValidation_DisableGraphicsJobs = "disable_graphics_jobs";
public static string strProjectValidation_Multithreaded = "multithreaded";
public static string strProjectValidation_DisplayBufferFormat = "display_buffer_format";
public static string strProjectValidation_RenderingPathToForward = "rendering_path_to_forward";
public static string strProjectValidation_Multiview = "multiview";
public static string strProjectValidation_URPIntermediatetexturetoAuto = "urp_intermediate_texture_to_auto";
public static string strProjectValidation_URPDisableSSAO = "urp_disable_ssao";
public static string strProjectValidation_FFRSubsampling = "ffr_subsampling";
public static string strProjectValidation_MSAA = "msaa";
public static string strProjectValidation_APPSWNoContentProtect = "appsw_no_content_protect";
public static string strProjectValidation_TrackingOriginModeDevice = "tracking_origin_mode_device";
public static string strProjectValidation_DisableRealtimeGI = "disable_realtime_gi";
public static string strProjectValidation_GPUSkinning = "gpu_skinning";
public static string strProjectValidation_EyeTrackingCalibration = "eye_tracking_calibration";
public static string strProjectValidation_WritePermissionAndroid14 = "write_permission_android14";
public static string strProjectValidation_Unity2020321Unity6 = "unity2020321_unity6";
public static string strProjectValidation_URPNoUseToDelete = "urp_no_use_to_delete";
public static string strProjectValidation_URPVSTNoPostProcessing = "urp_vst_no_post_processing";
public static string strProjectValidation_URPNoETFRAndFFR = "urp_no_etfr_and_ffr";
public static string strProjectValidation_APPSWNeed = "appsw_need";
public static string strProjectValidation_LateLatchingNeed = "late_latching_need";
public static string strProjectValidation_LateLatchingOrOverlay = "late_latching_or_overlay";
public static string strProjectValidation_Overlay7 = "overlay7";
public static string strProjectValidation_SuperResolutionOrSubsampling = "super_resolution_or_subsampling";
public static string strProjectValidation_SharpeningOrSubsampling = "sharpening_or_subsampling";
public static string strProjectValidation_Unity6URPOpenGLESMultiPassNoMSAA = "unity6_urp_opengles_multi_pass_no_msaa";
public static string strProjectValidation_Overlay4 = "overlay4";
public static string strProjectValidation_Unity6RunInBackground = "unity6_run_in_background";
public static string strProjectValidation_MRC = "mrc";
public static string strProjectValidation_DisplayRefreshRatesDefault = "display_refresh_rates_default";
public static string strProjectValidation_VKOptimizeBufferDiscards = "vk_optimize_buffer_discards";
// 3.3.0 new add
public static string strProjectValidation_SubsamplingOpenXR182Earlier = "subsampling_openxr_182_earlier";
#endregion
#region BuildingBlocks
public static string strBuildingBlocks = "building_blocks"; // param
public static string strBuildingBlocks_PICOControllerTracking = "pico_controller_tracking";
public static string strBuildingBlocks_ControllerCanvasInteraction = "controller_canvas_interaction";
public static string strBuildingBlocks_PICOHandTracking = "pico_hand_tracking";
public static string strBuildingBlocks_XRHandTracking = "xr_hand_tracking";
public static string strBuildingBlocks_XRIHandInteraction = "xri_hand_interaction";
public static string strBuildingBlocks_XRIGrabInteraction = "xri_grab_interaction";
public static string strBuildingBlocks_XRIPokeInteraction = "xri_poke_interaction";
public static string strBuildingBlocks_PICOVideoSeethrough = "pico_video_seethrough";
public static string strBuildingBlocks_PICOVideoSeethroughEffect = "pico_video_seethrough_effect";
public static string strBuildingBlocks_PICOBodyTracking = "pico_body_tracking";
public static string strBuildingBlocks_PICOBodyTrackingDebug = "pico_body_tracking_debug";
public static string strBuildingBlocks_PICOObjectTracking = "pico_object_tracking";
public static string strBuildingBlocks_PICOSpatialAudioFreeField = "pico_spatial_audio_free_field";
public static string strBuildingBlocks_PICOSpatialAudioAmbisonics = "pico_spatial_audio_ambisonics";
// 3.3.0 new add
public static string strBuildingBlocks_PICOSpatialAnchorSample = "pico_spatial_anchor_sample";
public static string strBuildingBlocks_PICOSpatialMesh = "pico_spatial_mesh";
public static string strBuildingBlocks_PICOSceneCapture = "pico_scene_capture";
public static string strBuildingBlocks_PICOCompositionLayerOverlay = "pico_composition_layer_overlay";
public static string strBuildingBlocks_PICOCompositionLayerUnderlay = "pico_composition_layer_underlay";
#endregion
#region PICO Debugger
public static string strPICODebugger = "XRSDK_PICO_debugger";
public static string strPICODebugger_Enable = strPICODebugger + "_enable";
public static string strPICODebugger_LauncherButton = strPICODebugger + "_launcher_button";
public static string strPICODebugger_InitialPosition = strPICODebugger + "_initial_position";
public static string strPICODebugger_MaxLogCount = strPICODebugger + "_max_log_count";
public static string strPICODebugger_RulerResetButton = strPICODebugger + "_ruler_reset_button";
#endregion
private static bool isInited = false;
private static void TryInitAppLog()
{
#if UNITY_EDITOR_WIN
if (isInited)
{
return;
}
isInited = true;
Debug.Log($"TryInitAppLog ");
AppLog_init("722442", "PICO_UnitySDK");
#endif
}
/// <summary>
/// Call the buried point collection wherever it is required, and pass in the name and parameters of the buried point (in a dictionary structure).
/// </summary>
/// <param name="eventName"></param>
/// <param name="properties"></param>
public static void PXR_OnEvent(string param, string value)
{
#if UNITY_EDITOR_WIN
if (PXR_ProjectSetting.GetProjectConfig().isDataCollectionDisabled)
{
return;
}
// Debug.Log($"PXR_OnEvent eventName:{strXRSDK}, param:{param}, value:{value}");
try
{
var contentData = new JsonData()
{
[param] = value,
};
TryInitAppLog();
AppLog_onEvent(strXRSDK, contentData.ToJson());
}
catch (Exception e)
{
//Debug.LogError($"PXR_OnEvent param:{param}, value={value}, e={e}.");
}
#endif
}
/// <summary>
/// Call the buried point collection wherever it is required, and pass in the name and parameters of the buried point (in a dictionary structure).
/// </summary>
/// <param name="eventName"></param>
/// <param name="properties"></param>
public static void PXR_OnEvent(string eventName, string param, string value = "1")
{
#if UNITY_EDITOR_WIN
if (PXR_ProjectSetting.GetProjectConfig().isDataCollectionDisabled)
{
return;
}
//Debug.Log($"PXR_OnEvent eventName:{eventName}, param:{param}, value:{value}");
try
{
var contentData = new JsonData()
{
[param] = value,
};
TryInitAppLog();
AppLog_onEvent(eventName, contentData.ToJson());
}
catch (Exception e)
{
//Debug.LogError($"PXR_OnEvent param:{param}, value={value}, e={e}.");
}
#endif
}
public static void PXR_SetLogEnabled(bool enable)
{
#if UNITY_EDITOR_WIN
Debug.Log($"PXR_SetLogEnabled start enable={enable}");
if (enable)
{
AppLog_setLogEnabled(1);
}
else
{
AppLog_setLogEnabled(0);
}
#endif
}
public static void PXR_AppLogDestroy(DestroyCallback observer)
{
#if UNITY_EDITOR_WIN
AppLog_destroy(observer);
#endif
}
private const string DllName = "applogrs";
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void AppLog_init(string appid, string channel);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void AppLog_setEventVerifyEnabled(uint enabled);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void AppLog_setLogEnabled(uint enabled);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern UInt64 AppLog_getDeviceId();
public delegate void LoggerCallback(string message);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void AppLog_setLogger(LoggerCallback observer);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void AppLog_onEvent(string eventName, string param);
public delegate void DestroyCallback();
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void AppLog_destroy(DestroyCallback destory_callback);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e0ece506a9761df4d8274c9f5e04b5bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,689 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using System.Collections.Generic;
using System.Xml;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor.Android;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor;
using UnityEditor.XR.Management;
using UnityEngine.XR.Management;
#if UNITY_OPENXR
#if XR_HAND
using UnityEngine.XR.Hands.OpenXR;
#endif
#if PICO_OPENXR_SDK
//using UnityEngine.XR.Hands.OpenXR;
using Unity.XR.OpenXR.Features.PICOSupport;
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
#endif
#endif
namespace Unity.XR.PXR.Editor
{
public class PXR_BuildProcessor : XRBuildHelper<PXR_Settings>
{
public override string BuildSettingsKey { get { return "Unity.XR.PXR.Settings"; } }
public static bool IsLoaderExists(bool isPlatform = false)
{
XRGeneralSettings generalSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(BuildTargetGroup.Android);
if (generalSettings == null) return false;
var assignedSettings = generalSettings.AssignedSettings;
if (assignedSettings == null) return false;
bool isPxrOpenXRFeatureEnabled = false;
bool isPxrOpenXRExtensionsEnabled = false;
#if UNITY_2021_1_OR_NEWER
foreach (XRLoader loader in assignedSettings.activeLoaders)
{
if (loader is PXR_Loader) return true;
#if PICO_OPENXR_SDK
if (loader is OpenXRLoader)
{
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
{
if (feature is PICOFeature)
{
isPxrOpenXRFeatureEnabled = feature.enabled;
if (!isPlatform)
{
return isPxrOpenXRFeatureEnabled;
}
}
if (feature is OpenXRExtensions)
{
isPxrOpenXRExtensionsEnabled = feature.enabled;
if (isPlatform)
{
return isPxrOpenXRExtensionsEnabled;
}
}
}
}
#endif
}
#else
foreach (XRLoader loader in assignedSettings.loaders)
{
if (loader is PXR_Loader) return true;
#if PICO_OPENXR_SDK
if (loader is OpenXRLoader)
{
Debug.Log("PXRLog [Build Check]OpenXR is enabled");
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
{
if (feature is PXR_OpenXRFeature)
{
return true;
}
if (feature is PXR_OpenXRFeature)
{
isPxrOpenXRFeatureEnabled = feature.enabled;
if (!isPlatform)
{
return isPxrOpenXRFeatureEnabled;
}
}
if (feature is PXR_OpenXRExtensions)
{
isPxrOpenXRExtensionsEnabled = feature.enabled;
if (isPlatform)
{
return isPxrOpenXRExtensionsEnabled;
}
}
}
}
#endif
}
#endif
return false;
}
private PXR_Settings PxrSettings
{
get
{
return SettingsForBuildTargetGroup(BuildTargetGroup.Android) as PXR_Settings;
}
}
private void SetRequiredPluginInBuild()
{
PluginImporter[] plugins = PluginImporter.GetAllImporters();
foreach (PluginImporter plugin in plugins)
{
if (plugin.assetPath.Contains("PxrPlatform.aar"))
{
plugin.SetIncludeInBuildDelegate((path) =>
{
return IsLoaderExists(true);
});
}
if (plugin.assetPath.Contains(".ForUnitySDK.aar"))
{
Debug.Log("PXRLog [Build Check]OpenXR is enabled");
plugin.SetIncludeInBuildDelegate((path) =>
{
#if PICO_OPENXR_SDK
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
{
if (feature is PICOFeature)
{
return feature.enabled;
}
}
return false;
#else
return IsLoaderExists(true);
#endif
});
}
}
}
public override void OnPreprocessBuild(BuildReport report)
{
SetRequiredPluginInBuild();
if (report.summary.platformGroup != BuildTargetGroup.Android)
return;
if (!IsLoaderExists())
return;
GraphicsDeviceType firstGfxType =
PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget)[0];
if (firstGfxType != GraphicsDeviceType.OpenGLES3 && firstGfxType != GraphicsDeviceType.Vulkan && firstGfxType != GraphicsDeviceType.OpenGLES2)
throw new BuildFailedException($"PICO Plugin on mobile platforms nonsupport the {firstGfxType}");
if (PxrSettings.stereoRenderingModeAndroid == PXR_Settings.StereoRenderingModeAndroid.Multiview && firstGfxType == GraphicsDeviceType.OpenGLES2)
PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new GraphicsDeviceType[] { GraphicsDeviceType.OpenGLES3 });
if (PlayerSettings.Android.minSdkVersion < AndroidSdkVersions.AndroidApiLevel29)
throw new BuildFailedException("Android Minimum API must be set to 29 or higher for PICO Plugin.");
base.OnPreprocessBuild(report);
}
}
#if UNITY_2021_3_OR_NEWER
internal class PXR_BuildHooks : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder { get; }
private static readonly Dictionary<string, string> AndroidBootConfigVars = new Dictionary<string, string>()
{
{ "xr-usable-core-mask-enabled", "1"},
{ "xr-require-backbuffer-textures", "0" },
{ "xr-hide-memoryless-render-texture", "1" },
{ "xr-vulkan-extension-fragment-density-map-enabled", "1"}
};
public void OnPreprocessBuild(BuildReport report)
{
if (report.summary.platformGroup == BuildTargetGroup.Android)
{
var bootConfig = new BootConfig(report);
bootConfig.ReadBootConfig();
foreach (var entry in AndroidBootConfigVars)
{
bootConfig.SetValueForKey(entry.Key, entry.Value);
}
bootConfig.WriteBootConfig();
var issues = PXR_ProjectValidationRequired.GetValidationIssues();
foreach (var issue in issues)
{
if (issue.error)
{
Debug.LogError($"PXR SDK validation failed: {issue.description}");
throw new BuildFailedException($"There are unresolved PXR configuration errors");
}
}
}
}
public void OnPostprocessBuild(BuildReport report)
{
if (report.summary.platformGroup == BuildTargetGroup.Android)
{
BootConfig bootConfig = new BootConfig(report);
bootConfig.ReadBootConfig();
foreach (KeyValuePair<string, string> entry in AndroidBootConfigVars)
{
bootConfig.ClearEntryForKeyAndValue(entry.Key, entry.Value);
}
bootConfig.WriteBootConfig();
}
}
}
/// <summary>
/// Small utility class for reading, updating and writing boot config.
/// </summary>
internal class BootConfig
{
private const string XrBootSettingsKey = "xr-boot-settings";
private readonly Dictionary<string, string> bootConfigSettings;
private readonly string buildTargetName;
public BootConfig(BuildReport report)
{
bootConfigSettings = new Dictionary<string, string>();
buildTargetName = BuildPipeline.GetBuildTargetName(report.summary.platform);
}
public void ReadBootConfig()
{
bootConfigSettings.Clear();
string xrBootSettings = EditorUserBuildSettings.GetPlatformSettings(buildTargetName, XrBootSettingsKey);
if (!string.IsNullOrEmpty(xrBootSettings))
{
var bootSettings = xrBootSettings.Split(';');
foreach (var bootSetting in bootSettings)
{
var setting = bootSetting.Split(':');
if (setting.Length == 2 && !string.IsNullOrEmpty(setting[0]) && !string.IsNullOrEmpty(setting[1]))
{
bootConfigSettings.Add(setting[0], setting[1]);
}
}
}
}
public void SetValueForKey(string key, string value) => bootConfigSettings[key] = value;
public bool TryGetValue(string key, out string value) => bootConfigSettings.TryGetValue(key, out value);
public void ClearEntryForKeyAndValue(string key, string value)
{
if (bootConfigSettings.TryGetValue(key, out string dictValue) && dictValue == value)
{
bootConfigSettings.Remove(key);
}
}
public void WriteBootConfig()
{
bool firstEntry = true;
var sb = new System.Text.StringBuilder();
foreach (var kvp in bootConfigSettings)
{
if (!firstEntry)
{
sb.Append(";");
}
sb.Append($"{kvp.Key}:{kvp.Value}");
firstEntry = false;
}
EditorUserBuildSettings.SetPlatformSettings(buildTargetName, XrBootSettingsKey, sb.ToString());
}
}
#endif
#if UNITY_ANDROID
internal class PXR_Manifest : IPostGenerateGradleAndroidProject
{
public void OnPostGenerateGradleAndroidProject(string path)
{
if (!PXR_BuildProcessor.IsLoaderExists())
return;
string originManifestPath = path + "/src/main/AndroidManifest.xml";
XmlDocument doc = new XmlDocument();
doc.Load(originManifestPath);
string manifestTagPath = "/manifest";
string applicationTagPath = manifestTagPath + "/application";
string metaDataTagPath = applicationTagPath + "/meta-data";
string usesPermissionTagName = "uses-permission";
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","pvr.app.type"}},new Dictionary<string, string>{{"value","vr"}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","pxr.sdk.version_code"}},new Dictionary<string, string>{{"value", "5140"}});
doc.InsertAttributeInTargetTag(applicationTagPath,null, new Dictionary<string, string>() {{"requestLegacyExternalStorage", "true"}});
#if PICO_OPENXR_SDK
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","use.pxr.sdk"}},new Dictionary<string, string>{{"value", "2"}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","pvr.sdk.version"}},new Dictionary<string, string>{{"value","Unity OpenXR "+PXR_Constants.SDKVersion}});
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
bool mrPermission = false;
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
{
if (feature is PICOSceneCapture)
{
if (feature.enabled)
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_scene_anchor" } },
new Dictionary<string, string> { { "value", "1" } });
mrPermission = true;
}
else
{
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_scene_anchor" } });
}
}
if (feature is PICOSpatialAnchor)
{
if (feature.enabled)
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_spatial_anchor" } },
new Dictionary<string, string> { { "value", "1" } });
mrPermission = true;
}
else
{
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_spatial_anchor" } });
}
}
if (feature is PICOSpatialMesh)
{
if (feature.enabled)
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_mesh_anchor" } },
new Dictionary<string, string> { { "value", "1" } });
mrPermission = true;
}
else
{
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_mesh_anchor" } });
}
}
#if XR_HAND
if (feature is HandTracking)
{
if (feature.enabled)
{
if (PXR_OpenXRProjectSetting.GetProjectConfig().isHandTracking)
{
doc.CreateElementInTag(manifestTagPath, usesPermissionTagName,
new Dictionary<string, string> { { "name", "com.picovr.permission.HAND_TRACKING" } });
if (PXR_OpenXRProjectSetting.GetProjectConfig().handTrackingSupportType == HandTrackingSupport.HandsOnly)
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } },
new Dictionary<string, string> { { "value", "1" } });
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } });
}
else
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } },
new Dictionary<string, string> { { "value", "1" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } },
new Dictionary<string, string> { { "value", "1" } });
}
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "Hand_Tracking_HighFrequency" } },
new Dictionary<string, string> { { "value", PXR_OpenXRProjectSetting.GetProjectConfig().highFrequencyHand ? "1" : "0" } });
}
else
{
doc.RemoveNameValueElementInTag(manifestTagPath, usesPermissionTagName,
"android:name", "com.picovr.permission.HAND_TRACKING");
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } });
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "Hand_Tracking_HighFrequency" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } },
new Dictionary<string, string> { { "value", "1" } });
}
}
else
{
doc.RemoveNameValueElementInTag(manifestTagPath, usesPermissionTagName,
"android:name", "com.picovr.permission.HAND_TRACKING");
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } });
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "Hand_Tracking_HighFrequency" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } },
new Dictionary<string, string> { { "value", "1" } });
}
}
}
#else
}
doc.RemoveNameValueElementInTag(manifestTagPath, usesPermissionTagName,
"android:name", "com.picovr.permission.HAND_TRACKING");
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } });
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "Hand_Tracking_HighFrequency" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } },
new Dictionary<string, string> { { "value", "1" } });
#endif
if (PXR_OpenXRProjectSetting.GetProjectConfig().isEyeTracking)
{
doc.CreateElementInTag(manifestTagPath, usesPermissionTagName,
new Dictionary<string, string> { { "name", "com.picovr.permission.EYE_TRACKING" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "picovr.software.eye_tracking" } },
new Dictionary<string, string> { { "value", "1" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "eyetracking_calibration" } },
new Dictionary<string, string> { { "value", PXR_OpenXRProjectSetting.GetProjectConfig().isEyeTrackingCalibration ? "true" : "false" } });
}
else
{
doc.RemoveNameValueElementInTag(manifestTagPath, usesPermissionTagName,
"android:name", "com.picovr.permission.EYE_TRACKING");
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "picovr.software.eye_tracking" } });
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "eyetracking_calibration" } });
}
if (PXR_OpenXRProjectSetting.GetProjectConfig().MRSafeguard)
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_mr_safeguard" } },
new Dictionary<string, string> { { "value", PXR_OpenXRProjectSetting.GetProjectConfig().MRSafeguard ? "1" : "0" } });
}
else
{
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_mr_safeguard" } });
}
if (mrPermission)
{
doc.CreateElementInTag(manifestTagPath, usesPermissionTagName,
new Dictionary<string, string> { { "name", "com.picovr.permission.SPATIAL_DATA" } });
}
else
{
doc.RemoveNameValueElementInTag(manifestTagPath, usesPermissionTagName,
"android:name", "com.picovr.permission.SPATIAL_DATA");
}
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "pvr.app.splash" } },
new Dictionary<string, string> { { "value", PXR_OpenXRProjectSetting.GetProjectConfig().GetSystemSplashScreen(path) } });
#else
var settings = PXR_XmlTools.GetSettings();
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","use.pxr.sdk"}},new Dictionary<string, string>{{"value", "1"}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","pvr.sdk.version"}},new Dictionary<string, string>{{"value","XR Platform_"+PXR_Constants.SDKVersion}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","enable_cpt"}},new Dictionary<string, string>{{"value",PXR_ProjectSetting.GetProjectConfig().useContentProtect ? "1" : "0"}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","Enable_AdaptiveHandModel"}},new Dictionary<string, string> {{"value",PXR_ProjectSetting.GetProjectConfig().adaptiveHand ? "1" : "0" }});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","Hand_Tracking_HighFrequency"}},new Dictionary<string, string> {{"value",PXR_ProjectSetting.GetProjectConfig().highFrequencyHand ? "1" : "0" }});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","rendering_mode"}},new Dictionary<string, string>{{"value",((int)settings.stereoRenderingModeAndroid).ToString()}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","display_rate"}},new Dictionary<string, string>{{"value",((int)settings.systemDisplayFrequency).ToString()}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","color_Space"}},new Dictionary<string, string>{{"value",QualitySettings.activeColorSpace == ColorSpace.Linear ? "1" : "0"}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","MRCsupport"}},new Dictionary<string, string>{{"value",PXR_ProjectSetting.GetProjectConfig().openMRC ? "1" : "0" }});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","pvr.LateLatching"}}, new Dictionary<string, string> {{"value",PXR_ProjectSetting.GetProjectConfig().latelatching ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","pvr.LateLatchingDebug"}}, new Dictionary<string, string> {{"value", PXR_ProjectSetting.GetProjectConfig().latelatching && PXR_ProjectSetting.GetProjectConfig().latelatchingDebug ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","pvr.app.splash"} },new Dictionary<string, string>{{"value",settings.GetSystemSplashScreen(path)}});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","PICO.swift.feature"}},new Dictionary<string, string>{{"value",PXR_ProjectSetting.GetProjectConfig().bodyTracking ? "1" : "0" }});
doc.InsertAttributeInTargetTag(metaDataTagPath,new Dictionary<string, string>{{"name","adaptive_resolution"}},new Dictionary<string, string>{{"value",PXR_ProjectSetting.GetProjectConfig().adaptiveResolution ? "1" : "0" }});
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_mr_safeguard" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().mrSafeguard ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_vst" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().videoSeeThrough ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_anchor" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().spatialAnchor ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "mr_map_mgr_auto_start" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().spatialAnchor ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_spatial_anchor" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().spatialAnchor ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_cloud_anchor" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().sharedAnchor ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_mesh_anchor" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().spatialMesh ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "enable_scene_anchor" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().sceneCapture ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "pvr.SuperResolution" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().superResolution ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "pvr.NormalSharpening" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().normalSharpening ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "pvr.QualitySharpening" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().qualitySharpening ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "pvr.FixedFoveatedSharpening" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().fixedFoveatedSharpening ? "1" : "0" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "pvr.SelfAdaptiveSharpening" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().selfAdaptiveSharpening ? "1" : "0" } });
doc.CreateElementInTag(manifestTagPath,usesPermissionTagName,new Dictionary<string, string>{{"name","android.permission.WRITE_SETTINGS"}});
if (PXR_ProjectSetting.GetProjectConfig().eyeTracking || PXR_ProjectSetting.GetProjectConfig().enableETFR)
{
doc.CreateElementInTag(manifestTagPath, usesPermissionTagName, new Dictionary<string, string> { { "name", "com.picovr.permission.EYE_TRACKING" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "picovr.software.eye_tracking" } }, new Dictionary<string, string> { { "value", "1" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "eyetracking_calibration" } }, new Dictionary<string, string> { { "value", PXR_ProjectSetting.GetProjectConfig().eyetrackingCalibration ? "true" : "false" } });
}
if (PXR_ProjectSetting.GetProjectConfig().spatialAnchor || PXR_ProjectSetting.GetProjectConfig().sceneCapture || PXR_ProjectSetting.GetProjectConfig().spatialMesh || PXR_ProjectSetting.GetProjectConfig().sharedAnchor)
{
doc.CreateElementInTag(manifestTagPath, usesPermissionTagName,
new Dictionary<string, string> { { "name", "com.picovr.permission.SPATIAL_DATA" } });
}
if (PXR_ProjectSetting.GetProjectConfig().handTracking)
{
if (PXR_ProjectSetting.GetProjectConfig().handTrackingSupportType==HandTrackingSupport.HandsOnly)
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } },
new Dictionary<string, string> { { "value", "1" } });
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } });
doc.CreateElementInTag(manifestTagPath, usesPermissionTagName,
new Dictionary<string, string> { { "name", "com.picovr.permission.HAND_TRACKING" } });
}
else
{
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } },
new Dictionary<string, string> { { "value", "1" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } },
new Dictionary<string, string> { { "value", "1" } });
doc.CreateElementInTag(manifestTagPath, usesPermissionTagName,
new Dictionary<string, string> { { "name", "com.picovr.permission.HAND_TRACKING" } });
}
}
else
{
doc.RemoveAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "handtracking" } });
doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "controller" } },
new Dictionary<string, string> { { "value", "1" } });
doc.RemoveNameValueElementInTag(manifestTagPath, usesPermissionTagName,
"android:name", "com.picovr.permission.HAND_TRACKING");
}
if (PXR_ProjectSetting.GetProjectConfig().faceTracking) { doc.CreateElementInTag(manifestTagPath, usesPermissionTagName, new Dictionary<string, string> { { "name", "com.picovr.permission.FACE_TRACKING" } }); }
if (PXR_ProjectSetting.GetProjectConfig().lipsyncTracking) { doc.CreateElementInTag(manifestTagPath, usesPermissionTagName, new Dictionary<string, string> { { "name", "android.permission.RECORD_AUDIO" } }); }
if (PXR_ProjectSetting.GetProjectConfig().faceTracking) { doc.InsertAttributeInTargetTag(metaDataTagPath, new Dictionary<string, string> { { "name", "picovr.software.face_tracking" } }, new Dictionary<string, string> { { "value", "false/true" } }); }
#endif
doc.Save(originManifestPath);
}
public int callbackOrder { get { return 10000; } }
}
#endif
public static class PXR_XmlTools
{
static readonly string androidURI = "http://schemas.android.com/apk/res/android";
public static void InsertAttributeInTargetTag(this XmlDocument doc, string tagPath, Dictionary<string, string> filterDic, Dictionary<string, string> attributeDic)
{
XmlElement targetElement = null;
if (filterDic == null)
targetElement = doc.SelectSingleNode(tagPath) as XmlElement;
else
{
XmlNodeList nodeList = doc.SelectNodes(tagPath);
if (nodeList != null)
{
foreach (XmlNode node in nodeList)
{
if (FilterCheck(node as XmlElement, filterDic))
{
targetElement = node as XmlElement;
break;
}
}
}
}
if (targetElement == null)
{
string parentPath = tagPath.Substring(0, tagPath.LastIndexOf("/"));
string tagName = tagPath.Substring(tagPath.LastIndexOf("/") + 1);
foreach (var item in attributeDic)
filterDic.Add(item.Key, item.Value);
doc.CreateElementInTag(parentPath, tagName, filterDic);
}
else UpdateOrCreateAttribute(targetElement, attributeDic);
}
public static void RemoveAttributeInTargetTag(this XmlDocument doc, string tagPath, Dictionary<string, string> filterDic)
{
if (filterDic != null)
{
XmlNodeList nodeList = doc.SelectNodes(tagPath);
if (nodeList != null)
{
foreach (XmlNode node in nodeList)
{
if (FilterCheck(node as XmlElement, filterDic))
{
node.ParentNode?.RemoveChild(node);
break;
}
}
}
}
}
public static void RemoveNameValueElementInTag(this XmlDocument doc, string parentPath, string tag, string name,
string value)
{
var xmlNodeList = doc.SelectNodes(parentPath + "/" + tag);
foreach (XmlNode node in xmlNodeList)
{
var attributeList = ((XmlElement)node).Attributes;
foreach (XmlAttribute attrib in attributeList)
{
if (attrib.Name == name && attrib.Value == value)
{
node.ParentNode?.RemoveChild(node);
}
}
}
}
public static void CreateElementInTag(this XmlDocument doc, string parentPath, string tagName,
Dictionary<string, string> attributeDic)
{
XmlNode parentNode = doc.SelectSingleNode(parentPath);
if (parentNode == null)
{
return;
}
foreach (XmlNode childNode in parentNode.ChildNodes)
{
if (childNode.NodeType == XmlNodeType.Element)
{
if (FilterCheck((XmlElement)childNode, attributeDic))
return;
}
}
XmlElement newElement = doc.CreateElement(tagName);
UpdateOrCreateAttribute(newElement, attributeDic);
parentNode.AppendChild(newElement);
}
private static bool FilterCheck(XmlElement element, Dictionary<string, string> filterDic)
{
foreach (var filterCase in filterDic)
{
string caseValue = element.GetAttribute(filterCase.Key, androidURI);
if (String.IsNullOrEmpty(caseValue) || caseValue != filterCase.Value)
return false;
}
return true;
}
private static void UpdateOrCreateAttribute(XmlElement element, Dictionary<string, string> attributeDic)
{
foreach (var attributeItem in attributeDic)
{
element.SetAttribute(attributeItem.Key, androidURI, attributeItem.Value);
}
}
public static PXR_Settings GetSettings()
{
PXR_Settings settings = null;
#if UNITY_EDITOR
UnityEditor.EditorBuildSettings.TryGetConfigObject<PXR_Settings>("Unity.XR.PXR.Settings", out settings);
#endif
#if UNITY_ANDROID && !UNITY_EDITOR
settings = PXR_Settings.settings;
#endif
return settings;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4ebbee757f020441995246fa9243022
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,500 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Unity.XR.PXR.Editor
{
[CanEditMultipleObjects]
[CustomEditor(typeof(PXR_CompositionLayer))]
public class PXR_CompositionLayerEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
var guiContent = new GUIContent();
foreach (PXR_CompositionLayer overlayTarget in targets)
{
EditorGUILayout.LabelField("Composition Layer Settings", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Type";
overlayTarget.overlayType = (PXR_CompositionLayer.OverlayType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.overlayType);
guiContent.text = "Shape";
overlayTarget.overlayShape = (PXR_CompositionLayer.OverlayShape)EditorGUILayout.EnumPopup(guiContent, overlayTarget.overlayShape);
guiContent.text = "Depth";
overlayTarget.layerDepth = EditorGUILayout.IntField(guiContent, overlayTarget.layerDepth);
EditorGUILayout.EndVertical();
guiContent.text = "Clones";
overlayTarget.isClones = EditorGUILayout.Toggle(guiContent, overlayTarget.isClones);
if (overlayTarget.isClones)
{
overlayTarget.originalOverLay = EditorGUILayout.ObjectField("Original OverLay", overlayTarget.originalOverLay, typeof(PXR_CompositionLayer), true) as PXR_CompositionLayer;
GUIStyle firstLevelStyle = new GUIStyle(GUI.skin.label);
firstLevelStyle.alignment = TextAnchor.UpperLeft;
firstLevelStyle.fontStyle = FontStyle.Bold;
firstLevelStyle.fontSize = 12;
firstLevelStyle.wordWrap = true;
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Note:", firstLevelStyle);
EditorGUILayout.LabelField("Original OverLay cannot be empty or itself!");
EditorGUILayout.EndVertical();
}
else
{
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Composition Layer Textures", EditorStyles.boldLabel);
guiContent.text = "Texture Type";
overlayTarget.textureType = (PXR_CompositionLayer.TextureType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.textureType);
EditorGUILayout.Separator();
if (overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.BlurredQuad)
{
overlayTarget.textureType = PXR_CompositionLayer.TextureType.ExternalSurface;
}
if (overlayTarget.textureType == PXR_CompositionLayer.TextureType.ExternalSurface)
{
overlayTarget.isExternalAndroidSurface = true;
overlayTarget.isDynamic = false;
}
else if (overlayTarget.textureType == PXR_CompositionLayer.TextureType.DynamicTexture)
{
overlayTarget.isExternalAndroidSurface = false;
overlayTarget.isDynamic = true;
}
else
{
overlayTarget.isExternalAndroidSurface = false;
overlayTarget.isDynamic = false;
}
if (overlayTarget.isExternalAndroidSurface)
{
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "DRM";
overlayTarget.isExternalAndroidSurfaceDRM = EditorGUILayout.Toggle(guiContent, overlayTarget.isExternalAndroidSurfaceDRM);
guiContent.text = "3D Surface Type";
guiContent.tooltip = "The functions of '3D Surface Type' and 'Source Rects' are similar, and only one of them can be used. ";
overlayTarget.externalAndroidSurface3DType = (PXR_CompositionLayer.Surface3DType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.externalAndroidSurface3DType);
EditorGUILayout.EndVertical();
if (overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.BlurredQuad)
{
EditorGUILayout.LabelField("Blurred Quad");
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Mode";
overlayTarget.blurredQuadMode = (PXR_CompositionLayer.BlurredQuadMode)EditorGUILayout.EnumPopup(guiContent, overlayTarget.blurredQuadMode);
guiContent.text = "Scale";
overlayTarget.blurredQuadScale = EditorGUILayout.FloatField(guiContent, Mathf.Abs(overlayTarget.blurredQuadScale));
guiContent.text = "Shift";
overlayTarget.blurredQuadShift = EditorGUILayout.Slider(guiContent, overlayTarget.blurredQuadShift, -1, 1);
guiContent.text = "FOV";
overlayTarget.blurredQuadFOV = EditorGUILayout.Slider(guiContent, overlayTarget.blurredQuadFOV, 0, 180f);
guiContent.text = "IPD";
overlayTarget.blurredQuadIPD = EditorGUILayout.Slider(guiContent, overlayTarget.blurredQuadIPD, 0.01f, 1.0f);
EditorGUILayout.EndVertical();
}
guiContent.tooltip = "";
}
else
{
EditorGUILayout.LabelField("Texture");
EditorGUILayout.BeginVertical("frameBox");
var labelControlRect = EditorGUILayout.GetControlRect();
EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left", "Texture used for the left eye"));
EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right", "Texture used for the right eye"));
var textureControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(64));
overlayTarget.layerTextures[0] = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x, textureControlRect.y, 64, textureControlRect.height), overlayTarget.layerTextures[0], typeof(Texture), false);
overlayTarget.layerTextures[1] = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x + textureControlRect.width / 2, textureControlRect.y, 64, textureControlRect.height), overlayTarget.layerTextures[1] != null ? overlayTarget.layerTextures[1] : overlayTarget.layerTextures[0], typeof(Texture), false);
EditorGUILayout.EndVertical();
}
EditorGUILayout.Separator();
if (overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Equirect ||
overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Fisheye)
{
guiContent.text = "Radius";
overlayTarget.radius = EditorGUILayout.FloatField(guiContent, Mathf.Abs(overlayTarget.radius));
}
}
if (overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Quad ||
overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Cylinder ||
overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Equirect ||
overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Eac ||
overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Fisheye)
{
guiContent.text = "Texture Rects";
overlayTarget.useImageRect = EditorGUILayout.Toggle(guiContent, overlayTarget.useImageRect);
if (overlayTarget.useImageRect)
{
EditorGUI.indentLevel++;
if (PXR_CompositionLayer.Surface3DType.Single != overlayTarget.externalAndroidSurface3DType)
{
GUI.enabled = false;
}
guiContent.text = "Source Rects";
guiContent.tooltip = "The functions of '3D Surface Type' and 'Source Rects' are similar, and only one of them can be used. ";
overlayTarget.textureRect = (PXR_CompositionLayer.TextureRect)EditorGUILayout.EnumPopup(guiContent, overlayTarget.textureRect);
if (PXR_CompositionLayer.Surface3DType.Single == overlayTarget.externalAndroidSurface3DType)
{
if (overlayTarget.textureRect == PXR_CompositionLayer.TextureRect.Custom)
{
EditorGUILayout.BeginVertical("frameBox");
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Left Rect");
EditorGUILayout.LabelField("Right Rect");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
overlayTarget.srcRectLeft = ClampRect(EditorGUILayout.RectField(overlayTarget.srcRectLeft));
EditorGUILayout.Space(15);
guiContent.text = "Right";
overlayTarget.srcRectRight = ClampRect(EditorGUILayout.RectField(overlayTarget.srcRectRight));
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
else if (overlayTarget.textureRect == PXR_CompositionLayer.TextureRect.MonoScopic)
{
overlayTarget.srcRectLeft = new Rect(0, 0, 1, 1);
overlayTarget.srcRectRight = new Rect(0, 0, 1, 1);
}
else if (overlayTarget.textureRect == PXR_CompositionLayer.TextureRect.StereoScopic)
{
overlayTarget.srcRectLeft = new Rect(0, 0, 0.5f, 1);
overlayTarget.srcRectRight = new Rect(0.5f, 0, 0.5f, 1);
}
}
else
{
overlayTarget.textureRect = PXR_CompositionLayer.TextureRect.MonoScopic;
overlayTarget.srcRectLeft = new Rect(0, 0, 1, 1);
overlayTarget.srcRectRight = new Rect(0, 0, 1, 1);
}
guiContent.tooltip = "";
GUI.enabled = true;
if (overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Quad ||
overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Equirect ||
overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Fisheye)
{
guiContent.text = "Destination Rects";
overlayTarget.destinationRect = (PXR_CompositionLayer.DestinationRect)EditorGUILayout.EnumPopup(guiContent, overlayTarget.destinationRect);
if (overlayTarget.destinationRect == PXR_CompositionLayer.DestinationRect.Custom)
{
EditorGUILayout.BeginVertical("frameBox");
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Left Rect");
EditorGUILayout.LabelField("Right Rect");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
overlayTarget.dstRectLeft = ClampRect(EditorGUILayout.RectField(overlayTarget.dstRectLeft));
EditorGUILayout.Space(15);
guiContent.text = "Right";
overlayTarget.dstRectRight = ClampRect(EditorGUILayout.RectField(overlayTarget.dstRectRight));
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
else
{
GUI.enabled = false;
overlayTarget.dstRectLeft = new Rect(0, 0, 1, 1);
overlayTarget.dstRectRight = new Rect(0, 0, 1, 1);
GUI.enabled = true;
}
}
EditorGUI.indentLevel--;
}
}
guiContent.text = "Use Premultiplied Alpha";
guiContent.tooltip = @"Enable premultiplied alpha for this content.
When enabled:
• RGB color channels are multiplied by Alpha (R*A, G*A, B*A)
• Improves performance for transparent elements (e.g., UI, particles)
• Fixes edge artifacts in semitransparent objects
• Matches OpenXR and GPU blending requirements
Recommended for:
• UI panels with transparency
• Particle effects
• Materials using alpha blending
• Any content requiring frequent transparency mixing
Note: Ensure textures are imported with 'Alpha Is Transparency'
or manually pre-multiply colors if needed.";
overlayTarget.usePremultipliedAlpha = EditorGUILayout.Toggle(guiContent, overlayTarget.usePremultipliedAlpha);
guiContent.text = "Use Texture Alpha for Blending";
guiContent.tooltip = @"Use the texture's alpha channel for transparency blending.
When enabled:
• Semi-transparent elements (UI, particles) will blend correctly with the background.
• Alpha values (0-1) control pixel transparency during composition.
• Works with premultiplied alpha textures if properly configured.
Recommended for:
• Any content requiring transparency (e.g., overlays, glass effects).
• Disabling may cause artifacts or incorrect rendering.";
overlayTarget.useTextureAlphaBlending = EditorGUILayout.Toggle(guiContent, overlayTarget.useTextureAlphaBlending);
guiContent.text = "Layer Blend";
overlayTarget.useLayerBlend = EditorGUILayout.Toggle(guiContent, overlayTarget.useLayerBlend);
if (overlayTarget.useLayerBlend)
{
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Src Color";
overlayTarget.srcColor = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.srcColor);
guiContent.text = "Dst Color";
overlayTarget.dstColor = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.dstColor);
guiContent.text = "Src Alpha";
overlayTarget.srcAlpha = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.srcAlpha);
guiContent.text = "Dst Alpha";
overlayTarget.dstAlpha = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.dstAlpha);
EditorGUILayout.EndVertical();
}
EditorGUILayout.Separator();
if (overlayTarget.overlayShape == PXR_CompositionLayer.OverlayShape.Eac)
{
guiContent.text = "Model Type";
overlayTarget.eacModelType = (PXR_CompositionLayer.EACModelType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.eacModelType);
if (PXR_CompositionLayer.EACModelType.Eac360ViewPort == overlayTarget.eacModelType ||
PXR_CompositionLayer.EACModelType.Eac180ViewPort == overlayTarget.eacModelType)
{
guiContent.text = "Offset Pos Left";
Vector3 offsetPosLeft = EditorGUILayout.Vector3Field(guiContent, overlayTarget.offsetPosLeft);
guiContent.text = "Offset Pos Right";
Vector3 offsetPosRight = EditorGUILayout.Vector3Field(guiContent, overlayTarget.offsetPosRight);
guiContent.text = "Offset Rot Left";
Vector4 offsetRotLeft = EditorGUILayout.Vector4Field(guiContent, overlayTarget.offsetRotLeft);
guiContent.text = "Offset Rot Right";
Vector4 offsetRotRight = EditorGUILayout.Vector4Field(guiContent, overlayTarget.offsetRotRight);
overlayTarget.SetEACOffsetPosAndRot(offsetPosLeft, offsetPosRight, offsetRotLeft, offsetRotRight);
}
guiContent.text = "Overlap Factor";
overlayTarget.overlapFactor = EditorGUILayout.FloatField(guiContent, overlayTarget.overlapFactor);
//overlayTarget.SetEACFactor(overlapFactor);
}
guiContent.text = "Override Color Scale";
overlayTarget.overrideColorScaleAndOffset = EditorGUILayout.Toggle(guiContent, overlayTarget.overrideColorScaleAndOffset);
if (overlayTarget.overrideColorScaleAndOffset)
{
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Scale";
Vector4 colorScale = EditorGUILayout.Vector4Field(guiContent, overlayTarget.colorScale);
guiContent.text = "Offset";
Vector4 colorOffset = EditorGUILayout.Vector4Field(guiContent, overlayTarget.colorOffset);
overlayTarget.SetLayerColorScaleAndOffset(colorScale, colorOffset);
EditorGUILayout.EndVertical();
}
//Super Resolution
var superresolutionContent = new GUIContent();
superresolutionContent.text = "Super Resolution";
superresolutionContent.tooltip = "Single pass spatial aware upscaling technique.\n\nThis can't be used with Sharpening. \nAlso can't be used along with subsample feature due to unsupported texture format. \n\nThis effect won't work properly under low resolutions when Adaptive Resolution is also enabled.";
overlayTarget.superResolution = EditorGUILayout.Toggle(superresolutionContent, overlayTarget.superResolution);
//Supersampling
var supersamplingContent = new GUIContent();
supersamplingContent.text = "Supersampling Mode";
supersamplingContent.tooltip = "Normal: Normal Quality \n\nQuality: Higher Quality, higher GPU usage\n\nThis effect won't work properly under low resolutions when Adaptive Resolution or Sharpening is also enabled.\n\nThis can't be used with Super Resolution or Sharpening. It will be automatically disabled when you enable Super Resolution or Sharpening. \nAlso can't be used along with subsample feature due to unsupported texture format";
var supersamplingEnhanceContent = new GUIContent();
supersamplingEnhanceContent.text = "Supersampling Enhance Mode";
supersamplingEnhanceContent.tooltip = "None: Full screen will be super sampled\n\nFixed Foveated: Only the central fixation point will be sharpened\n\nSelf Adaptive: Only when contrast between the current pixel and the surrounding pixels exceeds a certain threshold will be sharpened.\n\nThis menu will be only enabled while Sharpening (either Normal or Quality) is enabled.";
if (overlayTarget.superResolution)
{
GUI.enabled = false;
overlayTarget.supersamplingMode = SuperSamplingMode.None;
overlayTarget.supersamplingEnhance = SuperSamplingEnhance.None;
}
else
{
GUI.enabled = true;
}
overlayTarget.supersamplingMode = (SuperSamplingMode)EditorGUILayout.EnumPopup(supersamplingContent, overlayTarget.supersamplingMode);
if (overlayTarget.supersamplingMode == SuperSamplingMode.None)
{
overlayTarget.supersamplingEnhance = SuperSamplingEnhance.None;
}
else
{
EditorGUI.indentLevel++;
overlayTarget.supersamplingEnhance = (SuperSamplingEnhance)EditorGUILayout.EnumPopup(supersamplingEnhanceContent, overlayTarget.supersamplingEnhance);
EditorGUI.indentLevel--;
}
if (overlayTarget.supersamplingMode != SuperSamplingMode.None)
{
if (overlayTarget.supersamplingMode == SuperSamplingMode.Normal)
{
overlayTarget.normalSupersampling = true;
overlayTarget.qualitySupersampling = false;
}
else
{
overlayTarget.normalSupersampling = false;
overlayTarget.qualitySupersampling = true;
}
if (overlayTarget.supersamplingEnhance == SuperSamplingEnhance.FixedFoveated)
{
overlayTarget.fixedFoveatedSupersampling = true;
}
else
{
overlayTarget.fixedFoveatedSupersampling = false;
}
}
else
{
overlayTarget.normalSupersampling = false;
overlayTarget.qualitySupersampling = false;
overlayTarget.fixedFoveatedSupersampling = false;
}
//Sharpening
var sharpeningContent = new GUIContent();
sharpeningContent.text = "Sharpening Mode";
sharpeningContent.tooltip = "Normal: Normal Quality \n\nQuality: Higher Quality, higher GPU usage\n\nThis effect won't work properly under low resolutions when Adaptive Resolution is also enabled.\n\nThis can't be used with Super Resolution and Supersampling. It will be automatically disabled when you enable Super Resolution or Supersampling. \nAlso can't be used along with subsample feature due to unsupported texture format";
var sharpeningEnhanceContent = new GUIContent();
sharpeningEnhanceContent.text = "Sharpening Enhance Mode";
sharpeningEnhanceContent.tooltip = "None: Full screen will be sharpened\n\nFixed Foveated: Only the central fixation point will be sharpened\n\nSelf Adaptive: Only when contrast between the current pixel and the surrounding pixels exceeds a certain threshold will be sharpened.\n\nThis menu will be only enabled while Sharpening (either Normal or Quality) is enabled.";
if (overlayTarget.superResolution || overlayTarget.normalSupersampling || overlayTarget.qualitySupersampling || overlayTarget.fixedFoveatedSupersampling)
{
GUI.enabled = false;
overlayTarget.sharpeningMode = SharpeningMode.None;
overlayTarget.sharpeningEnhance = SharpeningEnhance.None;
}
else
{
GUI.enabled = true;
}
overlayTarget.sharpeningMode = (SharpeningMode)EditorGUILayout.EnumPopup(sharpeningContent, overlayTarget.sharpeningMode);
if (overlayTarget.sharpeningMode == SharpeningMode.None)
{
overlayTarget.sharpeningEnhance = SharpeningEnhance.None;
}
else
{
EditorGUI.indentLevel++;
overlayTarget.sharpeningEnhance = (SharpeningEnhance)EditorGUILayout.EnumPopup(sharpeningEnhanceContent, overlayTarget.sharpeningEnhance);
EditorGUI.indentLevel--;
}
if (overlayTarget.sharpeningMode != SharpeningMode.None)
{
if (overlayTarget.sharpeningMode == SharpeningMode.Normal)
{
overlayTarget.normalSharpening = true;
overlayTarget.qualitySharpening = false;
}
else
{
overlayTarget.normalSharpening = false;
overlayTarget.qualitySharpening = true;
}
if (overlayTarget.sharpeningEnhance == SharpeningEnhance.Both)
{
overlayTarget.fixedFoveatedSharpening = true;
overlayTarget.selfAdaptiveSharpening = true;
}
else if (overlayTarget.sharpeningEnhance == SharpeningEnhance.FixedFoveated)
{
overlayTarget.fixedFoveatedSharpening = true;
overlayTarget.selfAdaptiveSharpening = false;
}
else if (overlayTarget.sharpeningEnhance == SharpeningEnhance.SelfAdaptive)
{
overlayTarget.fixedFoveatedSharpening = false;
overlayTarget.selfAdaptiveSharpening = true;
}
else
{
overlayTarget.fixedFoveatedSharpening = false;
overlayTarget.selfAdaptiveSharpening = false;
}
}
else
{
overlayTarget.normalSharpening = false;
overlayTarget.qualitySharpening = false;
overlayTarget.fixedFoveatedSharpening = false;
overlayTarget.selfAdaptiveSharpening = false;
}
if (GUI.changed)
{
EditorUtility.SetDirty(overlayTarget);
EditorUtility.SetDirty(overlayTarget);
}
serializedObject.ApplyModifiedProperties();
}
if (GUI.changed)
{
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
}
}
private Rect ClampRect(Rect rect)
{
rect.x = Mathf.Clamp01(rect.x);
rect.y = Mathf.Clamp01(rect.y);
rect.width = Mathf.Clamp01(rect.width);
rect.height = Mathf.Clamp01(rect.height);
return rect;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e6903c7ff46f75648b231bb4f83b47a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,174 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEditor;
using UnityEngine;
namespace Unity.XR.PXR.Editor
{
public class PXR_EditorStyles
{
public Color colorLine = new Color32(0xD9, 0xD9, 0xD9, 255);
public Color colorSelected = new Color32(0x7B, 0x7B, 0x7B, 255);
public Color colorDocumentationUrlNormal = new Color32(0x0F, 0x6F, 0xD5, 255);
public Color colorDocumentationUrlHover = new Color32(0x0F, 0x6F, 0xD5, 205);
private GUIStyle _dialogIconStyle;
private GUIStyle _headerText;
private GUIStyle _versionText;
private GUIStyle _contentArea;
private GUIStyle _contentText;
private GUIStyle _buttonStyle;
private GUIStyle _buttonSelectedStyle;
private GUIStyle _buttonToOpenStyle;
private GUIStyle _backgroundColorStyle;
private GUIStyle _bigWhiteTitleStyle;
private GUIStyle _smallBlueLinkStyle;
public GUIStyle HeaderText => _headerText ??= new GUIStyle(EditorStyles.largeLabel)
{
fontStyle = FontStyle.Normal,
fontSize = 48,
alignment = TextAnchor.MiddleCenter,
fixedHeight = 69,
fixedWidth = 600,
normal = new GUIStyleState()
{
textColor = Color.white
}
};
public GUIStyle BigWhiteTitleStyle => _bigWhiteTitleStyle ??= new GUIStyle(EditorStyles.largeLabel)
{
fontStyle = FontStyle.Bold,
fontSize = 20,
fixedHeight = 25,
alignment = TextAnchor.MiddleLeft,
normal = new GUIStyleState()
{
textColor = Color.white
}
};
public GUIStyle VersionText => _versionText ??= new GUIStyle(EditorStyles.miniLabel)
{
fontStyle = FontStyle.Normal,
fontSize = 18,
alignment = TextAnchor.LowerCenter,
fixedHeight = 69,
fixedWidth = 150,
padding = new RectOffset(8, 0, 0, 8),
normal = new GUIStyleState()
{
textColor = Color.white
}
};
public GUIStyle ContentText => _contentText ??= new GUIStyle(EditorStyles.wordWrappedLabel)
{
richText = true,
stretchHeight = true,
fontSize = 16,
normal = new GUIStyleState()
{
textColor = Color.white
}
};
public GUIStyle SmallBlueLinkStyle => _smallBlueLinkStyle ??= new GUIStyle(EditorStyles.linkLabel)
{
fontStyle = FontStyle.Normal,
fontSize = 16,
fixedHeight = 25,
alignment = TextAnchor.MiddleCenter,
normal = new GUIStyleState()
{
textColor = colorDocumentationUrlNormal
},
hover = new GUIStyleState()
{
textColor = colorDocumentationUrlHover
}
};
public GUIStyle IconStyle => _dialogIconStyle ??= new GUIStyle()
{
fixedHeight = 80,
fixedWidth = 250,
padding = new RectOffset(0, 10, 0, 0),
alignment = TextAnchor.UpperRight,
};
public Texture2D MakeTexture(int width, int height, Color color)
{
Texture2D texture = new Texture2D(width, height);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
texture.SetPixel(x, y, color);
}
}
texture.Apply();
return texture;
}
public GUIStyle ContentArea => _contentArea ??= new GUIStyle(EditorStyles.textArea)
{
stretchHeight = true,
padding = new RectOffset(4, 4, 4, 4),
};
public GUIStyle Button => _buttonStyle ??= new GUIStyle(EditorStyles.miniButton)
{
stretchWidth = true,
fixedWidth = 150,
fixedHeight = 36,
fontStyle = FontStyle.Bold,
richText = true,
padding = new RectOffset(4, 4, 4, 4),
normal = new GUIStyleState() { background = MakeTexture(2, 2, colorLine) }
};
public GUIStyle ButtonSelected => _buttonSelectedStyle ??= new GUIStyle(EditorStyles.miniButton)
{
stretchWidth = true,
fixedWidth = 150,
fixedHeight = 36,
fontStyle = FontStyle.Bold,
richText = true,
padding = new RectOffset(4, 4, 4, 4),
normal = new GUIStyleState() { background = MakeTexture(2, 2, colorSelected) }
};
public GUIStyle ButtonToOpen => _buttonToOpenStyle ??= new GUIStyle(EditorStyles.miniButton)
{
stretchWidth = true,
fixedWidth = 250,
fixedHeight = 25,
fontSize = 16,
richText = true,
alignment = TextAnchor.MiddleCenter,
padding = new RectOffset(4, 4, 4, 4),
normal = new GUIStyleState()
{
textColor = Color.white,
background = MakeTexture(2, 2, colorSelected)
}
};
public GUIStyle BackgroundColor => _backgroundColorStyle ??= new GUIStyle(EditorStyles.wordWrappedLabel)
{
};
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f43138445b42d748b11284441ceed22
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
#if !PICO_OPENXR_SDK
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEditor;
using Unity.XR.PXR;
[CustomEditor(typeof(PXR_Hand))]
public class PXR_HandEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
serializedObject.ApplyModifiedProperties();
PXR_Hand hand = (PXR_Hand)target;
EditorGUILayout.LabelField("Hand Joints", EditorStyles.boldLabel);
for (int i = 0; i < (int)HandJoint.JointMax; i++)
{
string jointName = ((HandJoint)i).ToString();
hand.handJoints[i] = (Transform)EditorGUILayout.ObjectField(jointName, hand.handJoints[i], typeof(Transform), true);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53a39cdaaf582104da549e4a50988330
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,649 @@
#if !PICO_OPENXR_SDK
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
using UnityEditor;
using System;
using UnityEditorInternal;
using System.Collections.Generic;
namespace Unity.XR.PXR.Editor
{
[CustomEditor(typeof(PXR_HandPoseGenerator))]
public class PXR_HandPoseGeneratorEditor : UnityEditor.Editor
{
private static bool shapesRecognizer = true;
private static bool bonesRecognizer = false;
private static bool transRecognizer = false;
private static bool thumb = true;
private static bool index = true;
private static bool middle = true;
private static bool ring = true;
private static bool pinky = true;
private PXR_HandPoseGenerator m_Target;
private PXR_HandPoseConfig config;
private PXR_HandPosePreview preview;
private ReorderableList bonesArray;
private void OnEnable()
{
m_Target = (PXR_HandPoseGenerator)target;
InitHandPosePreview();
InitBonesGroup();
}
private void OnDisable()
{
DestroyHandPosePreview();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
GUILayout.BeginHorizontal();
GUILayout.Label("Hand Pose Config");
m_Target.config = (PXR_HandPoseConfig)EditorGUILayout.ObjectField(m_Target.config, typeof(PXR_HandPoseConfig), false);
if (GUILayout.Button("New"))
{
m_Target.config = CreateInstance<PXR_HandPoseConfig>();
AssetDatabase.CreateAsset(m_Target.config, string.Format("Assets/{0}.asset", typeof(PXR_HandPoseConfig).Name + "_" + DateTime.Now.ToString("MMddhhmmss")));
}
//if (GUILayout.Button("Play"))
//{
//}
GUILayout.EndHorizontal();
if (m_Target.config != null)
{
if (config != m_Target.config)
{
config = m_Target.config;
ConfigRead();
}
shapesRecognizer = EditorGUILayout.Foldout(shapesRecognizer, "Shapes");
if (shapesRecognizer)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Space(10);
using (new GUILayout.VerticalScope())
{
thumb = EditorGUILayout.Foldout(thumb, "Thumb");
if (thumb)
{
FingerConfig(m_Target.thumb);
}
index = EditorGUILayout.Foldout(index, "Index");
if (index)
{
FingerConfig(m_Target.index);
}
middle = EditorGUILayout.Foldout(middle, "Middle");
if (middle)
{
FingerConfig(m_Target.middle);
}
ring = EditorGUILayout.Foldout(ring, "Ring");
if (ring)
{
FingerConfig(m_Target.ring);
}
pinky = EditorGUILayout.Foldout(pinky, "Pinky");
if (pinky)
{
FingerConfig(m_Target.pinky);
}
EditorGUILayout.Space(5);
serializedObject.FindProperty("shapesholdDuration").floatValue = EditorGUILayout.FloatField("Hold Duration", Mathf.Max(0, serializedObject.FindProperty("shapesholdDuration").floatValue));
}
EditorGUILayout.EndHorizontal();
}
bonesRecognizer = EditorGUILayout.Foldout(bonesRecognizer, "Bones");
if (bonesRecognizer)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Space(10);
using (new GUILayout.VerticalScope())
{
BonesConfig(m_Target.Bones);
}
EditorGUILayout.EndHorizontal();
}
transRecognizer = EditorGUILayout.Foldout(transRecognizer, "Transform");
if (transRecognizer)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Space(10);
using (new GUILayout.VerticalScope())
{
TransConfig();
}
EditorGUILayout.EndHorizontal();
}
if (GUI.changed)
{
ConfigSave();
UpdatePosePreview();
EditorUtility.SetDirty(m_Target.config);
serializedObject.ApplyModifiedProperties();
}
}
}
private void ConfigSave()
{
try
{
m_Target.config.shapesRecognizer.holdDuration = m_Target.shapesholdDuration;
m_Target.config.shapesRecognizer.thumb = m_Target.thumb;
m_Target.config.shapesRecognizer.index = m_Target.index;
m_Target.config.shapesRecognizer.middle = m_Target.middle;
m_Target.config.shapesRecognizer.ring = m_Target.ring;
m_Target.config.shapesRecognizer.pinky = m_Target.pinky;
m_Target.config.bonesRecognizer.holdDuration = m_Target.bonesHoldDuration;
m_Target.config.bonesRecognizer.Bones = m_Target.Bones;
m_Target.config.transRecognizer.holdDuration = m_Target.transHoldDuration;
m_Target.config.transRecognizer.trackAxis = m_Target.trackAxis;
m_Target.config.transRecognizer.spaceType = m_Target.spaceType;
m_Target.config.transRecognizer.trackTarget = m_Target.trackTarget;
m_Target.config.transRecognizer.angleThreshold = m_Target.angleThreshold;
m_Target.config.transRecognizer.thresholdWidth = m_Target.thresholdWidth;
}
catch (Exception e)
{
Debug.LogError("Save Error " + e.ToString());
}
AssetDatabase.Refresh();
}
private void UpdatePosePreview()
{
if (shapesRecognizer)
{
preview.UpdateShapeState(m_Target.config.shapesRecognizer);
}
else
{
preview.ResetShapeState();
}
if (transRecognizer)
{
preview.UpdateTransformState(m_Target.config.transRecognizer);
}
else
{
preview.ResetTransformState();
}
}
private void ConfigRead()
{
m_Target.shapesholdDuration = m_Target.config.shapesRecognizer.holdDuration;
m_Target.thumb = m_Target.config.shapesRecognizer.thumb;
m_Target.index = m_Target.config.shapesRecognizer.index;
m_Target.middle = m_Target.config.shapesRecognizer.middle;
m_Target.ring = m_Target.config.shapesRecognizer.ring;
m_Target.pinky = m_Target.config.shapesRecognizer.pinky;
m_Target.bonesHoldDuration = m_Target.config.bonesRecognizer.holdDuration;
m_Target.Bones = m_Target.config.bonesRecognizer.Bones;
m_Target.transHoldDuration = m_Target.config.transRecognizer.holdDuration;
m_Target.trackAxis = m_Target.config.transRecognizer.trackAxis;
m_Target.spaceType = m_Target.config.transRecognizer.spaceType;
m_Target.trackTarget = m_Target.config.transRecognizer.trackTarget;
m_Target.angleThreshold = m_Target.config.transRecognizer.angleThreshold;
m_Target.thresholdWidth = m_Target.config.transRecognizer.thresholdWidth;
}
private void TransConfig()
{
EditorGUILayout.BeginHorizontal("box");
EditorGUILayout.Space(5);
using (new GUILayout.VerticalScope())
{
EditorGUILayout.Space(5);
m_Target.trackAxis = (TransRecognizer.TrackAxis)EditorGUILayout.EnumPopup("Track Axis", m_Target.trackAxis);
m_Target.trackTarget = (TransRecognizer.TrackTarget)EditorGUILayout.EnumPopup("Track Target", m_Target.trackTarget);
m_Target.angleThreshold = EditorGUILayout.FloatField("Angle Threshold", m_Target.angleThreshold);
m_Target.thresholdWidth = EditorGUILayout.FloatField("Margin", m_Target.thresholdWidth);
EditorGUILayout.Space(5);
}
EditorGUILayout.Space(5);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(5);
m_Target.transHoldDuration = EditorGUILayout.FloatField("Hold Duration", m_Target.transHoldDuration);
}
private void BonesConfig(List<BonesRecognizer.BonesGroup> listBones)
{
using (new GUILayout.VerticalScope())
{
bonesArray.DoLayoutList();
}
serializedObject.FindProperty("bonesHoldDuration").floatValue = EditorGUILayout.FloatField("Hold Duration", Mathf.Max(0, serializedObject.FindProperty("bonesHoldDuration").floatValue));
}
private void InitBonesGroup()
{
bonesArray = new ReorderableList(serializedObject, serializedObject.FindProperty("Bones"), true, true, true, true);
bonesArray.drawHeaderCallback = (Rect rect) =>
{
GUI.Label(rect, "Bones Groups");
};
bonesArray.elementHeightCallback = (index) =>
{
var element = bonesArray.serializedProperty.GetArrayElementAtIndex(index);
var h = EditorGUIUtility.singleLineHeight;
if (element.isExpanded)
h += EditorGUI.GetPropertyHeight(element) + EditorGUIUtility.singleLineHeight;
return h;
};
bonesArray.drawElementCallback = (Rect rect, int index, bool selected, bool focused) =>
{
SerializedProperty item = bonesArray.serializedProperty.GetArrayElementAtIndex(index);
var posRect_label = new Rect(rect)
{
x = rect.x + 14,
width = rect.width - 18,
height = EditorGUIUtility.singleLineHeight
};
item.isExpanded = EditorGUI.BeginFoldoutHeaderGroup(posRect_label, item.isExpanded, item.isExpanded ? "" : $"{index}");
if (item.isExpanded)
{
rect.height -= 8 + EditorGUIUtility.singleLineHeight;
rect.y += 18;
GUIStyle style = new GUIStyle(EditorStyles.label);
style.fontSize = 20;
style.fontStyle = FontStyle.Bold;
EditorGUI.LabelField(rect, " " + index.ToString(), style);
EditorGUI.DrawRect(rect, new Color(0, 0, 0, 0.2f));
rect.y += 6;
EditorGUI.PropertyField(rect, item, new GUIContent());
}
EditorGUI.EndFoldoutHeaderGroup();
};
bonesArray.onAddCallback = (ReorderableList list) =>
{
ReorderableList.defaultBehaviours.DoAddButton(list);
list.serializedProperty.GetArrayElementAtIndex(list.count - 1).FindPropertyRelative("distance").floatValue = 0.03f;
list.serializedProperty.GetArrayElementAtIndex(list.count - 1).FindPropertyRelative("thresholdWidth").floatValue = 0.01f;
};
bonesArray.onRemoveCallback = (ReorderableList list) =>
{
{
ReorderableList.defaultBehaviours.DoRemoveButton(list);
}
};
}
private void FingerConfig(ShapesRecognizer.Finger finger)
{
EditorGUILayout.BeginHorizontal("box");
EditorGUILayout.Space(5);
using (new GUILayout.VerticalScope())
{
EditorGUILayout.Space(5);
FlexionConfig(finger, finger.fingerConfigs.flexionConfigs);
CurlConfig(finger, finger.fingerConfigs.curlConfigs);
AbductionConfig(finger, finger.fingerConfigs.abductionConfigs);
EditorGUILayout.Space(5);
}
EditorGUILayout.Space(5);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(5);
}
private void FlexionConfig(ShapesRecognizer.Finger finger, ShapesRecognizer.RangeConfigs flexionConfigs)
{
finger.flexion = (ShapesRecognizer.Flexion)EditorGUILayout.EnumPopup("Flexion", finger.flexion);
Vector2 defaultVal = new Vector2();
switch (finger.flexion)
{
case ShapesRecognizer.Flexion.Any:
return;
case ShapesRecognizer.Flexion.Open:
defaultVal = GetDefaultShapeVal(finger.handFinger, ShapesRecognizer.ShapeType.flexion, true);
flexionConfigs.min = defaultVal.x;
flexionConfigs.max = defaultVal.y;
break;
case ShapesRecognizer.Flexion.Close:
defaultVal = GetDefaultShapeVal(finger.handFinger, ShapesRecognizer.ShapeType.flexion, false);
flexionConfigs.min = defaultVal.x;
flexionConfigs.max = defaultVal.y;
break;
//case ShapesRecognizer.Flexion.Custom:
// EditorGUILayout.MinMaxSlider("Custom Range",
// ref flexionConfigs.min,
// ref flexionConfigs.max,
// ShapesRecognizer.flexionMin,
// ShapesRecognizer.flexionMax);
// break;
default:
break;
}
flexionConfigs.width = EditorGUILayout.Slider("Margin", flexionConfigs.width, 0,
ShapesRecognizer.flexionMax - ShapesRecognizer.flexionMin);
EditorGUILayout.LabelField(new GUIContent("Flexion Range"),
new GUIContent($"[{flexionConfigs.min + " - " + flexionConfigs.width}, {flexionConfigs.max + " + " + flexionConfigs.width}]"));
}
private void CurlConfig(ShapesRecognizer.Finger finger, ShapesRecognizer.RangeConfigs curlConfigs)
{
finger.curl = (ShapesRecognizer.Curl)EditorGUILayout.EnumPopup("Curl", finger.curl);
Vector2 defaultVal;
switch (finger.curl)
{
case ShapesRecognizer.Curl.Any:
return;
case ShapesRecognizer.Curl.Open:
defaultVal = GetDefaultShapeVal(finger.handFinger, ShapesRecognizer.ShapeType.curl, true);
curlConfigs.min = defaultVal.x;
curlConfigs.max = defaultVal.y;
break;
case ShapesRecognizer.Curl.Close:
defaultVal = GetDefaultShapeVal(finger.handFinger, ShapesRecognizer.ShapeType.curl, false);
curlConfigs.min = defaultVal.x;
curlConfigs.max = defaultVal.y;
break;
//case ShapesRecognizer.Curl.Custom:
// EditorGUILayout.MinMaxSlider("Custom Range",
// ref curlConfigs.min,
// ref curlConfigs.max,
// finger.handFinger == HandFinger.Thumb ? ShapesRecognizer.curlThumbMin : ShapesRecognizer.curlMin,
// finger.handFinger == HandFinger.Thumb ? ShapesRecognizer.curlThumbMax : ShapesRecognizer.curlMax);
// break;
default:
break;
}
curlConfigs.width = EditorGUILayout.Slider("Margin", curlConfigs.width, 0,
ShapesRecognizer.curlMax - ShapesRecognizer.curlMin);
EditorGUILayout.LabelField(new GUIContent("Curl Range"),
new GUIContent($"[{curlConfigs.min + " - " + curlConfigs.width}, {curlConfigs.max + " + " + curlConfigs.width}]"));
}
private void AbductionConfig(ShapesRecognizer.Finger finger, ShapesRecognizer.RangeConfigsAbduction abductionConfigs)
{
if (finger.handFinger == HandFinger.Pinky) return;
finger.abduction = (ShapesRecognizer.Abduction)EditorGUILayout.EnumPopup("Abduction", finger.abduction);
Vector2 defaultVal = GetDefaultShapeVal(finger.handFinger, ShapesRecognizer.ShapeType.abduction);
abductionConfigs.mid = defaultVal.x;
switch (finger.abduction)
{
case ShapesRecognizer.Abduction.Any:
return;
case ShapesRecognizer.Abduction.Open:
break;
case ShapesRecognizer.Abduction.Close:
break;
default:
break;
}
abductionConfigs.width = EditorGUILayout.Slider("Margin", abductionConfigs.width, 0,
ShapesRecognizer.abductionMax - ShapesRecognizer.abductionMin);
EditorGUILayout.LabelField(new GUIContent("Abduction Range"),
new GUIContent($"[{abductionConfigs.mid + " ± " + abductionConfigs.width + "/2"}]"));
}
private Vector2 GetDefaultShapeVal(HandFinger finger, ShapesRecognizer.ShapeType shapeType, bool isOpen = true)
{
Vector2 val = new Vector2();
switch (shapeType)
{
case ShapesRecognizer.ShapeType.flexion:
val.x = finger == HandFinger.Thumb ? (isOpen ? ShapesRecognizer.flexionThumbOpenMin : ShapesRecognizer.flexionThumbCloseMin) :
(isOpen ? ShapesRecognizer.flexionOpenMin : ShapesRecognizer.flexionCloseMin);
val.y = finger == HandFinger.Thumb ? (isOpen ? ShapesRecognizer.flexionThumbOpenMax : ShapesRecognizer.flexionThumbCloseMax) :
(isOpen ? ShapesRecognizer.flexionOpenMax : ShapesRecognizer.flexionCloseMax);
break;
case ShapesRecognizer.ShapeType.curl:
val.x = finger == HandFinger.Thumb ? (isOpen ? ShapesRecognizer.curlThumbOpenMin : ShapesRecognizer.curlThumbCloseMin) :
(isOpen ? ShapesRecognizer.curlOpenMin : ShapesRecognizer.curlCloseMin);
val.y = finger == HandFinger.Thumb ? (isOpen ? ShapesRecognizer.curlThumbOpenMax : ShapesRecognizer.curlThumbCloseMax) :
(isOpen ? ShapesRecognizer.curlOpenMax : ShapesRecognizer.curlCloseMax);
break;
case ShapesRecognizer.ShapeType.abduction:
val.x = finger == HandFinger.Thumb ? ShapesRecognizer.abductionThumbMid : ShapesRecognizer.abductionMid;
val.y = finger == HandFinger.Thumb ? ShapesRecognizer.abductionThumbWidth : ShapesRecognizer.abductionWidth;
break;
}
return val;
}
public override bool HasPreviewGUI()
{
return true;
}
private void DestroyHandPosePreview()
{
if (previewInstance)
{
DestroyImmediate(previewInstance);
}
previewInstance = null;
if (previewRenderUtility != null)
{
previewRenderUtility.Cleanup();
previewRenderUtility = null;
}
}
public override GUIContent GetPreviewTitle()
{
return new GUIContent("Hand Pose");
}
public override void OnPreviewSettings()
{
if (GUILayout.Button("Reset", "preButton"))
{
dragPos = Vector2.zero;
}
}
private PreviewRenderUtility previewRenderUtility;
private GameObject previewInstance;
private Vector2 dragPos;
private void InitHandPosePreview()
{
if (previewRenderUtility == null)
{
previewRenderUtility = new PreviewRenderUtility(true);
previewRenderUtility.cameraFieldOfView = 60f;
previewInstance = Instantiate(m_Target.preview.gameObject);
previewInstance.SetActive(true);
preview = previewInstance.GetComponent<PXR_HandPosePreview>();
previewRenderUtility.AddSingleGO(previewInstance);
}
}
private static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
{
int controlID = GUIUtility.GetControlID("Slider".GetHashCode(), FocusType.Passive);
Event current = Event.current;
switch (current.GetTypeForControl(controlID))
{
case EventType.MouseDown:
{
bool flag = position.Contains(current.mousePosition) && position.width > 50f;
if (flag)
{
GUIUtility.hotControl = controlID;
current.Use();
EditorGUIUtility.SetWantsMouseJumping(1);
}
break;
}
case EventType.MouseUp:
{
bool flag2 = GUIUtility.hotControl == controlID;
if (flag2)
{
GUIUtility.hotControl = 0;
}
EditorGUIUtility.SetWantsMouseJumping(0);
break;
}
case EventType.MouseDrag:
{
bool flag3 = GUIUtility.hotControl == controlID;
if (flag3)
{
scrollPosition -= current.delta / Mathf.Min(position.width, position.height) * 140f;
current.Use();
GUI.changed = true;
}
break;
}
}
return scrollPosition;
}
public override void OnPreviewGUI(Rect rect, GUIStyle background)
{
dragPos = Drag2D(dragPos, rect);
if (Event.current.type != EventType.Repaint)
{
return;
}
if (previewRenderUtility != null)
{
previewRenderUtility.BeginPreview(rect, background);
Camera camera = previewRenderUtility.camera;
camera.clearFlags = CameraClearFlags.Depth;
camera.nearClipPlane = 0.01f;
camera.farClipPlane = 100f;
camera.transform.position = camera.transform.forward * -2f;
preview.posePreviewX.localEulerAngles = new Vector3(0, dragPos.x, 0);
preview.posePreviewY.localEulerAngles = new Vector3(Mathf.Clamp(dragPos.y, -60f, 0f), 0f, 0f);
camera.Render();
previewRenderUtility.EndAndDrawPreview(rect);
}
}
}
[CustomPropertyDrawer(typeof(DisplayOnly))]
public class DisplayOnlyDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, label, true);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUI.enabled = false;
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true;
}
}
[CustomPropertyDrawer(typeof(LabelAttribute))]
public class LabelAttributeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
LabelAttribute labelAttribute = this.attribute as LabelAttribute;
EditorGUI.PropertyField(position, property, new GUIContent(labelAttribute.name));
}
}
[CustomPropertyDrawer(typeof(BonesRecognizer.BonesGroup))]
public class PXR_BonesGroupPropertyDrawer : PropertyDrawer
{
private float propertyHeight = EditorGUIUtility.singleLineHeight;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
var Space_Height = 2;
var rect = position;
rect.height = EditorGUIUtility.singleLineHeight;
rect.width = position.width - position.width / 6;
rect.y += Space_Height;
var boneRect = rect;
boneRect.position = new Vector2(rect.position.x + rect.width / 15 * 2, rect.position.y);
var handAProperty = property.FindPropertyRelative("bone1");
EditorGUI.PropertyField(boneRect, handAProperty);
rect.y += EditorGUIUtility.singleLineHeight + Space_Height;
boneRect.position = new Vector2(rect.position.x + rect.width / 15 * 2, rect.position.y);
var handBProperty = property.FindPropertyRelative("bone2");
EditorGUI.PropertyField(boneRect, handBProperty);
rect.y += EditorGUIUtility.singleLineHeight + Space_Height;
boneRect.position = new Vector2(rect.position.x + rect.width / 15 * 2, rect.position.y);
var disProperty = property.FindPropertyRelative("distance");
EditorGUI.PropertyField(boneRect, disProperty);
rect.y += EditorGUIUtility.singleLineHeight + Space_Height;
boneRect.position = new Vector2(rect.position.x + rect.width / 15 * 2, rect.position.y);
var thresProperty = property.FindPropertyRelative("thresholdWidth");
EditorGUI.PropertyField(boneRect, thresProperty);
propertyHeight = rect.y - position.y + EditorGUIUtility.singleLineHeight;
EditorGUI.EndProperty();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return propertyHeight;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aae883d2d057e1e45939843a36892dd7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,445 @@
#if !PICO_OPENXR_SDK
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Unity.XR.CoreUtils;
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace Unity.XR.PXR.Editor
{
[CustomEditor(typeof(PXR_Manager))]
public class PXR_ManagerEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
GUI.changed = false;
DrawDefaultInspector();
PXR_Manager manager = (PXR_Manager)target;
PXR_ProjectSetting projectConfig = PXR_ProjectSetting.GetProjectConfig();
//Screen Fade
manager.screenFade = EditorGUILayout.Toggle("Open Screen Fade", manager.screenFade);
if (Camera.main != null)
{
var head = Camera.main.transform;
if (head)
{
var fade = head.GetComponent<PXR_ScreenFade>();
if (manager.screenFade)
{
if (!fade)
{
head.gameObject.AddComponent<PXR_ScreenFade>();
Selection.activeObject = head;
}
}
else
{
if (fade) DestroyImmediate(fade);
}
}
}
//ffr
manager.foveatedRenderingMode = (FoveatedRenderingMode)EditorGUILayout.EnumPopup("Foveated Rendering Mode", manager.foveatedRenderingMode);
if (FoveatedRenderingMode.FixedFoveatedRendering == manager.foveatedRenderingMode)
{
projectConfig.enableETFR = false;
projectConfig.recommendSubsamping = false;
projectConfig.validationFFREnabled = false;
projectConfig.validationETFREnabled = false;
projectConfig.foveationLevel= manager.foveationLevel = (FoveationLevel)EditorGUILayout.EnumPopup("Foveated Rendering Level", manager.foveationLevel);
manager.eyeFoveationLevel = FoveationLevel.None;
if (FoveationLevel.None != manager.foveationLevel)
{
projectConfig.validationFFREnabled = true;
if (GraphicsDeviceType.OpenGLES3 == PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget)[0] && PlayerSettings.colorSpace == ColorSpace.Gamma)
{
projectConfig.enableSubsampled = false;
projectConfig.recommendSubsamping = false;
}
else
{
projectConfig.enableSubsampled = EditorGUILayout.Toggle(" Subsampling", projectConfig.enableSubsampled);
projectConfig.recommendSubsamping = true;
}
}
}
else if (FoveatedRenderingMode.EyeTrackedFoveatedRendering == manager.foveatedRenderingMode) //etfr
{
projectConfig.enableETFR = true;
projectConfig.recommendSubsamping = false;
projectConfig.validationFFREnabled = false;
projectConfig.validationETFREnabled = false;
projectConfig.foveationLevel=manager.eyeFoveationLevel = (FoveationLevel)EditorGUILayout.EnumPopup("Foveated Rendering Level", manager.eyeFoveationLevel);
manager.foveationLevel = FoveationLevel.None;
if (FoveationLevel.None != manager.eyeFoveationLevel)
{
projectConfig.validationETFREnabled = true;
if (GraphicsDeviceType.OpenGLES3 == PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget)[0] && PlayerSettings.colorSpace == ColorSpace.Gamma)
{
projectConfig.enableSubsampled = false;
projectConfig.recommendSubsamping = false;
}
else
{
projectConfig.enableSubsampled = EditorGUILayout.Toggle(" Subsampling", projectConfig.enableSubsampled);
projectConfig.recommendSubsamping = true;
}
}
}
//eye tracking
GUIStyle firstLevelStyle = new GUIStyle(GUI.skin.label);
firstLevelStyle.alignment = TextAnchor.UpperLeft;
firstLevelStyle.fontStyle = FontStyle.Bold;
firstLevelStyle.fontSize = 12;
firstLevelStyle.wordWrap = true;
var guiContent = new GUIContent();
guiContent.text = "Eye Tracking";
guiContent.tooltip = "Before calling EyeTracking API, enable this option first, only for Neo3 Pro Eye , PICO 4 Pro device.";
projectConfig.eyeTracking = EditorGUILayout.Toggle(guiContent, projectConfig.eyeTracking);
manager.eyeTracking = projectConfig.eyeTracking;
if (manager.eyeTracking || FoveatedRenderingMode.EyeTrackedFoveatedRendering == manager.foveatedRenderingMode)
{
projectConfig.eyetrackingCalibration = EditorGUILayout.Toggle(new GUIContent("Eye Tracking Calibration"), projectConfig.eyetrackingCalibration);
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Note:", firstLevelStyle);
EditorGUILayout.LabelField("Eye Tracking is supported only on Neo 3 Pro Eye , PICO 4 Pro");
EditorGUILayout.EndVertical();
}
//face tracking
var FaceContent = new GUIContent();
FaceContent.text = "Face Tracking Mode";
manager.trackingMode = (FaceTrackingMode)EditorGUILayout.EnumPopup(FaceContent, manager.trackingMode);
if (manager.trackingMode == FaceTrackingMode.PXR_FTM_NONE)
{
projectConfig.faceTracking = false;
projectConfig.lipsyncTracking = false;
}
else if (manager.trackingMode == FaceTrackingMode.PXR_FTM_FACE_LIPS_VIS || manager.trackingMode == FaceTrackingMode.PXR_FTM_FACE_LIPS_BS)
{
projectConfig.faceTracking = true;
projectConfig.lipsyncTracking = true;
}
else if (manager.trackingMode == FaceTrackingMode.PXR_FTM_FACE)
{
projectConfig.faceTracking = true;
projectConfig.lipsyncTracking = false;
}
else if (manager.trackingMode == FaceTrackingMode.PXR_FTM_LIPS)
{
projectConfig.faceTracking = false;
projectConfig.lipsyncTracking = true;
}
manager.faceTracking = projectConfig.faceTracking;
manager.lipsyncTracking = projectConfig.lipsyncTracking;
//hand tracking
var handContent = new GUIContent();
handContent.text = "Hand Tracking";
projectConfig.handTracking = EditorGUILayout.Toggle(handContent, projectConfig.handTracking);
if (projectConfig.handTracking)
{
//hand tracking Support
var handSupport = new GUIContent();
handSupport.text = "Hand Tracking Support";
projectConfig.handTrackingSupportType =(HandTrackingSupport)EditorGUILayout.EnumPopup(handSupport, projectConfig.handTrackingSupportType);
}
//Adaptive Hand Model
var adaptiveContent = new GUIContent();
adaptiveContent.text = "Adaptive Hand Model(PICO)";
adaptiveContent.tooltip = "If this function is selected, the hand model will change according to the actual size of the user's palm. Note that the hand model only works on PICO.";
projectConfig.adaptiveHand = EditorGUILayout.Toggle(adaptiveContent, projectConfig.adaptiveHand);
//high frequency tracking
var highfrequencytracking = new GUIContent();
highfrequencytracking.text = "High Frequency Tracking(60Hz)";
highfrequencytracking.tooltip = "If turned on, hand tracking will run at a higher tracking frequency, which will improve the smoothness of hand tracking, but the power consumption will increase.";
projectConfig.highFrequencyHand = EditorGUILayout.Toggle(highfrequencytracking, projectConfig.highFrequencyHand);
//body tracking
var bodyContent = new GUIContent();
bodyContent.text = "Body Tracking";
projectConfig.bodyTracking = EditorGUILayout.Toggle(bodyContent, projectConfig.bodyTracking);
manager.bodyTracking = projectConfig.bodyTracking;
// content protect
projectConfig.useContentProtect = EditorGUILayout.Toggle("Use Content Protect", projectConfig.useContentProtect);
//MRC
var mrcContent = new GUIContent();
mrcContent.text = "MRC";
projectConfig.openMRC = EditorGUILayout.Toggle(mrcContent, projectConfig.openMRC);
manager.openMRC = projectConfig.openMRC;
if (manager.openMRC == true)
{
EditorGUILayout.BeginVertical("frameBox");
string[] layerNames = new string[32];
for (int i = 0; i < 32; i++)
{
layerNames[i] = LayerMask.LayerToName(i);
if (layerNames[i].Length == 0)
{
layerNames[i] = "LayerName " + i.ToString();
}
}
manager.foregroundLayerMask = EditorGUILayout.MaskField("Foreground Layer Masks", manager.foregroundLayerMask, layerNames);
manager.backgroundLayerMask = EditorGUILayout.MaskField("Background Layer Masks", manager.backgroundLayerMask, layerNames);
EditorGUILayout.EndVertical();
}
//Late Latching
projectConfig.latelatching = EditorGUILayout.Toggle("Use Late Latching", projectConfig.latelatching);
manager.lateLatching = projectConfig.latelatching;
if (manager.lateLatching)
{
projectConfig.latelatchingDebug = EditorGUILayout.Toggle(" Late Latching Debug", projectConfig.latelatchingDebug);
manager.latelatchingDebug = projectConfig.latelatchingDebug;
}
if (Camera.main != null)
{
var head = Camera.main.transform;
if (head)
{
var fade = head.GetComponent<PXR_LateLatching>();
if (manager.lateLatching)
{
if (!fade)
{
head.gameObject.AddComponent<PXR_LateLatching>();
Selection.activeObject = head;
}
}
else
{
if (fade) DestroyImmediate(fade);
}
}
}
// msaa
if (QualitySettings.renderPipeline != null)
{
EditorGUI.BeginDisabledGroup(true);
projectConfig.enableRecommendMSAA = EditorGUILayout.Toggle("Use Recommended MSAA", projectConfig.enableRecommendMSAA);
manager.useRecommendedAntiAliasingLevel = projectConfig.enableRecommendMSAA;
EditorGUI.EndDisabledGroup();
EditorGUILayout.HelpBox("A Scriptable Render Pipeline is in use,the 'Use Recommended MSAA' will not be used. ", MessageType.Info, true);
projectConfig.recommendMSAA = false;
}
else
{
projectConfig.enableRecommendMSAA = EditorGUILayout.Toggle("Use Recommended MSAA", projectConfig.enableRecommendMSAA);
manager.useRecommendedAntiAliasingLevel = projectConfig.enableRecommendMSAA;
if (!projectConfig.enableRecommendMSAA)
{
projectConfig.recommendMSAA = true;
}
}
//Adaptive Resolution
guiContent = new GUIContent();
guiContent.text = "Adaptive Resolution";
guiContent.tooltip = "Adaptively change resolution based on GPU performance using renderViewportScale. Render buffer will be allocated to max adaptive resolution scale size. Currently, FFR should be disabled with this feature.";
projectConfig.adaptiveResolution = EditorGUILayout.Toggle(guiContent, projectConfig.adaptiveResolution);
manager.adaptiveResolution = projectConfig.adaptiveResolution;
if (manager.adaptiveResolution)
{
EditorGUILayout.LabelField("Min Adaptive Resolution Scale:");
manager.minEyeTextureScale = EditorGUILayout.Slider(manager.minEyeTextureScale, 0.7f, 1.3f);
EditorGUILayout.LabelField("Max Adaptive Resolution Scale:");
manager.maxEyeTextureScale = EditorGUILayout.Slider(manager.maxEyeTextureScale, 0.7f, 1.3f);
manager.adaptiveResolutionPowerSetting = (AdaptiveResolutionPowerSetting)EditorGUILayout.EnumPopup(" Power Setting", manager.adaptiveResolutionPowerSetting);
}
#if UNITY_2021_3_OR_NEWER
XROrigin xrOrigin = FindAnyObjectByType<XROrigin>();
#else
XROrigin xrOrigin = FindObjectOfType<XROrigin>();
#endif
if (xrOrigin.RequestedTrackingOriginMode != XROrigin.TrackingOriginMode.Floor)
{
GUI.enabled = false;
projectConfig.stageMode = EditorGUILayout.Toggle("Stage Mode", false);
GUI.enabled = true;
}
else
{
projectConfig.stageMode = EditorGUILayout.Toggle("Stage Mode", projectConfig.stageMode);
}
//mr
EditorGUILayout.BeginVertical("frameBox");
projectConfig.videoSeeThrough = EditorGUILayout.Toggle("Video Seethrough", projectConfig.videoSeeThrough);
projectConfig.spatialAnchor = EditorGUILayout.Toggle("Spatial Anchor", projectConfig.spatialAnchor);
projectConfig.sceneCapture = EditorGUILayout.Toggle("Scene Capture", projectConfig.sceneCapture);
projectConfig.sharedAnchor = EditorGUILayout.Toggle("Shared Spatial Anchor", projectConfig.sharedAnchor);
projectConfig.spatialMesh = EditorGUILayout.Toggle("Spatial Mesh", projectConfig.spatialMesh);
if (projectConfig.spatialMesh)
{
projectConfig.meshLod = (PxrMeshLod)EditorGUILayout.EnumPopup(" LOD", projectConfig.meshLod);
}
EditorGUILayout.EndVertical();
//mr safeguard
var mrSafeguardContent = new GUIContent();
mrSafeguardContent.text = "MR Safeguard";
mrSafeguardContent.tooltip =
"MR safety, if you choose this option, your application will adopt MR safety policies during runtime. If not selected, it will continue to use VR safety policies by default.";
projectConfig.mrSafeguard = EditorGUILayout.Toggle(mrSafeguardContent, projectConfig.mrSafeguard);
var secureMRContent = new GUIContent();
secureMRContent.text = "SecureMR";
projectConfig.secureMR = EditorGUILayout.Toggle(secureMRContent, projectConfig.secureMR);
//Super Resolution
var superresolutionContent = new GUIContent();
superresolutionContent.text = "Super Resolution";
superresolutionContent.tooltip = "Single pass spatial aware upscaling technique.\n\nThis can't be used with Sharpening. \nAlso can't be used along with subsample feature due to unsupported texture format. \n\nThis effect won't work properly under low resolutions when Adaptive Resolution is also enabled.";
projectConfig.superResolution = EditorGUILayout.Toggle(superresolutionContent, projectConfig.superResolution);
manager.enableSuperResolution = projectConfig.superResolution;
//Sharpening
var sharpeningContent = new GUIContent();
sharpeningContent.text = "Sharpening Mode";
sharpeningContent.tooltip = "Normal: Normal Quality \n\nQuality: Higher Quality, higher GPU usage\n\nThis effect won't work properly under low resolutions when Adaptive Resolution is also enabled.\n\nThis can't be used with Super Resolution. It will be automatically disabled when you enable Super Resolution. \nAlso can't be used along with subsample feature due to unsupported texture format";
var sharpeningEnhanceContent = new GUIContent();
sharpeningEnhanceContent.text = "Sharpening Enhance Mode";
sharpeningEnhanceContent.tooltip = "None: Full screen will be sharpened\n\nFixed Foveated: Only the central fixation point will be sharpened\n\nSelf Adaptive: Only when contrast between the current pixel and the surrounding pixels exceeds a certain threshold will be sharpened.\n\nThis menu will be only enabled while Sharpening (either Normal or Quality) is enabled.";
if (projectConfig.superResolution)
{
GUI.enabled = false;
manager.sharpeningMode = SharpeningMode.None;
manager.sharpeningEnhance = SharpeningEnhance.None;
}
else
{
GUI.enabled = true;
}
manager.sharpeningMode = (SharpeningMode)EditorGUILayout.EnumPopup(sharpeningContent, manager.sharpeningMode);
if (manager.sharpeningMode == SharpeningMode.None)
{
manager.sharpeningEnhance = SharpeningEnhance.None;
}
else
{
manager.sharpeningEnhance = (SharpeningEnhance)EditorGUILayout.EnumPopup(sharpeningEnhanceContent, manager.sharpeningEnhance);
}
if (manager.sharpeningMode != SharpeningMode.None)
{
if (manager.sharpeningMode == SharpeningMode.Normal)
{
projectConfig.normalSharpening = true;
projectConfig.qualitySharpening = false;
}
else
{
projectConfig.normalSharpening = false;
projectConfig.qualitySharpening = true;
}
if (manager.sharpeningEnhance == SharpeningEnhance.Both)
{
projectConfig.fixedFoveatedSharpening = true;
projectConfig.selfAdaptiveSharpening = true;
}
else if (manager.sharpeningEnhance == SharpeningEnhance.FixedFoveated)
{
projectConfig.fixedFoveatedSharpening = true;
projectConfig.selfAdaptiveSharpening = false;
}
else if (manager.sharpeningEnhance == SharpeningEnhance.SelfAdaptive)
{
projectConfig.fixedFoveatedSharpening = false;
projectConfig.selfAdaptiveSharpening = true;
}
else
{
projectConfig.fixedFoveatedSharpening = false;
projectConfig.selfAdaptiveSharpening = false;
}
}
else
{
projectConfig.normalSharpening = false;
projectConfig.qualitySharpening = false;
projectConfig.fixedFoveatedSharpening = false;
projectConfig.selfAdaptiveSharpening = false;
}
var usePremultipliedAlphaContent = new GUIContent();
usePremultipliedAlphaContent.text = "Use Premultiplied Alpha";
usePremultipliedAlphaContent.tooltip = @"Enable premultiplied alpha for this content.
When enabled:
• RGB color channels are multiplied by Alpha (R*A, G*A, B*A)
• Improves performance for transparent elements (e.g., UI, particles)
• Fixes edge artifacts in semitransparent objects
• Matches OpenXR and GPU blending requirements
Recommended for:
• UI panels with transparency
• Particle effects
• Materials using alpha blending
• Any content requiring frequent transparency mixing
Note: Ensure textures are imported with 'Alpha Is Transparency'
or manually pre-multiply colors if needed.";
manager.usePremultipliedAlpha = EditorGUILayout.Toggle(usePremultipliedAlphaContent, manager.usePremultipliedAlpha);
guiContent.text = "Layer Blend";
manager.useLayerBlend = EditorGUILayout.Toggle(guiContent, manager.useLayerBlend);
if (manager.useLayerBlend)
{
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Src Color";
manager.srcColor = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, manager.srcColor);
guiContent.text = "Dst Color";
manager.dstColor = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, manager.dstColor);
guiContent.text = "Src Alpha";
manager.srcAlpha = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, manager.srcAlpha);
guiContent.text = "Dst Alpha";
manager.dstAlpha = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, manager.dstAlpha);
EditorGUILayout.EndVertical();
}
if (GUI.changed)
{
EditorUtility.SetDirty(projectConfig);
EditorUtility.SetDirty(manager);
}
serializedObject.ApplyModifiedProperties();
}
private void OnDisable()
{
EditorUtility.SetDirty(PXR_ProjectSetting.GetProjectConfig());
UnityEditor.AssetDatabase.SaveAssets();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 79735b12af5b1844aba3a1342ec41bb1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,63 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
#if XR_MGMT_GTE_320
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.XR.Management.Metadata;
using UnityEngine;
namespace Unity.XR.PXR.Editor
{
internal class PXR_Metadata : IXRPackage
{
private class PXR_PackageMetadata : IXRPackageMetadata
{
public string packageName => "PICO Plugin";
public string packageId => "com.unity.xr.picoxr";
public string settingsType => "Unity.XR.PXR.PXR_Settings";
public List<IXRLoaderMetadata> loaderMetadata => lLoaderMetadata;
private static readonly List<IXRLoaderMetadata> lLoaderMetadata = new List<IXRLoaderMetadata>() { new PXR_LoaderMetadata() };
}
private class PXR_LoaderMetadata : IXRLoaderMetadata
{
public string loaderName => "PICO";
public string loaderType => "Unity.XR.PXR.PXR_Loader";
public List<BuildTargetGroup> supportedBuildTargets => SupportedBuildTargets;
private static readonly List<BuildTargetGroup> SupportedBuildTargets = new List<BuildTargetGroup>()
{
BuildTargetGroup.Android
};
}
private static IXRPackageMetadata Metadata = new PXR_PackageMetadata();
public IXRPackageMetadata metadata => Metadata;
public bool PopulateNewSettingsInstance(ScriptableObject obj)
{
var settings = obj as PXR_Settings;
if (settings != null)
{
settings.stereoRenderingModeAndroid = PXR_Settings.StereoRenderingModeAndroid.MultiPass;
return true;
}
return false;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ef29a1525ea68f479c41ed3c17dced9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
#if PICO_OPENXR_SDK
using Unity.XR.PXR;
using UnityEditor;
using UnityEngine;
namespace Unity.XR.OpenXR.Features.PICOSupport
{
[CustomEditor(typeof(PICOFeature))]
internal class PXR_OpenXRFeatureEditor : Editor
{
private PXR_OpenXRProjectSetting projectConfig;
void OnEnable()
{
projectConfig = PXR_OpenXRProjectSetting.GetProjectConfig();
}
public override void OnInspectorGUI()
{
// Update anything from the serializable object
EditorGUIUtility.labelWidth = 215.0f;
//eye tracking
GUIStyle firstLevelStyle = new GUIStyle(GUI.skin.label);
firstLevelStyle.alignment = TextAnchor.UpperLeft;
firstLevelStyle.fontStyle = FontStyle.Bold;
firstLevelStyle.fontSize = 12;
firstLevelStyle.wordWrap = true;
var guiContent = new GUIContent();
guiContent.text = "Eye Tracking";
guiContent.tooltip = "Before calling EyeTracking API, enable this option first, only for Neo3 Pro Eye , PICO 4 Pro device.";
projectConfig.isEyeTracking = EditorGUILayout.Toggle(guiContent, projectConfig.isEyeTracking);
if (projectConfig.isEyeTracking)
{
projectConfig.isEyeTrackingCalibration = EditorGUILayout.Toggle(new GUIContent("Eye Tracking Calibration"), projectConfig.isEyeTrackingCalibration);
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Note: Eye Tracking is supported only on Neo 3 Pro Eye , PICO 4 Pro", firstLevelStyle);
EditorGUILayout.EndVertical();
}
projectConfig.isHandTracking = EditorGUILayout.Toggle("Hand Tracking", projectConfig.isHandTracking);
if (projectConfig.isHandTracking)
{
//hand tracking Support
var handSupport = new GUIContent();
handSupport.text = "Hand Tracking Support";
projectConfig.handTrackingSupportType =(HandTrackingSupport)EditorGUILayout.EnumPopup(handSupport, projectConfig.handTrackingSupportType);
//high frequency tracking
var highfrequencytracking = new GUIContent();
highfrequencytracking.text = "High Frequency Tracking(60Hz)";
highfrequencytracking.tooltip = "If turned on, hand tracking will run at a higher tracking frequency, which will improve the smoothness of hand tracking, but the power consumption will increase.";
projectConfig.highFrequencyHand = EditorGUILayout.Toggle(highfrequencytracking, projectConfig.highFrequencyHand);
}
var displayFrequencyContent = new GUIContent();
displayFrequencyContent.text = "Display Refresh Rates";
projectConfig.displayFrequency = (SystemDisplayFrequency)EditorGUILayout.EnumPopup(displayFrequencyContent, projectConfig.displayFrequency);
// content protect
projectConfig.useContentProtect = EditorGUILayout.Toggle("Use Content Protect", projectConfig.useContentProtect);
if (projectConfig.useContentProtect)
{
projectConfig.contentProtectFlags = (SecureContentFlag)EditorGUILayout.EnumPopup("Content Protect", projectConfig.contentProtectFlags);
}
//FFR
var foveationEnableContent = new GUIContent();
foveationEnableContent.text = "Foveated Rendering";
projectConfig.foveationEnable = EditorGUILayout.Toggle(foveationEnableContent, projectConfig.foveationEnable);
if (projectConfig.foveationEnable)
{
var foveationContent = new GUIContent();
foveationContent.text = "Foveated Rendering Mode";
projectConfig.foveatedRenderingMode = (FoveationFeature.FoveatedRenderingMode)EditorGUILayout.EnumPopup(foveationContent, projectConfig.foveatedRenderingMode);
var foveationLevel = new GUIContent();
foveationLevel.text = "Foveated Rendering Level";
projectConfig.foveatedRenderingLevel = (FoveationFeature.FoveatedRenderingLevel)EditorGUILayout.EnumPopup(foveationLevel, projectConfig.foveatedRenderingLevel);
if (projectConfig.foveatedRenderingLevel !=FoveationFeature.FoveatedRenderingLevel.Off)
{
GUILayout.BeginHorizontal();
var subsampledEnabledContent = new GUIContent();
subsampledEnabledContent.text = "Subsampling";
projectConfig.isSubsampledEnabled = EditorGUILayout.Toggle(subsampledEnabledContent, projectConfig.isSubsampledEnabled);
GUILayout.EndHorizontal();
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("This function has been replaced by the official interface in versions above 1.9.1.", firstLevelStyle);
EditorGUILayout.EndVertical();
}
}
GUILayout.BeginHorizontal();
guiContent.text = "System Splash Screen";
EditorGUILayout.LabelField(guiContent, GUILayout.Width(185));
projectConfig.systemSplashScreen = (Texture2D)EditorGUILayout.ObjectField(projectConfig.systemSplashScreen, typeof(Texture2D), true);
GUILayout.EndHorizontal();
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Note: Set the system splash screen picture in PNG format.", firstLevelStyle);
EditorGUILayout.EndVertical();
var MRSafeguard = new GUIContent();
MRSafeguard.text = "MR Safeguard";
MRSafeguard.tooltip = "MR safety, if you choose this option, your application will adopt MR safety policies during runtime. If not selected, it will continue to use VR safety policies by default.";
projectConfig.MRSafeguard = EditorGUILayout.Toggle(MRSafeguard, projectConfig.MRSafeguard);
serializedObject.Update();
if (GUI.changed)
{
EditorUtility.SetDirty(projectConfig);
}
serializedObject.ApplyModifiedProperties();
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e67ae0563df474ab807e604306a144b
timeCreated: 1738740836

View File

@@ -0,0 +1,60 @@
#if PICO_OPENXR_SDK
using UnityEditor;
using UnityEditor.XR.OpenXR.Features;
using UnityEngine.XR.OpenXR.Features.Interactions;
namespace Unity.XR.OpenXR.Features.PICOSupport
{
[OpenXRFeatureSet(
FeatureIds = new string[] {
LayerSecureContentFeature.featureId,
DisplayRefreshRateFeature.featureId,
PassthroughFeature.featureId,
FoveationFeature.featureId,
BodyTrackingFeature.featureId,
PICOSceneCapture.featureId,
PICOSpatialMesh.featureId,
PICOSpatialAnchor.featureId,
PICOFeature.featureId,
OpenXRExtensions.featureId,
PICO4ControllerProfile.featureId,
PICO4UltraControllerProfile.featureId,
PICONeo3ControllerProfile.featureId,
PICOG3ControllerProfile.featureId,
},
DefaultFeatureIds = new string[] {
LayerSecureContentFeature.featureId,
DisplayRefreshRateFeature.featureId,
PassthroughFeature.featureId,
FoveationFeature.featureId,
BodyTrackingFeature.featureId,
PICOSceneCapture.featureId,
PICOSpatialMesh.featureId,
PICOSpatialAnchor.featureId,
PICOFeature.featureId,
OpenXRExtensions.featureId,
PICO4ControllerProfile.featureId,
PICO4UltraControllerProfile.featureId,
PICONeo3ControllerProfile.featureId,
PICOG3ControllerProfile.featureId,
},
UiName = "PICO XR",
Description = "Feature set for using PICO XR Features",
FeatureSetId = featureSetId,
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.Android},
RequiredFeatureIds = new string[]
{
PICOFeature.featureId,
OpenXRExtensions.featureId,
PICO4ControllerProfile.featureId,
PICO4UltraControllerProfile.featureId,
PICONeo3ControllerProfile.featureId,
PICOG3ControllerProfile.featureId,
}
)]
public class PXR_OpenXRFeatureSet
{
public const string featureSetId = "com.picoxr.openxr.features";
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 091580be507bbc846bf44f8b65d67293
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,475 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using UnityEditor;
using UnityEngine;
namespace Unity.XR.PXR.Editor
{
[Obsolete("PXR_OverLayEditor is obsolete and will be removed in the next version. Please use PXR_CompositionLayerEditor instead.", false)]
[CanEditMultipleObjects]
[CustomEditor(typeof(PXR_OverLay))]
public class PXR_OverLayEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
var guiContent = new GUIContent();
foreach (PXR_OverLay overlayTarget in targets)
{
EditorGUILayout.LabelField("Overlay Settings", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Type";
overlayTarget.overlayType = (PXR_OverLay.OverlayType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.overlayType);
guiContent.text = "Shape";
overlayTarget.overlayShape = (PXR_OverLay.OverlayShape)EditorGUILayout.EnumPopup(guiContent, overlayTarget.overlayShape);
guiContent.text = "Depth";
overlayTarget.layerDepth = EditorGUILayout.IntField(guiContent, overlayTarget.layerDepth);
EditorGUILayout.EndVertical();
guiContent.text = "Clones";
overlayTarget.isClones = EditorGUILayout.Toggle(guiContent, overlayTarget.isClones);
if (overlayTarget.isClones)
{
overlayTarget.originalOverLay = EditorGUILayout.ObjectField("Original OverLay", overlayTarget.originalOverLay, typeof(PXR_OverLay), true) as PXR_OverLay;
GUIStyle firstLevelStyle = new GUIStyle(GUI.skin.label);
firstLevelStyle.alignment = TextAnchor.UpperLeft;
firstLevelStyle.fontStyle = FontStyle.Bold;
firstLevelStyle.fontSize = 12;
firstLevelStyle.wordWrap = true;
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("Note:", firstLevelStyle);
EditorGUILayout.LabelField("Original OverLay cannot be empty or itself!");
EditorGUILayout.EndVertical();
}
else
{
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Overlay Textures", EditorStyles.boldLabel);
guiContent.text = "Texture Type";
overlayTarget.textureType = (PXR_OverLay.TextureType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.textureType);
EditorGUILayout.Separator();
if (overlayTarget.overlayShape == PXR_OverLay.OverlayShape.BlurredQuad)
{
overlayTarget.textureType = PXR_OverLay.TextureType.ExternalSurface;
}
if (overlayTarget.textureType == PXR_OverLay.TextureType.ExternalSurface)
{
overlayTarget.isExternalAndroidSurface = true;
overlayTarget.isDynamic = false;
}
else if (overlayTarget.textureType == PXR_OverLay.TextureType.DynamicTexture)
{
overlayTarget.isExternalAndroidSurface = false;
overlayTarget.isDynamic = true;
}
else
{
overlayTarget.isExternalAndroidSurface = false;
overlayTarget.isDynamic = false;
}
if (overlayTarget.isExternalAndroidSurface)
{
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "DRM";
overlayTarget.isExternalAndroidSurfaceDRM = EditorGUILayout.Toggle(guiContent, overlayTarget.isExternalAndroidSurfaceDRM);
guiContent.text = "3D Surface Type";
guiContent.tooltip = "The functions of '3D Surface Type' and 'Source Rects' are similar, and only one of them can be used. ";
overlayTarget.externalAndroidSurface3DType = (PXR_OverLay.Surface3DType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.externalAndroidSurface3DType);
EditorGUILayout.EndVertical();
if (overlayTarget.overlayShape == PXR_OverLay.OverlayShape.BlurredQuad)
{
EditorGUILayout.LabelField("Blurred Quad");
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Mode";
overlayTarget.blurredQuadMode = (PXR_OverLay.BlurredQuadMode)EditorGUILayout.EnumPopup(guiContent, overlayTarget.blurredQuadMode);
guiContent.text = "Scale";
overlayTarget.blurredQuadScale = EditorGUILayout.FloatField(guiContent, Mathf.Abs(overlayTarget.blurredQuadScale));
guiContent.text = "Shift";
overlayTarget.blurredQuadShift = EditorGUILayout.Slider(guiContent, overlayTarget.blurredQuadShift, -1, 1);
guiContent.text = "FOV";
overlayTarget.blurredQuadFOV = EditorGUILayout.Slider(guiContent, overlayTarget.blurredQuadFOV, 0, 180f);
guiContent.text = "IPD";
overlayTarget.blurredQuadIPD = EditorGUILayout.Slider(guiContent, overlayTarget.blurredQuadIPD, 0.01f, 1.0f);
EditorGUILayout.EndVertical();
}
guiContent.tooltip = "";
}
else
{
EditorGUILayout.LabelField("Texture");
EditorGUILayout.BeginVertical("frameBox");
var labelControlRect = EditorGUILayout.GetControlRect();
EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left", "Texture used for the left eye"));
EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right", "Texture used for the right eye"));
var textureControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(64));
overlayTarget.layerTextures[0] = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x, textureControlRect.y, 64, textureControlRect.height), overlayTarget.layerTextures[0], typeof(Texture), false);
overlayTarget.layerTextures[1] = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x + textureControlRect.width / 2, textureControlRect.y, 64, textureControlRect.height), overlayTarget.layerTextures[1] != null ? overlayTarget.layerTextures[1] : overlayTarget.layerTextures[0], typeof(Texture), false);
EditorGUILayout.EndVertical();
}
EditorGUILayout.Separator();
if (overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Equirect ||
overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Fisheye)
{
guiContent.text = "Radius";
overlayTarget.radius = EditorGUILayout.FloatField(guiContent, Mathf.Abs(overlayTarget.radius));
}
}
if (overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Quad ||
overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Cylinder ||
overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Equirect ||
overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Eac ||
overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Fisheye)
{
guiContent.text = "Texture Rects";
overlayTarget.useImageRect = EditorGUILayout.Toggle(guiContent, overlayTarget.useImageRect);
if (overlayTarget.useImageRect)
{
EditorGUI.indentLevel++;
if (PXR_OverLay.Surface3DType.Single != overlayTarget.externalAndroidSurface3DType)
{
GUI.enabled = false;
}
guiContent.text = "Source Rects";
guiContent.tooltip = "The functions of '3D Surface Type' and 'Source Rects' are similar, and only one of them can be used. ";
overlayTarget.textureRect = (PXR_OverLay.TextureRect)EditorGUILayout.EnumPopup(guiContent, overlayTarget.textureRect);
if (PXR_OverLay.Surface3DType.Single == overlayTarget.externalAndroidSurface3DType)
{
if (overlayTarget.textureRect == PXR_OverLay.TextureRect.Custom)
{
EditorGUILayout.BeginVertical("frameBox");
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Left Rect");
EditorGUILayout.LabelField("Right Rect");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
overlayTarget.srcRectLeft = ClampRect(EditorGUILayout.RectField(overlayTarget.srcRectLeft));
EditorGUILayout.Space(15);
guiContent.text = "Right";
overlayTarget.srcRectRight = ClampRect(EditorGUILayout.RectField(overlayTarget.srcRectRight));
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
else if (overlayTarget.textureRect == PXR_OverLay.TextureRect.MonoScopic)
{
overlayTarget.srcRectLeft = new Rect(0, 0, 1, 1);
overlayTarget.srcRectRight = new Rect(0, 0, 1, 1);
}
else if (overlayTarget.textureRect == PXR_OverLay.TextureRect.StereoScopic)
{
overlayTarget.srcRectLeft = new Rect(0, 0, 0.5f, 1);
overlayTarget.srcRectRight = new Rect(0.5f, 0, 0.5f, 1);
}
}
else
{
overlayTarget.textureRect = PXR_OverLay.TextureRect.MonoScopic;
overlayTarget.srcRectLeft = new Rect(0, 0, 1, 1);
overlayTarget.srcRectRight = new Rect(0, 0, 1, 1);
}
guiContent.tooltip = "";
GUI.enabled = true;
if (overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Quad ||
overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Equirect ||
overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Fisheye)
{
guiContent.text = "Destination Rects";
overlayTarget.destinationRect = (PXR_OverLay.DestinationRect)EditorGUILayout.EnumPopup(guiContent, overlayTarget.destinationRect);
if (overlayTarget.destinationRect == PXR_OverLay.DestinationRect.Custom)
{
EditorGUILayout.BeginVertical("frameBox");
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Left Rect");
EditorGUILayout.LabelField("Right Rect");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
overlayTarget.dstRectLeft = ClampRect(EditorGUILayout.RectField(overlayTarget.dstRectLeft));
EditorGUILayout.Space(15);
guiContent.text = "Right";
overlayTarget.dstRectRight = ClampRect(EditorGUILayout.RectField(overlayTarget.dstRectRight));
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
else
{
GUI.enabled = false;
overlayTarget.dstRectLeft = new Rect(0, 0, 1, 1);
overlayTarget.dstRectRight = new Rect(0, 0, 1, 1);
GUI.enabled = true;
}
}
EditorGUI.indentLevel--;
}
}
guiContent.text = "Layer Blend";
overlayTarget.useLayerBlend = EditorGUILayout.Toggle(guiContent, overlayTarget.useLayerBlend);
if (overlayTarget.useLayerBlend)
{
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Src Color";
overlayTarget.srcColor = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.srcColor);
guiContent.text = "Dst Color";
overlayTarget.dstColor = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.dstColor);
guiContent.text = "Src Alpha";
overlayTarget.srcAlpha = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.srcAlpha);
guiContent.text = "Dst Alpha";
overlayTarget.dstAlpha = (PxrBlendFactor)EditorGUILayout.EnumPopup(guiContent, overlayTarget.dstAlpha);
EditorGUILayout.EndVertical();
}
EditorGUILayout.Separator();
if (overlayTarget.overlayShape == PXR_OverLay.OverlayShape.Eac)
{
guiContent.text = "Model Type";
overlayTarget.eacModelType = (PXR_OverLay.EACModelType)EditorGUILayout.EnumPopup(guiContent, overlayTarget.eacModelType);
if (PXR_OverLay.EACModelType.Eac360ViewPort == overlayTarget.eacModelType ||
PXR_OverLay.EACModelType.Eac180ViewPort == overlayTarget.eacModelType)
{
guiContent.text = "Offset Pos Left";
Vector3 offsetPosLeft = EditorGUILayout.Vector3Field(guiContent, overlayTarget.offsetPosLeft);
guiContent.text = "Offset Pos Right";
Vector3 offsetPosRight = EditorGUILayout.Vector3Field(guiContent, overlayTarget.offsetPosRight);
guiContent.text = "Offset Rot Left";
Vector4 offsetRotLeft = EditorGUILayout.Vector4Field(guiContent, overlayTarget.offsetRotLeft);
guiContent.text = "Offset Rot Right";
Vector4 offsetRotRight = EditorGUILayout.Vector4Field(guiContent, overlayTarget.offsetRotRight);
overlayTarget.SetEACOffsetPosAndRot(offsetPosLeft, offsetPosRight, offsetRotLeft, offsetRotRight);
}
guiContent.text = "Overlap Factor";
overlayTarget.overlapFactor = EditorGUILayout.FloatField(guiContent, overlayTarget.overlapFactor);
//overlayTarget.SetEACFactor(overlapFactor);
}
guiContent.text = "Override Color Scale";
overlayTarget.overrideColorScaleAndOffset = EditorGUILayout.Toggle(guiContent, overlayTarget.overrideColorScaleAndOffset);
if (overlayTarget.overrideColorScaleAndOffset)
{
EditorGUILayout.BeginVertical("frameBox");
guiContent.text = "Scale";
Vector4 colorScale = EditorGUILayout.Vector4Field(guiContent, overlayTarget.colorScale);
guiContent.text = "Offset";
Vector4 colorOffset = EditorGUILayout.Vector4Field(guiContent, overlayTarget.colorOffset);
overlayTarget.SetLayerColorScaleAndOffset(colorScale, colorOffset);
EditorGUILayout.EndVertical();
}
guiContent.text = "isAlphaPremultiplied";
overlayTarget.isPremultipliedAlpha = EditorGUILayout.Toggle(guiContent, overlayTarget.isPremultipliedAlpha);
//Super Resolution
var superresolutionContent = new GUIContent();
superresolutionContent.text = "Super Resolution";
superresolutionContent.tooltip = "Single pass spatial aware upscaling technique.\n\nThis can't be used with Sharpening. \nAlso can't be used along with subsample feature due to unsupported texture format. \n\nThis effect won't work properly under low resolutions when Adaptive Resolution is also enabled.";
overlayTarget.superResolution = EditorGUILayout.Toggle(superresolutionContent, overlayTarget.superResolution);
//Supersampling
var supersamplingContent = new GUIContent();
supersamplingContent.text = "Supersampling Mode";
supersamplingContent.tooltip = "Normal: Normal Quality \n\nQuality: Higher Quality, higher GPU usage\n\nThis effect won't work properly under low resolutions when Adaptive Resolution or Sharpening is also enabled.\n\nThis can't be used with Super Resolution or Sharpening. It will be automatically disabled when you enable Super Resolution or Sharpening. \nAlso can't be used along with subsample feature due to unsupported texture format";
var supersamplingEnhanceContent = new GUIContent();
supersamplingEnhanceContent.text = "Supersampling Enhance Mode";
supersamplingEnhanceContent.tooltip = "None: Full screen will be super sampled\n\nFixed Foveated: Only the central fixation point will be sharpened\n\nSelf Adaptive: Only when contrast between the current pixel and the surrounding pixels exceeds a certain threshold will be sharpened.\n\nThis menu will be only enabled while Sharpening (either Normal or Quality) is enabled.";
if (overlayTarget.superResolution)
{
GUI.enabled = false;
overlayTarget.supersamplingMode = SuperSamplingMode.None;
overlayTarget.supersamplingEnhance = SuperSamplingEnhance.None;
}
else
{
GUI.enabled = true;
}
overlayTarget.supersamplingMode = (SuperSamplingMode)EditorGUILayout.EnumPopup(supersamplingContent, overlayTarget.supersamplingMode);
if (overlayTarget.supersamplingMode == SuperSamplingMode.None)
{
overlayTarget.supersamplingEnhance = SuperSamplingEnhance.None;
}
else
{
EditorGUI.indentLevel++;
overlayTarget.supersamplingEnhance = (SuperSamplingEnhance)EditorGUILayout.EnumPopup(supersamplingEnhanceContent, overlayTarget.supersamplingEnhance);
EditorGUI.indentLevel--;
}
if (overlayTarget.supersamplingMode != SuperSamplingMode.None)
{
if (overlayTarget.supersamplingMode == SuperSamplingMode.Normal)
{
overlayTarget.normalSupersampling = true;
overlayTarget.qualitySupersampling = false;
}
else
{
overlayTarget.normalSupersampling = false;
overlayTarget.qualitySupersampling = true;
}
if (overlayTarget.supersamplingEnhance == SuperSamplingEnhance.FixedFoveated)
{
overlayTarget.fixedFoveatedSupersampling = true;
}
else
{
overlayTarget.fixedFoveatedSupersampling = false;
}
}
else
{
overlayTarget.normalSupersampling = false;
overlayTarget.qualitySupersampling = false;
overlayTarget.fixedFoveatedSupersampling = false;
}
//Sharpening
var sharpeningContent = new GUIContent();
sharpeningContent.text = "Sharpening Mode";
sharpeningContent.tooltip = "Normal: Normal Quality \n\nQuality: Higher Quality, higher GPU usage\n\nThis effect won't work properly under low resolutions when Adaptive Resolution is also enabled.\n\nThis can't be used with Super Resolution and Supersampling. It will be automatically disabled when you enable Super Resolution or Supersampling. \nAlso can't be used along with subsample feature due to unsupported texture format";
var sharpeningEnhanceContent = new GUIContent();
sharpeningEnhanceContent.text = "Sharpening Enhance Mode";
sharpeningEnhanceContent.tooltip = "None: Full screen will be sharpened\n\nFixed Foveated: Only the central fixation point will be sharpened\n\nSelf Adaptive: Only when contrast between the current pixel and the surrounding pixels exceeds a certain threshold will be sharpened.\n\nThis menu will be only enabled while Sharpening (either Normal or Quality) is enabled.";
if (overlayTarget.superResolution || overlayTarget.normalSupersampling || overlayTarget.qualitySupersampling || overlayTarget.fixedFoveatedSupersampling)
{
GUI.enabled = false;
overlayTarget.sharpeningMode = SharpeningMode.None;
overlayTarget.sharpeningEnhance = SharpeningEnhance.None;
}
else
{
GUI.enabled = true;
}
overlayTarget.sharpeningMode = (SharpeningMode)EditorGUILayout.EnumPopup(sharpeningContent, overlayTarget.sharpeningMode);
if (overlayTarget.sharpeningMode == SharpeningMode.None)
{
overlayTarget.sharpeningEnhance = SharpeningEnhance.None;
}
else
{
EditorGUI.indentLevel++;
overlayTarget.sharpeningEnhance = (SharpeningEnhance)EditorGUILayout.EnumPopup(sharpeningEnhanceContent, overlayTarget.sharpeningEnhance);
EditorGUI.indentLevel--;
}
if (overlayTarget.sharpeningMode != SharpeningMode.None)
{
if (overlayTarget.sharpeningMode == SharpeningMode.Normal)
{
overlayTarget.normalSharpening = true;
overlayTarget.qualitySharpening = false;
}
else
{
overlayTarget.normalSharpening = false;
overlayTarget.qualitySharpening = true;
}
if (overlayTarget.sharpeningEnhance == SharpeningEnhance.Both)
{
overlayTarget.fixedFoveatedSharpening = true;
overlayTarget.selfAdaptiveSharpening = true;
}
else if (overlayTarget.sharpeningEnhance == SharpeningEnhance.FixedFoveated)
{
overlayTarget.fixedFoveatedSharpening = true;
overlayTarget.selfAdaptiveSharpening = false;
}
else if (overlayTarget.sharpeningEnhance == SharpeningEnhance.SelfAdaptive)
{
overlayTarget.fixedFoveatedSharpening = false;
overlayTarget.selfAdaptiveSharpening = true;
}
else
{
overlayTarget.fixedFoveatedSharpening = false;
overlayTarget.selfAdaptiveSharpening = false;
}
}
else
{
overlayTarget.normalSharpening = false;
overlayTarget.qualitySharpening = false;
overlayTarget.fixedFoveatedSharpening = false;
overlayTarget.selfAdaptiveSharpening = false;
}
if (GUI.changed)
{
EditorUtility.SetDirty(overlayTarget);
EditorUtility.SetDirty(overlayTarget);
}
serializedObject.ApplyModifiedProperties();
}
if (GUI.changed)
{
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
}
}
private Rect ClampRect(Rect rect)
{
rect.x = Mathf.Clamp01(rect.x);
rect.y = Mathf.Clamp01(rect.y);
rect.width = Mathf.Clamp01(rect.width);
rect.height = Mathf.Clamp01(rect.height);
return rect;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f8f0bf8ebd71f76449ace919f41e1a38
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,71 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace Unity.XR.PXR.Editor
{
[InitializeOnLoad]
public static class PXR_SDKBuildCheck
{
private static bool doNotShowAgain = false;
static PXR_SDKBuildCheck()
{
ObjectFactory.componentWasAdded += ComponentWasAdded;
BuildPlayerWindow.RegisterBuildPlayerHandler(OnBuild);
doNotShowAgain = GetDoNotShowBuildWarning();
Debug.Log("PXRLog [Build Check]RegisterBuildPlayerHandler,Already Do not show: " + doNotShowAgain);
}
static void ComponentWasAdded(Component com)
{
if (com.name == "XR Rig")
{
if (!com.GetComponent<PXR_Manager>() && com.GetType() != typeof(Transform))
{
com.gameObject.AddComponent<PXR_Manager>();
}
}
}
static bool GetDoNotShowBuildWarning()
{
string path = PXR_SDKSettingEditor.assetPath + typeof(PXR_SDKSettingAsset).ToString() + ".asset";
if (File.Exists(path))
{
PXR_SDKSettingAsset asset = AssetDatabase.LoadAssetAtPath<PXR_SDKSettingAsset>(path);
if (asset != null)
{
return asset.doNotShowBuildWarning;
}
}
return false;
}
public static void OnBuild(BuildPlayerOptions options)
{
#if UNITY_2021_2_OR_NEWER
NamedBuildTarget recommendedBuildTarget = NamedBuildTarget.Android;
#else
BuildTargetGroup recommendedBuildTarget = BuildTargetGroup.Android;
#endif
PlayerSettings.SetScriptingBackend(recommendedBuildTarget, ScriptingImplementation.IL2CPP);
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
BuildPlayerWindow.DefaultBuildMethods.BuildPlayer(options);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cf7c5670489d91e439f9b568da17cfc3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using UnityEngine;
public class PXR_SDKSettingAsset : ScriptableObject
{
public bool ignoreSDKSetting = false;
public bool doNotShowBuildWarning = false;
public bool appIDChecked = false;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8e08befb1867d8945b4f1ddac43e65c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,896 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.IO;
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System;
using UnityEditor.XR.Management;
using UnityEngine.XR.Management;
using UnityEditor.XR.Management.Metadata;
using UnityEditor.Build;
namespace Unity.XR.PXR.Editor
{
[InitializeOnLoad]
public class PXR_SDKSettingEditor : EditorWindow
{
public static string assetPath = "Assets/Resources/";
private const string titleName = "PICO Integration SDK";
private const string windowName = titleName + "Window";
private static PXR_SDKSettingEditor instance;
private static PXR_EditorStyles _styles;
public event Action<Response> WhenResponded = delegate { };
private const string PICO_ICON_NAME = "PICO developer.png";
private Vector2 scrollPosition = Vector2.zero;
private const BuildTarget recommendedBuildTarget = BuildTarget.Android;
public enum Response
{
Configs,
Tools,
Samples,
About,
}
private Dictionary<Response, bool> buttonClickedStates = new Dictionary<Response, bool>()
{
{ Response.Configs, false },
{ Response.Tools, false },
{ Response.Samples, false },
{ Response.About, false }
};
Action openProjectValidationAction = () =>
{
SettingsService.OpenProjectSettings("Project/XR Plug-in Management/Project Validation");
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_ProjectValidation_Open);
};
Action applyARM64Action = () => {
PlayerSettings.SetScriptingBackend(NamedBuildTarget.Android, ScriptingImplementation.IL2CPP);
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
};
Action applyMinAndroidAPIAction = () =>
{
PlayerSettings.Android.minSdkVersion = PXR_Utils.minSdkVersionInEditor;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Configs_RequiredAndroidSdkVersionsApplied);
};
Action applyPICOXRPluginAction = () =>
{
SettingsService.OpenProjectSettings("Project/XR Plug-in Management");
var buildTargetSettings = AssetDatabase.FindAssets("t:XRGeneralSettingsPerBuildTarget")
.Select(guid => AssetDatabase.LoadAssetAtPath<XRGeneralSettingsPerBuildTarget>(AssetDatabase.GUIDToAssetPath(guid)))
.FirstOrDefault();
if (buildTargetSettings == null)
{
buildTargetSettings = ScriptableObject.CreateInstance<XRGeneralSettingsPerBuildTarget>();
AssetDatabase.CreateAsset(buildTargetSettings, "Assets/XRGeneralSettingsPerBuildTarget.asset");
Debug.Log($"PXR_Loader XRGeneralSettingsPerBuildTarget");
}
var generalSettings = buildTargetSettings.SettingsForBuildTarget(BuildTargetGroup.Android);
if (generalSettings == null)
{
generalSettings = ScriptableObject.CreateInstance<XRGeneralSettings>();
AssetDatabase.AddObjectToAsset(generalSettings, buildTargetSettings);
buildTargetSettings.SetSettingsForBuildTarget(BuildTargetGroup.Android, generalSettings);
var managerSettings = ScriptableObject.CreateInstance<XRManagerSettings>();
AssetDatabase.AddObjectToAsset(managerSettings, buildTargetSettings);
generalSettings.Manager = managerSettings;
EditorUtility.SetDirty(buildTargetSettings);
AssetDatabase.SaveAssets();
}
if (generalSettings.Manager)
{
while (generalSettings.Manager.activeLoaders.Count > 0)
{
var loaderName = generalSettings.Manager.activeLoaders[0].GetType().FullName;
XRPackageMetadataStore.RemoveLoader(generalSettings.Manager, loaderName, BuildTargetGroup.Android);
}
bool success = XRPackageMetadataStore.AssignLoader(generalSettings.Manager, "PXR_Loader", BuildTargetGroup.Android);
}
PXR_Utils.UpdateSDKSymbols();
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Configs_RequiredPICOXRPluginApplied);
};
Action applyBuildTargetAction = () =>
{
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, recommendedBuildTarget);
EditorUserBuildSettings.selectedBuildTargetGroup = BuildTargetGroup.Android;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Configs_RequiredBuildTargetAndroidApplied);
};
[MenuItem("PICO/Portal", false, 0)]
public static void ShowWindow()
{
if (instance == null)
{
instance = GetWindow<PXR_SDKSettingEditor>();
instance.Show();
}
else
{
instance.Focus();
}
string version = "_UnityXR_" + PXR_Plugin.System.UPxr_GetSDKVersion() + "_" + Application.unityVersion;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Enter + version);
}
[InitializeOnLoadMethod]
private static void InitializeOnLoad()
{
if (!PXR_ProjectSetting.GetProjectConfig().portalInited)
{
EditorApplication.delayCall += () =>
{
EditorApplication.update += UpdateOnce;
};
}
}
static void UpdateOnce()
{
EditorApplication.update -= UpdateOnce;
ShowWindow();
PXR_ProjectSetting.GetProjectConfig().portalInited = true;
PXR_ProjectSetting.SaveAssets();
}
private void Awake()
{
_styles ??= new PXR_EditorStyles();
titleContent = new GUIContent(titleName);
minSize = new Vector2(1080, 640);
maxSize = minSize + new Vector2(2, 2);
EditorApplication.delayCall += () => maxSize = new Vector2(4000, 4000);
buttonClickedStates[Response.Configs] = true;
}
private void OnEnable()
{
_styles ??= new PXR_EditorStyles();
buttonClickedStates[(Response)PXR_ProjectSetting.GetProjectConfig().portalFirstSelected] = true;
}
private void OnDestroy()
{
instance = null;
}
private void OnGUI()
{
if (EditorApplication.isPlayingOrWillChangePlaymode)
{
CloseWindow();
}
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.Space(20);
DrawTitle(titleName);
EditorGUILayout.Space(10);
EditorGUILayout.Separator();
DrawHorizontalLine(_styles.colorLine, 2);
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Space(30);
DrawLeftButton();
GUILayout.Space(30);
DrawVerticalLine(_styles.colorLine, 2);
GUILayout.Space(30);
Rect windowRect = position;
float xOffset = 30 + 200 + 30;
float width = windowRect.width - xOffset;
float topSpaceUsed = 30 + _styles.HeaderText.fixedHeight + 30;
float height = windowRect.height - topSpaceUsed - 30 - 2;
_styles.BackgroundColor.fixedWidth = width;
_styles.BackgroundColor.fixedHeight = height;
using (new GUILayout.VerticalScope(_styles.BackgroundColor))
{
if (buttonClickedStates[Response.Configs])
{
scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true);
GUILayout.Space(30);
using (new EditorGUILayout.VerticalScope())
{
string title = "Information";
GUILayout.Label(title, _styles.BigWhiteTitleStyle, GUILayout.ExpandWidth(true));
string bodyContent = "Supported Unity Version: Unity 2020.3.21 and above.";
EditorGUILayout.LabelField(bodyContent, _styles.ContentText);
GUILayout.Space(30);
title = "Configuration";
GUILayout.Label(title, _styles.BigWhiteTitleStyle, GUILayout.ExpandWidth(true));
string strinfo = $"Required: Build Target = {recommendedBuildTarget}";
bool appliedBuildTarget = EditorUserBuildSettings.activeBuildTarget == recommendedBuildTarget;
EditorConfigurations(strinfo, appliedBuildTarget, applyBuildTargetAction);
strinfo = $"Required: AndroidSdkVersions = {PXR_Utils.minSdkVersionInEditor}";
bool appliedAdroidSdkVersions = PlayerSettings.Android.minSdkVersion == PXR_Utils.minSdkVersionInEditor;
EditorConfigurations(strinfo, appliedAdroidSdkVersions, applyMinAndroidAPIAction);
strinfo = $"Required: ARM64 and IL2CPP scripting must be enabled";
bool appliedARM64 = PlayerSettings.Android.targetArchitectures == AndroidArchitecture.ARM64 &&
PlayerSettings.GetScriptingBackend(BuildTargetGroup.Android) == ScriptingImplementation.IL2CPP;
EditorConfigurations(strinfo, appliedARM64, applyARM64Action);
strinfo = "Required: PICO XR plugin must be enabled";
EditorConfigurations(strinfo, PXR_Utils.IsPXRPluginEnabled(), applyPICOXRPluginAction);
bool applied = appliedBuildTarget && appliedAdroidSdkVersions && appliedARM64 && PXR_Utils.IsPXRPluginEnabled();
if (!applied)
{
EditorGUILayout.BeginHorizontal();
{
bodyContent = "For one-click configuration, you can click 'Apply' one by one or use 'Apply All'.";
EditorGUILayout.LabelField(bodyContent, _styles.ContentText, GUILayout.Width(673), GUILayout.ExpandHeight(true));
if (GUILayout.Button("Apply All", GUILayout.ExpandWidth(false), GUILayout.Width(80), GUILayout.Height(30)))
{
applyBuildTargetAction.Invoke();
applyMinAndroidAPIAction.Invoke();
applyARM64Action.Invoke();
applyPICOXRPluginAction.Invoke();
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Configs_ToApplyAllApplied);
}
var buttonRectToApplyAll = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectToApplyAll, MouseCursor.Link);
}
GUILayout.FlexibleSpace();
}
EditorGUILayout.EndHorizontal();
}
GUILayout.Space(20);
using (new EditorGUILayout.HorizontalScope())
{
bodyContent = "For more configuration items, open Project Validation.";
EditorGUILayout.LabelField(bodyContent, _styles.ContentText, GUILayout.Width(673), GUILayout.ExpandHeight(true));
if (GUILayout.Button("Open", GUILayout.Width(80), GUILayout.Height(30)))
{
SettingsService.OpenProjectSettings("Project/XR Plug-in Management/Project Validation");
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Configs_ProjectValidation);
}
var buttonRectProjectValidation = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectProjectValidation, MouseCursor.Link);
}
GUILayout.FlexibleSpace();
}
GUILayout.Space(30);
title = "PICO XR Project Setting";
GUILayout.Label(title, _styles.BigWhiteTitleStyle, GUILayout.ExpandWidth(true));
GUILayout.Space(10);
using (new EditorGUILayout.HorizontalScope())
{
bodyContent = $"SDK Settings for turning on and off features. You can locate it at this filepath: {assetPath}PXR_ProjectSetting.asset.";
EditorGUILayout.LabelField(bodyContent, _styles.ContentText, GUILayout.Width(673), GUILayout.ExpandHeight(true));
if (GUILayout.Button("Open", GUILayout.ExpandWidth(false), GUILayout.Width(80), GUILayout.Height(30)))
{
PXR_ProjectSetting asset;
string path = assetPath + "PXR_ProjectSetting.asset";
if (!File.Exists(path))
{
asset = new PXR_ProjectSetting();
ScriptableObjectUtility.CreateAsset<PXR_ProjectSetting>(asset, assetPath);
}
asset = AssetDatabase.LoadAssetAtPath<PXR_ProjectSetting>(path);
if (asset != null)
{
AssetDatabase.OpenAsset(asset);
}
else
{
Debug.LogError("Asset not found at path: " + assetPath);
}
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Configs_OpenPICOXRProjectSetting);
}
var buttonRectProjectSetting = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectProjectSetting, MouseCursor.Link);
}
GUILayout.FlexibleSpace();
}
}
GUILayout.EndScrollView();
}
else if (buttonClickedStates[Response.Tools])
{
scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true);
GUILayout.Space(30);
using (new EditorGUILayout.VerticalScope())
{
string title = "Unity Editor Tools and Developer Tools";
GUILayout.Label(title, _styles.BigWhiteTitleStyle, GUILayout.ExpandWidth(true));
title = "Project Validation";
string links = "https://developer.picoxr.com/document/unity/project-validation/";
GUIContent bodyContent = new GUIContent("Project Validation can display the validation rules requiredby the installed XR package. For any validation rules that are not properly set up, you can use thhis feature to automatically fix them with a single click.");
DrawTwoRowLayout(title, bodyContent, links, openProjectValidationAction);
title = "PICO Building Blocks";
links = "https://developer.picoxr.com/document/unity/pico-building-blocks/";
bodyContent = new GUIContent("The PICO Building Block system allows you to set up features, including those in the SDK and Unity Engine, with a single click.");
DrawTwoRowLayout(title, bodyContent, links);
title = "PICO XR Toolkit-MR";
links = "https://developer.picoxr.com/document/unity/sense-pack-overview/";
bodyContent = new GUIContent("The PICO XR Toolkit-MR part is a set of tools included in the SensePack on top of the Mixed Reality API. It is used to perform common operations when building spatial perception applications.");
DrawTwoRowLayout(title, bodyContent, links);
title = "XR Profiling Toolkit";
links = "https://github.com/Pico-Developer/XR-Profiling-Toolkit";
bodyContent = new GUIContent("An automated and customizable graphics profiling tool for evaluating the performance of XR applications on cross-vendor headsets.");
DrawTwoRowLayout(title, bodyContent, links);
title = "PICO Developer Center";
links = "https://developer.picoxr.com/resources/#pdc";
bodyContent = new GUIContent("PICO Developer Center (referred to as PDC tools below) is a developer service platform that integrates essential tools like the ADB command debugging tool and real-time preview tool. You can efficiently manage, develop, and debug your apps using the PDC tool.");
DrawTwoRowLayout(title, bodyContent, links);
title = "Emulator";
links = "https://developer.picoxr.com/resources/#emulator";
bodyContent = new GUIContent("You can install your app on PICO Emulator and run it, so as to preview how your app performs.");
DrawTwoRowLayout(title, bodyContent, links);
title = "More Developer Tools";
links = "https://developer.picoxr.com/document/unity/developer-tools-overview/";
bodyContent = new GUIContent("PICO provides a range of developer tools covering app debugging, performance monitoring, haptic editing, and more.See the Developer Tools Documentationpage to learn more details.");
DrawTwoRowLayout(title, bodyContent, links);
}
GUILayout.EndScrollView();
}
else if (buttonClickedStates[Response.Samples])
{
scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, true);
GUILayout.Space(30);
using (new EditorGUILayout.VerticalScope())
{
string title = "PICO Unity Integration SDK Samples";
GUILayout.Label(title, _styles.BigWhiteTitleStyle, GUILayout.ExpandWidth(true));
GUILayout.Space(30);
string bodyContent = "Besides the Samples you can import through the Unity Paackage Manager interface, PICO provides comprehensive sample projects that coverthe core features of the Unity Integration SDK on GitHub.";
EditorGUILayout.LabelField(bodyContent, _styles.ContentText);
title = "Mixed Reality Sample";
string gitHubLink = "https://github.com/Pico-Developer/MRSample-Unity";
string documentationLink = "https://developer.picoxr.com/document/unity/mixed-reality-sample/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "Interaction Sample";
gitHubLink = "https://github.com/Pico-Developer/InteractionSample-Unity";
documentationLink = "https://developer.picoxr.com/document/unity/y3lpmdhw/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "Motion Tracker Sample";
gitHubLink = "https://github.com/Pico-Developer/PICOMotionTrackerSample-Unity";
documentationLink = "https://developer.picoxr.com/document/unity/6bona7fv/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "Platform Services Sample";
gitHubLink = "https://github.com/Pico-Developer/PlatformSample-Unity";
documentationLink = "https://developer.picoxr.com/document/unity/simple-demo/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "Spatial Audio Sample";
gitHubLink = "https://github.com/Pico-Developer/SpatialAudioSample-Unity";
documentationLink = "https://developer.picoxr.com/document/unity/spatial-audio-sample/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "AR Foundation Sample";
gitHubLink = "https://github.com/Pico-Developer/PICOARFoundationSamples-Unity";
documentationLink = "https://developer.picoxr.com/document/unity/ar-foundation-for-pico-unity-integration-sdk/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "Adaptive Resolution Sample";
gitHubLink = "https://github.com/Pico-Developer/AdaptiveResolutionSample-Unity";
documentationLink = "https://developer.picoxr.com/document/unity/adaptive-resolution-demo/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "Toon World";
gitHubLink = "https://github.com/Pico-Developer/ToonSample-Unity";
documentationLink = "https://developer.picoxr.com/document/unity/toon-world/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "MicroWar";
gitHubLink = "https://github.com/picoxr/MicroWar";
documentationLink = "https://developer.picoxr.com/document/unity/micro-war/";
DrawSDKSampleLayout(title, documentationLink, gitHubLink);
title = "PICO Avatar Sample";
gitHubLink = "https://github.com/Pico-Developer/PICO-Avatar-SDK-Unity";
DrawSDKSampleLayout(title, null, gitHubLink);
title = "URP Fork";
gitHubLink = "https://github.com/Pico-Developer/PICO-URP-Fork";
DrawSDKSampleLayout(title, null, gitHubLink);
}
GUILayout.EndScrollView();
}
else if (buttonClickedStates[Response.About])
{
string title = "About the SDK";
GUIContent bodyContent = new GUIContent("PICO's official Unity package for developing applications for PICO XR devices.");
DrawTwoRowLayout(title, bodyContent);
title = "Features";
bodyContent = new GUIContent("The SDK provides features covering rendering, input and interaction, mixed reality, spatial audio, motion tracker, platform services, and enterprise features, etc.");
DrawTwoRowLayout(title, bodyContent);
title = "Documentation";
bodyContent = new GUIContent("Please visit the following page on PICO Developer Website for the latest documentation and samples:");
DrawTwoRowLayout(title, bodyContent);
string link = "https://developer.picoxr.com/document/unity";
if (GUILayout.Button(link, _styles.SmallBlueLinkStyle, GUILayout.ExpandWidth(false)))
{
Application.OpenURL(link);
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_About_Documentation);
}
var buttonRectDocumentation = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectDocumentation, MouseCursor.Link);
}
title = "Installation";
bodyContent = new GUIContent("We recommend using 'add package from git URL' to add the SDK from the PICO Developer GitHub:");
DrawTwoRowLayout(title, bodyContent);
link = "https://github.com/Pico-Developer/PICO-Unity-Integration-SDK";
if (GUILayout.Button(link, _styles.SmallBlueLinkStyle, GUILayout.ExpandWidth(false)))
{
Application.OpenURL(link);
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_About_Installation);
}
var buttonRectInstallation = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectInstallation, MouseCursor.Link);
}
}
GUILayout.FlexibleSpace();
}
}
}
}
private void DrawTitle(string title)
{
using (new GUILayout.HorizontalScope())
{
EditorGUILayout.LabelField(title, _styles.HeaderText, GUILayout.ExpandWidth(true));
GUILayout.FlexibleSpace();
EditorGUILayout.LabelField("Version " + PXR_Plugin.System.UPxr_GetSDKVersion(), _styles.VersionText, GUILayout.ExpandWidth(true));
string iconPath = Path.Combine(PXR_Utils.sdkPackageName, assetPath, PICO_ICON_NAME);
var content = EditorGUIUtility.TrIconContent(iconPath, "PICO Logo");
EditorGUILayout.LabelField(content, _styles.IconStyle,
GUILayout.Width(_styles.IconStyle.fixedWidth),
GUILayout.Height(_styles.IconStyle.fixedHeight), GUILayout.ExpandWidth(true));
}
}
public void DrawTwoRowLayout(string title, GUIContent bodyContent, string link = null, System.Action buttonAction = null, string button = null)
{
GUILayout.Space(30);
using (new EditorGUILayout.VerticalScope())
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label(title, _styles.BigWhiteTitleStyle, GUILayout.ExpandWidth(true));
if (link != null)
{
if (GUILayout.Button("Documentation", _styles.SmallBlueLinkStyle, GUILayout.Width(200)))
{
Application.OpenURL(link);
if (title == "Project Validation")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_ProjectValidation_Documentation);
}
else if (title == "PICO Building Blocks")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_BuildingBlocks);
}
else if (title == "PICO XR Toolkit-MR")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_PICOXRToolkitMR);
}
else if (title == "XR Profiling Toolkit")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_XRProfilingToolkit);
}
else if (title == "PICO Developer Center")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_PICODeveloperCenter);
}
else if (title == "Emulator")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_Emulator);
}
else if (title == "More Developer Tools")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_MoreDeveloperTools);
}
}
var buttonRect = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);
}
}
if (buttonAction != null)
{
string buttonText = button != null ? button : "Open " + title;
if (GUILayout.Button(buttonText, _styles.ButtonToOpen, GUILayout.ExpandWidth(false)))
{
buttonAction?.Invoke();
}
var buttonRect = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);
}
}
else
{
GUIStyle Box = new GUIStyle()
{
fixedWidth = 250,
};
GUILayout.Box("", Box, GUILayout.ExpandWidth(false));
}
GUILayout.Space(30);
}
EditorGUILayout.Space(10);
if (bodyContent != null)
{
EditorGUILayout.LabelField(bodyContent, _styles.ContentText);
}
}
}
private void DrawHorizontalLine(Color color, int thickness)
{
Rect rect = EditorGUILayout.GetControlRect(false, thickness);
EditorGUI.DrawRect(rect, color);
}
private void DrawVerticalLine(Color color, int thickness)
{
Rect rect = new Rect(220, 122, thickness, Screen.height);
EditorGUI.DrawRect(rect, color);
}
private void DrawLeftButton()
{
using (new EditorGUILayout.VerticalScope())
{
EditorGUILayout.Space(30);
var buttons = new[] {
("<size=18>Configs</size>", Response.Configs),
("<size=18>Tools</size>", Response.Tools),
("<size=18>Samples</size>", Response.Samples),
("<size=18>About</size>", Response.About)
};
foreach (var (btnText, response) in buttons)
{
bool isClicked = GUILayout.Button(btnText,
buttonClickedStates[response] ? _styles.ButtonSelected : _styles.Button,
GUILayout.ExpandHeight(false));
var rect = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link);
}
if (isClicked)
{
ClickedButton(response);
}
EditorGUILayout.Space(30);
}
}
float windowHeight = position.height;
float toggleY = windowHeight - EditorGUIUtility.singleLineHeight - 20;
float toggleX = 20;
float toggleWidth = position.width - 30;
Rect toggleRect = new Rect(toggleX, toggleY, toggleWidth, EditorGUIUtility.singleLineHeight);
var guiContent = new GUIContent();
guiContent.text = "Allow usage data collection";
guiContent.tooltip = "To improve service quality, we will collect non-identifiable behavioral data (such as engine or sdk version, the status of sdk and engine capabilities being enabled, etc.). You can disable this at any time.";
PXR_ProjectSetting.GetProjectConfig().isDataCollectionDisabled = !EditorGUI.ToggleLeft(toggleRect, guiContent, !PXR_ProjectSetting.GetProjectConfig().isDataCollectionDisabled);
if (toggleRect.Contains(Event.current.mousePosition))
{
EditorGUIUtility.AddCursorRect(toggleRect, MouseCursor.Link);
}
}
private void ClickedButton(Response responseT)
{
var keys = buttonClickedStates.Keys.ToArray();
for (int i = 0; i < keys.Length; i++)
{
var response = keys[i];
buttonClickedStates[response] = responseT == response;
}
WhenResponded.Invoke(responseT);
switch (responseT)
{
case Response.Configs:
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Configs_Open);
break;
case Response.Tools:
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Tools_Open);
break;
case Response.Samples:
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Sample_Open);
break;
case Response.About:
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_About_Open);
break;
default:
break;
}
}
private void DrawSDKSampleLayout(string title, string documentationLink, string gitHubLink)
{
GUILayout.Space(20);
using (new EditorGUILayout.HorizontalScope())
{
_styles.BigWhiteTitleStyle.fontStyle = FontStyle.Bold;
GUILayout.Label(title, _styles.BigWhiteTitleStyle, GUILayout.ExpandWidth(false));
if (documentationLink != null)
{
GUILayout.Label(" | ", _styles.BigWhiteTitleStyle, GUILayout.Width(20));
if (GUILayout.Button("Documentation", _styles.SmallBlueLinkStyle, GUILayout.ExpandWidth(false)))
{
Application.OpenURL(documentationLink);
if (title == "Mixed Reality Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_MixedRealitySample_Documentation);
}
else if (title == "Interaction Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_InteractionSample_Documentation);
}
else if (title == "Motion Tracker Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_MotionTrackerSample_Documentation);
}
else if (title == "Platform Services Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_PlatformServicesSample_Documentation);
}
else if (title == "Spatial Audio Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_SpatialAudioSample_Documentation);
}
else if (title == "AR Foundation Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_ARFoundationSample_Documentation);
}
else if (title == "Adaptive Resolution Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_AdaptiveResolutionSample_Documentation);
}
else if (title == "Toon World")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_ToonWorldSample_Documentation);
}
else if (title == "MicroWar")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_MicroWarSample_Documentation);
}
else if (title == "PICO Avatar Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_PICOAvatarSample_Documentation);
}
else if (title == "URP Fork")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_URPFork_Documentation);
}
}
var buttonRectDoc = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectDoc, MouseCursor.Link);
}
}
GUILayout.Label(" | ", _styles.BigWhiteTitleStyle, GUILayout.Width(20));
if (GUILayout.Button("GitHub", _styles.SmallBlueLinkStyle, GUILayout.ExpandWidth(false)))
{
Application.OpenURL(gitHubLink);
if (title == "Mixed Reality Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_MixedRealitySample_GitHub);
}
else if (title == "Interaction Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_InteractionSample_GitHub);
}
else if (title == "Motion Tracker Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_MotionTrackerSample_GitHub);
}
else if (title == "Platform Services Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_PlatformServicesSample_GitHub);
}
else if (title == "Spatial Audio Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_SpatialAudioSample_GitHub);
}
else if (title == "AR Foundation Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_ARFoundationSample_GitHub);
}
else if (title == "Adaptive Resolution Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_AdaptiveResolutionSample_GitHub);
}
else if (title == "Toon World")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_ToonWorldSample_GitHub);
}
else if (title == "MicroWar")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_MicroWarSample_GitHub);
}
else if (title == "PICO Avatar Sample")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_PICOAvatarSample_GitHub);
}
else if (title == "URP Fork")
{
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strPortal, PXR_AppLog.strPortal_Samples_URPFork_GitHub);
}
}
var buttonRectGitHub = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectGitHub, MouseCursor.Link);
}
}
}
void EditorConfigurations(string strConfiguration, bool enable, Action buttonAction)
{
EditorGUILayout.BeginHorizontal();
var iconStyle = new GUIStyle
{
fixedWidth = 30,
stretchHeight = true,
alignment = TextAnchor.MiddleCenter,
};
if (enable)
{
GUI.color = Color.green;
EditorGUILayout.LabelField(EditorGUIUtility.IconContent("FilterSelectedOnly"), iconStyle, GUILayout.Width(30), GUILayout.ExpandHeight(true));
}
else
{
GUI.color = Color.yellow;
EditorGUILayout.LabelField(EditorGUIUtility.IconContent("console.warnicon"), iconStyle, GUILayout.Width(30), GUILayout.ExpandHeight(true));
}
GUI.color = Color.white;
EditorGUILayout.LabelField(strConfiguration, _styles.ContentText, GUILayout.Width(640), GUILayout.ExpandHeight(true));
_styles.ContentText.normal.textColor = Color.white;
GUIStyle styleApplied = new GUIStyle();
styleApplied.fontSize = 14;
styleApplied.fixedWidth = 80;
styleApplied.fixedHeight = 30;
styleApplied.padding = new RectOffset(4, 4, 4, 4);
styleApplied.alignment = TextAnchor.MiddleCenter;
if (enable)
{
styleApplied.normal.textColor = Color.green;
GUILayout.Label("Applied", styleApplied);
}
else
{
if (GUILayout.Button("Apply", GUILayout.ExpandWidth(false), GUILayout.Width(80), GUILayout.Height(30)))
{
buttonAction?.Invoke();
}
var buttonRectToApply = GUILayoutUtility.GetLastRect();
if (Event.current.type == EventType.Repaint)
{
EditorGUIUtility.AddCursorRect(buttonRectToApply, MouseCursor.Link);
}
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
}
private void CloseWindow()
{
Close();
}
}
public static class ScriptableObjectUtility
{
public static void CreateAsset<T>(T classdata, string path) where T : ScriptableObject
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + typeof(T).ToString() + ".asset");
AssetDatabase.CreateAsset(classdata, assetPathAndName);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bda4ef25984fa08429a6ed3e06f78303
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,192 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
using UnityEngine.SceneManagement;
using UnityEngine.Rendering;
#if AR_FOUNDATION_5 || AR_FOUNDATION_6
using UnityEngine.XR.ARFoundation;
#endif
namespace Unity.XR.PXR.Editor
{
[CustomEditor(typeof(PXR_Settings))]
public class PXR_SettingsEditor : UnityEditor.Editor
{
private const string StereoRenderingModeAndroid = "stereoRenderingModeAndroid";
private const string SystemDisplayFrequency = "systemDisplayFrequency";
private const string OptimizeBufferDiscards = "optimizeBufferDiscards";
private const string SystemSplashScreen = "systemSplashScreen";
static GUIContent guiStereoRenderingMode = EditorGUIUtility.TrTextContent("Stereo Rendering Mode");
static GUIContent guiDisplayFrequency = EditorGUIUtility.TrTextContent("Display Refresh Rates");
private static GUIContent guiOptimizeBuffer = EditorGUIUtility.TrTextContent("Optimize Buffer Discards(Vulkan)");
static GUIContent guiSystemSplashScreen = EditorGUIUtility.TrTextContent("System Splash Screen");
private SerializedProperty stereoRenderingModeAndroid;
private SerializedProperty systemDisplayFrequency;
private SerializedProperty optimizeBufferDiscards;
private SerializedProperty appLog;
private SerializedProperty systemSplashScreen;
void OnEnable()
{
if (stereoRenderingModeAndroid == null)
stereoRenderingModeAndroid = serializedObject.FindProperty(StereoRenderingModeAndroid);
if (systemDisplayFrequency == null)
systemDisplayFrequency = serializedObject.FindProperty(SystemDisplayFrequency);
if (optimizeBufferDiscards == null)
optimizeBufferDiscards = serializedObject.FindProperty(OptimizeBufferDiscards);
if (systemSplashScreen == null)
systemSplashScreen = serializedObject.FindProperty(SystemSplashScreen);
}
public override void OnInspectorGUI()
{
if (serializedObject == null || serializedObject.targetObject == null)
return;
serializedObject.Update();
EditorGUIUtility.labelWidth = 200.0f;
BuildTargetGroup selectedBuildTargetGroup = EditorGUILayout.BeginBuildTargetSelectionGrouping();
EditorGUILayout.Space();
EditorGUILayout.BeginVertical(GUILayout.ExpandWidth(true));
if (EditorApplication.isPlayingOrWillChangePlaymode)
{
EditorGUILayout.HelpBox("PICO settings cannot be changed when the editor is in play mode.", MessageType.Info);
EditorGUILayout.Space();
}
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
if (selectedBuildTargetGroup == BuildTargetGroup.Android)
{
EditorGUILayout.PropertyField(stereoRenderingModeAndroid, guiStereoRenderingMode);
EditorGUILayout.PropertyField(systemDisplayFrequency, guiDisplayFrequency);
EditorGUILayout.PropertyField(optimizeBufferDiscards, guiOptimizeBuffer);
bool aswDisabled = false;
#if !UNITY_2021_1_OR_NEWER
aswDisabled = true;
#endif
if (GraphicsDeviceType.OpenGLES3 == PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget)[0])
{
GUI.enabled = false;
serializedObject.FindProperty("enableAppSpaceWarp").boolValue = false;
EditorGUILayout.PropertyField(serializedObject.FindProperty("enableAppSpaceWarp"), new GUIContent("Application SpaceWarp", "Set Graphics API to Vulkan."));
}
else if (aswDisabled)
{
GUI.enabled = false;
serializedObject.FindProperty("enableAppSpaceWarp").boolValue = false;
EditorGUILayout.PropertyField(serializedObject.FindProperty("enableAppSpaceWarp"), new GUIContent("Application SpaceWarp", "Unity Editor: 2021 LTS or later."));
}
else if (serializedObject.FindProperty("stereoRenderingModeAndroid").intValue == 0)
{
GUI.enabled = false;
serializedObject.FindProperty("enableAppSpaceWarp").boolValue = false;
EditorGUILayout.PropertyField(serializedObject.FindProperty("enableAppSpaceWarp"), new GUIContent("Application SpaceWarp", "Set Stereo Rendering Mode to Multiview."));
}
else
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("enableAppSpaceWarp"), new GUIContent("Application SpaceWarp"));
}
GUI.enabled = true;
EditorGUILayout.PropertyField(systemSplashScreen, guiSystemSplashScreen);
#if AR_FOUNDATION_5 || AR_FOUNDATION_6
PXR_ProjectSetting projectConfig = PXR_ProjectSetting.GetProjectConfig();
var guiContent = new GUIContent();
guiContent.text = "AR Foundation";
projectConfig.arFoundation = EditorGUILayout.Toggle(guiContent, projectConfig.arFoundation);
if (projectConfig.arFoundation)
{
EditorGUI.indentLevel++;
// body tracking
guiContent.text = "Body Tracking";
projectConfig.bodyTracking = EditorGUILayout.Toggle(guiContent, projectConfig.bodyTracking);
// face tracking
guiContent.text = "Face Tracking";
projectConfig.faceTracking = EditorGUILayout.Toggle(guiContent, projectConfig.faceTracking);
// anchor
guiContent.text = "Anchor";
projectConfig.spatialAnchor = EditorGUILayout.Toggle(guiContent, projectConfig.spatialAnchor);
// anchor
guiContent.text = "Meshing";
projectConfig.spatialMesh = EditorGUILayout.Toggle(guiContent, projectConfig.spatialMesh);
List<ARCameraManager> components = FindComponentsInScene<ARCameraManager>().Where(component => (component.enabled && component.gameObject.CompareTag("MainCamera"))).ToList();
bool cameraEffect = false;
for (int i = 0; i < components.Count; i++)
{
ARCameraManager aRCamera = components[i];
if (aRCamera.gameObject.GetComponent<PXR_ARCameraEffectManager>())
{
cameraEffect = true;
}
Camera camera = aRCamera.gameObject.GetComponent<Camera>();
if (camera)
{
camera.clearFlags = CameraClearFlags.SolidColor;
camera.backgroundColor = new Color(0, 0, 0, 0);
}
}
if (!cameraEffect && components.Count > 0)
{
ARCameraManager aRCamera = components[0];
if (!aRCamera.gameObject.GetComponent<PXR_ARCameraEffectManager>())
{
aRCamera.gameObject.AddComponent<PXR_ARCameraEffectManager>();
}
cameraEffect = true;
}
EditorGUI.indentLevel--;
}
if (GUI.changed)
{
EditorUtility.SetDirty(projectConfig);
}
#endif
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndVertical();
EditorGUILayout.EndBuildTargetSelectionGrouping();
serializedObject.ApplyModifiedProperties();
EditorGUIUtility.labelWidth = 0f;
}
public static List<T> FindComponentsInScene<T>() where T : Component
{
var activeScene = SceneManager.GetActiveScene();
var foundComponents = new List<T>();
var rootObjects = activeScene.GetRootGameObjects();
foreach (var rootObject in rootObjects)
{
var components = rootObject.GetComponentsInChildren<T>(true);
foundComponents.AddRange(components);
}
return foundComponents;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61ac45442d9eb5f40a131d621c5f1ff7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll information contained herein is, and remains the property of
PICO Technology Co., Ltd. The intellectual and technical concepts
contained herein are proprietary to PICO Technology Co., Ltd. and may be
covered by patents, patents in process, and are protected by trade secret or
copyright law. Dissemination of this information or reproduction of this
material is strictly forbidden unless prior written permission is obtained from
PICO Technology Co., Ltd.
*******************************************************************************/
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Unity.XR.PXR.Editor
{
[CustomEditor(typeof(PXR_SpatialMeshManager))]
public class PXR_SpatialMeshManagerEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
PXR_SpatialMeshColorSetting colorSetting = PXR_SpatialMeshColorSetting.GetSpatialMeshColorSetting();
EditorGUILayout.BeginVertical("framebox");
GUILayout.Label("Custom Mesh Color", EditorStyles.boldLabel);
GUILayout.Space(5);
if (colorSetting.colorLists != null)
{
var labels = Enum.GetNames(typeof(PxrSemanticLabel));
for (int i = 0; i < colorSetting.colorLists.Count; i++)
{
colorSetting.colorLists[i] = EditorGUILayout.ColorField(labels[i], colorSetting.colorLists[i]);
}
}
EditorGUILayout.EndVertical();
if (GUI.changed)
{
PXR_SpatialMeshColorSetting.SaveAssets();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0577c31c891b4e40b6076926195776d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,777 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.XR.CoreUtils;
using Unity.XR.CoreUtils.Editor;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager.UI;
using UnityEditor.SceneManagement;
using UnityEditor.XR.Management;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.SceneManagement;
using static Unity.XR.CoreUtils.XROrigin;
using UnityEngine.Rendering;
using UnityEditor.Build;
using Unity.XR.CoreUtils.Capabilities.Editor;
using UnityEngine.XR.Management;
using Unity.XR.CoreUtils.Capabilities;
#if UNITY_OPENXR
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
#if XR_HAND
using UnityEngine.XR.Hands.OpenXR;
#endif
#if PICO_OPENXR_SDK
using Unity.XR.OpenXR.Features.PICOSupport;
#endif
#endif
#if URP
using UnityEngine.Rendering.Universal;
#endif
namespace Unity.XR.PXR
{
[InitializeOnLoad]
internal static class PXR_Utils
{
public static string BuildingBlock = "[Building Block]";
public const string BuildingBlockPathO = "GameObject/PICO Building Blocks/";
public const string BuildingBlockPathP = "PICO/PICO Building Blocks/";
public static string sdkPackageName = "Packages/com.unity.xr.picoxr/";
public static AndroidSdkVersions minSdkVersionInEditor = AndroidSdkVersions.AndroidApiLevel29;
#if UNITY_2021_2_OR_NEWER
public static NamedBuildTarget recommendedBuildTarget = NamedBuildTarget.Android;
#else
public static BuildTargetGroup recommendedBuildTarget = BuildTargetGroup.Android;
#endif
#region xr.interaction.toolkit
public static string xriPackageName = "com.unity.xr.interaction.toolkit";
public static string xriVersion = "2.5.4";
public static PackageVersion xriPackageVersion250 = new PackageVersion("2.5.0");
public static PackageVersion xriPackageVersion300 = new PackageVersion("3.0.0");
public static string xriCategory = "XR Interaction Toolkit";
public static string xriSamplesPath = "Assets/Samples/XR Interaction Toolkit";
public static string xriStarterAssetsSampleName = "Starter Assets";
public static string xriHandsInteractionDemoSampleName = "Hands Interaction Demo";
public static string xri2HandsSetupPefabName = "XR Interaction Hands Setup";
public static string xri3HandsSetupPefabName = "XR Origin Hands (XR Rig)";
public static PackageVersion XRICurPackageVersion
{
get
{
return new PackageVersion(xriVersion);
}
}
public static string XRIDefaultInputActions
{
get
{
return $"{xriSamplesPath}/{xriVersion}/Starter Assets/XRI Default Input Actions.inputactions";
}
}
public static string XRIDefaultLeftControllerPreset
{
get
{
if (XRICurPackageVersion >= xriPackageVersion250)
{
return $"{xriSamplesPath}/{xriVersion}/Starter Assets/Presets/XRI Default Left Controller.preset";
}
else
{
return $"{xriSamplesPath}/{xriVersion}/Starter Assets/XRI Default Left Controller.preset";
}
}
}
public static string XRIDefaultRightControllerPreset
{
get
{
if (XRICurPackageVersion >= xriPackageVersion250)
{
return $"{xriSamplesPath}/{xriVersion}/Starter Assets/Presets/XRI Default Right Controller.preset";
}
else
{
return $"{xriSamplesPath}/{xriVersion}/Starter Assets/XRI Default Right Controller.preset";
}
}
}
public static string XRInteractionHandsSetupPath
{
get
{
if (XRICurPackageVersion >= xriPackageVersion300)
{
return $"{xriSamplesPath}/{xriVersion}/{xriHandsInteractionDemoSampleName}/Prefabs/{xri3HandsSetupPefabName}.prefab";
}
else if (XRICurPackageVersion >= xriPackageVersion250 && XRICurPackageVersion < xriPackageVersion300)
{
return $"{xriSamplesPath}/{xriVersion}/{xriHandsInteractionDemoSampleName}/Prefabs/{xri2HandsSetupPefabName}.prefab";
}
else
{
return $"{xriSamplesPath}/{xriVersion}/{xriHandsInteractionDemoSampleName}/Runtime/Prefabs/{xri2HandsSetupPefabName}.prefab";
}
}
}
public static string XRInteractionPokeButtonPath
{
get
{
if (XRICurPackageVersion >= xriPackageVersion250)
{
return $"{xriSamplesPath}/{xriVersion}/{xriHandsInteractionDemoSampleName}/HandsDemoSceneAssets/Prefabs/PokeButton.prefab";
}
else
{
return $"{xriSamplesPath}/{xriVersion}/{xriHandsInteractionDemoSampleName}/Runtime/Prefabs/PokeButton.prefab";
}
}
}
public static string XRInteractionXRI300OriginPath
{
get
{
if (XRICurPackageVersion >= xriPackageVersion250)
{
return $"{xriSamplesPath}/{xriVersion}/{xriStarterAssetsSampleName}/Prefabs/XR Origin (XR Rig).prefab";
}
else
{
return $"{xriSamplesPath}/{xriVersion}/{xriStarterAssetsSampleName}/Runtime/Prefabs/XR Origin (XR Rig).prefab";
}
}
}
#endregion
#region xr.hands
public static string xrHandPackageName = "com.unity.xr.hands";
public static string xrHandVersion = "1.4.1";
public static PackageVersion xrHandRecommendedPackageVersion = new PackageVersion("1.3.0");
public static string xrHandSamplesPath = "Assets/Samples/XR Hands";
public static string xrHandGesturesSampleName = "Gestures";
public static string xrHandVisualizerSampleName = "HandVisualizer";
public static string XRHandLeftHandPrefabPath
{
get
{
return $"{xrHandSamplesPath}/{xrHandVersion}/HandVisualizer/Prefabs/Left Hand Tracking.prefab";
}
}
public static string XRHandRightHandPrefabPath
{
get
{
return $"{xrHandSamplesPath}/{xrHandVersion}/HandVisualizer/Prefabs/Right Hand Tracking.prefab";
}
}
static AddRequest xrHandsPackageAddRequest;
public static void InstallOrUpdateHands()
{
var currentT = DateTime.Now;
var endT = currentT + TimeSpan.FromSeconds(3);
var request = Client.Search(xrHandPackageName);
if (request.Status == StatusCode.InProgress)
{
Debug.Log($"Searching for ({xrHandPackageName}) in Unity Package Registry.");
while (request.Status == StatusCode.InProgress && currentT < endT)
{
currentT = DateTime.Now;
}
}
var addRequest = xrHandPackageName;
if (request.Status == StatusCode.Success && request.Result.Length > 0)
{
var versions = request.Result[0].versions;
#if UNITY_2022_2_OR_NEWER
var recommendedVersion = new PackageVersion(versions.recommended);
#else
var recommendedVersion = new PackageVersion(versions.verified);
#endif
var latestCompatible = new PackageVersion(versions.latestCompatible);
if (recommendedVersion < xrHandRecommendedPackageVersion && xrHandRecommendedPackageVersion <= latestCompatible)
addRequest = $"{xrHandPackageName}@{xrHandRecommendedPackageVersion}";
}
xrHandsPackageAddRequest = Client.Add(addRequest);
if (xrHandsPackageAddRequest.Error != null)
{
Debug.LogError($"Package installation error: {xrHandsPackageAddRequest.Error}: {xrHandsPackageAddRequest.Error.message}");
}
}
#endregion
#region xr.openxr
public static string openXRPackageName = "com.unity.xr.openxr";
public static PackageVersion openXRPackageVersion182 = new PackageVersion("1.8.2");
public static string openXRVersion = "1.7.1";
public static PackageVersion openXRCurPackageVersion
{
get
{
return new PackageVersion(openXRVersion);
}
}
public static string GetPackageVersionSync(string packageName)
{
var request = Client.List();
while (!request.IsCompleted) { }
return request.Result.FirstOrDefault(p => p.name == packageName)?.version;
}
public static void EnableHandTrackingFeature()
{
#if XR_HAND && PICO_OPENXR_SDK
EnableOpenXRFeature<HandTracking>();
EnableOpenXRFeature<UnityEngine.XR.OpenXR.Features.Interactions.HandInteractionProfile>();
#endif
}
#if PICO_OPENXR_SDK
public static void EnableOpenXRFeature<T>() where T : OpenXRFeature
{
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
foreach (var feature in settings.GetFeatures<OpenXRFeature>())
{
if (feature is T targetFeature && !targetFeature.enabled)
{
targetFeature.enabled = true;
}
}
}
#endif
#endregion
public static List<T> FindComponentsInScene<T>() where T : Component
{
var activeScene = SceneManager.GetActiveScene();
var foundComponents = new List<T>();
var rootObjects = activeScene.GetRootGameObjects();
foreach (var rootObject in rootObjects)
{
var components = rootObject.GetComponentsInChildren<T>(true);
foundComponents.AddRange(components);
}
return foundComponents;
}
public static List<T> FindGameObjectsInScene<T>() where T : Component
{
var activeScene = SceneManager.GetActiveScene();
var foundComponents = new List<T>();
var rootObjects = activeScene.GetRootGameObjects();
foreach (var rootObject in rootObjects)
{
var components = rootObject.GetComponentsInChildren<T>(true);
foundComponents.AddRange(components);
}
return foundComponents;
}
public static void AddNewTag(string newTag)
{
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
SerializedProperty tags = tagManager.FindProperty("tags");
bool tagExists = false;
for (int i = 0; i < tags.arraySize; i++)
{
if (tags.GetArrayElementAtIndex(i).stringValue == newTag)
{
tagExists = true;
break;
}
}
if (!tagExists)
{
tags.InsertArrayElementAtIndex(tags.arraySize);
tags.GetArrayElementAtIndex(tags.arraySize - 1).stringValue = newTag;
tagManager.ApplyModifiedProperties();
Debug.Log($"Tag '{newTag}' has been added.");
}
else
{
Debug.LogWarning($"Tag '{newTag}' already exists.");
}
}
public static bool TryFindSample(string packageName, string packageVersion, string sampleDisplayName, out Sample sample)
{
sample = default;
IEnumerable<Sample> packageSamples;
try
{
packageSamples = Sample.FindByPackage(packageName, packageVersion);
}
catch (Exception e)
{
Debug.LogError($"Couldn't find samples of the {ToString(packageName, packageVersion)} package. Exception: {e}");
return false;
}
if (packageSamples == null)
{
Debug.LogWarning($"Couldn't find samples of the {ToString(packageName, packageVersion)} package.");
return false;
}
foreach (var packageSample in packageSamples)
{
if (packageSample.displayName == sampleDisplayName)
{
Debug.Log($" TryFindSample packageSample.displayName={packageSample.displayName}, sampleDisplayName={sampleDisplayName}");
sample = packageSample;
return true;
}
}
Debug.LogWarning($"Couldn't find {sampleDisplayName} sample in the { packageName}:{ packageVersion}.");
return false;
}
private static string ToString(string packageName, string packageVersion)
{
return string.IsNullOrEmpty(packageVersion) ? packageName : $"{packageName}@{packageVersion}";
}
public static void SetTrackingOriginMode(TrackingOriginMode trackingOriginMode = TrackingOriginMode.Device)
{
List<XROrigin> components = FindComponentsInScene<XROrigin>().Where(component => component.isActiveAndEnabled).ToList();
foreach (XROrigin origin in components)
{
if (TrackingOriginMode.NotSpecified == origin.RequestedTrackingOriginMode)
{
Debug.Log($"SetTrackingOriginMode {trackingOriginMode}");
origin.RequestedTrackingOriginMode = trackingOriginMode;
EditorUtility.SetDirty(origin);
AssetDatabase.SaveAssets();
}
}
}
#if XRI_TOOLKIT_3
public static GameObject CheckAndCreateXROriginXRI300()
{
GameObject cameraOrigin;
string k_BuildingBlocksXRI300OriginName = BuildingBlock + " XR Origin (XR Rig) XRI300";
List<Transform> transforms = FindComponentsInScene<Transform>().Where(component => component.name == k_BuildingBlocksXRI300OriginName).ToList();
if (transforms.Count == 0)
{
GameObject buildingBlockGO = new GameObject();
Selection.activeGameObject = buildingBlockGO;
List<XROrigin> components = FindComponentsInScene<XROrigin>().Where(component => component.isActiveAndEnabled).ToList();
if (components.Count != 0)
{
foreach (var c in components)
{
c.gameObject.SetActive(false);
}
}
GameObject ob = PrefabUtility.LoadPrefabContents(XRInteractionXRI300OriginPath);
Undo.RegisterCreatedObjectUndo(ob, "Create XRInteractionXRI300OriginPath.");
var activeScene = SceneManager.GetActiveScene();
var rootObjects = activeScene.GetRootGameObjects();
Undo.SetTransformParent(ob.transform, buildingBlockGO.transform, true, "Parent to buildingBlockGO.");
ob.transform.localPosition = Vector3.zero;
ob.transform.localRotation = Quaternion.identity;
ob.transform.localScale = Vector3.one;
ob.SetActive(true);
cameraOrigin = ob;
if (!cameraOrigin.GetComponent<PXR_Manager>())
{
cameraOrigin.AddComponent<PXR_Manager>();
}
var characterController = cameraOrigin.GetComponent<CharacterController>();
if (characterController)
{
characterController.enabled = false;
}
if (cameraOrigin.transform.Find("Locomotion/Move"))
{
cameraOrigin.transform.Find("Locomotion/Move").gameObject.SetActive(false);
}
buildingBlockGO.name = k_BuildingBlocksXRI300OriginName;
Undo.RegisterCreatedObjectUndo(buildingBlockGO, "Create buildingBlockGO.");
EditorSceneManager.MarkSceneDirty(buildingBlockGO.scene);
EditorSceneManager.SaveScene(buildingBlockGO.scene);
SetTrackingOriginMode();
PXR_ProjectSetting.SaveAssets();
}
else
{
cameraOrigin = transforms[0].GetChild(0).gameObject;
}
return cameraOrigin;
}
#endif
public static GameObject CheckAndCreateXROrigin()
{
GameObject cameraOrigin;
List<XROrigin> components = FindComponentsInScene<XROrigin>().Where(component => component.isActiveAndEnabled).ToList();
if (components.Count == 0)
{
if (!EditorApplication.ExecuteMenuItem("GameObject/XR/XR Origin (VR)"))
{
EditorApplication.ExecuteMenuItem("GameObject/XR/XR Origin (Action-based)");
}
cameraOrigin = FindComponentsInScene<XROrigin>().Where(component => component.isActiveAndEnabled).ToList()[0].gameObject;
cameraOrigin.name = PXR_Utils.BuildingBlock + " XR Origin (XR Rig)";
Undo.RegisterCreatedObjectUndo(cameraOrigin, "Create XR Origin");
cameraOrigin.transform.localPosition = Vector3.zero;
cameraOrigin.transform.localRotation = Quaternion.identity;
cameraOrigin.transform.localScale = Vector3.one;
cameraOrigin.SetActive(true);
}
else
{
cameraOrigin = components[0].gameObject;
}
if (!cameraOrigin.GetComponent<PXR_Manager>())
{
cameraOrigin.AddComponent<PXR_Manager>();
}
return cameraOrigin;
}
public static GameObject GetMainCameraGOForXROrigin()
{
GameObject cameraGameObject = Camera.main.gameObject;
List<Camera> components = FindComponentsInScene<Camera>().Where(component => (component.enabled && component.gameObject.CompareTag("MainCamera"))).ToList();
for (int i = 0; i < components.Count; i++)
{
GameObject gameObject = components[i].transform.gameObject;
if (gameObject.GetComponentsInParent<XROrigin>().Length == 1)
{
gameObject.SetActive(true);
cameraGameObject = gameObject;
}
}
return cameraGameObject;
}
public static Camera GetMainCameraForXROrigin()
{
Camera mainCamera = Camera.main;
List<Camera> components = FindComponentsInScene<Camera>().Where(component => (component.enabled && component.gameObject.CompareTag("MainCamera"))).ToList();
for (int i = 0; i < components.Count; i++)
{
Camera camera = components[i];
if (camera.GetComponentsInParent<XROrigin>().Length == 1)
{
camera.gameObject.SetActive(true);
mainCamera = camera;
}
}
return mainCamera;
}
public static void SetOneMainCameraInScene()
{
bool hasOneMainCamera = false;
List<Camera> components = FindComponentsInScene<Camera>().Where(component => (component.enabled && component.gameObject.activeSelf)).ToList();
if (components.Count == 0)
{
if (!EditorApplication.ExecuteMenuItem("GameObject/XR/XR Origin (VR)"))
{
EditorApplication.ExecuteMenuItem("GameObject/XR/XR Origin (Action-based)");
}
return;
}
for (int i = 0; i < components.Count; i++)
{
GameObject gameObject = components[i].transform.gameObject;
if (gameObject.GetComponentsInParent<XROrigin>().Length >= 1 && !hasOneMainCamera)
{
if (!gameObject.CompareTag("MainCamera"))
{
gameObject.tag = "MainCamera";
}
gameObject.SetActive(true);
hasOneMainCamera = true;
}
else
{
string newTag = $"Camera{i}";
AddNewTag(newTag);
gameObject.tag = newTag;
gameObject.SetActive(false);
components[i].enabled = false;
}
}
}
public static bool UpdateSamples(string packageName, string sampleDisplayName)
{
Debug.LogError($"Need to import {sampleDisplayName} first! Once completed, click this Block again.");
bool result = EditorUtility.DisplayDialog($"{sampleDisplayName}", $"It's detected that {sampleDisplayName} has not been imported in the current project. You can choose OK to auto-import it, or Cancel and install it manually. ", "OK", "Cancel");
if (result)
{
if (TryFindSample(packageName, string.Empty, sampleDisplayName, out var sample))
{
sample.Import(Sample.ImportOptions.OverridePreviousImports);
AssetDatabase.Refresh();
return true;
}
}
return false;
}
public static string minUnityVersion = "2020.3.21f1";
public static int CompareUnityVersions(string versionA, string versionB)
{
string[] partsA = versionA.Split(new char[] { '.', 'f' }, StringSplitOptions.RemoveEmptyEntries);
string[] partsB = versionB.Split(new char[] { '.', 'f' }, StringSplitOptions.RemoveEmptyEntries);
int maxLength = Math.Max(partsA.Length, partsB.Length);
for (int i = 0; i < maxLength; i++)
{
int partA = i < partsA.Length ? int.Parse(partsA[i]) : 0;
int partB = i < partsB.Length ? int.Parse(partsB[i]) : 0;
if (partA > partB)
return 1;
if (partA < partB)
return -1;
}
return 0;
}
public static bool updateBasedOnCapabilityProfileSelection = false;
static PXR_Utils()
{
CapabilityProfileSelection.SelectionSaved += OnSelectionSaved;
}
private static void OnSelectionSaved()
{
updateBasedOnCapabilityProfileSelection = true;
}
public static bool IsPXRValidationEnabled()
{
if (updateBasedOnCapabilityProfileSelection)
{
return CapabilityProfileSelection.Selected.Any(c => c is PXR_SDKCapability);
}
return IsPXRPluginEnabled();
}
public static bool IsOpenXRValidationEnabled()
{
if (updateBasedOnCapabilityProfileSelection)
{
return CapabilityProfileSelection.Selected.Any(c => c is PXR_OpenXR_SDKCapability);
}
return IsOpenXRPluginEnabled();
}
public static void ReSetCapabilityProfileSelection()
{
CapabilityProfileSelection.Clear();
CapabilityProfileSelection.Save();
updateBasedOnCapabilityProfileSelection = false;
}
public static bool IsPXRPluginEnabled()
{
var generalSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(
BuildTargetGroup.Android);
if (generalSettings == null)
return false;
var managerSettings = generalSettings.AssignedSettings;
return managerSettings != null && managerSettings.activeLoaders.Any(loader => loader is PXR_Loader);
}
public static bool IsOpenXRPluginEnabled()
{
#if PICO_OPENXR_SDK
var generalSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(
BuildTargetGroup.Android);
if (generalSettings == null)
return false;
var managerSettings = generalSettings.AssignedSettings;
return managerSettings != null && managerSettings.activeLoaders.Any(loader => loader is OpenXRLoader);
#else
return false;
#endif
}
#region Symbols
public static string _openxr_xdk = "PICO_OPENXR_SDK";
[InitializeOnLoadMethod]
public static void IsPicoSpatializerAvailable()
{
string name = "PICO_SPATIALIZER";
#if UNITY_EDITOR
string spatializerPath = sdkPackageName + "SpatialAudio/ByteDance.PICO.XR.Spatializer.asmdef";
var asmDef = AssetDatabase.LoadAssetAtPath<AssemblyDefinitionAsset>(spatializerPath);
if (asmDef == null)
{
RemoveDefineSymbol(name);
}
else
{
SetDefineSymbols(name);
}
#endif
}
public static bool SetDefineSymbols(string name)
{
var buildTarget = NamedBuildTarget.FromBuildTargetGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
string currentDefines = PlayerSettings.GetScriptingDefineSymbols(buildTarget);
var defineSymbols = new HashSet<string>(currentDefines.Split(';', StringSplitOptions.RemoveEmptyEntries));
if (!defineSymbols.Contains(name))
{
defineSymbols.Add(name);
string newDefines = string.Join(";", defineSymbols);
PlayerSettings.SetScriptingDefineSymbols(buildTarget, newDefines);
Debug.Log($"SetDefineSymbols Final define symbols: {newDefines}");
return true;
}
return false;
}
public static void RemoveDefineSymbol(string name)
{
var buildTarget = NamedBuildTarget.FromBuildTargetGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
string currentDefines = PlayerSettings.GetScriptingDefineSymbols(buildTarget);
var defineSymbols = new HashSet<string>(currentDefines.Split(';', StringSplitOptions.RemoveEmptyEntries));
if (defineSymbols.Remove(name))
{
string newDefines = string.Join(";", defineSymbols);
PlayerSettings.SetScriptingDefineSymbols(buildTarget, newDefines);
}
}
public static bool UpdateSDKSymbols()
{
XRGeneralSettings generalSettings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(BuildTargetGroup.Android);
if (generalSettings == null) return false;
var assignedSettings = generalSettings.AssignedSettings;
if (assignedSettings == null) return false;
string[] defineSymbols = PlayerSettings.GetScriptingDefineSymbols(NamedBuildTarget.Android).Split(';');
List<string> defineSymbolsList = new List<string>(defineSymbols);
bool modified = false;
foreach (XRLoader loader in assignedSettings.activeLoaders)
{
#if UNITY_OPENXR
if (loader is OpenXRLoader)
{
if (!defineSymbolsList.Contains(_openxr_xdk))
{
defineSymbolsList.Add(_openxr_xdk);
modified = true;
}
}
#endif
if (loader is PXR_Loader)
{
modified |= defineSymbolsList.Remove(PXR_Utils._openxr_xdk);
}
}
if (modified)
{
PXR_Utils.ReSetCapabilityProfileSelection();
string finalSymbols = string.Join(";", defineSymbolsList);
PlayerSettings.SetScriptingDefineSymbols(NamedBuildTarget.Android, finalSymbols);
return true;
}
return false;
}
#endregion
#if URP
public static UniversalRenderPipelineAsset GetCurrentURPAsset()
{
UniversalRenderPipelineAsset universalRenderPipelineAsset = null;
if (QualitySettings.renderPipeline != null)
{
universalRenderPipelineAsset = (UniversalRenderPipelineAsset)QualitySettings.renderPipeline;
}
else if (GraphicsSettings.currentRenderPipeline != null)
{
universalRenderPipelineAsset = (UniversalRenderPipelineAsset)GraphicsSettings.defaultRenderPipeline;
}
return universalRenderPipelineAsset;
}
#endif
public static void DisableHDR()
{
#if URP
if (QualitySettings.renderPipeline != null)
{
UniversalRenderPipelineAsset universalRenderPipelineAsset = (UniversalRenderPipelineAsset)QualitySettings.renderPipeline;
universalRenderPipelineAsset.supportsHDR = false;
}
else if (GraphicsSettings.currentRenderPipeline != null)
{
UniversalRenderPipelineAsset universalRenderPipelineAsset = (UniversalRenderPipelineAsset)GraphicsSettings.defaultRenderPipeline;
universalRenderPipelineAsset.supportsHDR = false;
}
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dba8b5e166a8df943b94a4a307890a8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,63 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.XR.PXR;
using UnityEditor;
using UnityEditor.XR.Management;
using UnityEngine;
using UnityEngine.XR.Management;
#if UNITY_OPENXR
using UnityEngine.XR.OpenXR;
#endif
[XRCustomLoaderUI("Unity.XR.PXR.PXR_Loader", BuildTargetGroup.Standalone)]
[XRCustomLoaderUI("Unity.XR.PXR.PXR_Loader", BuildTargetGroup.Android)]
internal class PXR_XRLoaderUI : IXRCustomLoaderUI
{
public static readonly GUIContent k_LoaderName = new GUIContent("PICO");
protected float renderLineHeight = 0;
/// <inheritdoc/>
public float RequiredRenderHeight { get; protected set; }
public virtual void SetRenderedLineHeight(float height)
{
renderLineHeight = height;
RequiredRenderHeight = height;
}
protected Rect CalculateRectForContent(float xMin, float yMin, GUIStyle style, GUIContent content)
{
var size = style.CalcSize(content);
var rect = new Rect();
rect.xMin = xMin;
rect.yMin = yMin;
rect.width = size.x;
rect.height = renderLineHeight;
return rect;
}
public void OnGUI(Rect rect)
{
float xMin = rect.xMin;
float yMin = rect.yMin;
var labelRect = CalculateRectForContent(xMin, yMin, EditorStyles.toggle, k_LoaderName);
var newToggled = EditorGUI.ToggleLeft(labelRect, k_LoaderName, IsLoaderEnabled);
if (newToggled != IsLoaderEnabled)
{
IsLoaderEnabled = newToggled;
}
PXR_Utils.UpdateSDKSymbols();
}
public bool IsLoaderEnabled { get; set; }
public string[] IncompatibleLoaders => new string[]
{
"UnityEngine.XR.OpenXR.OpenXRLoader",
"UnityEngine.XR.WindowsMR.WindowsMRLoader",
"Unity.XR.Oculus.OculusLoader",
};
public BuildTargetGroup ActiveBuildTargetGroup { get; set; }
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea44ec7d2f0948146bf4054ce6b398bf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4d63b7efba6a1a4468976ca8dbc3572f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,122 @@
using System;
using System.Linq;
using Unity.XR.CoreUtils.Editor;
using Unity.XR.PXR;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Rendering;
using UnityEditor.XR.Management;
using UnityEngine;
#if PICO_OPENXR_SDK
using Unity.XR.OpenXR.Features.PICOSupport;
#endif
static class PXR_ProjectValidationOptional
{
const string k_Catergory = "PICO Optional";
[InitializeOnLoadMethod]
static void AddOptionalRules()
{
var androidGlobalRules = new[]
{
#region Cross-Platform Validation (PXR & OpenXR)
new BuildValidationRule
{
Category = k_Catergory,
Message = "Disable Realtime GI.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return !Lightmapping.realtimeGI;
},
FixItMessage = "Open Window > Rendering > Lighting > Realtime Lighting > Realtime Global lllumination: disabled.",
FixIt = () =>
{
Lightmapping.realtimeGI = false;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_DisableRealtimeGI);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Enable GPU Skinning.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return PlayerSettings.gpuSkinning;
},
FixItMessage = "Open Project Settings > Player Settings > Player> Other Settings > GPU Skinning :enabled",
FixIt = () =>
{
PlayerSettings.gpuSkinning = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_GPUSkinning);
},
Error = false
},
#endregion
#region PXR Platform Validation
new BuildValidationRule
{
Category = k_Catergory,
Message = "When enabling ET or ETFR, option 'Eye Tracking Calibration' can be used.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
if (PXR_ProjectSetting.GetProjectConfig().eyeTracking || PXR_ProjectSetting.GetProjectConfig().enableETFR)
{
return PXR_ProjectSetting.GetProjectConfig().eyetrackingCalibration;
}
return true;
},
FixItMessage = "PXR_Manager > 'Eye Tracking Calibration' set to enable.",
FixIt = () =>
{
PXR_ProjectSetting.GetProjectConfig().eyetrackingCalibration = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_EyeTrackingCalibration);
},
Error = false
},
#endregion
#region PICO OpenXR Validation
#if PICO_OPENXR_SDK
new BuildValidationRule
{
Category = k_Catergory,
Message = "When enabling ET or ETFR, option 'Eye Tracking Calibration' can be used.",
IsRuleEnabled = PXR_Utils.IsOpenXRValidationEnabled,
CheckPredicate = () =>
{
if (PXR_OpenXRProjectSetting.GetProjectConfig().isEyeTracking ||
(PXR_OpenXRProjectSetting.GetProjectConfig().foveatedRenderingMode == FoveationFeature.FoveatedRenderingMode.EyeTrackedFoveatedRendering &&
PXR_OpenXRProjectSetting.GetProjectConfig().foveatedRenderingLevel != FoveationFeature.FoveatedRenderingLevel.Off))
{
return PXR_OpenXRProjectSetting.GetProjectConfig().isEyeTrackingCalibration;
}
return true;
},
FixItMessage = "PXR_Manager > 'Eye Tracking Calibration' set to enable.",
FixIt = () =>
{
PXR_OpenXRProjectSetting.GetProjectConfig().isEyeTrackingCalibration = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_EyeTrackingCalibration);
},
Error = false
},
#endif
#endregion
};
BuildValidator.AddRules(BuildTargetGroup.Android, androidGlobalRules);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 722e801b1e226c44ebcb4c18060d4b11
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,726 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.XR.CoreUtils;
using Unity.XR.CoreUtils.Editor;
using Unity.XR.PXR;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Rendering;
using UnityEditor.XR.Management;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.XR;
using static Unity.XR.CoreUtils.XROrigin;
#if URP
using UnityEngine.Rendering.Universal;
#endif
#if PICO_OPENXR_SDK
using Unity.XR.OpenXR.Features.PICOSupport;
#endif
static class PXR_ProjectValidationRecommend
{
const string k_Catergory = "PICO Recommend";
[InitializeOnLoadMethod]
static void AddRecommendRules()
{
#if UNITY_2021_2_OR_NEWER
NamedBuildTarget recommendedBuildTarget = NamedBuildTarget.Android;
#else
const BuildTargetGroup recommendedBuildTarget = BuildTargetGroup.Android;
#endif
var androidGlobalRules = new[]
{
#region Cross-Platform Validation (PXR & OpenXR)
new BuildValidationRule
{
Category = k_Catergory,
Message = "Set 'Target API Level' to automatic.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return PlayerSettings.Android.targetSdkVersion == AndroidSdkVersions.AndroidApiLevelAuto;
},
FixItMessage = "Open Project Settings > Player Settings > Player> Other Settings > 'Target API Level' to set automatic.",
FixIt = () =>
{
PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_TargetAPILevelAuto);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Set 'Install Location' to automatic.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return PlayerSettings.Android.preferredInstallLocation == AndroidPreferredInstallLocation.Auto;
},
FixItMessage = "Open Project Settings > Player Settings > Player> Other Settings > 'Install Location' to set automatic.",
FixIt = () =>
{
PlayerSettings.Android.preferredInstallLocation = AndroidPreferredInstallLocation.Auto;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_InstallLocationAuto);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "'Graphics Jobs' using disable.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return !PlayerSettings.graphicsJobs;
},
FixItMessage = "Open Project Settings > Player Settings > Player> Other Settings > 'Graphics Jobs' set to disable.",
FixIt = () =>
{
PlayerSettings.graphicsJobs = false;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_DisableGraphicsJobs);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using tracking origin mode : Device or Floor.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
List<XROrigin> components = FindComponentsInScene<XROrigin>().Where(component => component.isActiveAndEnabled).ToList();
foreach(XROrigin origin in components)
{
if (TrackingOriginMode.NotSpecified == origin.RequestedTrackingOriginMode)
{
return false;
}
}
return true;
},
FixItMessage = "XROrigin > TrackingOriginMode.Device.",
FixIt = () =>
{
List<XROrigin> components = FindComponentsInScene<XROrigin>().Where(component => component.isActiveAndEnabled).ToList();
foreach(XROrigin origin in components)
{
origin.RequestedTrackingOriginMode = TrackingOriginMode.Device;
}
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_TrackingOriginModeDevice);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using recommended 'Texture compression': ETC2 or ASTC.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return EditorUserBuildSettings.androidBuildSubtarget == MobileTextureSubtarget.ASTC ||
EditorUserBuildSettings.androidBuildSubtarget == MobileTextureSubtarget.ETC2;
},
FixItMessage = "Open Project Settings > 'Texture compression'.",
FixIt = () =>
{
EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.ETC2;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_ETC2);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using '32-bit Display Buffer*'.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return PlayerSettings.use32BitDisplayBuffer;
},
FixItMessage = "Open Project Settings > Player Settings > Player> Resolution and Presentation > 'Use 32-bit Display Buffer*' set enable.",
FixIt = () =>
{
PlayerSettings.use32BitDisplayBuffer = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_DisplayBufferFormat);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using Multithreaded Rendering.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return PlayerSettings.GetMobileMTRendering(recommendedBuildTarget);
},
FixItMessage = "Open Project Settings > Player Settings > Player> Other Settings > 'Multithreaded Rendering' set to enable.",
FixIt = () =>
{
PlayerSettings.SetMobileMTRendering(recommendedBuildTarget, true);
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_Multithreaded);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using recommended 'Pixel Light Count'.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
if(EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
{
return QualitySettings.pixelLightCount <= 1;
}
return true;
},
FixItMessage = "Open Project Settings > Player Settings> Quality> 'Pixel Light Count' set to 1.",
FixIt = () =>
{
QualitySettings.pixelLightCount = 1;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_MaximumPixelLights);
},
Error = false
},
#if UNITY_2022_2_OR_NEWER
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using recommended Texture Quality.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return QualitySettings.globalTextureMipmapLimit == 0;
},
FixItMessage = "Open Project Settings > Player Settings> Quality> 'Global Mipmap Limit' set to '0: Full Resolution'.",
FixIt = () =>
{
QualitySettings.globalTextureMipmapLimit = 0;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_TextureQualitytoFullRes);
},
Error = false
},
#else
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using recommended Texture Quality.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return QualitySettings.masterTextureLimit == 0;
},
FixItMessage = "Open Project Settings > Player Settings> Quality> 'Texture Quality' set to 'Full Res'.",
FixIt = () =>
{
QualitySettings.masterTextureLimit = 0;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_TextureQualitytoFullRes);
},
Error = false
},
#endif
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using recommended 'Anisotropic Texture'.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return QualitySettings.anisotropicFiltering == AnisotropicFiltering.Enable;
},
FixItMessage = "Open Project Settings > Player Settings> Quality> 'Anisotropic Texture' set to 'Per Texture'.",
FixIt = () =>
{
QualitySettings.anisotropicFiltering = AnisotropicFiltering.Enable;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_AnisotropicFiltering);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using rendering path: forward.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Android, Graphics.activeTier).renderingPath == RenderingPath.Forward;
},
FixItMessage = "Open Project Settings > Player Settings> Graphics > RenderingPath.Forward.",
FixIt = () =>
{
var renderingTier = EditorGraphicsSettings.GetTierSettings(BuildTargetGroup.Android, Graphics.activeTier);
renderingTier.renderingPath = RenderingPath.Forward;
EditorGraphicsSettings.SetTierSettings(BuildTargetGroup.Android, Graphics.activeTier, renderingTier);
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_RenderingPathToForward);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using stereo rendering mode: multiview.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return GetSettings().stereoRenderingModeAndroid == PXR_Settings.StereoRenderingModeAndroid.Multiview;
},
FixItMessage = "Open Project Settings > Player Settings> PICO > Stereo Rendering Mode: Multiview.",
FixIt = () =>
{
GetSettings().stereoRenderingModeAndroid = PXR_Settings.StereoRenderingModeAndroid.Multiview;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_Multiview);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using Default Contact Offset: 0.01f.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return Physics.defaultContactOffset >= 0.01f;
},
FixItMessage = "Open Project Settings > Player Settings> Physics > Default Contact Offset: 0.01f.",
FixIt = () =>
{
Physics.defaultContactOffset = 0.01f;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_ContactOffset001);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using Sleep Threshold: 0.005f.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return Physics.sleepThreshold >= 0.005f;
},
FixItMessage = "Open Project Settings > Player Settings> Physics > Sleep Threshold: 0.005f.",
FixIt = () =>
{
Physics.sleepThreshold = 0.005f;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_SleepThreshold0005);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using Default Solver Iterations: 8.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return Physics.defaultSolverIterations <= 8;
},
FixItMessage = "Open Project Settings > Player Settings> Physics > Default Solver Iterations: 8.",
FixIt = () =>
{
Physics.defaultSolverIterations = 8;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_SolverIteration8);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = $"A single scene recommended up to 4 compositor layers.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
return FindComponentsInScene<PXR_CompositionLayer>().Where(component => component.isActiveAndEnabled).ToList().Count <= 4;
},
FixItMessage = "You can click 'Fix' to navigate to the designated developer documentation page and follow the instructions to set it. ",
FixIt = () =>
{
string url = "https://developer.picoxr.com/en/document/unity/vr-compositor-layers/";
Application.OpenURL(url);
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_Overlay4);
},
Error = false
},
#if URP
new BuildValidationRule
{
Category = k_Catergory,
Message = "When using URP, set IntermediateTextureMode.Auto.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
UniversalRenderPipelineAsset universalRenderPipelineAsset = PXR_Utils.GetCurrentURPAsset();
if(universalRenderPipelineAsset != null)
{
var path = AssetDatabase.GetAssetPath(universalRenderPipelineAsset);
var dependency = AssetDatabase.GetDependencies(path);
for (int i = 0; i < dependency.Length; i++)
{
if (AssetDatabase.GetMainAssetTypeAtPath(dependency[i]) != typeof(UniversalRendererData))
continue;
UniversalRendererData renderData = (UniversalRendererData)AssetDatabase.LoadAssetAtPath(dependency[i], typeof(UniversalRendererData));
return renderData.intermediateTextureMode == IntermediateTextureMode.Auto;
}
}
return true;
},
FixItMessage = "Open Universal Render Pipeline Asset_Renderer > set IntermediateTextureMode.Auto.",
FixIt = () =>
{
UniversalRenderPipelineAsset universalRenderPipelineAsset = PXR_Utils.GetCurrentURPAsset();
if(universalRenderPipelineAsset != null)
{
var path = AssetDatabase.GetAssetPath(universalRenderPipelineAsset);
var dependency = AssetDatabase.GetDependencies(path);
for (int i = 0; i < dependency.Length; i++)
{
if (AssetDatabase.GetMainAssetTypeAtPath(dependency[i]) != typeof(UniversalRendererData))
continue;
UniversalRendererData renderData = (UniversalRendererData)AssetDatabase.LoadAssetAtPath(dependency[i], typeof(UniversalRendererData));
renderData.intermediateTextureMode = IntermediateTextureMode.Auto;
}
}
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_URPIntermediatetexturetoAuto);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "When using URP, set disable SSAO.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
UniversalRenderPipelineAsset universalRenderPipelineAsset = PXR_Utils.GetCurrentURPAsset();
if(universalRenderPipelineAsset != null)
{
var path = AssetDatabase.GetAssetPath(universalRenderPipelineAsset);
var dependency = AssetDatabase.GetDependencies(path);
for (int i = 0; i < dependency.Length; i++)
{
if (AssetDatabase.GetMainAssetTypeAtPath(dependency[i]) != typeof(UniversalRendererData))
continue;
UniversalRendererData renderData = (UniversalRendererData)AssetDatabase.LoadAssetAtPath(dependency[i], typeof(UniversalRendererData));
return renderData.rendererFeatures.Count == 0 || !renderData.rendererFeatures.Any(feature => feature != null && (feature.isActive && feature.GetType().Name == "ScreenSpaceAmbientOcclusion"));
}
}
return true;
},
FixItMessage = "Open Universal Render Pipeline Asset_Renderer > disable ScreenSpaceAmbientOcclusion.",
FixIt = () =>
{
UniversalRenderPipelineAsset universalRenderPipelineAsset = PXR_Utils.GetCurrentURPAsset();
if(universalRenderPipelineAsset != null)
{
var path = AssetDatabase.GetAssetPath(universalRenderPipelineAsset);
var dependency = AssetDatabase.GetDependencies(path);
for (int i = 0; i < dependency.Length; i++)
{
if (AssetDatabase.GetMainAssetTypeAtPath(dependency[i]) != typeof(UniversalRendererData))
continue;
UniversalRendererData renderData = (UniversalRendererData)AssetDatabase.LoadAssetAtPath(dependency[i], typeof(UniversalRendererData));
foreach( var feature in renderData.rendererFeatures)
{
if (feature != null && feature.GetType().Name == "ScreenSpaceAmbientOcclusion")
feature.SetActive(false);
}
}
}
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_URPDisableSSAO);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "When the URP package is installed but not set up and used, it is recommended to use or delete it.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
if (QualitySettings.renderPipeline == null && GraphicsSettings.currentRenderPipeline == null)
{
return false;
}
return true;
},
FixItMessage = "If you are not clear about how to set it, you can click 'Fix' to navigate to the designated developer documentation page and follow the instructions to set it.",
FixIt = () =>
{
string url = "https://developer-cn.picoxr.com/document/unity/universal-render-pipeline/";
Application.OpenURL(url);
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_URPNoUseToDelete);
},
Error = false
},
#endif
#if UNITY_6000_0_OR_NEWER
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using recommended 'Run Without Focus'.",
IsRuleEnabled = ()=>
{
return PXR_Utils.IsPXRValidationEnabled() || PXR_Utils.IsOpenXRValidationEnabled();
},
CheckPredicate = () =>
{
bool isRunInBackgroundEnabled = PlayerSettings.runInBackground;
return isRunInBackgroundEnabled;
},
FixItMessage = "Open Project Settings > Player Settings > Player > Resolution and Presentation > Resolution > 'Run Without Focus' set to enable.",
FixIt = () =>
{
PlayerSettings.runInBackground = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_Unity6RunInBackground);
},
Error = false
},
#endif
#endregion
#region PXR Platform Validation
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using MRC.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
return PXR_ProjectSetting.GetProjectConfig().openMRC;
},
FixItMessage = "PXR_Manager > 'MRC' set to enable.",
FixIt = () =>
{
PXR_ProjectSetting.GetProjectConfig().openMRC = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_MRC);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Recommended to set system refresh rate to default. After setting, executed based on device rates.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
return GetSettings().systemDisplayFrequency == PXR_Settings.SystemDisplayFrequency.Default;
},
FixItMessage = "Open Project Settings > Player Settings> PICO > Display Refresh Rates: Default.",
FixIt = () =>
{
GetSettings().systemDisplayFrequency = PXR_Settings.SystemDisplayFrequency.Default;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_DisplayRefreshRatesDefault);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "When using Vulkan, it is recommended to check the 'Optimize Buffer Discards' option.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
if (GraphicsDeviceType.OpenGLES3 == PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget)[0])
{
return true;
}
return GetSettings().optimizeBufferDiscards;
},
FixItMessage = "Open Project Settings > Player Settings> PICO > 'Optimize Buffer Discards' set to enable.",
FixIt = () =>
{
GetSettings().optimizeBufferDiscards = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_VKOptimizeBufferDiscards);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "'Color Space' using Linear.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
return PlayerSettings.colorSpace == ColorSpace.Linear;
},
FixItMessage = "Open Project Settings > Player Settings > Player> Other Settings > 'Color Space' set to 'Linear'.",
FixIt = () =>
{
PlayerSettings.colorSpace = ColorSpace.Linear;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_ColorSpaceLinear);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "When using ETFR/FFR, it is recommended to enable subsampling to improve performance.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
if (PXR_ProjectSetting.GetProjectConfig().recommendSubsamping)
{
return PXR_ProjectSetting.GetProjectConfig().enableSubsampled;
}
return true;
},
FixItMessage = "PXR_Manager > Subsamping set to enable.",
FixIt = () =>
{
PXR_ProjectSetting.GetProjectConfig().enableSubsampled = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_FFRSubsampling);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Using recommended MSAA.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
if (PXR_ProjectSetting.GetProjectConfig().recommendMSAA)
{
return PXR_ProjectSetting.GetProjectConfig().enableRecommendMSAA;
}
return true;
},
FixItMessage = "PXR_Manager > 'Use Recommended MSAA' set to enable.",
FixIt = () =>
{
PXR_ProjectSetting.GetProjectConfig().enableRecommendMSAA = true;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_MSAA);
},
Error = false
},
new BuildValidationRule
{
Category = k_Catergory,
Message = "Not recommended to use both 'Application SpaceWarp' and 'Content Protect' simultaneously.",
IsRuleEnabled = PXR_Utils.IsPXRValidationEnabled,
CheckPredicate = () =>
{
return !(PXR_ProjectSetting.GetProjectConfig().useContentProtect && GetSettings().enableAppSpaceWarp);
},
FixItMessage = "Open Project Settings > Player Settings> PICO > Application SpaceWarp: disabled.",
FixIt = () =>
{
GetSettings().enableAppSpaceWarp = false;
PXR_AppLog.PXR_OnEvent(PXR_AppLog.strProjectValidation, PXR_AppLog.strProjectValidation_APPSWNoContentProtect);
},
Error = false
},
#endregion
#region PICO OpenXR Validation
#endregion
};
BuildValidator.AddRules(BuildTargetGroup.Android, androidGlobalRules);
}
static PXR_Settings GetSettings()
{
PXR_Settings settings = null;
#if UNITY_EDITOR
UnityEditor.EditorBuildSettings.TryGetConfigObject<PXR_Settings>("Unity.XR.PXR.Settings", out settings);
#endif
#if UNITY_ANDROID && !UNITY_EDITOR
settings = PXR_Settings.settings;
#endif
return settings;
}
public static List<T> FindComponentsInScene<T>() where T : Component
{
var activeScene = SceneManager.GetActiveScene();
var foundComponents = new List<T>();
var rootObjects = activeScene.GetRootGameObjects();
foreach (var rootObject in rootObjects)
{
var components = rootObject.GetComponentsInChildren<T>(true);
foundComponents.AddRange(components);
}
return foundComponents;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0de36cde8e3d3df4684f21ecfea95d77
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ee7b364f4dea3945a08be5340c61410
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,67 @@
{
"name": "Unity.XR.PICO.Editor",
"rootNamespace": "",
"references": [
"Unity.XR.PICO",
"Unity.XR.Management",
"Unity.XR.Management.Editor",
"Unity.XR.ARFoundation",
"Unity.XR.CoreUtils",
"Unity.XR.CoreUtils.Editor",
"Unity.RenderPipelines.Universal.Runtime",
"Unity.XR.Interaction.Toolkit",
"Unity.InputSystem",
"Unity.XR.Hands.Samples.VisualizerSample",
"Unity.XR.Hands",
"Unity.XR.OpenXR",
"Unity.XR.OpenXR.Editor",
"Pico.Spatializer"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.xr.management",
"expression": "3.2.0",
"define": "XR_MGMT_GTE_320"
},
{
"name": "com.unity.xr.hands",
"expression": "1.3.0",
"define": "XR_HAND"
},
{
"name": "com.unity.render-pipelines.universal",
"expression": "12.1.12",
"define": "URP"
},
{
"name": "com.unity.xr.openxr",
"expression": "",
"define": "UNITY_OPENXR"
},
{
"name": "com.unity.xr.arfoundation",
"expression": "[5.1.2,6.0.0]",
"define": "AR_FOUNDATION_5"
},
{
"name": "com.unity.xr.arfoundation",
"expression": "6.0.0",
"define": "AR_FOUNDATION_6"
},
{
"name": "com.unity.xr.interaction.toolkit",
"expression": "3.0.0",
"define": "XRI_TOOLKIT_3"
}
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: cc14c791d414ba84589e05cbda4403fd
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: