private void SpatialLocalizationSettingsGUI(string deviceTypeLabel, int selectedLocalizerIndex, ISpatialLocalizer[] localizers)
        {
            GUIStyle   iconButtonStyle = GUI.skin.FindStyle("IconButton") ?? EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("IconButton");
            GUIContent content         = new GUIContent(EditorGUIUtility.Load("icons/d__Popup.png") as Texture2D);

            ISpatialLocalizationSettings         settings       = localizers == null ? null : LoadLocalizerSettings(localizers[selectedLocalizerIndex]);
            IEditableSpatialLocalizationSettings settingsEditor = settings as IEditableSpatialLocalizationSettings;

            bool wasEnabled = GUI.enabled;

            GUI.enabled = settingsEditor != null;

            if (EditorGUILayout.DropdownButton(content, FocusType.Passive, iconButtonStyle, GUILayout.Width(settingsButtonWidth)))
            {
                Action <SpatialLocalizationSettingsEditor> editingCompleted = null;
                Guid localizerId = localizers[selectedLocalizerIndex].SpatialLocalizerId;
                editingCompleted = e =>
                {
                    e.EditingCompleted -= editingCompleted;
                    SaveLocalizerSettings(localizerId, settings);
                };

                var editor = settingsEditor.CreateEditor();
                editor.EditingCompleted += editingCompleted;
                PopupWindow.Show(buttonRects[deviceTypeLabel], editor);
            }

            if (Event.current.type == EventType.Repaint)
            {
                buttonRects[deviceTypeLabel] = GUILayoutUtility.GetLastRect();
            }

            GUI.enabled = wasEnabled;
        }
 private void SaveLocalizerSettings(Guid spatialLocalizerId, ISpatialLocalizationSettings settings)
 {
     using (MemoryStream stream = new MemoryStream())
         using (BinaryWriter writer = new BinaryWriter(stream))
         {
             settings.Serialize(writer);
             PlayerPrefs.SetString(spatialLocalizerId.ToString(), Convert.ToBase64String(stream.ToArray()));
             PlayerPrefs.Save();
         }
 }
 bool ISpatialLocalizer.TryDeserializeSettings(BinaryReader reader, out ISpatialLocalizationSettings settings)
 {
     if (TryDeserializeSettings(reader, out TSpatialLocalizationSettings specificSettings))
     {
         settings = specificSettings;
         return(true);
     }
     else
     {
         settings = default(ISpatialLocalizationSettings);
         return(false);
     }
 }
        /// <summary>
        /// Runs a localization session on the specific <see cref="SpatialCoordinateSystemParticipant"/>'s connected peer, followed
        /// by creating a persisted WorldAnchor-based <see cref="ISpatialCoordinate"/> based on the located coordinate.
        /// </summary>
        /// <param name="participant">The participant to use to initiate the remote localization sessions.</param>
        /// <param name="spatialLocalizerId">The ID of the <see cref="ISpatialLocalizer"/> to use
        /// for discovering a spatial coordinate.</param>
        /// <param name="settings">The settings to pass to the remote localizer.</param>
        public async void RunRemoteLocalizationWithWorldAnchorPersistence(SpatialCoordinateSystemParticipant participant, Guid spatialLocalizerId, ISpatialLocalizationSettings settings)
        {
            // If the initial request to restore a coordinate from a WorldAnchor hasn't completed, wait for that to complete first.
            if (participantLocalizationTasks.TryGetValue(participant, out Task <bool> currentTask))
            {
                await currentTask;
            }

            // Request localization using the specific localizer and settings, and wait for that localization to complete.
            participantLocalizationTasks[participant] = currentTask = SpatialCoordinateSystemManager.Instance.RunRemoteLocalizationAsync(participant.SocketEndpoint, spatialLocalizerId, settings);
            bool localizationSucceeded = await currentTask;

            if (localizationSucceeded)
            {
                // Once the specific localizer has found a shared coordinate, ask the WorldAnchorSpatialLocalizer
                // to create a WorldAnchor-based coordinate at the same location, and persist that coordinate across sessions.
                participantLocalizationTasks[participant] = currentTask = SpatialCoordinateSystemManager.Instance.RunRemoteLocalizationAsync(participant.SocketEndpoint, WorldAnchorSpatialLocalizer.Id, new WorldAnchorSpatialLocalizationSettings
                {
                    Mode           = WorldAnchorLocalizationMode.CreateAnchorAtWorldTransform,
                    AnchorId       = CompositorWorldAnchorId,
                    AnchorPosition = participant.PeerSpatialCoordinateWorldPosition,
                    AnchorRotation = participant.PeerSpatialCoordinateWorldRotation
                });
                await currentTask;
            }
            else
            {
                Debug.LogError($"Remote localization failed on device {participant.SocketEndpoint.Address} for spatial localizer {spatialLocalizerId}");
            }
        }
 bool ISpatialLocalizer.TryCreateLocalizationSession(IPeerConnection peerConnection, ISpatialLocalizationSettings settings, out ISpatialLocalizationSession session)
 {
     if (settings is TSpatialLocalizationSettings specificSettings)
     {
         return(TryCreateLocalizationSession(peerConnection, specificSettings, out session));
     }
     else
     {
         throw new ArgumentException(nameof(settings));
     }
 }
        public Task <bool> LocalizeAsync(SocketEndpoint socketEndpoint, Guid spatialLocalizerID, ISpatialLocalizationSettings settings)
        {
            DebugLog("LocalizeAsync");
            if (currentLocalizationSession != null)
            {
                Debug.LogError($"Failed to start localization session because an existing localization session is in progress");
                return(Task.FromResult(false));
            }

            if (!participants.TryGetValue(socketEndpoint, out SpatialCoordinateSystemParticipant participant))
            {
                Debug.LogError($"Could not find a SpatialCoordinateSystemParticipant for SocketEndpoint {socketEndpoint.Address}");
                return(Task.FromResult(false));
            }

            if (!localizers.TryGetValue(spatialLocalizerID, out ISpatialLocalizer localizer))
            {
                Debug.LogError($"Could not find a ISpatialLocalizer for spatialLocalizerID {spatialLocalizerID}");
                return(Task.FromResult(false));
            }

            DebugLog("Returning a localization session.");
            return(RunLocalizationSessionAsync(localizer, settings, participant));
        }
        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 Task <bool> RunRemoteLocalizationAsync(SocketEndpoint socketEndpoint, Guid spatialLocalizerID, ISpatialLocalizationSettings settings)
        {
            DebugLog($"Initiating remote localization: {socketEndpoint.Address}, {spatialLocalizerID.ToString()}");
            TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>();

            remoteLocalizationSessions.Add(socketEndpoint, taskCompletionSource);

            using (MemoryStream stream = new MemoryStream())
                using (BinaryWriter message = new BinaryWriter(stream))
                {
                    message.Write(LocalizeCommand);
                    message.Write(spatialLocalizerID);
                    settings.Serialize(message);

                    socketEndpoint.Send(stream.ToArray());
                }

            return(taskCompletionSource.Task);
        }
        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);
        }
Esempio n. 10
0
        public Task <bool> LocalizeAsync(SocketEndpoint socketEndpoint, Guid spatialLocalizerID, ISpatialLocalizationSettings settings)
        {
            DebugLog("LocalizeAsync");
            if (!participants.TryGetValue(socketEndpoint, out SpatialCoordinateSystemParticipant participant))
            {
                Debug.LogError($"Could not find a SpatialCoordinateSystemParticipant for SocketEndpoint {socketEndpoint.Address}");
                return(Task.FromResult(false));
            }

            if (currentLocalizationSession != null)
            {
                if (participant == currentLocalizationSession.Peer &&
                    remoteLocalizationSessions.TryGetValue(socketEndpoint, out var taskCompletionSource) &&
                    taskCompletionSource.TrySetCanceled())
                {
                    DebugLog($"Current localization session for {socketEndpoint.Address} was canceled based on a new localization request.");
                    remoteLocalizationSessions.Remove(socketEndpoint);
                }
                else
                {
                    Debug.LogError($"Failed to start localization session because an existing localization session is in progress");
                    return(Task.FromResult(false));
                }
            }

            if (!localizers.TryGetValue(spatialLocalizerID, out ISpatialLocalizer localizer))
            {
                Debug.LogError($"Could not find a ISpatialLocalizer for spatialLocalizerID {spatialLocalizerID}");
                return(Task.FromResult(false));
            }

            DebugLog("Returning a localization session.");
            return(RunLocalizationSessionAsync(localizer, settings, participant));
        }
Esempio n. 11
0
        public Task <bool> LocalizeAsync(INetworkConnection connection, Guid spatialLocalizerID, ISpatialLocalizationSettings settings)
        {
            DebugLog("LocalizeAsync");
            if (!participants.TryGetValue(connection, out SpatialCoordinateSystemParticipant participant))
            {
                Debug.LogError($"Could not find a SpatialCoordinateSystemParticipant for INetworkConnection {connection.ToString()}");
                return(Task.FromResult(false));
            }

            if (!localizers.TryGetValue(spatialLocalizerID, out ISpatialLocalizer localizer))
            {
                Debug.LogError($"Could not find a ISpatialLocalizer for spatialLocalizerID {spatialLocalizerID}");
                return(Task.FromResult(false));
            }

            DebugLog("Returning a localization session.");
            return(RunLocalizationSessionAsync(localizer, settings, participant));
        }
Esempio n. 12
0
        public Task <bool> RunRemoteLocalizationAsync(INetworkConnection connection, Guid spatialLocalizerID, ISpatialLocalizationSettings settings)
        {
            DebugLog($"Initiating remote localization: {connection.ToString()}, {spatialLocalizerID.ToString()}");
            if (remoteLocalizationSessions.TryGetValue(connection, out var currentCompletionSource))
            {
                DebugLog($"Canceling existing remote localization session: {connection.ToString()}");
                currentCompletionSource.TrySetCanceled();
                remoteLocalizationSessions.Remove(connection);
            }

            TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>();

            remoteLocalizationSessions.Add(connection, taskCompletionSource);

            using (MemoryStream stream = new MemoryStream())
                using (BinaryWriter message = new BinaryWriter(stream))
                {
                    message.Write(LocalizeCommand);
                    message.Write(spatialLocalizerID);
                    settings.Serialize(message);

                    byte[] data = stream.ToArray();
                    connection.Send(ref data);
                }

            return(taskCompletionSource.Task);
        }