// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.Utilities; using System.Collections; using UnityEngine; namespace Microsoft.MixedReality.Toolkit.SpatialAwareness { /// /// Class providing a base implementation of the interface. /// public abstract class BaseSpatialObserver : BaseDataProvider, IMixedRealitySpatialAwarenessObserver { /// /// Default dedicated layer for spatial awareness layer used by most components in MRTK /// public const int DefaultSpatialAwarenessLayer = 31; /// /// Constructor. /// /// The to which the observer is providing data. /// The friendly name of the data provider. /// The registration priority of the data provider. /// The configuration profile for the data provider. protected BaseSpatialObserver( IMixedRealitySpatialAwarenessSystem spatialAwarenessSystem, string name = null, uint priority = DefaultPriority, BaseMixedRealityProfile profile = null) : base(spatialAwarenessSystem, name, priority, profile) { SourceId = (Service != null) ? Service.GenerateNewSourceId() : 0; SourceName = name; } /// /// The spatial awareness system that is associated with this observer. /// [System.Obsolete("Call Service instead.")] protected IMixedRealitySpatialAwarenessSystem SpatialAwarenessSystem => Service; private GameObject observedObjectParent = null; protected virtual GameObject ObservedObjectParent => observedObjectParent != null ? observedObjectParent : (observedObjectParent = Service?.CreateSpatialAwarenessObservationParent(Name)); /// /// The parent GameObject for all observed meshes to be placed under. /// public GameObject ObservationParent => ObservedObjectParent; /// /// Creates the spatial observer and handles the desired startup behavior. /// protected virtual void CreateObserver() { } /// /// Ensures that the spatial observer has been stopped and destroyed. /// protected virtual void CleanupObserver() { } #region BaseService Implementation /// protected override void Dispose(bool disposing) { if (disposed) { return; } base.Dispose(disposing); if (disposing) { CleanupObservationsAndObserver(); } disposed = true; } #endregion BaseService Implementation #region IMixedRealityDataProvider Implementation /// /// Creates the observer. /// public override void Initialize() { CreateObserver(); base.Initialize(); } /// /// Suspends the observer, clears observations, cleans up the observer, then re-initializes. /// public override void Reset() { Destroy(); Initialize(); } /// public override void Enable() { base.Enable(); if (!IsRunning && StartupBehavior == AutoStartBehavior.AutoStart) { Resume(); } } /// public override void Disable() { // If we are disabled while running... if (IsRunning) { // Suspend the observer Suspend(); } base.Disable(); } /// public override void Destroy() { CleanupObservationsAndObserver(); base.Destroy(); } #endregion IMixedRealityDataProvider Implementation #region IMixedRealityEventSource Implementation /// bool IEqualityComparer.Equals(object x, object y) { return x.Equals(y); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((IMixedRealitySpatialAwarenessObserver)obj); } private bool Equals(IMixedRealitySpatialAwarenessObserver other) { return ((other != null) && (SourceId == other.SourceId) && string.Equals(SourceName, other.SourceName)); } /// public int GetHashCode(object obj) { return obj.GetHashCode(); } public override int GetHashCode() { return Mathf.Abs(SourceName.GetHashCode()); } /// public uint SourceId { get; } /// public string SourceName { get; } #endregion IMixedRealityEventSource Implementation #region IMixedRealitySpatialAwarenessObserver Implementation /// public AutoStartBehavior StartupBehavior { get; set; } = AutoStartBehavior.AutoStart; /// public int DefaultPhysicsLayer { get; protected set; } = DefaultSpatialAwarenessLayer; /// public bool IsRunning { get; protected set; } = false; /// public bool IsStationaryObserver { get; set; } = false; /// public Quaternion ObserverRotation { get; set; } = Quaternion.identity; /// public Vector3 ObserverOrigin { get; set; } = Vector3.zero; /// public VolumeType ObserverVolumeType { get; set; } = VolumeType.AxisAlignedCube; /// public Vector3 ObservationExtents { get; set; } = Vector3.one * 3f; // 3 meter sides / radius /// public float UpdateInterval { get; set; } = 3.5f; // 3.5 seconds /// public virtual void Resume() { } /// public virtual void Suspend() { } /// public virtual void ClearObservations() { } #endregion IMixedRealitySpatialAwarenessObserver Implementation #region Helpers /// /// Destroys all observed objects and the observer. /// private void CleanupObservationsAndObserver() { Disable(); // Destroys all observed objects and the observer. ClearObservations(); CleanupObserver(); } #endregion Helpers #region Obsolete /// /// Constructor. /// /// The instance that loaded the observer. /// The to which the observer is providing data. /// The friendly name of the data provider. /// The registration priority of the data provider. /// The configuration profile for the data provider. [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.")] protected BaseSpatialObserver( IMixedRealityServiceRegistrar registrar, IMixedRealitySpatialAwarenessSystem spatialAwarenessSystem, string name = null, uint priority = DefaultPriority, BaseMixedRealityProfile profile = null) : this(spatialAwarenessSystem, name, priority, profile) { Registrar = registrar; } #endregion } }