protected override MLResult.Code StartAPI()
        {
            if (!MLDevice.IsReady())
            {
                MLPluginLog.WarningFormat("MLCamera API is attempting to start before the MagicLeap XR Loader has been initialiazed, this could cause issues with MLCVCamera features. If your application needs these features please wait to start API until Monobehavior.Start and if issue persists make sure ProjectSettings/XR/Initialize On Startup is enabled.");
            }

            MLResult result = MLHeadTracking.Start();

            if (result.IsOk)
            {
                result = MLHeadTracking.GetState(out MLHeadTracking.State headTrackingState);
                if (!result.IsOk)
                {
                    MLPluginLog.ErrorFormat("MLCVCamera.StartAPI failed to get head pose state. Reason: {0}", result);
                }

                headTrackerHandle = headTrackingState.Handle;
                MLHeadTracking.Stop();
            }
            else
            {
                MLPluginLog.ErrorFormat("MLCVCamera.StartAPI failed to get head pose state. MLHeadTracking could not be successfully started.");
            }

            return(MLCVCameraNativeBindings.MLCVCameraTrackingCreate(ref Handle));
        }
        /// <summary>
        /// Utility function set up instance and tracks successful _startCount
        /// </summary>
        /// <param name="requiresXRLoader">Flag to determine if this API requires the XR Loader being initialized.</param>
        /// <returns>
        /// MLResult.Result will be <c>MLResult.Code.Ok</c> if successful.
        /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to internal error (MagicLeap XR Loader not loaded, no device, DLL not found, no API symbols).
        /// MLResult.Result will otherwise be return value specific API's StartAPI function.
        /// </returns>
        protected static MLResult BaseStart(bool requiresXRLoader = false)
        {
            MLResult result;

            try
            {
                // Check to see if we have already successfully initialized a valid instance
                if (startCount > 0)
                {
                    startCount++;
                    result = MLResult.Create(MLResult.Code.Ok);
                }
                else
                {
                    if (requiresXRLoader && !MLDevice.IsReady())
                    {
                        MLPluginLog.ErrorFormat("MLAPISingleton.BaseStart failed to start {0} API. Reason: MagicLeap XR Loader is not initialized. Please wait to start API until Monobehavior.Start and if issue persists make sure ProjectSettings/XR/Initialize On Startup is enabled.", typeof(T).Name);
                        return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MagicLeap XR Loader not initialized"));
                    }

                    result = Instance.StartAPI();
                    if (result.IsOk)
                    {
                        // Everything started correctly register the update and increament _startCount
                        MLDevice.RegisterUpdate(Instance.Update);
                        MLDevice.RegisterApplicationPause(Instance.OnApplicationPause);
                        startCount++;

                        Instance.perceptionHandle     = PerceptionHandle.Acquire();
                        Instance.perceptionHasStarted = true;
                    }
                    else
                    {
                        MLPluginLog.ErrorFormat("MLAPISingleton.BaseStart failed to start {0} API. Reason: {1}", typeof(T).Name, result);
                        _instance = null;
                    }
                }

                return(result);
            }
            catch (System.DllNotFoundException)
            {
                MLPluginLog.ErrorFormat(_instance.DllNotFoundError, typeof(T).Name);
                result = MLResult.Create(MLResult.Code.UnspecifiedFailure, "Dll not found");
                MLPluginLog.ErrorFormat("MLAPISingleton.BaseStart failed to start {0} API. Reason: {1}", typeof(T).Name, result);
                _instance = null;
            }
            catch (System.EntryPointNotFoundException)
            {
                string errorMessage = string.Format("{0} API symbols not found", typeof(T).Name);
                result = MLResult.Create(MLResult.Code.UnspecifiedFailure, errorMessage);
                MLPluginLog.ErrorFormat("MLAPISingleton.BaseStart failed to start {0} API. Reason: {1}", typeof(T).Name, result);
                _instance = null;
            }

            return(result);
        }
                /// <summary>
                /// Unsubscribes from pause and lifecycle events.
                /// </summary>
                internal void Cleanup()
                {
                    // While local tracks can be unsubscribed in the DestroyLocal(), the only place to do that for remote tracks is in the finalizer.
#if PLATFORM_LUMIN
                    UnityEngine.Lumin.Lifecycle.deviceStandbyEvent -= this.HandleDeviceStandby;
                    UnityEngine.Lumin.Lifecycle.deviceRealityEvent -= this.HandleDeviceReality;
                    UnityEngine.Lumin.Lifecycle.deviceActiveEvent  -= this.HandleDeviceActive;
                    MLDevice.UnregisterApplicationPause(this.OnApplicationPause);
#endif
                }
Beispiel #4
0
 /// <summary>
 /// Disables key poses and unregisters from the gesture subsystem.
 /// </summary>
 private void Cleanup()
 {
     #if PLATFORM_LUMIN
     if (MLDevice.GestureSubsystem != null)
     {
         MLDevice.GestureSubsystem.onTouchpadGestureChanged -= this.HandleOnTouchpadGestureChanged;
         MLDevice.UnregisterGestureSubsystem();
     }
     #endif
 }
            /// <summary>
            /// Disables key poses and unregisters from the gesture subsystem.
            /// </summary>
            private void Cleanup()
            {
                this.DisableAllKeyPoses();

                if (MLDevice.GestureSubsystem != null)
                {
                    MLDevice.GestureSubsystem.onKeyPoseGestureChanged -= this.HandleOnKeyPoseChanged;
                    MLDevice.UnregisterGestureSubsystem();
                }
            }
                /// <summary>
                /// Initializes a new instance of the <see cref="Track" /> class.
                /// </summary>
                internal Track(string trackId)
                {
#if PLATFORM_LUMIN
                    UnityEngine.Lumin.Lifecycle.deviceStandbyEvent += this.HandleDeviceStandby;
                    UnityEngine.Lumin.Lifecycle.deviceRealityEvent += this.HandleDeviceReality;
                    UnityEngine.Lumin.Lifecycle.deviceActiveEvent  += this.HandleDeviceActive;
                    MLDevice.RegisterApplicationPause(this.OnApplicationPause);

                    Id = trackId;
#endif
                }
        /// <summary>
        /// Calls OnUpdateActions event and dispatches all queued callbacks.
        /// </summary>
        protected override void Update()
        {
            base.Update();

            if (!this.isReady && !(this.isReady = MLDevice.IsReady()))
            {
                return;
            }

            this.OnUpdateEvent?.Invoke();

            MLThreadDispatch.DispatchAll();
        }
            /// <summary>
            /// Handles a page request failure.
            /// </summary>
            /// <param name="resultCode">The result of the request.</param>
            private void PageFailed(MLResult.Code resultCode)
            {
                this.Status = PageStatus.Failed;

                MLContacts.ReleaseRequest(this.RequestHandle);

                this.RequestHandle = MagicLeapNativeBindings.InvalidHandle;

                this.PageFailedAction?.Invoke(this, MLResult.Create(resultCode));

                this.UnregisterUpdate = false;
                MLDevice.Unregister(this.Update);
            }
            /// <summary>
            /// Initializes a new instance of the <see cref="KeyposeManager" /> class.
            /// </summary>
            /// <param name="leftHand">Left hand to which KeyPoseManager will subscribe for events.</param>
            /// <param name="rightHand">Right hand to which KeyPoseManager will subscribe for events.</param>
            public KeyposeManager(Hand leftHand, Hand rightHand)
            {
                // Array length excludes [NoHand], since we do not allow it to be disabled.
                this.config.KeyposeConfig = new byte[(int)MLHandTracking.HandKeyPose.NoHand];

                this.hands[(int)MLHandTracking.HandType.Left]  = leftHand;
                this.hands[(int)MLHandTracking.HandType.Right] = rightHand;

                // Start the Unity gesture subsystem.s
                MLDevice.RegisterGestureSubsystem();
                if (MLDevice.GestureSubsystem != null)
                {
                    MLDevice.GestureSubsystem.onKeyPoseGestureChanged += this.HandleOnKeyPoseChanged;
                }
            }
        private void StartInternal()
        {
            MLPluginLog.Debug($"Initializing {typeof(T).Name} API...");

            if (DidNativeCallSucceed(StartAPI(), $"{typeof(T).Name} Start"))
            {
                IsStarted = true;
                MLDevice.RegisterUpdate(instance.Update);
                MLDevice.RegisterApplicationPause(instance.OnApplicationPause);
                MLDevice.RegisterDestroy(instance.StopInternal);

                instance.perceptionHandle = PerceptionHandle.Acquire();
                MLPluginLog.Debug($"{typeof(T).Name} API initialized.");
            }
        }
Beispiel #11
0
            /// <summary>
            /// Initializes a new instance of the <see cref="Controller"/> class.
            /// </summary>
            /// <param name="inputTrackerHandle">The input tracker handle.</param>
            /// <param name="controllerId">The controller id.</param>
            /// <param name="inputHand">The hand that should be assigned.</param>
            public Controller(ulong inputTrackerHandle, byte controllerId, MLInput.Hand inputHand)
            {
                // InputTracker is still required, for LED Patterns & Control Vibrations.
                this.inputTrackerHandle = inputTrackerHandle;
                this.controllerId       = controllerId;

                this.Hand = inputHand;
                this.CurrentTouchpadGesture = new MLInput.Controller.TouchpadGesture();

                // Start the Unity gesture subsystem.
                MLDevice.RegisterGestureSubsystem();
                if (MLDevice.GestureSubsystem != null)
                {
                    MLDevice.GestureSubsystem.onTouchpadGestureChanged += this.HandleOnTouchpadGestureChanged;
                }
            }
        /// <summary>
        ///     This is the only way to initialize this class.
        /// </summary>
        private static void Init()
        {
            allowInit = true;
            instance  = new T();
            allowInit = false;

            if (requiresXRLoader && !MLDevice.IsReady())
            {
                MLPluginLog.Error($"Magic Leap XR Loader is not initialized, and the {typeof(T).Name} API must be started afterwards.");
                return;
            }
            else
            {
                instance.StartInternal();
            }
        }
            /// <summary>
            /// Request a new page
            /// </summary>
            /// <param name="pageLength">The length of the page</param>
            /// <param name="offset">Offset into the page</param>
            /// <returns>
            /// MLResult.Result will be <c>MLResult.Code.Ok</c> if successfully submitted
            /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if either of the parameters are invalid.
            /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing.
            /// </returns>
            protected virtual MLResult InternalNewPage(uint pageLength, string offset)
            {
                MLResult.Code resultCode = MLContacts.GetList(pageLength, offset, out ulong handle);
                this.RequestHandle = handle;

                if (resultCode != MLResult.Code.Ok)
                {
                    this.Status = PageStatus.Failed;
                    return(MLResult.Create(resultCode));
                }

                this.Status = PageStatus.Pending;
                MLDevice.Register(this.Update);
                this.UnregisterUpdate = true;

                return(MLResult.Create(MLResult.Code.Ok));
            }
        /// <summary>
        /// Decrement API instance count and cleanup if this is the last one.
        /// </summary>
        private void StopAPI()
        {
            if (startCount > 0)
            {
                --startCount;
                if (startCount == 0)
                {
                    MLDevice.UnregisterUpdate(this.Update);
                    MLDevice.UnregisterApplicationPause(this.OnApplicationPause);
                    this.CleanupAPI(true);

                    if (this.perceptionHasStarted)
                    {
                        this.perceptionHandle.Dispose();
                        this.perceptionHasStarted = false;
                    }

                    _instance = null;
                }
            }
        }
        private void StopInternal()
        {
            if (IsStarted)
            {
                MLDevice.UnregisterUpdate(this.Update);
                MLDevice.UnregisterApplicationPause(this.OnApplicationPause);
                MLDevice.UnregisterDestroy(instance.StopInternal);

                MLResult.Code resultCode = instance.StopAPI();

                if (DidNativeCallSucceed(resultCode, $"{typeof(T).Name} Stop"))
                {
                    MLPluginLog.Debug($"{typeof(T).Name} API stopped successfully");
                }

                if (perceptionHandle.active)
                {
                    perceptionHandle.Dispose();
                }

                IsStarted = false;
            }
        }
            /// <summary>
            /// Handles a page being ready.
            /// </summary>
            private void PageReady()
            {
                this.Status = PageStatus.Ready;

                if (this.listResult.Offset == null)
                {
                    this.nextPageOffset = string.Empty;
                    this.Status         = PageStatus.LastPage;
                }
                else
                {
                    this.nextPageOffset = string.Copy(this.listResult.Offset);
                }

                MLContacts.ReleaseRequest(this.RequestHandle);

                this.RequestHandle = MagicLeapNativeBindings.InvalidHandle;

                this.PageReadyAction?.Invoke(this);

                this.TotalHits        = this.listResult.TotalHits;
                this.UnregisterUpdate = false;
                MLDevice.Unregister(this.Update);
            }