From 3cdab9fd186a46c5d29d0d019288c6b3a66a20f6 Mon Sep 17 00:00:00 2001 From: chrisfromwork Date: Wed, 25 Sep 2019 13:10:05 -0700 Subject: [PATCH 1/2] enable resetting localization --- .../SpatialAnchorsCoordinateService.cs | 21 ++++- ...nchorsCoordinateLocalizationInitializer.cs | 25 ++++-- .../SpectatorView/SpatialAnchorsLocalizer.cs | 2 + .../ISpatialLocalizationSession.cs | 17 +++- .../MarkerVisualCoordinateService.cs | 4 +- .../MarkerVisualDetectorSpatialLocalizer.cs | 2 + .../MarkerVisualLocalizationInitializer.cs | 23 ++++- .../MarkerVisualSpatialLocalizer.cs | 2 + .../MarkerDetectorSpatialLocalizer.cs | 8 +- .../SpatialCoordinateSystemManager.cs | 83 +++++++++++++++---- .../SpatialLocalizationInitializer.cs | 17 +++- .../WorldAnchorSpatialLocalizer.cs | 8 +- .../SpectatorView/Scripts/SpectatorView.cs | 81 ++++++++++++++---- 13 files changed, 243 insertions(+), 50 deletions(-) diff --git a/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpatialAlignment/SpatialAnchorsCoordinateService.cs b/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpatialAlignment/SpatialAnchorsCoordinateService.cs index 4c370701f..7894b59b8 100644 --- a/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpatialAlignment/SpatialAnchorsCoordinateService.cs +++ b/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpatialAlignment/SpatialAnchorsCoordinateService.cs @@ -95,7 +95,15 @@ public override async Task TryDeleteCoordinateAsync(string id, Cancellatio #if UNITY_EDITOR return await TryDeleteCoordinateEditorAsync(id, cancellationToken); #else - return await TryDeleteCoordinateImplAsync(id, cancellationToken); + if (id != null && + id.StartsWith(simulatedCoordinateIdPrefix)) + { + return await TryDeleteCoordinateEditorAsync(id, cancellationToken); + } + else + { + return await TryDeleteCoordinateImplAsync(id, cancellationToken); + } #endif } @@ -155,7 +163,16 @@ protected override async Task OnDiscoverCoordinatesAsync(CancellationToken cance #if UNITY_EDITOR await OnDiscoverCoordinatesEditorAsync(cancellationToken, idsToLocate); #else - await OnDiscoverCoordinatesImplAsync(cancellationToken, idsToLocate); + if (idsToLocate != null && + idsToLocate.Length > 0 && + idsToLocate[0].StartsWith(simulatedCoordinateIdPrefix)) + { + await OnDiscoverCoordinatesEditorAsync(cancellationToken, idsToLocate); + } + else + { + await OnDiscoverCoordinatesImplAsync(cancellationToken, idsToLocate); + } #endif } diff --git a/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsCoordinateLocalizationInitializer.cs b/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsCoordinateLocalizationInitializer.cs index c5da4d029..2753b6466 100644 --- a/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsCoordinateLocalizationInitializer.cs +++ b/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsCoordinateLocalizationInitializer.cs @@ -2,8 +2,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. using System; -using System.Collections; -using System.Collections.Generic; +using System.Threading.Tasks; using UnityEngine; namespace Microsoft.MixedReality.SpectatorView @@ -19,12 +18,28 @@ public class SpatialAnchorsCoordinateLocalizationInitializer : SpatialLocalizati public override Guid PeerSpatialLocalizerId => SpatialAnchorsLocalizer.Id; - public override void RunLocalization(SpatialCoordinateSystemParticipant participant) + /// + public override async Task TryRunLocalizationAsync(SpatialCoordinateSystemParticipant participant) { - SpatialCoordinateSystemManager.Instance.LocalizeAsync(participant.SocketEndpoint, SpatialAnchorsLocalizer.Id, configuration); + return await TryRunLocalizationImplAsync(participant); + } + /// + public override async Task TryResetLocalizationAsync(SpatialCoordinateSystemParticipant participant) + { + return await TryRunLocalizationImplAsync(participant); + } + + private async Task TryRunLocalizationImplAsync(SpatialCoordinateSystemParticipant participant) + { + configuration.IsCoordinateCreator = false; + Task localTask = SpatialCoordinateSystemManager.Instance.LocalizeAsync(participant.SocketEndpoint, SpatialAnchorsLocalizer.Id, configuration); configuration.IsCoordinateCreator = true; - SpatialCoordinateSystemManager.Instance.RunRemoteLocalizationAsync(participant.SocketEndpoint, SpatialAnchorsLocalizer.Id, configuration); + Task remoteTask = SpatialCoordinateSystemManager.Instance.RunRemoteLocalizationAsync(participant.SocketEndpoint, SpatialAnchorsLocalizer.Id, configuration); + await Task.WhenAll(localTask, remoteTask); + bool localSuccess = await localTask; + bool remoteSuccess = await remoteTask; + return localSuccess && remoteSuccess; } } } \ No newline at end of file diff --git a/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsLocalizer.cs b/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsLocalizer.cs index 101db465b..617507b4e 100644 --- a/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsLocalizer.cs +++ b/src/SpectatorView.Unity/Assets/SpatialAlignment.ASA/Scripts/SpectatorView/SpatialAnchorsLocalizer.cs @@ -92,6 +92,8 @@ private void Update() private class SpatialCoordinateLocalizationSession : DisposableBase, ISpatialLocalizationSession { + public IPeerConnection Peer => peerConnection; + private readonly IPeerConnection peerConnection; private readonly SpatialAnchorsCoordinateService coordinateService; private readonly SpatialAnchorsConfiguration configuration; diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/ISpatialLocalizationSession.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/ISpatialLocalizationSession.cs index ee0d38b40..8149d26a7 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/ISpatialLocalizationSession.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/ISpatialLocalizationSession.cs @@ -3,19 +3,30 @@ using Microsoft.MixedReality.SpatialAlignment; using System; -using System.Collections; -using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; -using UnityEngine; namespace Microsoft.MixedReality.SpectatorView { public interface ISpatialLocalizationSession : IDisposable { + /// + /// Participant associated with the current localization session + /// + IPeerConnection Peer { get; } + + /// + /// Call to obtain a spatial coordinate from this localization session + /// + /// + /// Task LocalizeAsync(CancellationToken cancellationToken); + /// + /// Call to provide network information + /// + /// reader containing a network payload void OnDataReceived(BinaryReader reader); } } \ No newline at end of file diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualCoordinateService.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualCoordinateService.cs index 928d194f6..319bb70e5 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualCoordinateService.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualCoordinateService.cs @@ -99,7 +99,9 @@ protected override async Task OnDiscoverCoordinatesAsync(CancellationToken cance DebugLog($"Waiting for cancellation token: CanBeCanceled:{cancellationToken.CanBeCanceled}, IsCancellationRequested:{cancellationToken.IsCancellationRequested}"); await Task.WhenAny(Task.Delay(-1, cancellationToken)); - markerCoordinate.WorldToCoordinate = cameraTransform.localToWorldMatrix * cameraToMarker; + + // Use the local position and local rotation to avoid using camera parent transforms. + markerCoordinate.WorldToCoordinate = Matrix4x4.TRS(cameraTransform.localPosition, cameraTransform.localRotation, Vector3.one) * cameraToMarker; DebugLog($"Hiding marker"); markerCoordinate.HideMarker(); diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualDetectorSpatialLocalizer.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualDetectorSpatialLocalizer.cs index d88e4a0aa..5fd74c22d 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualDetectorSpatialLocalizer.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualDetectorSpatialLocalizer.cs @@ -42,6 +42,8 @@ public override bool TryDeserializeSettings(BinaryReader reader, out MarkerVisua private class LocalizationSession : DisposableBase, ISpatialLocalizationSession { + public IPeerConnection Peer => peerConnection; + private readonly MarkerVisualDetectorSpatialLocalizer localizer; private readonly MarkerVisualDetectorLocalizationSettings settings; private readonly IPeerConnection peerConnection; diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualLocalizationInitializer.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualLocalizationInitializer.cs index 1669bbfb9..a95e91b79 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualLocalizationInitializer.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualLocalizationInitializer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. using System; +using System.Threading.Tasks; using UnityEngine; namespace Microsoft.MixedReality.SpectatorView @@ -54,13 +55,29 @@ private Guid LocalSpatialLocalizerId } } - public override void RunLocalization(SpatialCoordinateSystemParticipant participant) + /// + public override async Task TryRunLocalizationAsync(SpatialCoordinateSystemParticipant participant) + { + return await TryRunLocalizationImplAsync(participant); + } + + /// + public override async Task TryResetLocalizationAsync(SpatialCoordinateSystemParticipant participant) + { + return await TryRunLocalizationImplAsync(participant); + } + + private async Task TryRunLocalizationImplAsync(SpatialCoordinateSystemParticipant participant) { DebugLog($"Marker-based localization started for: {participant?.SocketEndpoint?.Address ?? "IPAddress unknown"} with marker type {markerType}"); // Note: We need to send the remote localization message prior to starting marker visual localization. The MarkerVisualSpatialLocalizer won't return until localization has completed. - SpatialCoordinateSystemManager.Instance.RunRemoteLocalizationAsync(participant.SocketEndpoint, PeerSpatialLocalizerId, new MarkerVisualDetectorLocalizationSettings()); - SpatialCoordinateSystemManager.Instance.LocalizeAsync(participant.SocketEndpoint, LocalSpatialLocalizerId, new MarkerVisualLocalizationSettings()); + Task remoteTask = SpatialCoordinateSystemManager.Instance.RunRemoteLocalizationAsync(participant.SocketEndpoint, PeerSpatialLocalizerId, new MarkerVisualDetectorLocalizationSettings()); + Task localTask = SpatialCoordinateSystemManager.Instance.LocalizeAsync(participant.SocketEndpoint, LocalSpatialLocalizerId, new MarkerVisualLocalizationSettings()); + await Task.WhenAll(remoteTask, localTask); + bool localSuccess = await localTask; + bool remoteSuccess = await remoteTask; + return localSuccess && remoteSuccess; } private void DebugLog(string message) diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualSpatialLocalizer.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualSpatialLocalizer.cs index da7c31c31..f3cfe2b11 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualSpatialLocalizer.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/MarkerVisual/MarkerVisualSpatialLocalizer.cs @@ -79,6 +79,8 @@ public override bool TryDeserializeSettings(BinaryReader reader, out MarkerVisua private class LocalizationSession : DisposableBase, ISpatialLocalizationSession { + public IPeerConnection Peer => peerConnection; + private readonly MarkerVisualSpatialLocalizer localizer; private readonly MarkerVisualLocalizationSettings settings; private readonly IPeerConnection peerConnection; diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/PhysicalMarker/MarkerDetectorSpatialLocalizer.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/PhysicalMarker/MarkerDetectorSpatialLocalizer.cs index 855ba9960..961c8b4a2 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/PhysicalMarker/MarkerDetectorSpatialLocalizer.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/PhysicalMarker/MarkerDetectorSpatialLocalizer.cs @@ -23,20 +23,24 @@ public override bool TryDeserializeSettings(BinaryReader reader, out MarkerDetec public override bool TryCreateLocalizationSession(IPeerConnection peerConnection, MarkerDetectorLocalizationSettings settings, out ISpatialLocalizationSession session) { - session = new LocalizationSession(this, settings); + session = new LocalizationSession(this, settings, peerConnection); return true; } private class LocalizationSession : DisposableBase, ISpatialLocalizationSession { + public IPeerConnection Peer => peerConnection; + private readonly MarkerDetectorSpatialLocalizer localizer; private readonly MarkerDetectorLocalizationSettings settings; + private readonly IPeerConnection peerConnection; private readonly MarkerDetectorCoordinateService coordinateService; - public LocalizationSession(MarkerDetectorSpatialLocalizer localizer, MarkerDetectorLocalizationSettings settings) + public LocalizationSession(MarkerDetectorSpatialLocalizer localizer, MarkerDetectorLocalizationSettings settings, IPeerConnection peerConnection) { this.localizer = localizer; this.settings = settings; + this.peerConnection = peerConnection; this.localizer.markerDetector.SetMarkerSize(settings.MarkerSize); this.coordinateService = new MarkerDetectorCoordinateService(this.localizer.markerDetector, this.localizer.debugLogging); diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialCoordinateSystemManager.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialCoordinateSystemManager.cs index 6f4cf3ae7..db591b417 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialCoordinateSystemManager.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialCoordinateSystemManager.cs @@ -101,6 +101,29 @@ public TrackingState TrackingState private ITrackingObserver trackingObserver = null; private bool lookedForTrackingObservers = false; + /// + /// True if all local and peer coordinates known to the device have been found in the shared experience space. + /// + public bool AllCoordinatesLocated + { + get + { + bool allFound = participants.Count > 0; + foreach (var participantPair in participants) + { + if (participantPair.Value.Coordinate == null || + participantPair.Value.IsLocatingSpatialCoordinate || + !participantPair.Value.PeerSpatialCoordinateIsLocated) + { + allFound = false; + break; + } + } + + return allFound; + } + } + public IReadOnlyCollection Localizers { get @@ -154,6 +177,13 @@ public void UnregisterNetworkManager(INetworkManager networkManager) public Task RunRemoteLocalizationAsync(SocketEndpoint socketEndpoint, Guid spatialLocalizerID, ISpatialLocalizationSettings settings) { DebugLog($"Initiating remote localization: {socketEndpoint.Address}, {spatialLocalizerID.ToString()}"); + if (remoteLocalizationSessions.TryGetValue(socketEndpoint, out var currentCompletionSource)) + { + DebugLog("Canceling existing remote localization session: {socketEndpoint.Address}"); + currentCompletionSource.TrySetCanceled(); + remoteLocalizationSessions.Remove(socketEndpoint); + } + TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); remoteLocalizationSessions.Add(socketEndpoint, taskCompletionSource); @@ -173,16 +203,26 @@ public Task RunRemoteLocalizationAsync(SocketEndpoint socketEndpoint, Guid public Task LocalizeAsync(SocketEndpoint socketEndpoint, Guid spatialLocalizerID, ISpatialLocalizationSettings settings) { DebugLog("LocalizeAsync"); - if (currentLocalizationSession != null) + if (!participants.TryGetValue(socketEndpoint, out SpatialCoordinateSystemParticipant participant)) { - Debug.LogError($"Failed to start localization session because an existing localization session is in progress"); + Debug.LogError($"Could not find a SpatialCoordinateSystemParticipant for SocketEndpoint {socketEndpoint.Address}"); return Task.FromResult(false); } - if (!participants.TryGetValue(socketEndpoint, out SpatialCoordinateSystemParticipant participant)) + if (currentLocalizationSession != null) { - Debug.LogError($"Could not find a SpatialCoordinateSystemParticipant for SocketEndpoint {socketEndpoint.Address}"); - return Task.FromResult(false); + 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)) @@ -292,22 +332,42 @@ private void OnLocalizationCompleteMessageReceived(SocketEndpoint socketEndpoint if (!remoteLocalizationSessions.TryGetValue(socketEndpoint, out TaskCompletionSource taskSource)) { - Debug.LogError($"Remote session from endpoint {socketEndpoint.Address} completed but we were no longer tracking that session"); + DebugLog($"Remote session from endpoint {socketEndpoint.Address} completed but we were no longer tracking that session"); return; } + DebugLog($"Localization completed message received: {socketEndpoint.Address}"); remoteLocalizationSessions.Remove(socketEndpoint); taskSource.SetResult(localizationSuccessful); } private async void OnLocalizeMessageReceived(SocketEndpoint socketEndpoint, string command, BinaryReader reader, int remainingDataSize) { - if (currentLocalizationSession != null) + DebugLog("LocalizeMessageReceived"); + if (!participants.TryGetValue(socketEndpoint, out SpatialCoordinateSystemParticipant participant)) { - Debug.LogError($"Failed to start localization session because an existing localization session is in progress"); + Debug.LogError($"Could not find a SpatialCoordinateSystemParticipant for SocketEndpoint {socketEndpoint.Address}"); + SendLocalizationCompleteCommand(socketEndpoint, localizationSuccessful: false); return; } + 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 that couldn't be canceled."); + SendLocalizationCompleteCommand(socketEndpoint, localizationSuccessful: false); + return; + } + } + Guid spatialLocalizerID = reader.ReadGuid(); if (!localizers.TryGetValue(spatialLocalizerID, out ISpatialLocalizer localizer)) @@ -324,13 +384,6 @@ private async void OnLocalizeMessageReceived(SocketEndpoint socketEndpoint, stri return; } - if (!participants.TryGetValue(socketEndpoint, out SpatialCoordinateSystemParticipant participant)) - { - Debug.LogError($"Could not find a SpatialCoordinateSystemParticipant for SocketEndpoint {socketEndpoint.Address}"); - SendLocalizationCompleteCommand(socketEndpoint, localizationSuccessful: false); - return; - } - bool localizationSuccessful = await RunLocalizationSessionAsync(localizer, settings, participant); // Ensure that the participant's fully-localized state is sent before sending the LocalizationComplete command (versus waiting diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialLocalizationInitializer.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialLocalizationInitializer.cs index 15fad5c50..b75d8d3a0 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialLocalizationInitializer.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/SpatialLocalizationInitializer.cs @@ -2,8 +2,7 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. using System; -using System.Collections; -using System.Collections.Generic; +using System.Threading.Tasks; using UnityEngine; namespace Microsoft.MixedReality.SpectatorView @@ -16,6 +15,18 @@ public abstract class SpatialLocalizationInitializer : MonoBehaviour /// public abstract Guid PeerSpatialLocalizerId { get; } - public abstract void RunLocalization(SpatialCoordinateSystemParticipant participant); + /// + /// Call to attempt localization with for provided participant. + /// + /// participant to localize with + /// True if localization succeeded, otherwise false + public abstract Task TryRunLocalizationAsync(SpatialCoordinateSystemParticipant participant); + + /// + /// Call to attempt relocalization with for provided participant. + /// + /// participant to localize with + /// True if relocalization succeeded, otherwise false + public abstract Task TryResetLocalizationAsync(SpatialCoordinateSystemParticipant participant); } } \ No newline at end of file diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/WorldAnchor/WorldAnchorSpatialLocalizer.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/WorldAnchor/WorldAnchorSpatialLocalizer.cs index 085e131b2..8a93c0d60 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/WorldAnchor/WorldAnchorSpatialLocalizer.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpatialAlignment/WorldAnchor/WorldAnchorSpatialLocalizer.cs @@ -59,19 +59,23 @@ public override bool TryDeserializeSettings(BinaryReader reader, out WorldAnchor /// public override bool TryCreateLocalizationSession(IPeerConnection peerConnection, WorldAnchorSpatialLocalizationSettings settings, out ISpatialLocalizationSession session) { - session = new LocalizationSession(this, settings); + session = new LocalizationSession(this, settings, peerConnection); return true; } private class LocalizationSession : DisposableBase, ISpatialLocalizationSession { + public IPeerConnection Peer => peerConnection; + private readonly WorldAnchorSpatialLocalizer localizer; private readonly WorldAnchorSpatialLocalizationSettings settings; + private readonly IPeerConnection peerConnection; - public LocalizationSession(WorldAnchorSpatialLocalizer localizer, WorldAnchorSpatialLocalizationSettings settings) + public LocalizationSession(WorldAnchorSpatialLocalizer localizer, WorldAnchorSpatialLocalizationSettings settings, IPeerConnection peerConnection) { this.localizer = localizer; this.settings = settings; + this.peerConnection = peerConnection; } public async Task LocalizeAsync(CancellationToken cancellationToken) diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpectatorView.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpectatorView.cs index 6bc76e8c3..62e43ad60 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpectatorView.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/SpectatorView.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Collections.Generic; using System; +using System.Threading.Tasks; +using Microsoft.MixedReality.SpatialAlignment; [assembly: InternalsVisibleToAttribute("Microsoft.MixedReality.SpectatorView.Editor")] @@ -123,6 +125,8 @@ public class SpectatorView : MonoBehaviour private bool hideDeveloperConsole = false; private GameObject settingsGameObject; + private Dictionary> peerSupportedLocalizers = new Dictionary>(); + private SpatialCoordinateSystemParticipant currentParticipant = null; #if UNITY_ANDROID || UNITY_IOS private GameObject mobileRecordingServiceVisual = null; @@ -364,31 +368,63 @@ private void DebugLog(string message) } } - private async void OnParticipantConnected(SpatialCoordinateSystemParticipant participant) + private void OnParticipantConnected(SpatialCoordinateSystemParticipant participant) + { + currentParticipant = participant; + TryRunLocalizationForParticipantAsync(currentParticipant).FireAndForget(); + } + + /// + /// Call to reset spatial alignment for the current participant + /// + /// Returns true if resetting localization succeeds, otherwise False. + public async Task TryResetLocalizationAsync() + { + if (Role == Role.User) + { + Debug.LogError("Relocalization was called for a User but is only supported for Spectators. Resetting localization failed."); + return await Task.FromResult(false); + } + + if (currentParticipant != null) + { + return await TryRunLocalizationForParticipantAsync(currentParticipant); + } + + DebugLog("No participants have connected. Resetting localization failed."); + return await Task.FromResult(false); + } + + private async Task TryRunLocalizationForParticipantAsync(SpatialCoordinateSystemParticipant participant) { DebugLog($"Waiting for the set of supported localizers from connected participant {participant.SocketEndpoint.Address}"); - // When a remote participant connects, get the set of ISpatialLocalizers that peer - // supports. This is asynchronous, as it comes across the network. - ISet peerSupportedLocalizers = await participant.GetPeerSupportedLocalizersAsync(); + if (!peerSupportedLocalizers.ContainsKey(participant)) + { + // When a remote participant connects, get the set of ISpatialLocalizers that peer + // supports. This is asynchronous, as it comes across the network. + peerSupportedLocalizers[participant] = await participant.GetPeerSupportedLocalizersAsync(); + } // If there are any supported localizers, find the first configured localizer in the // list that supports that type. If and when one is found, use it to perform localization. - if (peerSupportedLocalizers != null) + if (peerSupportedLocalizers.TryGetValue(participant, out var supportedLocalizers) && + supportedLocalizers != null) { DebugLog($"Received a set of {peerSupportedLocalizers.Count} supported localizers"); - + DebugLog($"Using prioritized initializers list from spectator view settings: {SpatialLocalizationInitializationSettings.IsInitialized && SpatialLocalizationInitializationSettings.Instance.PrioritizedInitializers != null}"); + if (SpatialLocalizationInitializationSettings.IsInitialized && - TryRunLocalization(SpatialLocalizationInitializationSettings.Instance.PrioritizedInitializers, peerSupportedLocalizers, participant)) + await TryRunLocalizationWithInitializerAsync(SpatialLocalizationInitializationSettings.Instance.PrioritizedInitializers, supportedLocalizers, participant)) { // Succeeded at using a custom localizer specified by the app. - return; + return true; } - if (TryRunLocalization(defaultSpatialLocalizationInitializers, peerSupportedLocalizers, participant)) + if (await TryRunLocalizationWithInitializerAsync(defaultSpatialLocalizationInitializers, supportedLocalizers, participant)) { // Succeeded at using one of the default localizers from the prefab. - return; + return true; } Debug.LogWarning($"None of the configured LocalizationInitializers were supported by the connected participant, localization will not be started"); @@ -397,10 +433,14 @@ private async void OnParticipantConnected(SpatialCoordinateSystemParticipant par { Debug.LogWarning($"No supported localizers were received from the participant, localization will not be started"); } + + return false; } - private bool TryRunLocalization(IList initializers, ISet supportedLocalizers, SpatialCoordinateSystemParticipant participant) + private async Task TryRunLocalizationWithInitializerAsync(IList initializers, ISet supportedLocalizers, SpatialCoordinateSystemParticipant participant) { + DebugLog($"TryRunLocalizationWithInitializerAsync"); + if (initializers == null) { return false; @@ -411,12 +451,25 @@ private bool TryRunLocalization(IList initialize if (supportedLocalizers.Contains(initializers[i].PeerSpatialLocalizerId)) { DebugLog($"Localization initializer {initializers[i].GetType().Name} supported localization with ID {initializers[i].PeerSpatialLocalizerId}, starting localization"); - initializers[i].RunLocalization(participant); - return true; + bool result = await initializers[i].TryRunLocalizationAsync(participant); + if (!result) + { + Debug.LogError($"Failed to localize experience with participant: {participant.SocketEndpoint.Address}"); + } + else + { + DebugLog($"Succeeded in localizing experience with participant: {participant.SocketEndpoint.Address}"); + } + + return result; + } + else + { + DebugLog($"Localization initializer {initializers[i].GetType().Name} not supported by peer."); } } - return false; + return await Task.FromResult(false); } } } From 4cdeea4c6518a5faa37c77dfc5deda61c0e9f54b Mon Sep 17 00:00:00 2001 From: chrisfromwork Date: Wed, 25 Sep 2019 13:10:34 -0700 Subject: [PATCH 2/2] show localization state to end user --- .../Prefabs/Default Mobile UI.prefab | 347 +++++++++++++++++- .../AndroidRecordingService.cs | 6 +- .../Scripts/UI/SpatialAlignmentVisual.cs | 54 +++ .../Scripts/UI/SpatialAlignmentVisual.cs.meta | 11 + 4 files changed, 413 insertions(+), 5 deletions(-) create mode 100644 src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs create mode 100644 src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs.meta diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Prefabs/Default Mobile UI.prefab b/src/SpectatorView.Unity/Assets/SpectatorView/Prefabs/Default Mobile UI.prefab index 3e35b3721..a9a1be1fc 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Prefabs/Default Mobile UI.prefab +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Prefabs/Default Mobile UI.prefab @@ -66,6 +66,85 @@ MonoBehaviour: m_InputActionsPerSecond: 10 m_RepeatDelay: 0.5 m_ForceModuleActive: 0 +--- !u!1 &2398307369725772544 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7118063823493895357} + - component: {fileID: 8484094671795383891} + - component: {fileID: 6937370796152144178} + m_Layer: 0 + m_Name: Reset Button Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7118063823493895357 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2398307369725772544} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 9046834047398750378} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8484094671795383891 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2398307369725772544} + m_CullTransparentMesh: 0 +--- !u!114 &6937370796152144178 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2398307369725772544} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 1 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: RESET --- !u!1 &3896832436934509116 GameObject: m_ObjectHideFlags: 0 @@ -78,7 +157,7 @@ GameObject: - component: {fileID: 3896832436934509057} - component: {fileID: 3896832436934509058} m_Layer: 0 - m_Name: Device tracking state text + m_Name: Device Tracking State text m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -250,6 +329,7 @@ RectTransform: m_Children: - {fileID: 3896832437885072083} - {fileID: 3896832439046039162} + - {fileID: 9046834047398750378} m_Father: {fileID: 3896832438808263179} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -479,7 +559,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: -10} + m_AnchoredPosition: {x: 0, y: -30} m_SizeDelta: {x: 160, y: 30} m_Pivot: {x: 0.5, y: 0.5} --- !u!222 &3896832437284674444 @@ -628,6 +708,7 @@ RectTransform: m_LocalScale: {x: 0, y: 0, z: 0} m_Children: - {fileID: 3896832438687853193} + - {fileID: 421412754127275907} - {fileID: 3896832438520703527} - {fileID: 3896832438808263179} m_Father: {fileID: 3896832437802547648} @@ -1204,8 +1285,9 @@ RectTransform: m_Children: - {fileID: 3896832437284674446} - {fileID: 3896832436934509059} + - {fileID: 8093266987797645601} m_Father: {fileID: 3896832437504863526} - m_RootOrder: 1 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} m_AnchorMax: {x: 0.5, y: 1} @@ -1418,7 +1500,7 @@ RectTransform: - {fileID: 3896832438816233583} - {fileID: 3896832437064721190} m_Father: {fileID: 3896832437504863526} - m_RootOrder: 2 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1651,3 +1733,260 @@ MonoBehaviour: m_CallState: 2 m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +--- !u!1 &5424918999611943612 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 421412754127275907} + - component: {fileID: 997470939485467333} + m_Layer: 0 + m_Name: Spatial Alignment Visual + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &421412754127275907 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5424918999611943612} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3896832437504863526} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &997470939485467333 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5424918999611943612} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 308c72e779d37f147b6f9ae919182ef2, type: 3} + m_Name: + m_EditorClassIdentifier: + spatialAlignmentStateText: {fileID: 6067051665112448766} +--- !u!1 &8980422870419623511 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9046834047398750378} + - component: {fileID: 3692404666896821053} + - component: {fileID: 2453057085164664703} + - component: {fileID: 5580009476422422365} + m_Layer: 0 + m_Name: Reset Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &9046834047398750378 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8980422870419623511} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 7118063823493895357} + m_Father: {fileID: 3896832437064721190} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 28, y: 0} + m_SizeDelta: {x: 57, y: 57} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &3692404666896821053 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8980422870419623511} + m_CullTransparentMesh: 0 +--- !u!114 &2453057085164664703 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8980422870419623511} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!114 &5580009476422422365 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8980422870419623511} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 0} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 0} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 2453057085164664703} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 997470939485467333} + m_MethodName: OnResetLocalizationClick + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &9046659272272765493 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8093266987797645601} + - component: {fileID: 1478968306187689785} + - component: {fileID: 6067051665112448766} + m_Layer: 0 + m_Name: Device Localization State Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8093266987797645601 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9046659272272765493} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3896832438520703527} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -10} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &1478968306187689785 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9046659272272765493} + m_CullTransparentMesh: 0 +--- !u!114 &6067051665112448766 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9046659272272765493} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 1 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: 'Experience spatially aligned: False' diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/ScreenRecording/AndroidRecordingService.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/ScreenRecording/AndroidRecordingService.cs index 598ee662c..a58df1184 100644 --- a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/ScreenRecording/AndroidRecordingService.cs +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/ScreenRecording/AndroidRecordingService.cs @@ -16,7 +16,10 @@ public class AndroidRecordingService : MonoBehaviour, private readonly string _fileNameExt = ".mp4"; private bool _initialized = false; private bool _recording = false; + +#pragma warning disable 414 private bool _isRecordingAvailable = false; +#pragma warning restore 414 /// public void Dispose() @@ -132,7 +135,7 @@ public bool IsRecordingAvailable() { #if UNITY_EDITOR return true; -#endif +#else // With the AndroidRecordingService once a recording has been performed, it's always available. if (_isRecordingAvailable) @@ -155,6 +158,7 @@ public bool IsRecordingAvailable() } return false; +#endif } /// diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs new file mode 100644 index 000000000..bf0980f27 --- /dev/null +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.MixedReality.SpatialAlignment; +using UnityEngine; +using UnityEngine.UI; + +namespace Microsoft.MixedReality.SpectatorView +{ + public class SpatialAlignmentVisual : MonoBehaviour + { + [Tooltip("Text used to display experience spatial alignment state.")] + [SerializeField] + private Text spatialAlignmentStateText = null; + + private SpectatorView spectatorView; + private readonly string spatialAlignmentStatePrompt = "Experience spatially aligned:"; + + private void Start() + { + spectatorView = FindObjectOfType(); + } + + private void Update() + { + if (spatialAlignmentStateText != null) + { + if (SpatialCoordinateSystemManager.IsInitialized && + SpatialCoordinateSystemManager.Instance.AllCoordinatesLocated) + { + spatialAlignmentStateText.text = $"{spatialAlignmentStatePrompt} True"; + spatialAlignmentStateText.color = Color.green; + } + else + { + spatialAlignmentStateText.text = $"{spatialAlignmentStatePrompt} False"; + spatialAlignmentStateText.color = Color.yellow; + } + } + } + + public void OnResetLocalizationClick() + { + if (spectatorView != null) + { + spectatorView.TryResetLocalizationAsync().FireAndForget(); + } + else + { + Debug.LogError("SpectatorView was not found in the scene, failed to reset localiation."); + } + } + } +} diff --git a/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs.meta b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs.meta new file mode 100644 index 000000000..010e600d0 --- /dev/null +++ b/src/SpectatorView.Unity/Assets/SpectatorView/Scripts/UI/SpatialAlignmentVisual.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 308c72e779d37f147b6f9ae919182ef2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: