// 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
}
}