using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.XR.Management.Metadata;
namespace UnityEditor.XR.Management
{
/// Interface for specifying package initialization information
public interface XRPackageInitializationBase
{
/// Package name property
/// The name of the package
string PackageName { get; }
/// The loader full type name for this package
/// Loader fulltype name
string LoaderFullTypeName { get; }
/// The loader type name for this package
/// Loader type name
string LoaderTypeName { get; }
/// The settings full type name for this package
/// Settings full type name
string SettingsFullTypeName { get; }
/// The settings type name for this package
/// Settings type name
string SettingsTypeName { get; }
/// Package initialization key
/// The init key for the package
string PackageInitKey { get; }
/// Initialize package settings
/// The scriptable object instance to initialize
/// True if successful, false if not.
bool PopulateSettingsOnInitialization(ScriptableObject obj);
}
[InitializeOnLoad]
class XRPackageInitializationBootstrap
{
static XRPackageInitializationBootstrap()
{
if (!EditorApplication.isPlayingOrWillChangePlaymode)
{
EditorApplication.update += BeginPackageInitialization;
}
EditorApplication.playModeStateChanged += PlayModeStateChanged;
}
private static void PlayModeStateChanged(PlayModeStateChange state)
{
switch (state)
{
case PlayModeStateChange.EnteredPlayMode:
BeginPackageInitialization();
break;
case PlayModeStateChange.EnteredEditMode:
BeginPackageInitialization();
break;
}
}
internal static void BeginPackageInitialization()
{
EditorApplication.update -= BeginPackageInitialization;
foreach (var t in TypeLoaderExtensions.GetAllTypesWithInterface())
{
if (t.IsInterface || t.FullName.Contains("Unity.XR.Management.TestPackage") || t.FullName.Contains("UnityEditor.XR.Management.Metadata.KnownPackages"))
continue;
IXRPackage package = Activator.CreateInstance(t) as IXRPackage;
if (package == null)
{
Debug.LogError($"Unable to find an implementation for expected package type {t.FullName}.");
continue;
}
InitPackage(package);
}
foreach (var t in TypeLoaderExtensions.GetAllTypesWithInterface())
{
if (t.IsInterface)
continue;
XRPackageInitializationBase packageInit = Activator.CreateInstance(t) as XRPackageInitializationBase;
if (packageInit == null)
{
Debug.LogError($"Unable to find an implementation for expected package type {t.FullName}.");
continue;
}
InitPackage(packageInit);
}
if (XRSettingsManager.Instance != null) XRSettingsManager.Instance.ResetUi = true;
}
internal static void InitPackage(IXRPackage package)
{
var packageMetadata = package.metadata;
if (packageMetadata == null)
{
Debug.LogError($"Package {package.GetType().Name} has a package definition but has no metadata. Skipping initialization.");
return;
}
XRPackageMetadataStore.AddPluginPackage(package);
if (!InitializePackageFromMetadata(package, packageMetadata))
{
Debug.LogWarning(
String.Format("{0} package Initialization not completed. You will need to create any instances of the loaders and settings manually before you can use the intended XR Plug-in Package.", packageMetadata.packageName));
}
}
static bool InitializePackageFromMetadata(IXRPackage package, IXRPackageMetadata packageMetadata)
{
bool ret = true;
ret = ret && InitializeLoaderFromMetadata(packageMetadata.packageName, packageMetadata.loaderMetadata);
ret = ret && InitializeSettingsFromMetadata(package, packageMetadata.packageName, packageMetadata.settingsType);
return ret;
}
static bool InitializeLoaderFromMetadata(string packageName, List loaderMetadatas)
{
if (String.IsNullOrEmpty(packageName))
return false;
if (loaderMetadatas == null || loaderMetadatas.Count == 0)
{
Debug.LogWarning($"Package {packageName} has no loader metadata. Skipping loader initialization.");
return true;
}
bool ret = true;
foreach (var loader in loaderMetadatas)
{
bool hasInstance = EditorUtilities.AssetDatabaseHasInstanceOfType(loader.loaderType);
if (!hasInstance)
{
var obj = EditorUtilities.CreateScriptableObjectInstance(loader.loaderType,
EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultLoaderPath));
hasInstance = (obj != null);
if (!hasInstance)
{
Debug.LogError($"Error creating instance of loader {loader.loaderName} for package {packageName}");
}
}
ret |= hasInstance;
}
return ret;
}
static bool InitializeSettingsFromMetadata(IXRPackage package, string packageName, string settingsType)
{
if (String.IsNullOrEmpty(packageName))
return false;
if (settingsType == null)
{
Debug.LogWarning($"Package {packageName} has no settings metadata. Skipping settings initialization.");
return true;
}
bool ret = EditorUtilities.AssetDatabaseHasInstanceOfType(settingsType);
if (!ret)
{
var obj = EditorUtilities.CreateScriptableObjectInstance( settingsType,
EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultSettingsPath));
ret = package.PopulateNewSettingsInstance(obj);
}
return ret;
}
static void InitPackage(XRPackageInitializationBase packageInit)
{
if (!InitializeLoaderInstance(packageInit))
{
Debug.LogWarning(
String.Format("{0} Loader Initialization not completed. You will need to create an instance of the loader manually before you can use the intended XR Plug-in Package.", packageInit.PackageName));
}
if (!InitializeSettingsInstance(packageInit))
{
Debug.LogWarning(
String.Format("{0} Settings Initialization not completed. You will need to create an instance of settings to customize options specific to this package.", packageInit.PackageName));
}
}
static bool InitializeLoaderInstance(XRPackageInitializationBase packageInit)
{
bool ret = EditorUtilities.AssetDatabaseHasInstanceOfType(packageInit.LoaderTypeName);
if (!ret)
{
var obj = EditorUtilities.CreateScriptableObjectInstance(packageInit.LoaderFullTypeName,
EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultLoaderPath));
ret = (obj != null);
}
return ret;
}
static bool InitializeSettingsInstance(XRPackageInitializationBase packageInit)
{
bool ret = EditorUtilities.AssetDatabaseHasInstanceOfType(packageInit.SettingsTypeName);
if (!ret)
{
var obj = EditorUtilities.CreateScriptableObjectInstance(packageInit.SettingsFullTypeName,
EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultSettingsPath));
ret = packageInit.PopulateSettingsOnInitialization(obj);
}
return ret;
}
}
}