Пример #1
0
        /// <summary>
        /// Ensures the camera transform is at the origin.
        /// </summary>
        /// <param name="scene">Current scene.</param>
        /// <param name="mode">Scene loading mode.</param>
        private void CheckMainCameraTransform(Scene scene, LoadSceneMode mode)
        {
            Camera mainCamera = Camera.main;

            // Return if there is no camera or if we are loading an additive scene.
            if (mainCamera == null || mode == LoadSceneMode.Additive)
            {
                return;
            }

            Transform cameraTransform = mainCamera.transform;

            if (cameraTransform.localPosition != Vector3.zero ||
                cameraTransform.localRotation != Quaternion.identity ||
                cameraTransform.localScale != Vector3.one)
            {
                MLPluginLog.WarningFormat(
                    "The main camera's transform is not set to identity in scene \"{0}\": " +
                    "position : {1}, rotation : {2}, scale : {3}. " +
                    "Those changes can cause undesired effects.",
                    scene.name,
                    cameraTransform.localPosition,
                    cameraTransform.localRotation.eulerAngles,
                    cameraTransform.localScale);
            }
        }
Пример #2
0
        /// <summary>
        /// <para>Submit a request to start the invite sending process. Request an invite to be sent for other connections to join a multi-user
        /// experience. This call will trigger a connections invite dialog requesting the user to select up to the specified number of online
        /// users to be invited. The system will then initiate a push notification to other online devices, start a copy of the application
        /// requesting the invite and deliver the given payload.</para>
        /// <para>Only one invite can be processed at a time. Will return an error if the first invite request is incomplete/pending in the service
        /// when a second request is sent.</para>
        /// <para>Will receive a DispatchFailed status if the invitee is not registered to receive invites for the specific application. If multiple invitees
        /// are selected, SendInvite will dispatch successfully if at least one of them is registered to receive invites for the specific application.</para>
        /// <para>Note: You cannot invite users who are not following the Sender.</para>
        /// </summary>
        /// <param name="inviteeCount">Max number of connections to be invited. Min limit is 1.</param>
        /// <param name="filterLevel">Type of filter applied by default to ML connections list in invitee selection dialog.</param>
        /// <param name="textPrompt">Text prompt to be displayed to the user with invitee selection dialog.</param>
        /// <param name="payload">Payload message to be delivered to remote copy of the application with invite.</param>
        /// <returns>
        /// <para>MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if a given argument is invalid.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.Ok</c> if successfully requested the start of the invite dialog.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if there was an unexpected failure.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if permissions haven't been granted to make this API call.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.Timeout</c> if the request to request sending an invite timed out.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsIllegalState</c> if there was an issue with the connections system, e.g. service is not available for any reason.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsInvalidInviteeCount</c> if number of invitees is invalid.</para>
        /// </returns>
        public static MLResult SendInvite(uint inviteeCount, InviteeFilter filterLevel, string textPrompt, string payload)
        {
            if (MLConnections.IsValidInstance())
            {
                MLResult requestResult = NativeBindings.InviteArgs.SendInviteHelper(inviteeCount, filterLevel, textPrompt, payload, ref _instance.requestHandle);

                if (!requestResult.IsOk)
                {
                    MLPluginLog.ErrorFormat("MLConnections.SendInvite failed to initialize resources for sending an invite. Reason: {0}", requestResult);
                }
                else
                {
                    if (_instance.activeInvite)
                    {
                        MLPluginLog.WarningFormat("MLConnections.SendInvite allowed multiple active invites.");
                    }

                    _instance.activeInvite = true;
                }

                return(requestResult);
            }
            else
            {
                MLPluginLog.ErrorFormat("MLConnections.SendInvite failed. Reason: No Instance for MLConnections");
                return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLConnections.SendInvite failed. Reason: No Instance for MLConnections"));
            }
        }
Пример #3
0
        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));
        }
Пример #4
0
        /// <summary>
        /// Retrieves the PCF associated with the given CFUID.
        /// </summary>
        /// <param name="cfuid">The CFUID to look up the PCF type with.</param>
        /// <param name="pcf">Stores the resulting PCF.</param>
        /// <param name="update">Determines if the PCF should have it's pose and state updated.</param>
        /// <returns>
        /// MLResult.Result will be <c>MLResult.Code.Ok</c> if a valid PCF was found.
        /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to an invalid input parameter.
        /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing.
        /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map.
        /// </returns>
        public static MLResult FindPCFByCFUID(MagicLeapNativeBindings.MLCoordinateFrameUID cfuid, out PCF pcf, bool update = true)
        {
            pcf = null;
            if (MLPersistentCoordinateFrames.IsValidInstance())
            {
                if (_instance.mapAllPCFs.ContainsKey(cfuid))
                {
                    pcf = _instance.mapAllPCFs[cfuid];
                    if (update)
                    {
                        MLResult updateResult = pcf.Update();
                        if (!updateResult.IsOk)
                        {
                            MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed to update the found PCF. Reason: {0}", updateResult);
                        }

                        return(updateResult);
                    }

                    return(MLResult.Create(MLResult.Code.Ok));
                }
                else
                {
                    MLResult result = FindAllPCFs(out List <PCF> list, update: false);
                    if (result.IsOk)
                    {
                        pcf = list.Find(PCF => PCF.CFUID == cfuid);
                        if (update && pcf != null)
                        {
                            MLResult updateResult = pcf.Update();
                            if (!updateResult.IsOk)
                            {
                                MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed to update the found PCF. Reason: {0}", updateResult);
                            }

                            return(updateResult);
                        }
                    }
                    else
                    {
                        if (result.Result == MLResult.Code.PassableWorldLowMapQuality || result.Result == MLResult.Code.PassableWorldUnableToLocalize)
                        {
                            MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.FindPCFByCFUID. Reason: {0}", result);
                        }
                        else
                        {
                            MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: {0}", result);
                        }
                    }

                    return(result);
                }
            }
            else
            {
                MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames.");
                return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindPCFByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames."));
            }
        }
        /// <summary>
        /// Sets the localization status based on if PCFs can currently be found
        /// </summary>
        private void SetLocalizationStatus()
        {
            if (MLPersistentCoordinateFrames.IsValidInstance())
            {
                try
                {
                    MLResult      result     = MLResult.Create(MLResult.Code.Ok);
                    uint          numPCFs    = 0;
                    MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFrameGetCount(MLPersistentCoordinateFrames._instance.nativeTracker, ref numPCFs);

                    if (!MLResult.IsOK(resultCode))
                    {
                        if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize)
                        {
                            MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.SetLocalizationStatus. Reason: {0}", MLResult.CodeToString(resultCode));
                        }
                        else
                        {
                            MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode));
                        }

                        result = MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode)));
                    }

                    bool foundPCFs = result.IsOk && numPCFs > 0;
                    if (!MLPersistentCoordinateFrames.IsLocalized && foundPCFs)
                    {
                        MLPersistentCoordinateFrames.IsLocalized = true;
                        MLPersistentCoordinateFrames.OnLocalized?.Invoke(IsLocalized);
                    }
                    else if (MLPersistentCoordinateFrames.IsLocalized && !foundPCFs)
                    {
                        List <PCF> allPCFs = new List <PCF>(MLPersistentCoordinateFrames._instance.mapAllPCFs.Values);

                        MLPersistentCoordinateFrames._instance.mapTrackedPCFs.Clear();
                        MLPersistentCoordinateFrames._instance.mapAllPCFs.Clear();

                        MLPersistentCoordinateFrames.IsLocalized = false;

                        foreach (PCF pcf in allPCFs)
                        {
                            pcf.Update();
                        }

                        MLPersistentCoordinateFrames._instance.mapUpdatedPCFsThisFrame.Clear();
                        MLPersistentCoordinateFrames.OnLocalized?.Invoke(MLPersistentCoordinateFrames.IsLocalized);
                    }
                }
                catch (EntryPointNotFoundException)
                {
                    MLPluginLog.Error("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: API symbols not found.");
                }
            }
            else
            {
                MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: No Instance for MLPersistentCoordinateFrames.");
            }
        }
            /// <summary>
            /// Sets the values of a specific key pose.
            /// </summary>
            /// <param name="config">The native config object of key poses to use.</param>
            /// <param name="handKeyPose">The key pose to set.</param>
            /// <param name="enable">The value to set the key pose with.</param>
            private static void SetKeyPoseConfig(NativeBindings.ConfigurationNative config, MLHandTracking.HandKeyPose handKeyPose, bool enable)
            {
                if (handKeyPose > MLHandTracking.HandKeyPose.NoPose)
                {
                    MLPluginLog.WarningFormat("KeyPoseManager.SetKeyPoseConfig trying to set {0}. Ignoring.", handKeyPose);
                    return;
                }

                config.KeyposeConfig[(uint)handKeyPose] = Convert.ToByte(enable);
            }
            /// <summary>
            /// Queries a profile for a list of attribute values asynchronously.
            /// </summary>
            private void RequestAttributeValuesAsync()
            {
                MLResult.Code resultCode = MLIdentity.NativeBindings.RequestAttributeValuesAsync(this, ref this.attributes);

                if (MLResult.IsOK(resultCode))
                {
                    this.request.RequestState = Request.State.LISTENING_ATTRIB_VALUES;
                }
                else
                {
                    MLPluginLog.WarningFormat("MLIdentity.Profile.RequestAttributeValuesAsync failed request for attribute values async. Reason: {0}", MLResult.CodeToString(resultCode));
                    this.request.RequestState = Request.State.DONE;
                }
            }
Пример #8
0
        /// <summary>
        /// Called by MLAPISingleton to start the API
        /// </summary>
        /// <returns>
        /// <para>MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if the registration resource allocation failed.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if a given argument is invalid.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.Ok</c> if successfully initialized.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if there was an unexpected failure.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsAlreadyRegistered</c> if this is a duplicate registration.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsNetworkFailure</c> if communication to the network failed.</para>
        /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsSystemFailure</c> if there was system failure.</para>
        /// </returns>
        protected override MLResult StartAPI()
        {
            MLResult.Code resultCode = NativeBindings.MLConnectionsRegistrationStartup(ref _instance.registerHandle);

            if (!MLResult.IsOK(resultCode) || !Native.MagicLeapNativeBindings.MLHandleIsValid(_instance.registerHandle))
            {
                MLResult resultError = MLResult.Create(resultCode);

                MLPluginLog.ErrorFormat("MLConnections.Start failed in StartAPI() to register to receive invites. Handle is invalid or Reason: {0}", resultError);

                return(resultError);
            }

            NativeBindings.InviteCallbacks connectionCallbacks = NativeBindings.InviteCallbacks.Create();

            resultCode = NativeBindings.MLConnectionsRegisterForInvite(_instance.registerHandle, connectionCallbacks, IntPtr.Zero);

            if (!MLResult.IsOK(resultCode))
            {
                MLResult resultError = MLResult.Create(resultCode);

                MLPluginLog.ErrorFormat("MLConnections.Start failed in StartAPI() to set callbacks. Reason: {0}", resultError);

                return(resultError);
            }
            else
            {
                if (_instance.activeRequest)
                {
                    // This check is just precautionary, but it should never happen.
                    MLPluginLog.WarningFormat("MLConnections.Start allowed multiple active registrations.");
                }

                Instance.activeRequest = true;
            }

            resultCode = NativeBindings.MLConnectionsStartup();

            if (!MLResult.IsOK(resultCode))
            {
                MLPluginLog.ErrorFormat("MLConnections.Start failed in StartAPI() to initialize resources for sending an invite. Reason: {0}", MLResult.CodeToString(resultCode));
            }
            else
            {
                _instance.sendInviteHasStarted = true;
            }

            return(MLResult.Create(resultCode));
        }
Пример #9
0
        /// <summary>
        /// Called by MLAPISingleton to start the API
        /// </summary>
        /// <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.
        /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if a parameter is invalid.
        /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if <c>AudioCaptureMic</c> privilege is denied.
        /// MLResult.Result will be <c>MLResult.Code.AudioNotImplemented</c> if the function is not implemented.
        /// </returns>
        protected override MLResult StartAPI()
        {
            // Set the initial audio device.
            Instance.lastAudioDevice = Instance.InternalGetOutputDevice();

            MLResult.Code result;

            // Get the initial MasterVolume value.
            result = Instance.GetMasterVolume(out this.masterVolume);
            if (result != MLResult.Code.Ok)
            {
                return(MLResult.Create(result));
            }

            // Master Volume Callback
            result = this.RegisterOnVolumeChangeCallback();
            if (result != MLResult.Code.Ok)
            {
                return(MLResult.Create(result));
            }

            // Attempt to register Microphone Muted Callback
            result = this.RegisterOnMicrophoneMuteCallback();
            if (result == MLResult.Code.PrivilegeDenied)
            {
                MLPluginLog.WarningFormat("MLAudio.StartAPI missing AudioCaptureMic privilege, microphone specific features disabled.");
                result = MLResult.Code.Ok;
            }
            else if (result == MLResult.Code.Ok)
            {
                // Get the initial IsMicrophoneMuted value.
                result = Instance.GetMicrophoneMuted(out this.isMicrophoneMuted);
                if (result != MLResult.Code.Ok)
                {
                    this.UnregisterOnVolumeChangeCallback();
                    this.UnregisterOnMicrophoneMuteCallback();
                    return(MLResult.Create(result));
                }
            }
            else
            {
                this.UnregisterOnVolumeChangeCallback();
            }

            return(MLResult.Create(result));
        }
            /// <summary>
            /// Queries a profile for a list of attribute names asynchronously.
            /// </summary>
            private void RequestAttributeNamesAsync()
            {
                MLResult.Code resultCode = MLIdentity.NativeBindings.RequestAttributeNamesAsync(this, this.requestAttributes, ref this.attributes);

                if (MLResult.IsOK(resultCode))
                {
                    this.request.ResultCode   = MLResult.Code.Pending;
                    this.request.RequestState = (this.requestAttributes != null && this.requestAttributes.Length > 0) ?
                                                MLIdentity.Profile.Request.State.REQUEST_ATTRIB_VALUES :
                                                MLIdentity.Profile.Request.State.LISTENING_ATTRIB_NAMES;
                }
                else
                {
                    MLPluginLog.WarningFormat("MLIdentity.Profile.RequestAttributeNamesAsync failed request for attribute names async. Reason: {0}", MLResult.CodeToString(resultCode));
                    this.request.ResultCode   = resultCode;
                    this.request.RequestState = MLIdentity.Profile.Request.State.DONE;
                }
            }
Пример #11
0
        /// <summary>
        /// Update is called every frame. <c>>Moonobehaviour</c>. callback.
        /// </summary>
        protected override void Update()
        {
            MLResult.Code result = MLLightingTrackingNativeBindings.MLLightingTrackingGetAmbientGlobalState(this.nativeTracker, ref this.intensityState);
            if (result != MLResult.Code.Ok)
            {
                if (!this.getAmbientGlobalStateFailed)
                {
                    MLPluginLog.WarningFormat("MLLightingTracking.Update failed getting ambient global state. Reason: {0}", MagicLeapNativeBindings.MLGetResultString(result));
                    this.getAmbientGlobalStateFailed = true;
                }
            }
            else
            {
                this.getAmbientGlobalStateFailed = false;
            }

            this.CalculateGlobalAmbientScalar();
            result = MLLightingTrackingNativeBindings.MLLightingTrackingGetColorTemperatureState(this.nativeTracker, ref this.temperatureState);
            if (result != MLResult.Code.Ok)
            {
                if (!this.getColorTemperatureStateFailed)
                {
                    MLPluginLog.WarningFormat("MLLightingTracking.Update failed getting color temperature state. Reason: {0}", MagicLeapNativeBindings.MLGetResultString(result));
                    this.getColorTemperatureStateFailed = true;
                }
            }
            else
            {
                this.getColorTemperatureStateFailed = false;

                // populate tristimulus values
                this.tristimulusValues.x = this.temperatureState.XCIE;
                this.tristimulusValues.y = this.temperatureState.YCIE;
                this.tristimulusValues.z = this.temperatureState.ZCIE;

                // populate raw pixel accumulation vectors
                this.rawPixelAccumulation.x = this.temperatureState.RawPixelAverageR;
                this.rawPixelAccumulation.y = this.temperatureState.RawPixelAverageG;
                this.rawPixelAccumulation.z = this.temperatureState.RawPixelAverageB;
            }

            this.CalculateGlobalTemperatureColor();
        }
Пример #12
0
        /// <summary>
        /// Retrieves the type of the PCF associated with the given CFUID.
        /// </summary>
        /// <param name="cfuid">The CFUID to look up the PCF type with.</param>
        /// <param name="type">Stores the type of PCF associated with the given CFUID.</param>
        /// <returns>
        /// MLResult.Result will be <c>MLResult.Code.Ok</c> if a valid PCF was found.
        /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to an invalid input parameter.
        /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing.
        /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldNotFound</c> if the passed CFUID is not available.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map.
        /// </returns>
        public static MLResult GetPCFTypeByCFUID(MagicLeapNativeBindings.MLCoordinateFrameUID cfuid, out PCF.Types type)
        {
            type = 0;

            if (MLPersistentCoordinateFrames.IsValidInstance())
            {
                try
                {
                    NativeBindings.FrameStateNative nativeState = NativeBindings.FrameStateNative.Create();
                    MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFramesGetFrameState(_instance.nativeTracker, in cfuid, ref nativeState);
                    if (!MLResult.IsOK(resultCode))
                    {
                        if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize)
                        {
                            MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.GetPCFTypeByCFUID. Reason: {0}", MLResult.CodeToString(resultCode));
                        }
                        else
                        {
                            MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: {0}", MLResult.CodeToString(resultCode));
                        }

                        return(MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: {0}", MLResult.CodeToString(resultCode))));
                    }
                    else
                    {
                        type = nativeState.Type;
                        return(MLResult.Create(resultCode));
                    }
                }
                catch (EntryPointNotFoundException)
                {
                    MLPluginLog.Error("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: API symbols not found.");
                    return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: API symbols not found."));
                }
            }
            else
            {
                MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames.");
                return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.GetPCFTypeByCFUID failed. Reason: No Instance for MLPersistentCoordinateFrames."));
            }
        }
Пример #13
0
        /// <summary>
        /// Retrieves the closest known PCF of the types provided by the typesMask to the given position.
        /// </summary>
        /// <param name="position">The position of the object we want to anchor.</param>
        /// <param name="pcf">Stores the resulting PCF.</param>
        /// <param name="typesMask">The bitmask of which PCF types to consider.</param>
        /// <param name="update">Determines if the PCF should have it's pose and state updated.</param>
        /// <returns>
        /// MLResult.Result will be <c>MLResult.Code.Ok</c> if a valid PCF was found.
        /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to an invalid input parameter.
        /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing.
        /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map.
        /// </returns>
        public static MLResult FindClosestPCF(Vector3 position, out PCF pcf, PCF.Types typesMask = PCF.Types.SingleUserSingleSession | PCF.Types.SingleUserMultiSession | PCF.Types.MultiUserMultiSession, bool update = true)
        {
            pcf = null;

            if (MLPersistentCoordinateFrames.IsValidInstance())
            {
                QueryFilter queryFilter = QueryFilter.Create();
                queryFilter.TargetPoint = position;
                queryFilter.TypesMask   = typesMask;
                queryFilter.Sorted      = true;

                MLResult result = FindPCFsByFilter(queryFilter, out List <PCF> pcfList, update);

                if (!result.IsOk || pcfList.Count == 0)
                {
                    if (result.Result == MLResult.Code.PassableWorldLowMapQuality || result.Result == MLResult.Code.PassableWorldUnableToLocalize)
                    {
                        MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.FindClosestPCF. Reason: {0}", result);
                    }
                    else
                    {
                        MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindClosestPCF failed. Reason: {0}", result);
                    }
                }
                else
                {
                    pcf = pcfList[0];
                }

                return(result);
            }
            else
            {
                MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindClosestPCF failed. Reason: No Instance for MLPersistentCoordinateFrames.");
                return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindClosestPCF failed. Reason: No Instance for MLPersistentCoordinateFrames."));
            }
        }
Пример #14
0
        /// <summary>
        /// Returns filtered list of PCFs based on the parameters of the given queryFilter.
        /// </summary>
        /// <param name="queryFilter">Parameters used to curate the returned values.</param>
        /// <param name="pcfList">Stores the resulting list of PCFs.</param>
        /// <param name="update">Determines if the PCFs should have their pose updated.</param>
        /// <returns>
        /// MLResult.Result will be <c>MLResult.Code.Ok</c> if all the PCFs from the current map have been found successfully.
        /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing.
        /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map.
        /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map.
        /// </returns>
        public static MLResult FindPCFsByFilter(QueryFilter queryFilter, out List <PCF> pcfList, bool update = true)
        {
            pcfList = new List <PCF>();

            if (MLPersistentCoordinateFrames.IsValidInstance())
            {
                try
                {
                    uint          numPCFs    = 0;
                    MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFrameGetCount(_instance.nativeTracker, ref numPCFs);

                    if (MLResult.IsOK(resultCode) && numPCFs > 0)
                    {
                        MagicLeapNativeBindings.MLCoordinateFrameUID[] cfuidArray = new MagicLeapNativeBindings.MLCoordinateFrameUID[numPCFs];
                        NativeBindings.QueryFilterNative queryFilterNative        = NativeBindings.QueryFilterNative.Create();
                        queryFilterNative.Data = queryFilter;

                        uint cfuidCount = 0;

                        //// With these conditions the user is asking for all PCFs, no need to use the slower filtered query call.
                        if (queryFilter.TypesMask == (PCF.Types.SingleUserSingleSession | PCF.Types.SingleUserMultiSession | PCF.Types.MultiUserMultiSession) &&
                            queryFilter.Radius <= 0 && !queryFilter.Sorted)
                        {
                            resultCode = NativeBindings.MLPersistentCoordinateFrameGetAllEx(_instance.nativeTracker, numPCFs, cfuidArray);
                            cfuidCount = (uint)cfuidArray.Length;
                        }
                        else
                        {
                            resultCode = NativeBindings.MLPersistentCoordinateFrameQuery(_instance.nativeTracker, in queryFilterNative, cfuidArray, out cfuidCount);
                        }

                        if (MLResult.IsOK(resultCode))
                        {
                            for (int i = 0; i < cfuidCount; ++i)
                            {
                                MagicLeapNativeBindings.MLCoordinateFrameUID pcfCFUID = cfuidArray[i];
                                if (!pcfCFUID.Equals(MagicLeapNativeBindings.MLCoordinateFrameUID.EmptyFrame))
                                {
                                    PCF pcf = null;
                                    if (_instance.mapAllPCFs.ContainsKey(pcfCFUID))
                                    {
                                        pcf = _instance.mapAllPCFs[pcfCFUID];
                                    }
                                    else
                                    {
                                        pcf = new PCF(pcfCFUID);
                                        _instance.mapAllPCFs.Add(pcfCFUID, pcf);
                                    }

                                    pcfList.Add(pcf);

                                    if (update)
                                    {
                                        MLResult result = pcf.Update();
                                        if (!result.IsOk)
                                        {
                                            MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed to update the found PCF with CFUID {0}, Reason: {1}", pcf.CFUID, result);
                                        }
                                    }
                                }
                            }

                            return(MLResult.Create(MLResult.Code.Ok));
                        }
                        else
                        {
                            if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize)
                            {
                                MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.FindPCFsByFilter. Reason: {0}", MLResult.CodeToString(resultCode));
                            }
                            else
                            {
                                MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.CodeToString(resultCode));
                            }

                            return(MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.CodeToString(resultCode))));
                        }
                    }
                    else
                    {
                        if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize)
                        {
                            MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.FindPCFsByFilter. Reason: {0}", MLResult.CodeToString(resultCode));
                        }
                        else
                        {
                            MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode));
                        }

                        return(MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode))));
                    }
                }
                catch (EntryPointNotFoundException)
                {
                    MLPluginLog.Error("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: API symbols not found.");
                    return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: API symbols not found."));
                }
            }
            else
            {
                MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: No Instance for MLPersistentCoordinateFrames.");
                return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.FindPCFsByFilter failed. Reason: No Instance for MLPersistentCoordinateFrames."));
            }
        }