// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using System;
using System.Collections.Generic;
using Unity.Profiling;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit
{
///
/// Abstract class for core MRTK system with functionality defined for managing and accessing IMixedRealityDataProviders
///
public abstract class BaseDataProviderAccessCoreSystem : BaseCoreSystem, IMixedRealityDataProviderAccess
{
private readonly List dataProviders = new List();
public override void Reset()
{
base.Reset();
foreach (var provider in dataProviders)
{
provider.Reset();
}
}
///
public override void Enable()
{
base.Enable();
foreach (var provider in dataProviders)
{
provider.Enable();
}
}
private static readonly ProfilerMarker UpdatePerfMarker = new ProfilerMarker("[MRTK] BaseDataProviderAccessCoreSystem.Update");
///
public override void Update()
{
using (UpdatePerfMarker.Auto())
{
base.Update();
foreach (var provider in dataProviders)
{
provider.Update();
}
}
}
private static readonly ProfilerMarker LateUpdatePerfMarker = new ProfilerMarker("[MRTK] BaseDataProviderAccessCoreSystem.LateUpdate");
///
public override void LateUpdate()
{
using (LateUpdatePerfMarker.Auto())
{
base.LateUpdate();
foreach (var provider in dataProviders)
{
provider.LateUpdate();
}
}
}
///
/// Constructor.
///
/// The instance that loaded the service.
/// The configuration profile for the service.
[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 BaseDataProviderAccessCoreSystem(
IMixedRealityServiceRegistrar registrar,
BaseMixedRealityProfile profile = null) : this(profile)
{
Registrar = registrar;
}
///
/// Constructor.
///
/// The configuration profile for the service.
protected BaseDataProviderAccessCoreSystem(
BaseMixedRealityProfile profile = null) : base(profile)
{ }
#region IMixedRealityDataProviderAccess Implementation
///
public virtual IReadOnlyList GetDataProviders()
{
return dataProviders.AsReadOnly();
}
///
public virtual IReadOnlyList GetDataProviders() where T : IMixedRealityDataProvider
{
List selected = new List();
foreach (var provider in dataProviders)
{
if (provider is T providerT)
{
selected.Add(providerT);
}
}
return selected;
}
///
public virtual IMixedRealityDataProvider GetDataProvider(string name)
{
foreach (var provider in dataProviders)
{
if (provider.Name == name)
{
return provider;
}
}
return null;
}
///
public virtual T GetDataProvider(string name = null) where T : IMixedRealityDataProvider
{
foreach (var provider in dataProviders)
{
if (provider is T providerT)
{
if (name == null || provider.Name == name)
{
return providerT;
}
}
}
return default(T);
}
#endregion IMixedRealityDataProviderAccess Implementation
///
/// Registers a data provider of the specified type.
///
protected bool RegisterDataProvider(
Type concreteType,
string providerName,
SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1),
params object[] args) where T : IMixedRealityDataProvider
{
return RegisterDataProviderInternal(
true, // Retry with an added IMixedRealityService parameter
concreteType,
providerName,
supportedPlatforms,
args);
}
///
/// Registers a data provider of the specified type.
///
[Obsolete("RegisterDataProvider(Type, SupportedPlatforms, param object[]) is obsolete and will be removed from a future version of MRTK\n" +
"Please use RegisterDataProvider(Type, string, SupportedPlatforms, params object[])")]
protected bool RegisterDataProvider(
Type concreteType,
SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1),
params object[] args) where T : IMixedRealityDataProvider
{
return RegisterDataProvider(
concreteType,
string.Empty,
supportedPlatforms,
args);
}
///
/// Internal method that creates an instance of the specified concrete type and registers the provider.
///
private bool RegisterDataProviderInternal(
bool retryWithRegistrar,
Type concreteType,
string providerName,
SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1),
params object[] args) where T : IMixedRealityDataProvider
{
if (!PlatformUtility.IsPlatformSupported(supportedPlatforms))
{
DebugUtilities.LogVerboseFormat(
"Not registering data provider of type {0} with name {1} because the current platform is not in supported platforms {2}",
concreteType,
providerName,
supportedPlatforms);
return false;
}
if (concreteType == null)
{
if (!Application.isEditor)
{
Debug.LogWarning($"Unable to register {typeof(T).Name} data provider ({(!string.IsNullOrWhiteSpace(providerName) ? providerName : "unknown")}) because the value of concreteType is null.\n" +
"This may be caused by code being stripped during linking. The link.xml file in the MixedRealityToolkit.Generated folder is used to control code preservation.\n" +
"More information can be found at https://docs.unity3d.com/Manual/ManagedCodeStripping.html.");
}
return false;
}
SupportedUnityXRPipelines selectedPipeline =
#if UNITY_2020_1_OR_NEWER
SupportedUnityXRPipelines.XRSDK;
#elif UNITY_2019
XRSettingsUtilities.XRSDKEnabled ? SupportedUnityXRPipelines.XRSDK : SupportedUnityXRPipelines.LegacyXR;
#else
SupportedUnityXRPipelines.LegacyXR;
#endif
if (MixedRealityExtensionServiceAttribute.Find(concreteType) is MixedRealityDataProviderAttribute providerAttribute
&& !providerAttribute.SupportedUnityXRPipelines.IsMaskSet(selectedPipeline))
{
DebugUtilities.LogVerboseFormat("{0} not suitable for the current XR pipeline ({1})", concreteType.Name, selectedPipeline);
return false;
}
if (!typeof(IMixedRealityDataProvider).IsAssignableFrom(concreteType))
{
Debug.LogError($"Unable to register the {concreteType.Name} data provider. It does not implement {typeof(IMixedRealityDataProvider)}.");
return false;
}
T dataProviderInstance;
try
{
dataProviderInstance = (T)Activator.CreateInstance(concreteType, args);
}
catch (Exception e)
{
if (retryWithRegistrar && (e is MissingMethodException))
{
Debug.LogWarning($"Failed to find an appropriate constructor for the {concreteType.Name} data provider. Adding the Registrar instance and re-attempting registration.");
#pragma warning disable 0618
List