using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.XR.Management;
using UnityEditor.XR.Management.Metadata;
namespace UnityEditor.XR.Management
{
#if UNITY_EDITOR
[InitializeOnLoad]
#endif
/// Container class that holds general settings for each build target group installed in Unity.
public class XRGeneralSettingsPerBuildTarget : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField]
List Keys = new List();
[SerializeField]
List Values = new List();
Dictionary Settings = new Dictionary();
#if UNITY_EDITOR
static XRGeneralSettingsPerBuildTarget()
{
EditorApplication.playModeStateChanged -= PlayModeStateChanged;
EditorApplication.playModeStateChanged += PlayModeStateChanged;
}
// Simple class to give us updates when the asset database changes.
class AssetCallbacks : AssetPostprocessor
{
static bool m_Upgrade = true;
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
if (m_Upgrade)
{
m_Upgrade = false;
BeginUpgradeSettings();
}
}
static void BeginUpgradeSettings()
{
string searchText = "t:XRGeneralSettings";
string[] assets = AssetDatabase.FindAssets(searchText);
if (assets.Length > 0)
{
string path = AssetDatabase.GUIDToAssetPath(assets[0]);
XRGeneralSettingsUpgrade.UpgradeSettingsToPerBuildTarget(path);
}
}
}
void OnEnable()
{
foreach (var setting in Settings.Values)
{
var assignedSettings = setting.AssignedSettings;
if (assignedSettings == null)
continue;
var filteredLoaders = from ldr in assignedSettings.activeLoaders where ldr != null select ldr;
assignedSettings.TrySetLoaders(filteredLoaders.ToList());
}
XRGeneralSettings.Instance = XRGeneralSettingsForBuildTarget(BuildTargetGroup.Standalone);
}
static void PlayModeStateChanged(PlayModeStateChange state)
{
XRGeneralSettingsPerBuildTarget buildTargetSettings = null;
EditorBuildSettings.TryGetConfigObject(XRGeneralSettings.k_SettingsKey, out buildTargetSettings);
if (buildTargetSettings == null)
{
buildTargetSettings = GetOrCreate();
}
XRGeneralSettings instance = buildTargetSettings.SettingsForBuildTarget(BuildTargetGroup.Standalone);
if (instance == null || !instance.InitManagerOnStart)
return;
instance.InternalPlayModeStateChanged(state);
}
internal static bool ContainsLoaderForAnyBuildTarget(string loaderTypeName)
{
XRGeneralSettingsPerBuildTarget buildTargetSettings = null;
EditorBuildSettings.TryGetConfigObject(XRGeneralSettings.k_SettingsKey, out buildTargetSettings);
if (buildTargetSettings == null)
return false;
foreach (var settings in buildTargetSettings.Settings.Values)
{
if (XRPackageMetadataStore.IsLoaderAssigned(settings.Manager, loaderTypeName))
return true;
}
return false;
}
[MethodImpl(MethodImplOptions.Synchronized)]
internal static XRGeneralSettingsPerBuildTarget GetOrCreate()
{
EditorBuildSettings.TryGetConfigObject(XRGeneralSettings.k_SettingsKey, out var generalSettings);
if (generalSettings == null)
{
string searchText = "t:XRGeneralSettings";
string[] assets = AssetDatabase.FindAssets(searchText);
if (assets.Length > 0)
{
string path = AssetDatabase.GUIDToAssetPath(assets[0]);
generalSettings = AssetDatabase.LoadAssetAtPath(path, typeof(XRGeneralSettingsPerBuildTarget)) as XRGeneralSettingsPerBuildTarget;
}
}
if (generalSettings == null)
{
generalSettings = CreateInstance(typeof(XRGeneralSettingsPerBuildTarget)) as XRGeneralSettingsPerBuildTarget;
string assetPath = EditorUtilities.GetAssetPathForComponents(EditorUtilities.s_DefaultGeneralSettingsPath);
if (!string.IsNullOrEmpty(assetPath))
{
assetPath = Path.Combine(assetPath, "XRGeneralSettings.asset");
AssetDatabase.CreateAsset(generalSettings, assetPath);
}
}
EditorBuildSettings.AddConfigObject(XRGeneralSettings.k_SettingsKey, generalSettings, true);
return generalSettings;
}
#endif
///
/// Query this settings store to see if there are settings for a specific .
///
/// Build target to check
/// True if there are settings, otherwise false.
public bool HasSettingsForBuildTarget(BuildTargetGroup buildTargetGroup)
{
return SettingsForBuildTarget(buildTargetGroup) != null;
}
///
/// Create default settings for a given build target.
///
/// This will overwrite any current settings for that build target.
///
/// Build target to create default settings for.
public void CreateDefaultSettingsForBuildTarget(BuildTargetGroup buildTargetGroup)
{
var settings = ScriptableObject.CreateInstance() as XRGeneralSettings;
SetSettingsForBuildTarget(buildTargetGroup, settings);
settings.name = $"{buildTargetGroup.ToString()} Settings";
AssetDatabase.AddObjectToAsset(settings, AssetDatabase.GetAssetOrScenePath(this));
AssetDatabase.SaveAssets();
}
/// Set specific settings for a given build target.
///
/// An enum specifying which platform group this build is for.
/// An instance of to assign for the given key.
public void SetSettingsForBuildTarget(BuildTargetGroup targetGroup, XRGeneralSettings settings)
{
// Ensures the editor's "runtime instance" is the most current for standalone settings
if (targetGroup == BuildTargetGroup.Standalone)
XRGeneralSettings.Instance = settings;
Settings[targetGroup] = settings;
}
/// Get specific settings for a given build target.
/// An enum specifying which platform group this build is for.
/// The instance of assigned to the key, or null if not.
public XRGeneralSettings SettingsForBuildTarget(BuildTargetGroup targetGroup)
{
XRGeneralSettings ret = null;
Settings.TryGetValue(targetGroup, out ret);
return ret;
}
///
/// Check if current settings instance has an instance of .
///
/// An enum specifying which platform group this build is for.
/// True if it exists, false otherwise.
public bool HasManagerSettingsForBuildTarget(BuildTargetGroup targetGroup)
{
return (SettingsForBuildTarget(targetGroup)?.Manager ?? null) != null;
}
///
/// Create a new default instance of for a build target. Requires
/// that the there exists a settings instance for the build target. If there isn't, then one is created.
///
/// This will overwrite any current settings for that build target.
///
/// An enum specifying which platform group this build is for.
public void CreateDefaultManagerSettingsForBuildTarget(BuildTargetGroup targetGroup)
{
if (!HasSettingsForBuildTarget(targetGroup))
CreateDefaultSettingsForBuildTarget(targetGroup);
var xrManagerSettings = ScriptableObject.CreateInstance() as XRManagerSettings;
xrManagerSettings.name = $"{targetGroup.ToString()} Providers";
SettingsForBuildTarget(targetGroup).Manager = xrManagerSettings;
AssetDatabase.AddObjectToAsset(xrManagerSettings, AssetDatabase.GetAssetOrScenePath(this));
AssetDatabase.SaveAssets();
}
///
/// Return the current instance of for a build target.
///
/// An enum specifying which platform group this build is for.
///
public XRManagerSettings ManagerSettingsForBuildTarget(BuildTargetGroup targetGroup)
{
return SettingsForBuildTarget(targetGroup)?.Manager ?? null;
}
/// Serialization override.
public void OnBeforeSerialize()
{
Keys.Clear();
Values.Clear();
foreach (var kv in Settings)
{
Keys.Add(kv.Key);
Values.Add(kv.Value);
}
}
/// Serialization override.
public void OnAfterDeserialize()
{
Settings = new Dictionary();
for (int i = 0; i < Math.Min(Keys.Count, Values.Count); i++)
{
Settings.Add(Keys[i], Values[i]);
}
}
/// Given a build target, get the general settings container assigned to it.
/// An enum specifying which platform group this build is for.
/// The instance of assigned to the key, or null if not.
public static XRGeneralSettings XRGeneralSettingsForBuildTarget(BuildTargetGroup targetGroup)
{
XRGeneralSettingsPerBuildTarget buildTargetSettings = null;
EditorBuildSettings.TryGetConfigObject(XRGeneralSettings.k_SettingsKey, out buildTargetSettings);
if (buildTargetSettings == null)
return null;
return buildTargetSettings.SettingsForBuildTarget(targetGroup);
}
}
}