diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ea0951..2ef9c44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [2.1.0] + +### Features +- Update OpenXR Plugin dependency to `1.10.0`. +- Added `Magic Leap 2 Facial Expressions` OpenXR Feature. +- Added `Magic Leap 2 Environmental Meshing` OpenXR feature. +- Added `Magic Leap 2 Spatial Anchors` OpenXR Feature +- Added `Magic Leap 2 Spatial Anchors Storage` OpenXR Feature +- Added `MagicLeap.Android.Permissions`, a new and improved Permissions API. +- Included an AprilTagSettings struct to the `Magic Leap 2 Marker Understanding` OpenXR Feature + +### Experimental +- Added `AndroidCamera` APIs for performing basic YUV and JPEG Camera capture. + +### Bugfixes +- Fixed issue where JPEG screen capture with `MLCamera` was not displaying an image. +- Fixed legacy `MLPlanes` subsystem not being initialized when using Magic Leap XR Provider. +- Added project validation rules to check for Player Settings required by Magic Leap 2. +- Fixed `MLCVCamera` being unable to query Headpose from the MLSDK when the OpenXR PRovider is active. +- Fixed `MLMarkerTracker` issue where detected `AprilTag` markers are flipped. + +### Deprecations & Removals +- Removed Preferences>External Tools>Magic Leap. +- Marked `MLPermissions` Obsolete. Use `MagicLeap.Android.Permissions` instead. + +### Known Issues +- `MLAnchors` API does not work when the `Magic Leap 2 Spatial Anchors` or `Magic Leap 2 Spatial Anchors Storage` OpenXR Features are enabled. + +### Misc. +- Renamed the ML Rig & Inputs Sample input actions asset as well as the old `MagicLeapInputs` asset to make it clear what the differences are. + ## [2.0.0] ### Features diff --git a/Editor/APKBuilder.cs b/Editor/APKBuilder.cs index cb993c6..bf50ca1 100644 --- a/Editor/APKBuilder.cs +++ b/Editor/APKBuilder.cs @@ -15,13 +15,6 @@ public class APKBuilder private static readonly string Arg_ForceSDKPathFromEnvVar = "--force_sdk_path_from_env_var"; private static readonly string Arg_AppVersionCodeValue = "--version-code"; -#if !UNITY_2022_2_OR_NEWER - private static readonly Dictionary BuildTargetToGroup = new Dictionary() - { - { BuildTarget.Relish, BuildTargetGroup.Relish } - }; -#endif - private bool didSetSDKPathFromEnvVar = false; private class BuildSettingsCache @@ -71,15 +64,8 @@ private void Build() { throw new System.Exception("You must be on the Android Build Target to use APKBuilder."); } -#else - if (!BuildTargetToGroup.ContainsKey(EditorUserBuildSettings.activeBuildTarget)) - { - throw new System.Exception($"Unsupported build target {EditorUserBuildSettings.activeBuildTarget} for APKBuilder. Only Relish build target is supported."); - } #endif - SetupSDKPaths(System.Array.IndexOf(System.Environment.GetCommandLineArgs(), Arg_ForceSDKPathFromEnvVar) != -1); - BuildSettingsCache buildSettingsCache = new BuildSettingsCache(); try @@ -252,43 +238,6 @@ private bool TryGetArgValue(string arg, ref string value) return false; } - /// - /// Magic Leap SDK is required during the build process to include the - /// correct permissions in AndroidManifest.xml. - /// - /// - private void SetupSDKPaths(bool bForceSetFromEnvVar) - { - bool didSetFromEnvVar = false; - if (bForceSetFromEnvVar || !MagicLeapSDKUtil.SdkAvailable) - { - string relishSDKPath = System.Environment.GetEnvironmentVariable("RELISHSDK_UNITY"); - if (string.IsNullOrEmpty(relishSDKPath)) - { - Debug.LogWarning("No SDK path found for Relish in editor preferences or RELISHSDK_UNITY environment variable. Build will probably fail OR Magic Leap permissions will not be included in AndroidManifest.xml."); - } - else - { - if (bForceSetFromEnvVar) - { - Debug.LogFormat("{0} was passed as cmd line arg. Force setting Relish SDK Path to {1} from env vars.", Arg_ForceSDKPathFromEnvVar, relishSDKPath); - } - else - { - Debug.LogFormat("No SDK path set for Relish in editor preferences. Using {0} from env vars.", relishSDKPath); - } - MagicLeapSDKUtil.SdkPath = relishSDKPath; - didSetFromEnvVar = true; - } - } - else - { - Debug.LogFormat("Relish SDK found in editor preferences at {0}", MagicLeapSDKUtil.SdkPath); - } - - this.didSetSDKPathFromEnvVar = didSetFromEnvVar; - } - [Serializable] private class SimplePackageManifest { diff --git a/Editor/MLAppSim/AppSimShimLibSupport.cs b/Editor/MLAppSim/AppSimShimLibSupport.cs deleted file mode 100644 index dd2cec2..0000000 --- a/Editor/MLAppSim/AppSimShimLibSupport.cs +++ /dev/null @@ -1,114 +0,0 @@ -// %BANNER_BEGIN% -// --------------------------------------------------------------------- -// %COPYRIGHT_BEGIN% -// Copyright (c) (2021-2022) Magic Leap, Inc. All Rights Reserved. -// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2 -// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein. -// %COPYRIGHT_END% -// --------------------------------------------------------------------- -// %BANNER_END% - -using System; -using System.Collections.Generic; -using System.IO; -using UnityEngine; -using System.Linq; -using UnityEngine.XR.MagicLeap; -using UnityEngine.XR.Management; -using UnityEditor.XR.Management; -#if UNITY_OPENXR_1_9_0_OR_NEWER -using UnityEngine.XR.OpenXR; -#endif - -namespace UnityEditor.XR.MagicLeap -{ - public static class AppSimShimLibSupport - { - private static string LaunchProcess => Path.Combine(MagicLeapSDKUtil.AppSimRuntimePath, "bin/ZIDiscovery"); - - public static readonly string SessionStateKey_ZISearchPaths = "ZI_SEARCH_PATHS"; - private static List libSearchPaths = new List(); - - /// - /// Gets called before the XR Loader starts initializing all the subsystems. - /// Runs ZIDiscovery.exe to get the list of folders where the ZI shim - /// libs reside and sends them to the SDK loader lib. - /// - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] - private static void CheckForLibrarySearchPaths() - { - var settings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(BuildTargetGroup.Standalone); - if (settings == null || settings.Manager == null ) - { - return; - } - - bool foundSupportedLoader = false; -#if UNITY_XR_MAGICLEAP_PROVIDER - foundSupportedLoader = settings.Manager.activeLoaders.Any(l => l is MagicLeapLoader); -#elif UNITY_OPENXR_1_9_0_OR_NEWER - foundSupportedLoader = settings.Manager.activeLoaders.Any(l => l is OpenXRLoader); -#endif - - if (!foundSupportedLoader) - { - Debug.LogError("No supported XR loader found for AppSim"); - return; - } - - string cachedSearchPaths = SessionState.GetString(SessionStateKey_ZISearchPaths, string.Empty); - if (string.IsNullOrEmpty(cachedSearchPaths)) - { - var ziRuntime = MagicLeapSDKUtil.AppSimRuntimePath; - if (string.IsNullOrEmpty(ziRuntime)) - { - Debug.LogError("Zero Iteration Runtime path is not set."); - SettingsService.OpenUserPreferences("Preferences/External Tools/Magic Leap"); - return; - } - -#if UNITY_EDITOR_WIN - ziRuntime = ziRuntime.Replace("/", "\\"); -#endif - var startInfo = new System.Diagnostics.ProcessStartInfo - { - UseShellExecute = false, - FileName = LaunchProcess, - Arguments = $"-m\"{MagicLeapSDKUtil.SdkPath}\" -p", - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true - }; - - var discoveryProc = new System.Diagnostics.Process(); - discoveryProc.EnableRaisingEvents = true; - discoveryProc.StartInfo = startInfo; - - discoveryProc.Start(); - - StreamReader outputStream = discoveryProc.StandardOutput; - - string output = outputStream.ReadToEnd(); - - discoveryProc.WaitForExit(); - - if (discoveryProc.ExitCode != 0) - { - StreamReader errorStream = discoveryProc.StandardError; - var error = errorStream.ReadToEnd(); - Debug.LogError($"ZIDiscovery returned with code {discoveryProc.ExitCode}: {error}"); - return; - } - - libSearchPaths = new List(output.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries)); - SessionState.SetString(SessionStateKey_ZISearchPaths, string.Join(Path.PathSeparator, libSearchPaths)); - } - else - { - libSearchPaths = new List(cachedSearchPaths.Split(Path.PathSeparator)); - } - - MagicLeapXrProvider.AddLibrarySearchPaths(libSearchPaths, settings.Manager.activeLoaders); - } - } -} diff --git a/Editor/MLAppSim/LabDriverControl.cs b/Editor/MLAppSim/LabDriverControl.cs deleted file mode 100644 index 0f816a9..0000000 --- a/Editor/MLAppSim/LabDriverControl.cs +++ /dev/null @@ -1,431 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using UnityEditor; -using UnityEditor.UIElements; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.UIElements; - -namespace UnityEditor.XR.MagicLeap -{ - public class LabDriverControl : EditorWindow - { - private IMGUIContainer _remoteChecksUi; - private VisualElement _mainVisualContainer; - - private string[] _availablePackages = new string[] { }; - - internal static StringBuilder s_LabdriverLog = new StringBuilder(); - internal static StringBuilder s_LabdriverErrorLog = new StringBuilder(); - - internal static bool s_LabdriverIsRunning = false; - internal static bool s_LabdriverExit = false; - internal static bool s_LabdriverOutputDone = false; - internal static bool s_LabdriverIsImport = false; - internal static Action s_LabdriverOnComplete = null; - - private static int progressId; - - private static Process s_Process; - - internal class JSONObject - { - public List results = null; - public bool success; - } - - [Serializable] - internal class JSONResult - { - public List output = null; - public List error = null; - } - - private void OnDisable() - { - } - - private void OnEnable() - { - _remoteChecksUi = new IMGUIContainer(OnRemoteChecksUI); - _mainVisualContainer = new VisualElement() - { - name = "MainVisualContainer" - }; - _mainVisualContainer.Add(_remoteChecksUi); - var root = this.rootVisualElement; - root.Add(_mainVisualContainer); - - _availablePackages = MagicLeapPackageLocator.GetUnityPackages().ToArray(); - } - - private void OnGUI() - { - - } - - private void OnRemoteChecksUI() - { - GUILayout.Label("Magic Leap App Simulator Requirements", EditorStyles.boldLabel); - - using (new GUILayout.HorizontalScope()) - { - if (GUILayout.Button("Import MagicLeap unitypackage")) - { - var rect = GUILayoutUtility.GetLastRect(); - var versions = new GenericMenu(); - foreach (var pkg in _availablePackages) - { - versions.AddItem(new GUIContent(pkg), false, InstallPackage, pkg); - } - // show options as a drop down. - versions.DropDown(rect); - } - } - } - - //[MenuItem("Window/XR/MagicLeap Dashboard", false, 1)] - private static void Display() - { - // Get existing open window or if none, make a new one: - EditorWindow.GetWindow(false, "ML Dashboard").Show(); - } - - private void InstallPackage(object p) - { - var path = p as string; - UnityEngine.Debug.LogFormat("Importing: {0}", path); - AssetDatabase.ImportPackage(path, true); - } - - // EditorUtility.DisplayProgressbar must be called from the main thread - // Typically you would call it from OnGUI, but this class may not have its own GUI calls - // so instead we place it in the Editor's global update ticks. - private static void ShowProgressDialog() - { - if (s_LabdriverIsRunning) - { - EditorUtility.DisplayProgressBar("Magic Leap Hub", "Issuing command to Magic Leap Hub...", 1f); - } - else - { - EditorUtility.ClearProgressBar(); - EditorApplication.update -= ShowProgressDialog; - } - } - - internal static void LaunchLabDriver(List args, Action onComplete, bool importCommand = false, bool useVirtualDevice = false) - { - EditorApplication.update += ShowProgressDialog; - - s_LabdriverIsRunning = true; - s_LabdriverExit = false; - s_LabdriverOutputDone = false; - s_LabdriverLog.Clear(); - - var startInfo = new ProcessStartInfo - { - UseShellExecute = false, -#if UNITY_EDITOR_WIN - FileName = "cmd.exe", -#else // OSX or Linux - FileName = "/bin/sh", -#endif - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true - }; - - // copy arguments into new-style ArgumentList, which handles spaces properly -#if UNITY_EDITOR_WIN - // i.e. "cmd /C labdriver ..." runs this command rather than an interactive shell - startInfo.ArgumentList.Add("/C"); -#endif - foreach (string arg in args) - { - startInfo.ArgumentList.Add(arg); - } - - if (useVirtualDevice) - { - if (!startInfo.EnvironmentVariables.ContainsKey("ML_ZI_ROOT")) - { - startInfo.EnvironmentVariables.Add("ML_ZI_ROOT", MagicLeapSDKUtil.SdkPath + "/VirtualDevice"); - } - } - - s_Process = new System.Diagnostics.Process(); - s_Process.EnableRaisingEvents = true; - s_Process.OutputDataReceived += OnOutputReceived; - s_Process.Exited += OnProcessExit; - s_Process.ErrorDataReceived += OnErrorReceived; - s_Process.StartInfo = startInfo; - - s_LabdriverIsImport = importCommand; - s_LabdriverOnComplete = onComplete; - s_LabdriverLog.Clear(); - s_LabdriverErrorLog.Clear(); - - progressId = Progress.Start("Running labdriver process"); - - s_Process.Start(); - s_Process.BeginOutputReadLine(); - s_Process.BeginErrorReadLine(); - } - - private static void LaunchLabDriverCommand(List commands, Action onComplete) - { - var sdkPath = MagicLeapSDKUtil.SdkPath; - if (string.IsNullOrEmpty(sdkPath)) - { - UnityEngine.Debug.LogError("Magic Leap SDK path not configured!"); - return; - } - else if (!File.Exists(Path.Combine(sdkPath, "labdriver"))) - { - UnityEngine.Debug.LogErrorFormat("labdriver executable not found in configured SDK path \"{0}\"! Make sure the path is valid.", sdkPath); - return; - } - if (!s_LabdriverIsRunning) - { - UnityEngine.Debug.Log("Launching labdriver with: " + string.Join(" ", commands)); -#if UNITY_EDITOR_WIN - commands.InsertRange(0, new List{$"{sdkPath}/labdriver.cmd", "-pretty"}); -#else // OSX or Linux - commands.InsertRange(0, new List{$"{sdkPath}/labdriver", "-pretty"}); -#endif - LaunchLabDriver(commands, onComplete); - } - else - { - UnityEngine.Debug.Log("Previous Magic Leap Hub command is still running. Please wait until it completes."); - } - } - - private static void HandleLabDriverResult(bool success, string json) - { - if (!success) - { - UnityEngine.Debug.LogError("Magic Leap Hub command failed:\n" + json); - } - } - - [MenuItem("Magic Leap/Launch Magic Leap Hub")] - private static void LaunchHub() - { - LaunchLabDriverCommand(new List{"start-gui"}, HandleLabDriverResult); - } - - [MenuItem("Magic Leap/Save Diagnostic Logs...")] - private static void SaveLogs() - { - bool result = EditorUtility.DisplayDialog("Privacy Notice", - String.Concat( - "Create an error report file (.zip) to help us diagnose problems.\n\n", - "(Note: if you are using a Magic Leap device, please connect it now.)\n\n", - "Ask a question in the Magic Leap Developer Portal (https://developer.magicleap.cloud/support) " + - "and attach the error report .zip file.\n\n", - "Error reports are public, and the .zip file may contain identifying information, so you should inspect the .zip before sending.\n\n", - "See https://developer-docs.magicleap.cloud/docs/guides/developer-tools/ml-hub/error-reporting" - ), "Ok", "Cancel"); - if (!result) - { - return; - } - - string dateTime = DateTime.Now.ToString("yyyyMMddHHmmss"); - string tempFile = $"MLHubLogs-{dateTime}.zip"; - string tempFileDir = Path.GetTempPath(); - string tempFilePath = Path.Combine(tempFileDir, tempFile); - - void OpenLogFile(bool success, string json) - { - if (!success) - { - HandleLabDriverResult(success, json); - return; - } - - // reveal file in explorer/finder - ProcessStartInfo startInfo = null; -#if UNITY_EDITOR_OSX - startInfo = new ProcessStartInfo - { - UseShellExecute = false, - FileName = "/usr/bin/open", - ArgumentList = { "-R", tempFilePath }, - CreateNoWindow = true - }; -#elif UNITY_EDITOR_WIN - startInfo = new ProcessStartInfo - { - UseShellExecute = false, - FileName = "explorer.exe", - ArgumentList = { "/select,", tempFilePath }, // the embedded comma is needed - CreateNoWindow = true - }; -#endif - if (startInfo != null) - { - var process = new System.Diagnostics.Process(); - process.StartInfo = startInfo; - process.Start(); - } - } - - LaunchLabDriverCommand(new List{"save-logs", tempFilePath}, OpenLogFile); - } - - private static void WaitForComplete() - { - // Confirm the process has exited and the output has completed before processing logs. - if (s_LabdriverExit && s_LabdriverOutputDone) - { - s_Process.CancelErrorRead(); - s_Process.CancelOutputRead(); - String finalResult = s_LabdriverLog.ToString(); - - s_LabdriverIsRunning = false; - - Progress.Report(progressId, 1.0f); - - if (!String.IsNullOrEmpty(finalResult)) - { - JSONObject fullLog = JsonUtility.FromJson(finalResult); - - if (!fullLog.success) - { - ProcessLogs(fullLog); - } - else if (s_LabdriverIsImport) - { - IEnumerable ZILibraries = fullLog.results[0].output; - - // TODO : Lib discovery is no longer run via LabDriverControl. - // Refactor this class to remove unnecesarry code. - //ZeroIterationImportSupport.DiscoveryReturned(ZILibraries); - } - - Progress.Remove(progressId); - - if (s_LabdriverOnComplete != null) - { - // success - s_LabdriverOnComplete(true, finalResult); - } - } - else - { - String finalError = s_LabdriverErrorLog.ToString(); - - Progress.Remove(progressId); - - if (s_LabdriverOnComplete != null) - { - // failure - s_LabdriverOnComplete(false, finalError); - } - } - - s_LabdriverIsImport = false; - s_LabdriverOnComplete = null; - } - } - - private static void OnOutputReceived(object sender, DataReceivedEventArgs e) - { - if (!String.IsNullOrEmpty(e.Data)) - { - s_LabdriverLog.Append(e.Data); - - string statusCheck = s_LabdriverLog.ToString(); - - if ((statusCheck.Substring(statusCheck.Length - 1, 1) == "}") && statusCheck.Contains("\"success\":")) - { - s_LabdriverOutputDone = true; - WaitForComplete(); - } - s_LabdriverLog.Append(' '); - } - else - { - if (!s_LabdriverOutputDone) - { - s_LabdriverOutputDone = true; - WaitForComplete(); - } - } - } - - private static void OnErrorReceived(object sender, DataReceivedEventArgs e) - { - if (!String.IsNullOrEmpty(e.Data)) - { - s_LabdriverErrorLog.Append(e.Data); - s_LabdriverErrorLog.Append(' '); - } - } - - private static void OnProcessExit(object sender, EventArgs e) - { - s_LabdriverExit = true; - - WaitForComplete(); - } - - private static void ProcessLogs(JSONObject currentLogs) - { - string logToPrint = ""; - - foreach (JSONResult result in currentLogs.results) - { - foreach (string item in result.error) - { - if (!String.IsNullOrEmpty(item)) - { - logToPrint += "\n" + item; - } - } - } - - if (String.IsNullOrEmpty(logToPrint) || s_LabdriverIsImport) - { - String currentAction = s_LabdriverIsImport ? "import support libraries" : "launch Magic Leap App Simulator"; - logToPrint = String.Format("Magic Leap Hub encountered an unknown error while attempting to {0}. " + - "Please confirm Magic Leap Hub in installed and up to date with the Magic Leap App Simulator Module and " + - "Magic Leap App Simulator Runtime package installed.\n", currentAction) + logToPrint; - } - - String finalLog = "labdriver completed with errors. \nErrors:" + logToPrint; - - UnityEngine.Debug.LogError(finalLog); - } - } - - - internal static class MagicLeapPackageLocator - { - public static IEnumerable GetUnityPackages() - { - var tools = Path.Combine(MagicLeapRoot, "tools"); - return new DirectoryInfo(tools).GetFiles("*.unitypackage", SearchOption.AllDirectories).Select(fi => fi.FullName); - } - - private static string HomeFolder - { - get - { - var home = Environment.GetEnvironmentVariable("USERPROFILE"); - return (string.IsNullOrEmpty(home)) - ? Environment.GetEnvironmentVariable("HOME") - : home; - } - } - - public static string MagicLeapRoot { get { return Path.Combine(HomeFolder, "MagicLeap"); } } - } -} diff --git a/Editor/MagicLeapSDKUtil.cs b/Editor/MagicLeapSDKUtil.cs index e84b6d9..4568752 100644 --- a/Editor/MagicLeapSDKUtil.cs +++ b/Editor/MagicLeapSDKUtil.cs @@ -19,11 +19,7 @@ public sealed class MagicLeapSDKUtil { private const string kManifestPath = ".metadata/sdk.manifest"; private const string kMagicLeapSDKRoot = "MagicLeapSDKRoot"; -#if UNITY_2022_2_OR_NEWER private const UnityEditor.BuildTarget kBuildTarget = BuildTarget.Android; -#else - private const UnityEditor.BuildTarget kBuildTarget = BuildTarget.Relish; -#endif private static uint minApiLevel = 0; [Serializable] @@ -42,9 +38,10 @@ public static bool SdkAvailable { get { - if (string.IsNullOrEmpty(SdkPath)) + var path = SdkPath; + if (string.IsNullOrEmpty(path)) return false; - return File.Exists(Path.Combine(SdkPath, kManifestPath)); + return Directory.Exists(path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar)); } } @@ -69,7 +66,7 @@ public static uint MinimumApiLevel } /// - /// MLSDK path for the relish target. + /// MLSDK path for the android target. /// public static string SdkPath { @@ -77,14 +74,6 @@ public static string SdkPath set { SetSDKPath(kBuildTarget, value); } } - public static string AppSimRuntimePath => MagicLeapEditorPreferences.ZeroIterationRuntimePath; - public static bool SearchingForZI => MagicLeapEditorPreferences.RunningLabdriver; - public static event Action OnZeroIterationPathChanged - { - add { MagicLeapEditorPreferences.ZIRuntimePathChangeEvt += value; } - remove { MagicLeapEditorPreferences.ZIRuntimePathChangeEvt -= value; } - } - /// /// MLSDK version /// @@ -105,7 +94,7 @@ public static void DeleteSDKPathFromEditorPrefs(BuildTarget target) /// /// Get the MLSDK path for the given build target platform. /// - /// Relish is the only valid target for now. + /// Android is the only valid target for now. /// private static string GetSDKPath(BuildTarget target) { diff --git a/Editor/OpenXR/MagicLeapFeatureGroup.cs b/Editor/OpenXR/MagicLeapFeatureGroup.cs index c62c78a..e40e2a5 100644 --- a/Editor/OpenXR/MagicLeapFeatureGroup.cs +++ b/Editor/OpenXR/MagicLeapFeatureGroup.cs @@ -9,18 +9,18 @@ // %BANNER_END% #if UNITY_OPENXR_1_9_0_OR_NEWER -using UnityEditor; -using UnityEditor.XR.OpenXR.Features; +using UnityEngine.XR.OpenXR.Features.MagicLeapSupport; -namespace UnityEngine.XR.OpenXR.Features.MagicLeapSupport +namespace UnityEditor.XR.OpenXR.Features.MagicLeapSupport { [OpenXRFeatureSet( UiName = "Magic Leap", - Description = "All Magic Leap OpenXR Features", + Description = "Features supported by the Magic Leap 2 platform.", FeatureSetId = "com.magicleap.openxr.featuregroup", - SupportedBuildTargets = new [] { BuildTargetGroup.Android, BuildTargetGroup.Standalone }, - FeatureIds = new [] { - MagicLeapFeature.FeatureId , + SupportedBuildTargets = new [] { BuildTargetGroup.Android }, + FeatureIds = new[] { + MagicLeapFeature.FeatureId, + MagicLeapControllerProfile.FeatureId, MagicLeapRenderingExtensionsFeature.FeatureId, MagicLeapReferenceSpacesFeature.FeatureId, MagicLeapPlanesFeature.FeatureId, @@ -28,22 +28,60 @@ namespace UnityEngine.XR.OpenXR.Features.MagicLeapSupport MagicLeapSystemNotificationsFeature.FeatureId, MagicLeapMarkerUnderstandingFeature.FeatureId, MagicLeapLocalizationMapFeature.FeatureId, - MagicLeapSpatialAnchorsFeature.FeatureId - }, - RequiredFeatureIds = new[] { - MagicLeapFeature.FeatureId + MagicLeapSpatialAnchorsFeature.FeatureId, + MagicLeapSpatialAnchorsStorageFeature.FeatureId, + MagicLeapFacialExpressionFeature.FeatureId, + MagicLeapMeshingFeature.FeatureId }, DefaultFeatureIds = new[] { + MagicLeapFeature.FeatureId, + MagicLeapControllerProfile.FeatureId, + MagicLeapRenderingExtensionsFeature.FeatureId, + MagicLeapReferenceSpacesFeature.FeatureId, + MagicLeapPlanesFeature.FeatureId, + MagicLeapUserCalibrationFeature.FeatureId, + MagicLeapSystemNotificationsFeature.FeatureId, + MagicLeapMarkerUnderstandingFeature.FeatureId, + MagicLeapLocalizationMapFeature.FeatureId, + MagicLeapSpatialAnchorsFeature.FeatureId, + MagicLeapSpatialAnchorsStorageFeature.FeatureId, + MagicLeapFacialExpressionFeature.FeatureId, + MagicLeapMeshingFeature.FeatureId + } + )] + public class MagicLeapFeatureGroup { } + +#if UNITY_EDITOR_WIN + [OpenXRFeatureSet( + UiName = "Magic Leap AppSim", + Description = "All features supported by the Magic Leap 2 platform.", + FeatureSetId = "com.magicleap.openxr.featuregroup.appsim", + SupportedBuildTargets = new[] { BuildTargetGroup.Standalone }, + FeatureIds = new[] { + MagicLeapFeature.FeatureId, + MagicLeapControllerProfile.FeatureId, MagicLeapRenderingExtensionsFeature.FeatureId, MagicLeapReferenceSpacesFeature.FeatureId, MagicLeapPlanesFeature.FeatureId, MagicLeapUserCalibrationFeature.FeatureId, MagicLeapSystemNotificationsFeature.FeatureId, MagicLeapMarkerUnderstandingFeature.FeatureId, - MagicLeapLocalizationMapFeature.FeatureId + MagicLeapLocalizationMapFeature.FeatureId, + MagicLeapSpatialAnchorsFeature.FeatureId, + MagicLeapSpatialAnchorsStorageFeature.FeatureId, + MagicLeapFacialExpressionFeature.FeatureId, + MagicLeapMeshingFeature.FeatureId + }, + DefaultFeatureIds = new[] { + MagicLeapFeature.FeatureId, + MagicLeapControllerProfile.FeatureId, + MagicLeapPlanesFeature.FeatureId, + MagicLeapMarkerUnderstandingFeature.FeatureId, + MagicLeapSpatialAnchorsFeature.FeatureId, + MagicLeapMeshingFeature.FeatureId } )] - public class MagicLeapFeatureGroup - { } +#endif + public class MagicLeapFeatureAppSimGroup { } } #endif diff --git a/Editor/OpenXR/MagicLeapRenderingExtensionsFeatureEditor.cs b/Editor/OpenXR/MagicLeapRenderingExtensionsFeatureEditor.cs new file mode 100644 index 0000000..876ad40 --- /dev/null +++ b/Editor/OpenXR/MagicLeapRenderingExtensionsFeatureEditor.cs @@ -0,0 +1,55 @@ +// %BANNER_BEGIN% +// --------------------------------------------------------------------- +// %COPYRIGHT_BEGIN% +// Copyright (c) (2019-2023) Magic Leap, Inc. All Rights Reserved. +// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2 +// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein. +// %COPYRIGHT_END% +// --------------------------------------------------------------------- +// %BANNER_END% + +using UnityEditor; +using UnityEngine.XR.OpenXR.Features.MagicLeapSupport; +using UnityEngine.XR.OpenXR.NativeTypes; + +#if UNITY_OPENXR_1_9_0_OR_NEWER +[CustomEditor(typeof(MagicLeapRenderingExtensionsFeature))] +public class MagicLeapRenderingExtensionsFeatureEditor : Editor +{ + private SerializedProperty protectedSurfaceProperty; + private SerializedProperty vignetteProperty; + private SerializedProperty blendModeProperty; + private SerializedProperty globalDimmerProperty; + private SerializedProperty globalDimmerValueProperty; + + private enum SupportedBlendModes + { + Additive = XrEnvironmentBlendMode.Additive, + AlphaBlend = XrEnvironmentBlendMode.AlphaBlend + } + + private void OnEnable() + { + blendModeProperty = serializedObject.FindProperty("BlendMode"); + protectedSurfaceProperty = serializedObject.FindProperty("UseProtectedSurface"); + vignetteProperty = serializedObject.FindProperty("UseVignetteMode"); + globalDimmerProperty = serializedObject.FindProperty("GlobalDimmerEnabled"); + globalDimmerValueProperty = serializedObject.FindProperty("GlobalDimmerValue"); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + blendModeProperty.intValue = (int)(SupportedBlendModes) EditorGUILayout.EnumPopup("Blend Mode", (SupportedBlendModes)blendModeProperty.intValue); + protectedSurfaceProperty.boolValue = EditorGUILayout.Toggle("Protected Surface", protectedSurfaceProperty.boolValue); + vignetteProperty.boolValue = EditorGUILayout.Toggle("Vignette", vignetteProperty.boolValue); + globalDimmerProperty.boolValue = EditorGUILayout.Toggle("Enable Global Dimmer", globalDimmerProperty.boolValue); + + var dimmerEnabled = globalDimmerProperty.boolValue; + globalDimmerValueProperty.floatValue = EditorGUILayout.Slider("Global Dimmer Value", dimmerEnabled ? globalDimmerValueProperty.floatValue : 0f, 0f, 1f); + + serializedObject.ApplyModifiedProperties(); + } +} +#endif diff --git a/Editor/SettingsProviders/Preferences/MagicLeapEditorPreferences.cs.meta b/Editor/OpenXR/MagicLeapRenderingExtensionsFeatureEditor.cs.meta similarity index 83% rename from Editor/SettingsProviders/Preferences/MagicLeapEditorPreferences.cs.meta rename to Editor/OpenXR/MagicLeapRenderingExtensionsFeatureEditor.cs.meta index 4ee88bf..eceb268 100644 --- a/Editor/SettingsProviders/Preferences/MagicLeapEditorPreferences.cs.meta +++ b/Editor/OpenXR/MagicLeapRenderingExtensionsFeatureEditor.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 99ce30e5b1edc124b8e4e0b12a5bac03 +guid: bc0418a2644a443cd8ebc8031c2c0cd8 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/SettingsProviders/Permissions/PermissionSettingsLoader.cs b/Editor/SettingsProviders/Permissions/PermissionSettingsLoader.cs index 5daba57..9c8456c 100644 --- a/Editor/SettingsProviders/Permissions/PermissionSettingsLoader.cs +++ b/Editor/SettingsProviders/Permissions/PermissionSettingsLoader.cs @@ -14,9 +14,10 @@ namespace UnityEditor.XR.MagicLeap { - public class PermissionSettingsLoader + internal class PermissionSettingsLoader { - private string FilePath => Path.Combine(MagicLeapSDKUtil.SdkPath, "data", "ml_permissions.json"); + private const string manifestFileName = "ml_permissions.json"; + public string ManifestFilePath => Path.Combine("Packages/com.magicleap.unitysdk/Editor/SettingsProviders/Permissions/data~", manifestFileName); internal PermissionsListJson settingJson { get; private set; } public PermissionSettingsLoader() => Initialize(); @@ -25,7 +26,7 @@ private void Initialize() { try { - var json = File.ReadAllText(FilePath, Encoding.UTF8); + var json = File.ReadAllText(ManifestFilePath, Encoding.UTF8); settingJson = JsonUtility.FromJson($"{{\"Settings\":{json}}}"); } diff --git a/Editor/SettingsProviders/Permissions/data~/ml_permissions.json b/Editor/SettingsProviders/Permissions/data~/ml_permissions.json new file mode 100644 index 0000000..0018979 --- /dev/null +++ b/Editor/SettingsProviders/Permissions/data~/ml_permissions.json @@ -0,0 +1,93 @@ +[ + { + "name": "android.permission.CAMERA", + "description": "Permission to use device camera(s).", + "level": "dangerous", + "min_api_level": 20 + }, + { + "name": "android.permission.RECORD_AUDIO", + "description": "Permission to use device microphone to record audio.", + "level": "dangerous", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.EYE_TRACKING", + "description": "Permission to obtain eye tracking data.", + "level": "dangerous", + "min_api_level": 9 + }, + { + "name": "com.magicleap.permission.PUPIL_SIZE", + "description": "Permission to obtain eye pupil size data.", + "level": "dangerous", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.SPATIAL_ANCHOR", + "description": "Permission to obtain spatial anchor(s) data.", + "level": "normal", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.HAND_TRACKING", + "description": "Permission to obtain hand tracking data.", + "level": "normal", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.WEBVIEW", + "description": "Permission to enable WebView access.", + "level": "normal", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.MARKER_TRACKING", + "description": "Permission to obtain marker tracking data.", + "level": "normal", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.VOICE_INPUT", + "description": "Permission to obtain voice input data.", + "level": "dangerous", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.SPATIAL_MAPPING", + "description": "Permission to obtain following spatial data: planes data, meshing data.", + "level": "dangerous", + "min_api_level": 20 + }, + { + "name": "com.magicleap.permission.DEPTH_CAMERA", + "description": "Permission to use depth camera.", + "level": "dangerous", + "min_api_level": 23 + }, + { + "name": "com.magicleap.permission.EYE_CAMERA", + "description": "Permission to use eye cameras.", + "level": "dangerous", + "min_api_level": 26 + }, + { + "name": "com.magicleap.permission.SPACE_MANAGER", + "description": "Permission to use Magic Leap Space manager.", + "level": "normal", + "min_api_level": 26 + }, + { + "name": "com.magicleap.permission.SPACE_IMPORT_EXPORT", + "description": "Permission to export and import Magic Leap Spaces.", + "level": "dangerous", + "min_api_level": 26 + }, + { + "name": "com.magicleap.permission.FACIAL_EXPRESSION", + "description": "Permission to obtain facial expression data.", + "level": "dangerous", + "min_api_level": 29 + } + +] diff --git a/Editor/SettingsProviders/Preferences/MagicLeapEditorPreferences.cs b/Editor/SettingsProviders/Preferences/MagicLeapEditorPreferences.cs deleted file mode 100644 index d3a960b..0000000 --- a/Editor/SettingsProviders/Preferences/MagicLeapEditorPreferences.cs +++ /dev/null @@ -1,471 +0,0 @@ -using System.Collections.Generic; -using UnityEngine.UIElements; -using System.IO; -using UnityEngine.XR.MagicLeap; -using System.Diagnostics; -using System.Threading.Tasks; -using System; - -namespace UnityEditor.XR.MagicLeap -{ - internal static class MagicLeapEditorPreferences - { - private static readonly string SdkPathEditorPrefsKey = "MagicLeapSDKRoot"; - private static readonly string UserCustomZIBackendPath = "ZI_User_Selected_ZI_Runtime"; - private static readonly string LabdriverFoundBackendPath = "ZI_Labdriver_Found_ZI_Runtime"; - private static readonly string ToggleZIPathEnableOverride = "ZI_Path_Enable_Override"; - - private static readonly string PathToUIAsset = "Packages/com.magicleap.unitysdk/Editor/SettingsProviders/Preferences/MagicLeapEditorPreferences.uxml"; - - private static TextField sdkInputField; - private static TextField ziInputField; - private static Button sdkPathBrowseBtn; - private static Button ziPathBrowseBtn; - private static VisualElement sdkPathHelpContainer; - private static VisualElement ziPathHelpContainer; - private static HelpBox sdkPathHelp; - private static HelpBox ziPathHelp; - private static Toggle ziPathOverrideToggle; - - private static bool labdriverRunning = false; - private static int progressId = -1; - - private static string mlsdkPath = ""; - private static string ziRuntimePath; - private static string labdriverResultPath = ""; - private static bool enableOverrideZiPath; - private static bool usingLabdriverFoundPath = false; - - public static string ZeroIterationRuntimePath => ziRuntimePath; - - public static bool RunningLabdriver => labdriverRunning; - - public static event Action ZIRuntimePathChangeEvt; - - [InitializeOnLoad] - class PreferencesLoader - { - static PreferencesLoader() - { - var path = GetSavedSDKPath(); - if (Directory.Exists(path)) - { - mlsdkPath = path; - } - enableOverrideZiPath = EditorPrefs.GetBool(ToggleZIPathEnableOverride); - if (enableOverrideZiPath) - { - path = EditorPrefs.GetString(UserCustomZIBackendPath); - if (Directory.Exists(path)) - { - ziRuntimePath = path; - } - } - else - { - LocateZIRuntimeFromMLSDK(); - } - - EditorApplication.update += () => - { - if (!string.IsNullOrEmpty(labdriverResultPath)) - { - EditorPrefs.SetString(LabdriverFoundBackendPath, labdriverResultPath); - if (ziRuntimePath != labdriverResultPath) - { - ziRuntimePath = labdriverResultPath; - ZIRuntimePathChangeEvt?.Invoke(ziRuntimePath); - } - labdriverResultPath = ""; - } - if (labdriverRunning) - { - Progress.Report(progressId, 1f, "Searching for latest ML App Sim installation..."); - } - else - { - progressId = Progress.Remove(progressId); - } - }; - } - } - - [SettingsProvider] - public static SettingsProvider CreateMLPreferencesTabProvider() - { - var provider = new SettingsProvider("Preferences/External Tools/Magic Leap", SettingsScope.User) - { - label = "Magic Leap", - - // activateHandler is called when the user clicks on the Settings item in the Settings window. - activateHandler = (searchContext, rootElement) => - { - var visualTree = AssetDatabase.LoadAssetAtPath(PathToUIAsset); - - visualTree.CloneTree(rootElement); - - sdkInputField = rootElement.Q("MLSDK-Input"); - ziInputField = rootElement.Q("ZI-Input"); - sdkPathBrowseBtn = rootElement.Q