// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections.Generic;
using Unity.Profiling;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.SpatialAwareness
{
///
/// Class providing the default implementation of the interface.
///
[HelpURL("https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/spatial-awareness/spatial-awareness-getting-started")]
public class MixedRealitySpatialAwarenessSystem :
BaseDataProviderAccessCoreSystem,
IMixedRealitySpatialAwarenessSystem,
IMixedRealityCapabilityCheck
{
///
/// Constructor.
///
/// The instance that loaded the service.
/// The configuration profile for the service.
[System.Obsolete("This constructor is obsolete (registrar parameter is no longer required) and will be removed in a future version of the Microsoft Mixed Reality Toolkit.")]
public MixedRealitySpatialAwarenessSystem(
IMixedRealityServiceRegistrar registrar,
MixedRealitySpatialAwarenessSystemProfile profile) : this(profile)
{
Registrar = registrar;
}
///
/// Constructor.
///
/// The instance that loaded the service.
/// The configuration profile for the service.
public MixedRealitySpatialAwarenessSystem(
MixedRealitySpatialAwarenessSystemProfile profile) : base(profile)
{ }
///
public override string Name { get; protected set; } = "Mixed Reality Spatial Awareness System";
#region IMixedRealityCapabilityCheck Implementation
///
public bool CheckCapability(MixedRealityCapability capability)
{
foreach (var observer in GetDataProviders())
{
// If one of the running data providers supports the requested capability,
// the application has the needed support to leverage the desired functionality.
if (observer is IMixedRealityCapabilityCheck capabilityChecker &&
capabilityChecker.CheckCapability(capability))
{
return true;
}
}
return false;
}
#endregion IMixedRealityCapabilityCheck Implementation
#region IMixedRealityToolkitService Implementation
///
public override void Initialize()
{
// Mark not initialized early so observers can use this state in their own initialization
IsInitialized = false;
InitializeInternal();
base.Initialize();
}
///
/// Performs initialization tasks for the spatial awareness system.
///
private void InitializeInternal()
{
MixedRealitySpatialAwarenessSystemProfile profile = ConfigurationProfile as MixedRealitySpatialAwarenessSystemProfile;
if (profile != null && GetDataProviders().Count == 0)
{
// Register the spatial observers.
for (int i = 0; i < profile.ObserverConfigurations.Length; i++)
{
MixedRealitySpatialObserverConfiguration configuration = profile.ObserverConfigurations[i];
object[] args = { this, configuration.ComponentName, configuration.Priority, configuration.ObserverProfile };
RegisterDataProvider(
configuration.ComponentType.Type,
configuration.ComponentName,
configuration.RuntimePlatform,
args);
}
}
}
///
public override void Disable()
{
base.Disable();
foreach (var provider in GetDataProviders())
{
UnregisterDataProvider(provider);
}
}
///
public override void Enable()
{
InitializeInternal();
// Ensure data providers are enabled (performed by the base class)
base.Enable();
}
///
public override void Reset()
{
base.Reset();
Disable();
Initialize();
Enable();
}
///
public override void Destroy()
{
// Cleanup game objects created during execution.
if (Application.isPlaying)
{
// Detach the child objects and clean up the parent.
if (spatialAwarenessObjectParent != null)
{
if (Application.isEditor)
{
Object.DestroyImmediate(spatialAwarenessObjectParent);
}
else
{
spatialAwarenessObjectParent.transform.DetachChildren();
Object.Destroy(spatialAwarenessObjectParent);
}
spatialAwarenessObjectParent = null;
}
}
base.Destroy();
}
#endregion IMixedRealityToolkitService Implementation
#region IMixedRealitySpatialAwarenessSystem Implementation
///
/// The parent object, in the hierarchy, under which all observed game objects will be placed.
///
private GameObject spatialAwarenessObjectParent = null;
///
public GameObject SpatialAwarenessObjectParent => spatialAwarenessObjectParent != null ? spatialAwarenessObjectParent : (spatialAwarenessObjectParent = CreateSpatialAwarenessObjectParent);
///
/// Creates the parent for spatial awareness objects so that the scene hierarchy does not get overly cluttered.
///
///
/// The GameObject to which spatial awareness created objects will be parented.
///
private GameObject CreateSpatialAwarenessObjectParent
{
get
{
GameObject newParent = new GameObject("Spatial Awareness System");
/// Preserve local transform when attaching to playspace.
newParent.transform.SetParent(MixedRealityPlayspace.Transform, false);
return newParent;
}
}
///
public GameObject CreateSpatialAwarenessObservationParent(string name)
{
GameObject objectParent = new GameObject(name);
/// Preserve local transform when attaching to SA object parent.
objectParent.transform.SetParent(SpatialAwarenessObjectParent.transform, false);
return objectParent;
}
private uint nextSourceId = 0;
///
public uint GenerateNewSourceId()
{
return nextSourceId++;
}
private MixedRealitySpatialAwarenessSystemProfile spatialAwarenessSystemProfile = null;
///
public MixedRealitySpatialAwarenessSystemProfile SpatialAwarenessSystemProfile
{
get
{
if (spatialAwarenessSystemProfile == null)
{
spatialAwarenessSystemProfile = ConfigurationProfile as MixedRealitySpatialAwarenessSystemProfile;
}
return spatialAwarenessSystemProfile;
}
}
private static readonly ProfilerMarker GetObserversPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.GetObservers");
///
public IReadOnlyList GetObservers()
{
using (GetObserversPerfMarker.Auto())
{
return GetDataProviders() as IReadOnlyList;
}
}
private static readonly ProfilerMarker GetObserversTPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.GetObservers");
///
public IReadOnlyList GetObservers() where T : IMixedRealitySpatialAwarenessObserver
{
using (GetObserversTPerfMarker.Auto())
{
return GetDataProviders();
}
}
private static readonly ProfilerMarker GetObserverPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.GetObserver");
///
public IMixedRealitySpatialAwarenessObserver GetObserver(string name)
{
using (GetObserverPerfMarker.Auto())
{
return GetDataProvider(name) as IMixedRealitySpatialAwarenessObserver;
}
}
private static readonly ProfilerMarker GetObserverTPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.GetObserver");
///
public T GetObserver(string name = null) where T : IMixedRealitySpatialAwarenessObserver
{
using (GetObserverTPerfMarker.Auto())
{
return GetDataProvider(name);
}
}
#region IMixedRealityDataProviderAccess Implementation
private static readonly ProfilerMarker GetDataProvidersPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.GetDataProviders");
///
public override IReadOnlyList GetDataProviders()
{
using (GetDataProvidersPerfMarker.Auto())
{
if (!typeof(IMixedRealitySpatialAwarenessObserver).IsAssignableFrom(typeof(T)))
{
return null;
}
return base.GetDataProviders();
}
}
private static readonly ProfilerMarker GetDataProviderPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.GetDataProvider");
///
public override T GetDataProvider(string name = null)
{
using (GetDataProviderPerfMarker.Auto())
{
if (!typeof(IMixedRealitySpatialAwarenessObserver).IsAssignableFrom(typeof(T)))
{
return default(T);
}
return base.GetDataProvider(name);
}
}
#endregion IMixedRealityDataProviderAccess Implementation
private static readonly ProfilerMarker ResumeObserversPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.ResumeObservers");
///
public void ResumeObservers()
{
using (ResumeObserversPerfMarker.Auto())
{
foreach (var observer in GetDataProviders())
{
observer.Resume();
}
}
}
private static readonly ProfilerMarker ResumeObserversTPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.ResumeObservers");
///
public void ResumeObservers() where T : IMixedRealitySpatialAwarenessObserver
{
using (ResumeObserversTPerfMarker.Auto())
{
foreach (var observer in GetDataProviders())
{
if (observer is T)
{
observer.Resume();
}
}
}
}
private static readonly ProfilerMarker ResumeObserverPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.ResumeObserver");
///
public void ResumeObserver(string name) where T : IMixedRealitySpatialAwarenessObserver
{
using (ResumeObserverPerfMarker.Auto())
{
foreach (var observer in GetDataProviders())
{
if (observer is T && observer.Name == name)
{
observer.Resume();
break;
}
}
}
}
private static readonly ProfilerMarker SuspendObserversPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.SuspendObservers");
///
public void SuspendObservers()
{
using (SuspendObserversPerfMarker.Auto())
{
foreach (var observer in GetDataProviders())
{
observer.Suspend();
}
}
}
private static readonly ProfilerMarker SuspendObserversTPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.SuspendObservers");
///
public void SuspendObservers() where T : IMixedRealitySpatialAwarenessObserver
{
using (SuspendObserversTPerfMarker.Auto())
{
foreach (var observer in GetDataProviders())
{
if (observer is T)
{
observer.Suspend();
}
}
}
}
private static readonly ProfilerMarker SuspendObserverPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.SuspendObserver");
///
public void SuspendObserver(string name) where T : IMixedRealitySpatialAwarenessObserver
{
using (SuspendObserverPerfMarker.Auto())
{
foreach (var observer in GetDataProviders())
{
if (observer is T && observer.Name == name)
{
observer.Suspend();
break;
}
}
}
}
private static readonly ProfilerMarker ClearObservationsPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.ClearObservations");
///
public void ClearObservations()
{
using (ClearObservationsPerfMarker.Auto())
{
foreach (var observer in GetDataProviders())
{
observer.ClearObservations();
}
}
}
private static readonly ProfilerMarker ClearObservationsTPerfMarker = new ProfilerMarker("[MRTK] MixedRealitySpatialAwarenessSystem.ClearObservations");
///
public void ClearObservations(string name) where T : IMixedRealitySpatialAwarenessObserver
{
using (ClearObservationsTPerfMarker.Auto())
{
T observer = GetObserver(name);
observer?.ClearObservations();
}
}
#endregion IMixedRealitySpatialAwarenessSystem Implementation
}
}