private ISpatialLocalizationSettings LoadLocalizerSettings(ISpatialLocalizer spatialLocalizer)
        {
            ISpatialLocalizationSettings settings;
            string settingsString = PlayerPrefs.GetString(spatialLocalizer.SpatialLocalizerId.ToString(), null);

            if (string.IsNullOrEmpty(settingsString))
            {
                settings = spatialLocalizer.CreateDefaultSettings();
            }
            else
            {
                byte[] settingsBytes = Convert.FromBase64String(settingsString);
                using (MemoryStream stream = new MemoryStream(settingsBytes))
                    using (BinaryReader reader = new BinaryReader(stream))
                    {
                        if (!spatialLocalizer.TryDeserializeSettings(reader, out settings))
                        {
                            Debug.LogError($"Failed to deserialize settings for spatial localizer {spatialLocalizer.DisplayName} ({spatialLocalizer.SpatialLocalizerId}), using default settings");
                            settings = spatialLocalizer.CreateDefaultSettings();
                        }
                    }
            }

            return(settings);
        }
 public void UnregisterSpatialLocalizer(ISpatialLocalizer localizer)
 {
     if (!localizers.Remove(localizer.SpatialLocalizerId))
     {
         Debug.LogError($"Attempted to unregister SpatialLocalizer with ID {localizer.SpatialLocalizerId} that was not registered.");
     }
 }
        private async Task <bool> RunLocalizationSessionAsync(ISpatialLocalizer localizer, ISpatialLocalizationSettings settings, SpatialCoordinateSystemParticipant participant)
        {
            DebugLog($"Creating localization session: {participant.SocketEndpoint.Address}, {settings.ToString()}, {localizer.ToString()}");
            if (!localizer.TryCreateLocalizationSession(participant, settings, out ISpatialLocalizationSession currentLocalizationSession))
            {
                Debug.LogError($"Failed to create an ISpatialLocalizationSession from localizer {localizer.SpatialLocalizerId}");
                return(false);
            }

            using (currentLocalizationSession)
            {
                DebugLog($"Setting localization session for participant: {participant.SocketEndpoint.Address}, {currentLocalizationSession.ToString()}");
                participant.CurrentLocalizationSession = currentLocalizationSession;

                try
                {
                    DebugLog($"Starting localization: {participant.SocketEndpoint.Address}, {currentLocalizationSession.ToString()}");
                    // Some SpatialLocalizers/SpatialCoordinateServices key off of token cancellation for their logic flow.
                    // Therefore, we need to create a cancellation token even it is never actually cancelled by the SpatialCoordinateSystemManager.
                    using (var localizeCTS = new CancellationTokenSource())
                    {
                        var coordinate = await currentLocalizationSession.LocalizeAsync(localizeCTS.Token);

                        participant.Coordinate = coordinate;
                    }
                }
                finally
                {
                    participant.CurrentLocalizationSession = null;
                }
            }
            currentLocalizationSession = null;
            return(participant.Coordinate != null);
        }
        public void RegisterSpatialLocalizer(ISpatialLocalizer localizer)
        {
            if (localizers.ContainsKey(localizer.SpatialLocalizerId))
            {
                Debug.LogError($"Cannot register multiple SpatialLocalizers with the same ID {localizer.SpatialLocalizerId}");
                return;
            }

            DebugLog($"Registering spatial localizer: {localizer.SpatialLocalizerId}");
            localizers.Add(localizer.SpatialLocalizerId, localizer);
        }
        private async Task <bool> RunLocalizationSessionAsync(ISpatialLocalizer localizer, ISpatialLocalizationSettings settings, SpatialCoordinateSystemParticipant participant)
        {
            if (!TryCleanupExistingLocalizationSession(participant))
            {
                DebugLog("Existing localization session with different participant prevented creating new localization session");
                return(false);
            }

            if (!localizer.TryCreateLocalizationSession(participant, settings, out var localizationSession))
            {
                Debug.LogError($"Failed to create an ISpatialLocalizationSession from localizer {localizer.SpatialLocalizerId}");
                return(false);
            }

            Task <bool> resultTask;
            bool        startSession = false;
            var         localizationSessionDetails = new LocalizationSessionDetails(localizationSession, participant);

            lock (localizationLock)
            {
                if (currentLocalizationSession != null)
                {
                    DebugLog($"Current localization session repopulated after cleanup, localization not performed.");
                    localizationSessionDetails.Session.Dispose();
                    resultTask = Task.FromResult(false);
                }
                else
                {
                    currentLocalizationSession = localizationSessionDetails;
                    localizationSessionDetails.Participant.CurrentLocalizationSession = localizationSessionDetails.Session;
                    resultTask   = localizationSessionDetails.CompletionSource.Task;
                    startSession = true;
                }
            }

            if (startSession)
            {
                await Dispatcher.ScheduleAsync(async() =>
                {
                    try
                    {
                        // Some SpatialLocalizers/SpatialCoordinateServices key off of token cancellation for their logic flow.
                        // Therefore, we need to create a cancellation token even it is never actually cancelled by the SpatialCoordinateSystemManager.
                        using (var localizeCTS = new CancellationTokenSource())
                        {
                            var coordinate = await localizationSessionDetails.Session.LocalizeAsync(localizeCTS.Token);
                            bool succeeded = (coordinate != null);
                            localizationSessionDetails.Session.Dispose();
                            localizationSessionDetails.CompletionSource.TrySetResult(succeeded);

                            if (localizationSessionDetails.Participant.CurrentLocalizationSession == localizationSessionDetails.Session)
                            {
                                localizationSessionDetails.Participant.Coordinate = coordinate;
                                localizationSessionDetails.Participant.CurrentLocalizationSession = null;
                            }
                            else
                            {
                                Debug.LogWarning("Localization session completed but was no longer assigned to the associated participant");
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        DebugLog("Localization operation cancelled.");
                    }
                    catch (Exception e)
                    {
                        Debug.LogError($"Exception thrown localizing experience: {e.ToString()}");
                    }
                }, CancellationToken.None, true);
            }

            return(await resultTask);
        }