コード例 #1
0
        /// <summary>
        /// Loads the study with the provided index.
        /// </summary>
        /// <param name="studyIndex">The index of the study to load.</param>
        public async void LoadStudy(int studyIndex)
        {
            _ = ProgressIndicator.StartProgressIndicator("Loading data...");

            // tell other clients to also load the study
            var command = new MessageLoadStudy(studyIndex);

            Services.NetworkManager().SendMessage(command.Pack());

            // delete all current Visualizations
            Services.VisManager().DeleteAllVisualizations(false);

            // load the actual data
            await Services.DataManager().LoadStudyAsync(studyIndex);

            StudyChangeBroadcast.Invoke(studyIndex);

            // set session filter (also remotely)
            Services.StudyManager().UpdateSessionFilter(new List <int> {
                0
            }, new List <int> {
                0
            });

            _ = ProgressIndicator.StopProgressIndicator();
        }
コード例 #2
0
        /// <summary>
        /// Stops/pauses playback.
        /// </summary>
        public void StopPlayback()
        {
            TimelineStatus = TimelineStatus.PAUSED;
            var message = new MessageUpdateTimeline(new TimelineState(TimelineStatus, CurrentTimestamp, MinTimestamp, MaxTimestamp, PlaybackSpeed));

            Services.NetworkManager().SendMessage(message.Pack());
            TimelineEventBroadcast.Invoke(message.TimelineState);
        }
コード例 #3
0
        /// <summary>
        /// Sets the playback speed.
        /// </summary>
        /// <param name="playbackSpeed">The new playback speed factor.</param>
        public void SetPlaybackSpeed(float playbackSpeed)
        {
            PlaybackSpeed = playbackSpeed;
            var message = new MessageUpdateTimeline(new TimelineState(TimelineStatus, CurrentTimestamp, MinTimestamp, MaxTimestamp, PlaybackSpeed));

            Services.NetworkManager().SendMessage(message.Pack());
            TimelineEventBroadcast.Invoke(message.TimelineState);
        }
コード例 #4
0
 // Start is called before the first frame update
 private void Start()
 {
     CurrentTimeFilter.MinTime = 0;
     CurrentTimeFilter.MaxTime = 1;
     Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.LOAD_STUDY, OnLoadStudy);
     Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.UPDATE_TIMELINE, OnTimelineChange);
     Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.UPDATE_TIME_FILTER, OnTimeFilterChange);
     Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.UPDATE_SESSION_FILTER, OnSessionFilterChange);
 }
コード例 #5
0
        /// <summary>
        /// Updates the session filter with the provided <see cref="List{int}">Lists</see> of sessions and conditions.
        /// </summary>
        /// <param name="sessions">The indices of the sessions to select.</param>
        /// <param name="conditions">The indices of the conditions to select.</param>
        public void UpdateSessionFilter(List <int> sessions, List <int> conditions)
        {
            CurrentStudyConditions = conditions;
            CurrentStudySessions   = sessions;

            UpdateTimestampBounds();

            var message = new MessageUpdateSessionFilter(sessions, conditions);

            Services.NetworkManager().SendMessage(message.Pack());
            SessionFilterEventBroadcast.Invoke();
        }
コード例 #6
0
 /// <summary>
 /// Updates an existing visualization with the provided <see cref="VisProperties"/>.
 /// </summary>
 /// <param name="config">The struct containing the settings for the updated visualization.</param>
 /// <param name="syncWithRemote">Indicates whether this update should also happen on remote clients.</param>
 public void UpdateVisualization(VisProperties config, bool syncWithRemote = true)
 {
     if (Visualizations.TryGetValue(config.VisId, out AbstractView visualization))
     {
         visualization.UpdateView(config);
         if (syncWithRemote)
         {
             var message = new MessageUpdateVisualization(config);
             Services.NetworkManager().SendMessage(message.Pack());
         }
     }
 }
コード例 #7
0
        /// <summary>
        /// Updates the time filter.
        /// </summary>
        /// <param name="min">A float between 0 and 1 indicating the lower bound of the filter.</param>
        /// <param name="max">A float between 0 and 1 indicating the upper bound of the filter.</param>
        public void UpdateTimeFilter(float min, float max)
        {
            CurrentTimeFilter.MinTime = min;
            CurrentTimeFilter.MaxTime = max;

            UpdateTimestampBounds();

            var message = new MessageUpdateTimeFilter(CurrentTimeFilter);

            Services.NetworkManager().SendMessage(message.Pack());
            TimeFilterEventBroadcast.Invoke(message.TimeFilter);
        }
コード例 #8
0
        /// <summary>
        /// Unity start function.
        /// </summary>
        public void Start()
        {
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.CREATE_VISUALIZATION, OnCreateVisualization);
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.CREATE_CONTAINER, OnCreateVisContainer);
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.UPDATE_VISUALIZATION, OnUpdateVisualization);
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.DELETE_VISUALIZATION, OnDeleteVisualization);
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.DELETE_ALL_VISUALIZATIONS, OnDeleteAllVisualizations);
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.DELETE_ALL_CONTAINERS, OnDeleteAllContainers);
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.CENTER_DATA, OnCenterData);

            Services.StudyManager().SessionFilterEventBroadcast.AddListener(OnSessionFilterChange);
            Services.StudyManager().StudyChangeBroadcast.AddListener(OnStudyLoaded);
        }
コード例 #9
0
        private void SendUserUpdate()
        {
            if (cameraTransform != null && message != null)
            {
                LocalUserPosition.position = cameraTransform.position;
                LocalUserPosition.rotation = cameraTransform.rotation;

                message.Color       = Color;
                message.Position    = LocalUserPosition.localPosition;
                message.Orientation = LocalUserPosition.localRotation;
                message.Id          = id;
                Services.NetworkManager().SendMessage(message.Pack());
            }
        }
コード例 #10
0
        /// <summary>
        /// Sends the anchor to a client.
        /// </summary>
        /// <param name="client">The client connection to send the anchor to.</param>
        public void SendAnchor(Socket client)
        {
#if UNITY_WSA && !UNITY_EDITOR
            if (exportingAnchorBytes != null && IsAnchorEstablished)
            {
                // Send existing anchor data to clients
                var Command = new MessageWorldAnchor(exportingAnchorBytes.ToArray());
                Services.NetworkManager().Network.SendToClient(Command.Pack(), client);
            }
            else
            {
                // create new anchor and send it to clients
                CreateAnchor();
            }
#endif
        }
コード例 #11
0
        private void Start()
        {
#if UNITY_EDITOR
            IsAnchorEstablished = true;
#elif UNITY_WSA && !(ENABLE_IL2CPP && NET_STANDARD_2_0)
            if (HolographicSettings.IsDisplayOpaque)
            {
                IsAnchorEstablished = true;
            }
            else
            {
                Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.WORLD_ANCHOR, OnAnchorData);
            }
#else
            IsAnchorEstablished = true;
#endif
        }
コード例 #12
0
        /// <summary>
        /// Centers or un-centers the data to the origin, based on the average position of the samples.
        /// </summary>
        /// <param name="isCentering">Indicated whether to center or to reverse.</param>
        /// <param name="syncWithRemote">Indicates whether the centering should also happen on remote clients.</param>
        public void CenterData(bool isCentering, bool syncWithRemote = true)
        {
            var GlobalOffset = GameObject.FindGameObjectWithTag("GlobalOffset");

            if (GlobalOffset != null)
            {
                // center or un-center data
                if (isCentering == true && GlobalOffset.transform.position == Vector3.zero)
                {
                    Vector3 averagePosition = Vector3.zero;
                    foreach (var studyObject in Services.DataManager().DataSets.Values)
                    {
                        averagePosition += studyObject.AveragePosition;
                    }

                    averagePosition /= Services.DataManager().DataSets.Values.Count;

                    GameObject.FindGameObjectWithTag("GlobalOffset").transform.localPosition -= averagePosition;

                    // send message to the other clients
                    if (syncWithRemote)
                    {
                        var message = new MessageCenterData(isCentering);
                        Services.NetworkManager().SendMessage(message.Pack());
                    }

                    // send notification event that the data was centered or un-centered
                    DataCenteringEventBroadcast.Invoke(true);
                }
                else
                {
                    GameObject.FindGameObjectWithTag("GlobalOffset").transform.localPosition = Vector3.zero;

                    // send message to the other clients
                    if (syncWithRemote)
                    {
                        var message = new MessageCenterData(isCentering);
                        Services.NetworkManager().SendMessage(message.Pack());
                    }

                    // send notification event that the data was centered or un-centered
                    DataCenteringEventBroadcast.Invoke(false);
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// Deletes all existing <see cref="ViewContainer">ViewContainers</see>.
        /// </summary>
        /// <param name="syncWithRemote">Indicates whether the containers should also be deleted on remote clients.</param>
        public void DeleteAllViewContainers(bool syncWithRemote = true)
        {
            if (ViewContainers != null)
            {
                foreach (var container in ViewContainers)
                {
                    Destroy(container.Value.gameObject);
                }

                ViewContainers.Clear();
            }

            if (syncWithRemote)
            {
                var message = new MessageDeleteAllVisContainers();
                Services.NetworkManager().SendMessage(message.Pack());
            }
        }
コード例 #14
0
        // Start is called before the first frame update
        private void Start()
        {
            SetColor(0);
            worldAnchor = GameObject.FindGameObjectWithTag("RootWorldAnchor").transform;
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.UPDATE_USER, OnRemoteUserUpdate);
            Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.ACCEPT_CLIENT, OnAcceptedAsClient);

            Transform cameraTransform = CameraCache.Main ? CameraCache.Main.transform : null;

            if (cameraTransform != null)
            {
                message = new MessageUpdateUser(cameraTransform.position, cameraTransform.rotation, id, Color);
                Services.NetworkManager().SendMessage(message.Pack());

                LocalUserPosition          = new GameObject().transform;
                LocalUserPosition.position = cameraTransform.position;
                LocalUserPosition.rotation = cameraTransform.rotation;
            }
        }
コード例 #15
0
        /// <summary>
        /// Deletes all existing visualizations from the scene.
        /// </summary>
        /// <param name="syncWithRemote">Indicates whether the visualization should also be deleted on remote clients.</param>
        public void DeleteAllVisualizations(bool syncWithRemote = true)
        {
            foreach (var kvp in Visualizations)
            {
                var settings = kvp.Value.Settings;
                kvp.Value.Dispose();

                // send notification event that a vis was deleted
                VisualizationDeletedEventBroadcast.Invoke(settings);
            }

            Visualizations.Clear();

            if (syncWithRemote)
            {
                var message = new MessageDeleteAllVisualizations();
                Services.NetworkManager().SendMessage(message.Pack());
            }
        }
コード例 #16
0
        /// <summary>
        /// Deletes a single visualization with the provided <see cref="Guid"/>.
        /// </summary>
        /// <param name="visId">The <see cref="Guid"/> of the visualization.</param>
        /// <param name="syncWithRemote">Indicates whether the visualization should also be deleted on remote clients.</param>
        /// <returns>A bool indicating whether a visualization was successfully deleted.
        /// Returns <see langword="false"/> when there is no visualization with the provided <see cref="Guid"/>.</returns>
        public bool DeleteVisualization(Guid visId, bool syncWithRemote = true)
        {
            if (Visualizations.ContainsKey(visId))
            {
                var settings = Visualizations[visId].Settings;
                Visualizations[visId].Dispose();
                Visualizations.Remove(visId);
                if (syncWithRemote)
                {
                    var message = new MessageDeleteVisualization(visId);
                    Services.NetworkManager().SendMessage(message.Pack());
                }

                // send notification event that a vis was deleted
                VisualizationDeletedEventBroadcast.Invoke(settings);

                return(true);
            }

            return(false);
        }
コード例 #17
0
        /// <summary>
        /// Called when serializing an anchor is complete.
        /// </summary>
        /// <param name="status">If the serialization succeeded.</param>
        private void ExportComplete(SerializationCompletionReason status)
        {
            if (status == SerializationCompletionReason.Succeeded && exportingAnchorBytes.Count > MinTrustworthySerializedAnchorDataSize)
            {
                AnchorName = exportingAnchorName;
                anchorData = exportingAnchorBytes.ToArray();
                ////createdAnchor = true;
                Debug.Log("Anchor ready " + exportingAnchorBytes.Count);
                IsAnchorEstablished = true;

                // Send anchor data to clients
                var command = new MessageWorldAnchor(exportingAnchorBytes.ToArray());
                Services.NetworkManager().SendMessage(command.Pack());
            }
            else
            {
                Debug.Log("Create anchor failed " + status + " " + exportingAnchorBytes.Count);
                exportingAnchorBytes.Clear();
                DestroyImmediate(ObjectToAnchor.GetComponent <WorldAnchor>());
                CreateAnchor();
            }
        }
コード例 #18
0
        /// <summary>
        /// Creates a new <see cref="ViewContainer"/> and adds it to the list of containers.
        /// </summary>
        /// <param name="container">The <see cref="VisContainer"/> object representing the settings for the new <see cref="ViewContainer"/>.</param>
        /// <param name="syncWithRemote">Indicates whether the container should also be created on remote clients.</param>
        public void CreateViewContainer(VisContainer container, bool syncWithRemote = true)
        {
            // add to list of containers or update list
            if (ViewContainers.ContainsKey(container.Id))
            {
                // already in list, update
                ViewContainers[container.Id].Init(container);
            }
            else
            {
                // not in list, create and add
                Transform worldAnchor = GameObject.FindGameObjectWithTag("VisRootAnchor").transform;
                var       placeholder = Instantiate(VisPlaceholderPrefab, worldAnchor);       // instantiate placeholder prefab, set the World Anchor as parent, to make sure every client sees the same
                placeholder.Init(container);
                ViewContainers.Add(container.Id, placeholder.GetComponent <ViewContainer>()); // add to list
            }

            if (syncWithRemote)
            {
                var message = new MessageCreateVisContainer(container);
                Services.NetworkManager().SendMessage(message.Pack());
            }
        }
コード例 #19
0
        private async Task OnLoadStudy(MessageContainer obj)
        {
            Debug.Log("Loading Study");
            Services.NetworkManager().Pause();
            MessageLoadStudy message = MessageLoadStudy.Unpack(obj);

            if (message != null)
            {
                _ = ProgressIndicator.StartProgressIndicator("Loading data...");

                // delete all current Visualizations
                Services.VisManager().DeleteAllVisualizations(false);

                // load the actual data
                await Services.DataManager().LoadStudyAsync(message.StudyIndex);

                StudyChangeBroadcast.Invoke(message.StudyIndex);

                _ = ProgressIndicator.StopProgressIndicator();
            }

            Services.NetworkManager().Unpause();
            Debug.Log("Loading Study - Completed");
        }
コード例 #20
0
ファイル: AnnotationManager.cs プロジェクト: imldresden/miria
 // Start is called before the first frame update
 private void Start()
 {
     worldAnchor = GameObject.FindGameObjectWithTag("VisRootAnchor").transform;
     Services.NetworkManager().RegisterMessageHandler(MessageContainer.MessageType.UPDATE_ANNOTATION, OnAnnotationUpdated);
 }
コード例 #21
0
ファイル: AnnotationManager.cs プロジェクト: imldresden/miria
        /// <summary>
        /// This method adds a new annotation.
        /// </summary>
        public void AddAnnotation()
        {
            if (!AnnotationPrefab)
            {
                return;
            }

            Transform cameraTransform = CameraCache.Main ? CameraCache.Main.transform : null;

            foreach (var source in CoreServices.InputSystem.DetectedInputSources)
            {
                // Only look for hands
                if (source.SourceType == Microsoft.MixedReality.Toolkit.Input.InputSourceType.Hand)
                {
                    foreach (var pointer in source.Pointers)
                    {
                        if (pointer is IMixedRealityNearPointer || true)
                        {
                            Vector3 position;
                            if (pointer.Result != null)
                            {
                                position = pointer.Result.Details.Point;
                            }
                            else
                            {
                                position = pointer.Position;
                            }

                            if (cameraTransform != null)
                            {
                                if ((cameraTransform.position - position).magnitude > 3)
                                {
                                    position = cameraTransform.position + ((position - cameraTransform.position) * 0.5f);
                                }
                            }

                            var annotation = Instantiate(AnnotationPrefab, worldAnchor);
                            annotation.transform.position = position;
                            annotation.Id = Guid.NewGuid();
                            annotation.SetColor(Services.UserManager().Color);
                            annotationList.Add(annotation.Id, annotation);

                            var message = new MessageUpdateAnnotation(annotation.Id, annotation.transform.localPosition, annotation.Color);
                            Services.NetworkManager().SendMessage(message.Pack());

                            return; // only take first valid pointer
                        }
                    }
                }
            }

            if (cameraTransform != null)
            {
                Vector3 position   = cameraTransform.position;
                var     annotation = Instantiate(AnnotationPrefab, worldAnchor);
                annotation.transform.position = position;
                annotation.Id = Guid.NewGuid();
                annotation.SetColor(Services.UserManager().Color);
                annotationList.Add(annotation.Id, annotation);

                var message = new MessageUpdateAnnotation(annotation.Id, annotation.transform.localPosition, annotation.Color);
                Services.NetworkManager().SendMessage(message.Pack());

                return; // only take first valid pointer
            }
        }
コード例 #22
0
        /// <summary>
        /// Creates a visualization from a <see cref="VisProperties"/>.
        /// </summary>
        /// <param name="settings">The struct containing the settings for the visualization.</param>
        /// <param name="syncWithRemote">Indicates whether the visualization should also be created on other clients.</param>
        /// <returns>A <see cref="GameObject"/> with the visualization.</returns>
        public GameObject CreateVisualization(VisProperties settings, bool syncWithRemote = true)
        {
            try
            {
                if (Visualizations.ContainsKey(settings.VisId))
                {
                    throw new Exception("VisId " + settings.VisId + " has been used twice!");
                }

                // if the vis id is empty, create a new, non-colliding GUID
                if (settings.VisId == Guid.Empty)
                {
                    settings.VisId = Guid.NewGuid();

                    // This is extremely unlikely to ever happen
                    while (Visualizations.ContainsKey(settings.VisId))
                    {
                        Debug.LogWarning("GUID collision! Probably someone made a mistake. If not, you should start playing the lottery!");
                        settings.VisId = Guid.NewGuid();
                    }
                }

                // special case: timeline control view & coordinate system
                GameObject vis;
                if (settings.VisType == VisType.TimelineControl)
                {
                    var timelineControl = Instantiate(TimelineControlPrefab);
                    timelineControl.Init(settings);
                    vis = timelineControl.gameObject;
                    timelineController = timelineControl;
                }
                else if (settings.VisType == VisType.CoordinateSystem3D)
                {
                    var coordinateSystem = Instantiate(CoordinateSystemPrefab);
                    coordinateSystem.Init(settings);
                    vis = coordinateSystem.gameObject;
                    coordinateSystemVis = coordinateSystem;
                }

                // get correct prefab
                AbstractView visPrefab = null;
                foreach (var prefab in VisualizationPrefabs)
                {
                    if (prefab.VisType == settings.VisType)
                    {
                        visPrefab = prefab;
                        break;
                    }
                }

                if (visPrefab == null)
                {
                    throw new Exception("Attempt to spawn unknown visualization! Type: " + settings.VisType);
                }

                // instantiate prefab
                var visInstance = Instantiate(visPrefab);
                visInstance.Init(settings);
                vis = visInstance.gameObject;

                if (settings.AnchorId != -1 && ViewContainers.ContainsKey(settings.AnchorId))
                {
                    // anchor is available
                    ViewContainers[settings.AnchorId].AttachVis(vis.GetComponent <AbstractView>());
                }
                else if (settings.VisType == VisType.TimelineControl)
                {
                    // anchor not available, put at world anchor
                    Transform worldAnchor = GameObject.FindGameObjectWithTag("RootWorldAnchor").transform;
                    vis.transform.SetParent(worldAnchor, false);
                }
                else
                {
                    // anchor not available, put at world anchor
                    Transform worldAnchor = GameObject.FindGameObjectWithTag("VisRootAnchor").transform;
                    vis.transform.SetParent(worldAnchor, false);
                }

                Visualizations[settings.VisId] = vis.GetComponent <AbstractView>();

                // at this point, creation was successful; send message to the other clients if needed
                if (syncWithRemote)
                {
                    var message = new MessageCreateVisualization(settings);
                    Services.NetworkManager().SendMessage(message.Pack());
                }

                // send notification event that a new vis was created
                VisualizationCreatedEventBroadcast.Invoke(settings);

                return(vis);
            }
            catch (Exception e)
            {
                Debug.LogWarning("Creation of requested Visualization failed.");
                Debug.LogError(e.Message);
                Debug.LogError(e.StackTrace);
                return(new GameObject("Creation Failed"));
            }
        }