Files
2025-07-21 09:11:14 +02:00

1080 lines
38 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if OVR_UNITY_ASSET_STORE
#if USING_XR_MANAGEMENT && (USING_XR_SDK_OCULUS || USING_XR_SDK_OPENXR)
#define USING_XR_SDK
#endif
#if UNITY_2020_1_OR_NEWER
#define REQUIRES_XR_SDK
#endif
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;
using Oculus.VR.Editor;
[InitializeOnLoad]
public class OVRPluginUpdater : IOVRPluginInfoSupplier
{
enum PluginPlatform
{
Android,
AndroidUniversal,
AndroidOpenXR,
OSXUniversal,
Win,
Win64,
Win64OpenXR,
}
class PluginPackage
{
public string RootPath;
public System.Version Version;
public Dictionary<PluginPlatform, string> Plugins = new Dictionary<PluginPlatform, string>();
public bool IsBundledPluginPackage()
{
return (RootPath == GetBundledPluginRootPath());
}
public bool IsEnabled()
{
foreach (PluginPlatform platform in Enum.GetValues(typeof(PluginPlatform)))
{
string path = "";
if (Plugins.TryGetValue(platform, out path) && File.Exists(path))
{
return true;
}
}
return false;
}
public bool IsWin64Enabled()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.Win64, out path))
{
if (File.Exists(path))
{
string basePath = GetCurrentProjectPath();
string relPath = path.Substring(basePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(relPath) as PluginImporter;
if (pi != null)
{
return pi.GetCompatibleWithPlatform(BuildTarget.StandaloneWindows64) &&
pi.GetCompatibleWithEditor();
}
}
}
return false;
}
public bool IsWin64Present()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.Win64, out path))
{
string disabledPath = path + GetDisabledPluginSuffix();
if (File.Exists(path) || File.Exists(disabledPath))
{
return true;
}
}
return false;
}
public bool IsWin64OpenXREnabled()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.Win64OpenXR, out path))
{
if (File.Exists(path))
{
string basePath = GetCurrentProjectPath();
string relPath = path.Substring(basePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(relPath) as PluginImporter;
if (pi != null)
{
return pi.GetCompatibleWithPlatform(BuildTarget.StandaloneWindows64) &&
pi.GetCompatibleWithEditor();
}
}
}
return false;
}
public bool IsWin64OpenXRPresent()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.Win64OpenXR, out path))
{
string disabledPath = path + GetDisabledPluginSuffix();
if (File.Exists(path) || File.Exists(disabledPath))
{
return true;
}
}
return false;
}
public bool IsAndroidUniversalEnabled()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.AndroidUniversal, out path))
{
if (File.Exists(path))
{
string basePath = GetCurrentProjectPath();
string relPath = path.Substring(basePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(relPath) as PluginImporter;
if (pi != null)
{
return pi.GetCompatibleWithPlatform(BuildTarget.Android);
}
}
}
return false;
}
public bool IsAndroidUniversalPresent()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.AndroidUniversal, out path))
{
string disabledPath = path + GetDisabledPluginSuffix();
if (File.Exists(path) || File.Exists(disabledPath))
{
return true;
}
}
return false;
}
public bool IsAndroidOpenXREnabled()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.AndroidOpenXR, out path))
{
if (File.Exists(path))
{
string basePath = GetCurrentProjectPath();
string relPath = path.Substring(basePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(relPath) as PluginImporter;
if (pi != null)
{
return pi.GetCompatibleWithPlatform(BuildTarget.Android);
}
}
}
return false;
}
public bool IsAndroidOpenXRPresent()
{
string path = "";
if (Plugins.TryGetValue(PluginPlatform.AndroidOpenXR, out path))
{
string disabledPath = path + GetDisabledPluginSuffix();
if (File.Exists(path) || File.Exists(disabledPath))
{
return true;
}
}
return false;
}
}
private static bool restartPending = false;
private static bool unityRunningInBatchmode = false;
private static bool unityVersionSupportsAndroidUniversal = true;
private static bool enableAndroidUniversalSupport = true;
private static System.Version invalidVersion = new System.Version("0.0.0");
private static System.Version minimalProductionVersionForOpenXR = new Version(1, 63, 0);
static OVRPluginUpdater()
{
EditorApplication.delayCall += OnDelayCall;
}
static void OnDelayCall()
{
if (System.Environment.CommandLine.Contains("-batchmode"))
{
unityRunningInBatchmode = true;
}
if (enableAndroidUniversalSupport)
{
unityVersionSupportsAndroidUniversal = true;
}
if (ShouldAttemptPluginUpdate())
{
AttemptPluginUpdate(true);
}
}
private static PluginPackage GetPluginPackage(string rootPath)
{
return new PluginPackage()
{
RootPath = rootPath,
Version = GetPluginVersion(rootPath),
Plugins = new Dictionary<PluginPlatform, string>()
{
{ PluginPlatform.Android, rootPath + GetPluginBuildTargetSubPath(PluginPlatform.Android) },
{
PluginPlatform.AndroidUniversal,
rootPath + GetPluginBuildTargetSubPath(PluginPlatform.AndroidUniversal)
},
{ PluginPlatform.AndroidOpenXR, rootPath + GetPluginBuildTargetSubPath(PluginPlatform.AndroidOpenXR) },
{ PluginPlatform.OSXUniversal, rootPath + GetPluginBuildTargetSubPath(PluginPlatform.OSXUniversal) },
{ PluginPlatform.Win, rootPath + GetPluginBuildTargetSubPath(PluginPlatform.Win) },
{ PluginPlatform.Win64, rootPath + GetPluginBuildTargetSubPath(PluginPlatform.Win64) },
{ PluginPlatform.Win64OpenXR, rootPath + GetPluginBuildTargetSubPath(PluginPlatform.Win64OpenXR) },
}
};
}
private static PluginPackage GetBundledPluginPackage()
{
return GetPluginPackage(GetBundledPluginRootPath());
}
private static List<PluginPackage> GetAllUtilitiesPluginPackages()
{
string pluginRootPath = GetUtilitiesPluginRootPath();
List<PluginPackage> packages = new List<PluginPackage>();
if (Directory.Exists(pluginRootPath))
{
var dirs = Directory.GetDirectories(pluginRootPath);
foreach (string dir in dirs)
{
packages.Add(GetPluginPackage(dir));
}
}
return packages;
}
private static string GetCurrentProjectPath()
{
return Directory.GetParent(Application.dataPath).FullName;
}
private static string GetUtilitiesPluginRootPath()
{
return Path.Combine(OVRPluginInfo.GetUtilitiesRootPath(), "Plugins");
}
private static string GetBundledPluginRootPath()
{
string basePath = EditorApplication.applicationContentsPath;
string pluginPath = @"/UnityExtensions/Unity/VR";
return basePath + pluginPath;
}
private static string GetPluginBuildTargetSubPath(PluginPlatform target)
{
string path = string.Empty;
switch (target)
{
case PluginPlatform.Android:
path = @"/Android/OVRPlugin.aar";
break;
case PluginPlatform.AndroidUniversal:
path = @"/AndroidUniversal/OVRPlugin.aar";
break;
case PluginPlatform.AndroidOpenXR:
path = @"/AndroidOpenXR/OVRPlugin.aar";
break;
case PluginPlatform.OSXUniversal:
path = @"/OSXUniversal/OVRPlugin.bundle";
break;
case PluginPlatform.Win:
path = @"/Win/OVRPlugin.dll";
break;
case PluginPlatform.Win64:
path = @"/Win64/OVRPlugin.dll";
break;
case PluginPlatform.Win64OpenXR:
path = @"/Win64OpenXR/OVRPlugin.dll";
break;
default:
throw new ArgumentException("Attempted GetPluginBuildTargetSubPath() for unsupported BuildTarget: " +
target);
}
return path;
}
private static string GetDisabledPluginSuffix()
{
return @".disabled";
}
private static System.Version GetPluginVersion(string path)
{
System.Version pluginVersion = invalidVersion;
try
{
pluginVersion = new System.Version(Path.GetFileName(path));
}
catch
{
pluginVersion = invalidVersion;
}
if (pluginVersion == invalidVersion)
{
//Unable to determine version from path, fallback to Win64 DLL meta data
path += GetPluginBuildTargetSubPath(PluginPlatform.Win64);
if (!File.Exists(path))
{
path += GetDisabledPluginSuffix();
if (!File.Exists(path))
{
return invalidVersion;
}
}
FileVersionInfo pluginVersionInfo = FileVersionInfo.GetVersionInfo(path);
if (pluginVersionInfo == null || pluginVersionInfo.ProductVersion == null ||
pluginVersionInfo.ProductVersion == "")
{
return invalidVersion;
}
pluginVersion = new System.Version(pluginVersionInfo.ProductVersion);
}
return pluginVersion;
}
public static string GetVersionDescription(System.Version version)
{
return IsVersionValid(version) ? version.ToString() : "(Unknown)";
}
private static bool IsVersionValid(Version version)
{
return version != invalidVersion;
}
public static string GetEnabledUtilsPluginRootPath()
{
PluginPackage package = GetEnabledUtilsPluginPkg();
if (package == null)
{
return null;
}
else
{
return package.RootPath;
}
}
private static bool ShouldAttemptPluginUpdate()
{
if (unityRunningInBatchmode || OVRPluginInfo.IsInsidePackageDistribution())
{
return false;
}
else
{
return !UnitySupportsEnabledAndroidPlugin() ||
(autoUpdateEnabled && !restartPending && !Application.isPlaying);
}
}
private static void DisableAllUtilitiesPluginPackages()
{
List<PluginPackage> allUtilsPluginPkgs = GetAllUtilitiesPluginPackages();
foreach (PluginPackage pluginPkg in allUtilsPluginPkgs)
{
foreach (string path in pluginPkg.Plugins.Values)
{
if ((Directory.Exists(path)) || (File.Exists(path)))
{
string basePath = GetCurrentProjectPath();
string relPath = path.Substring(basePath.Length + 1);
string relDisabledPath = relPath + GetDisabledPluginSuffix();
AssetDatabase.MoveAsset(relPath, relDisabledPath);
AssetDatabase.ImportAsset(relDisabledPath, ImportAssetOptions.ForceUpdate);
}
}
}
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
}
private static void EnablePluginPackage(PluginPackage pluginPkg)
{
UnityEngine.Debug.Log("OVRPlugin with OpenXR backend is activated by default");
foreach (var kvp in pluginPkg.Plugins)
{
PluginPlatform platform = kvp.Key;
string path = kvp.Value;
if ((Directory.Exists(path + GetDisabledPluginSuffix())) || (File.Exists(path + GetDisabledPluginSuffix())))
{
string basePath = GetCurrentProjectPath();
string relPath = path.Substring(basePath.Length + 1);
string relDisabledPath = relPath + GetDisabledPluginSuffix();
AssetDatabase.MoveAsset(relDisabledPath, relPath);
AssetDatabase.ImportAsset(relPath, ImportAssetOptions.ForceUpdate);
PluginImporter pi = PluginImporter.GetAtPath(relPath) as PluginImporter;
if (pi == null)
{
continue;
}
// Disable support for all platforms, then conditionally enable desired support below
pi.SetCompatibleWithEditor(false);
pi.SetCompatibleWithAnyPlatform(false);
pi.SetCompatibleWithPlatform(BuildTarget.Android, false);
pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false);
pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false);
pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, false);
switch (platform)
{
case PluginPlatform.Android:
break;
case PluginPlatform.AndroidUniversal:
break;
case PluginPlatform.AndroidOpenXR:
pi.SetCompatibleWithPlatform(BuildTarget.Android, unityVersionSupportsAndroidUniversal);
break;
case PluginPlatform.OSXUniversal:
pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, true);
pi.SetCompatibleWithEditor(true);
pi.SetEditorData("CPU", "AnyCPU");
pi.SetEditorData("OS", "OSX");
pi.SetPlatformData("Editor", "CPU", "AnyCPU");
pi.SetPlatformData("Editor", "OS", "OSX");
break;
case PluginPlatform.Win:
break;
case PluginPlatform.Win64:
break;
case PluginPlatform.Win64OpenXR:
pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, true);
pi.SetCompatibleWithEditor(true);
pi.SetEditorData("CPU", "X86_64");
pi.SetEditorData("OS", "Windows");
pi.SetPlatformData("Editor", "CPU", "X86_64");
pi.SetPlatformData("Editor", "OS", "Windows");
break;
default:
throw new ArgumentException("Attempted EnablePluginPackage() for unsupported BuildTarget: " +
platform);
}
AssetDatabase.ImportAsset(relPath, ImportAssetOptions.ForceUpdate);
}
}
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
}
private static readonly string autoUpdateEnabledKey =
"Oculus_Utilities_OVRPluginUpdater_AutoUpdate2_" + OVRManager.utilitiesVersion;
private static bool autoUpdateEnabled
{
get => PlayerPrefs.GetInt(autoUpdateEnabledKey, 1) == 1;
set
{
PlayerPrefs.SetInt(autoUpdateEnabledKey, value ? 1 : 0);
PlayerPrefs.Save();
}
}
private static PluginPackage GetEnabledUtilsPluginPkg()
{
List<PluginPackage> allUtilsPluginPkgs = GetAllUtilitiesPluginPackages();
PluginPackage enabledUtilsPluginPkg = null;
foreach (PluginPackage pluginPkg in allUtilsPluginPkgs)
{
if (pluginPkg.IsEnabled())
{
if ((enabledUtilsPluginPkg == null) || (pluginPkg.Version > enabledUtilsPluginPkg.Version))
{
enabledUtilsPluginPkg = pluginPkg;
}
}
}
return enabledUtilsPluginPkg;
}
const string k_disablePluginMenuStr =
"Oculus/Tools/OVR Utilities Plugin/Set OVRPlugin to Package Manager-provided (Disable OVR Utilities Plugin version)";
[MenuItem(k_disablePluginMenuStr, true, 102)]
private static bool IsDisableOVRPluginMenuEnabled()
{
//This section controls whether we draw a checkmark next to this menu item (it's currently active...)
Menu.SetChecked(k_disablePluginMenuStr, GetEnabledUtilsPluginPkg() == null);
//And this section controls whether the menu item is enabled (you're allowed to toggle it)
return true;
}
[MenuItem(k_disablePluginMenuStr, false, 102)]
private static void AttemptPluginDisable()
{
if (OVRPluginInfo.IsInsidePackageDistribution())
{
UnityEngine.Debug.LogError("Unable to change plugin when using package distribution");
return;
}
PluginPackage enabledUtilsPluginPkg = GetEnabledUtilsPluginPkg();
if (enabledUtilsPluginPkg == null)
{
if (unityRunningInBatchmode
|| EditorUtility.DisplayDialog("Disable Oculus Utilities Plugin",
"The OVRPlugin included with Oculus Utilities is already disabled."
+ " The OVRPlugin installed through the Package Manager will continue to be used.\n",
"Ok",
""))
{
return;
}
}
else
{
if (unityRunningInBatchmode
|| EditorUtility.DisplayDialog("Disable Oculus Utilities Plugin",
"Do you want to disable the OVRPlugin included with Oculus Utilities and revert to the OVRPlugin installed through the Package Manager?\n\n"
+ "Current version: " + GetVersionDescription(enabledUtilsPluginPkg.Version),
"Yes",
"No"))
{
DisableAllUtilitiesPluginPackages();
autoUpdateEnabled = false;
if (unityRunningInBatchmode
|| EditorUtility.DisplayDialog("Restart Unity",
"Now you will be using the OVRPlugin installed through Package Manager."
+ "\n\nPlease restart the Unity Editor to complete the update process.",
"Restart",
"Not Now"))
{
RestartUnityEditor();
}
}
}
}
[MenuItem("Oculus/Tools/OVR Utilities Plugin/Manual Update OVRPlugin (to OVR Utilities version)", false, 0)]
private static void RunPluginUpdate()
{
if (OVRPluginInfo.IsInsidePackageDistribution())
{
UnityEngine.Debug.LogError("Unable to change plugin when using package distribution");
return;
}
autoUpdateEnabled = true;
AttemptPluginUpdate(false);
}
private static void BatchmodeActivateOVRPluginOpenXR()
{
OnDelayCall(); // manually invoke when running editor in batchmode
ActivateOVRPluginOpenXR();
}
const string k_setToOpenXRPluginMenuStr = "Oculus/Tools/OVR Utilities Plugin/Set OVRPlugin to OpenXR";
[MenuItem(k_setToOpenXRPluginMenuStr, true, 100)]
private static bool IsActivateOVRPluginOpenXRMenuEnabled()
{
//This section controls whether we draw a checkmark next to this menu item (it's currently active...)
Menu.SetChecked(k_setToOpenXRPluginMenuStr, IsOVRPluginOpenXRActivatedInternal());
//And this section controls whether the menu item is enabled (you're allowed to toggle it)
#if !USING_XR_SDK && !REQUIRES_XR_SDK
return false;
#else
return true;
#endif
}
[MenuItem(k_setToOpenXRPluginMenuStr, false, 100)]
private static void ActivateOVRPluginOpenXR()
{
if (!unityVersionSupportsAndroidUniversal)
{
UnityEngine.Debug.LogError(
"Unexpected error: Unity must support AndroidUniversal version of Oculus Utilities Plugin for accessing OpenXR");
return;
}
if (OVRPluginInfo.IsInsidePackageDistribution())
{
UnityEngine.Debug.LogError("Unable to change plugin when using package distribution");
return;
}
#if !USING_XR_SDK && !REQUIRES_XR_SDK
UnityEngine.Debug.LogError("Oculus Utilities Plugin with OpenXR only supports XR Plug-in Management with Oculus XR Plugin");
return;
#else
List<PluginPackage> allUtilsPluginPkgs = GetAllUtilitiesPluginPackages();
PluginPackage enabledUtilsPluginPkg = null;
foreach (PluginPackage pluginPkg in allUtilsPluginPkgs)
{
if (pluginPkg.IsEnabled())
{
enabledUtilsPluginPkg = pluginPkg;
break;
}
}
if (enabledUtilsPluginPkg == null)
{
UnityEngine.Debug.LogError(
"Unable to Activate OVRPlugin with OpenXR: Oculus Utilities Plugin package not activated");
return;
}
if (!enabledUtilsPluginPkg.IsAndroidOpenXRPresent() && !enabledUtilsPluginPkg.IsWin64OpenXRPresent())
{
UnityEngine.Debug.LogError(
"Unable to Activate OVRPlugin with OpenXR: Both AndroidOpenXR/OVRPlugin.aar or Win64OpenXR/OVRPlugin.dll does not exist");
return;
}
if (enabledUtilsPluginPkg.IsAndroidOpenXREnabled() && enabledUtilsPluginPkg.IsWin64OpenXREnabled())
{
if (!unityRunningInBatchmode)
{
EditorUtility.DisplayDialog("Unable to Activate OVRPlugin with OpenXR",
"Both AndroidOpenXR/OVRPlugin.aar and Win64OpenXR/OVRPlugin.dll already enabled", "Ok");
}
return;
}
if (enabledUtilsPluginPkg.Version < minimalProductionVersionForOpenXR)
{
if (!unityRunningInBatchmode)
{
bool accepted = EditorUtility.DisplayDialog("Warning",
"OVRPlugin with OpenXR backend is experimental before v31. You may expect to encounter stability issues and/or missing functionalities, " +
"including but not limited to, fixed foveated rendering / composition layer / display refresh rates / etc." +
"\n\n" +
"Also, OVRPlugin with OpenXR backend only supports XR Plug-in Management with Oculus XR Plugin on Quest",
"Continue", "Cancel");
if (!accepted)
{
return;
}
}
}
if (enabledUtilsPluginPkg.IsAndroidOpenXRPresent() && !enabledUtilsPluginPkg.IsAndroidOpenXREnabled())
{
if (enabledUtilsPluginPkg.IsAndroidUniversalEnabled())
{
string androidUniveralPluginPath = enabledUtilsPluginPkg.Plugins[PluginPlatform.AndroidUniversal];
string androidUniveralPluginBasePath = GetCurrentProjectPath();
string androidUniveralPluginRelPath =
androidUniveralPluginPath.Substring(androidUniveralPluginBasePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(androidUniveralPluginRelPath) as PluginImporter;
if (pi != null)
{
pi.SetCompatibleWithPlatform(BuildTarget.Android, false);
AssetDatabase.ImportAsset(androidUniveralPluginRelPath, ImportAssetOptions.ForceUpdate);
}
else
{
UnityEngine.Debug.LogWarning("Unable to find PluginImporter: " + androidUniveralPluginRelPath);
}
}
{
string androidOpenXRPluginPath = enabledUtilsPluginPkg.Plugins[PluginPlatform.AndroidOpenXR];
string androidOpenXRPluginBasePath = GetCurrentProjectPath();
string androidOpenXRPluginRelPath =
androidOpenXRPluginPath.Substring(androidOpenXRPluginBasePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(androidOpenXRPluginRelPath) as PluginImporter;
if (pi != null)
{
pi.SetCompatibleWithPlatform(BuildTarget.Android, true);
AssetDatabase.ImportAsset(androidOpenXRPluginRelPath, ImportAssetOptions.ForceUpdate);
}
else
{
UnityEngine.Debug.LogWarning("Unable to find PluginImporter: " + androidOpenXRPluginRelPath);
}
}
}
bool win64PluginUpdated = false;
if (enabledUtilsPluginPkg.IsWin64OpenXRPresent() && !enabledUtilsPluginPkg.IsWin64OpenXREnabled())
{
if (enabledUtilsPluginPkg.IsWin64Enabled())
{
string win64PluginPath = enabledUtilsPluginPkg.Plugins[PluginPlatform.Win64];
string win64PluginBasePath = GetCurrentProjectPath();
string win64PluginRelPath = win64PluginPath.Substring(win64PluginBasePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(win64PluginRelPath) as PluginImporter;
if (pi != null)
{
pi.ClearSettings();
pi.SetCompatibleWithEditor(false);
pi.SetCompatibleWithAnyPlatform(false);
AssetDatabase.ImportAsset(win64PluginRelPath, ImportAssetOptions.ForceUpdate);
}
else
{
UnityEngine.Debug.LogWarning("Unable to find PluginImporter: " + win64PluginRelPath);
}
}
{
string win64OpenXRPluginPath = enabledUtilsPluginPkg.Plugins[PluginPlatform.Win64OpenXR];
string win64OpenXRPluginBasePath = GetCurrentProjectPath();
string win64OpenXRPluginRelPath = win64OpenXRPluginPath.Substring(win64OpenXRPluginBasePath.Length + 1);
PluginImporter pi = PluginImporter.GetAtPath(win64OpenXRPluginRelPath) as PluginImporter;
if (pi != null)
{
pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, true);
pi.SetCompatibleWithEditor(true);
pi.SetEditorData("CPU", "X86_64");
pi.SetEditorData("OS", "Windows");
pi.SetPlatformData("Editor", "CPU", "X86_64");
pi.SetPlatformData("Editor", "OS", "Windows");
AssetDatabase.ImportAsset(win64OpenXRPluginRelPath, ImportAssetOptions.ForceUpdate);
}
else
{
UnityEngine.Debug.LogWarning("Unable to find PluginImporter: " + win64OpenXRPluginRelPath);
}
}
win64PluginUpdated = true;
}
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
if (!unityRunningInBatchmode)
{
EditorUtility.DisplayDialog("Activate OVRPlugin with OpenXR",
"Oculus Utilities Plugin with OpenXR has been enabled on Android", "Ok");
if (win64PluginUpdated && EditorUtility.DisplayDialog("Restart Unity",
"Win64 plugin updated. Do you want to restart Unity editor?",
"Restart",
"Not Now"))
{
RestartUnityEditor();
}
}
#endif // !USING_XR_SDK
}
public static bool IsOVRPluginLegacyAPIActivated()
{
PluginPackage enabledUtilsPluginPkg = GetEnabledUtilsPluginPkg();
if (enabledUtilsPluginPkg == null)
{
return false;
}
return enabledUtilsPluginPkg.IsAndroidUniversalEnabled();
}
// Separate entry point needed since "-executeMethod" does not support parameters or default parameter values
private static void BatchmodePluginUpdate()
{
OnDelayCall(); // manually invoke when running editor in batchmode
AttemptPluginUpdate(false);
}
private static void AttemptPluginUpdate(bool triggeredByAutoUpdate)
{
OVRPlugin.SendEvent("attempt_plugin_update_auto", triggeredByAutoUpdate.ToString());
PluginPackage bundledPluginPkg = GetBundledPluginPackage();
List<PluginPackage> allUtilsPluginPkgs = GetAllUtilitiesPluginPackages();
PluginPackage enabledUtilsPluginPkg = null;
PluginPackage newestUtilsPluginPkg = null;
foreach (PluginPackage pluginPkg in allUtilsPluginPkgs)
{
if ((newestUtilsPluginPkg == null) || (pluginPkg.Version > newestUtilsPluginPkg.Version))
{
newestUtilsPluginPkg = pluginPkg;
}
if (pluginPkg.IsEnabled())
{
if ((enabledUtilsPluginPkg == null) || (pluginPkg.Version > enabledUtilsPluginPkg.Version))
{
enabledUtilsPluginPkg = pluginPkg;
}
}
}
bool reenableCurrentPluginPkg = false;
PluginPackage targetPluginPkg = null;
if ((newestUtilsPluginPkg != null) && (newestUtilsPluginPkg.Version > bundledPluginPkg.Version))
{
if ((enabledUtilsPluginPkg == null) || (enabledUtilsPluginPkg.Version != newestUtilsPluginPkg.Version))
{
targetPluginPkg = newestUtilsPluginPkg;
}
}
else if ((enabledUtilsPluginPkg != null) && (enabledUtilsPluginPkg.Version < bundledPluginPkg.Version))
{
targetPluginPkg = bundledPluginPkg;
}
PluginPackage currentPluginPkg = (enabledUtilsPluginPkg != null) ? enabledUtilsPluginPkg : bundledPluginPkg;
if ((targetPluginPkg == null) && !UnitySupportsEnabledAndroidPlugin())
{
// Force reenabling the current package to configure the correct android plugin for this unity version.
reenableCurrentPluginPkg = true;
targetPluginPkg = currentPluginPkg;
}
if (targetPluginPkg == null)
{
if (!triggeredByAutoUpdate && !unityRunningInBatchmode)
{
EditorUtility.DisplayDialog("Update Oculus Utilities Plugin",
"OVRPlugin is already up to date.\n\nCurrent version: "
+ GetVersionDescription(currentPluginPkg.Version),
"Ok",
"");
}
return; // No update necessary.
}
System.Version targetVersion = targetPluginPkg.Version;
bool userAcceptsUpdate = false;
if (unityRunningInBatchmode)
{
userAcceptsUpdate = true;
}
else
{
string dialogBody = "Oculus Utilities has detected that a newer OVRPlugin is available."
+ " Using the newest version is recommended. Do you want to enable it?\n\n"
+ "Current version: "
+ GetVersionDescription(currentPluginPkg.Version)
+ "\nAvailable version: "
+ targetVersion;
if (reenableCurrentPluginPkg)
{
dialogBody =
"Oculus Utilities has detected a configuration change that requires re-enabling the current OVRPlugin."
+ " Do you want to proceed?\n\nCurrent version: "
+ GetVersionDescription(currentPluginPkg.Version);
}
if (IsVersionValid(currentPluginPkg.Version))
{
int dialogResult = EditorUtility.DisplayDialogComplex("Update Oculus Utilities Plugin", dialogBody,
"Yes", "No, Don't Ask Again", "No");
switch (dialogResult)
{
case 0: // "Yes"
userAcceptsUpdate = true;
break;
case 1: // "No, Don't Ask Again"
autoUpdateEnabled = false;
EditorUtility.DisplayDialog("Oculus Utilities OVRPlugin",
"To manually update in the future, use the following menu option:\n\n"
+ "[Oculus -> Tools -> Update OVR Utilities Plugin]",
"Ok",
"");
return;
case 2: // "No"
return;
}
}
else
{
// if there's no current valid version, update it automatically
userAcceptsUpdate = true;
}
}
if (userAcceptsUpdate)
{
DisableAllUtilitiesPluginPackages();
if (!targetPluginPkg.IsBundledPluginPackage())
{
EnablePluginPackage(targetPluginPkg);
}
if (unityRunningInBatchmode
|| EditorUtility.DisplayDialog("Restart Unity",
"OVRPlugin has been updated to "
+ GetVersionDescription(targetPluginPkg.Version)
+ ".\n\nPlease restart the Unity Editor to complete the update process."
,
"Restart",
"Not Now"))
{
RestartUnityEditor();
}
}
}
private static bool UnitySupportsEnabledAndroidPlugin()
{
List<PluginPackage> allUtilsPluginPkgs = GetAllUtilitiesPluginPackages();
foreach (PluginPackage pluginPkg in allUtilsPluginPkgs)
{
if (pluginPkg.IsEnabled())
{
if ((pluginPkg.IsAndroidUniversalEnabled() || pluginPkg.IsAndroidOpenXREnabled()) &&
!unityVersionSupportsAndroidUniversal)
{
// Android Universal should only be enabled on supported Unity versions since it can prevent app launch.
return false;
}
else if (!pluginPkg.IsAndroidUniversalEnabled() && pluginPkg.IsAndroidUniversalPresent() &&
!pluginPkg.IsAndroidOpenXREnabled() && pluginPkg.IsAndroidOpenXRPresent() &&
unityVersionSupportsAndroidUniversal)
{
// Android Universal is present and should be enabled on supported Unity versions since ARM64 config will fail otherwise.
return false;
}
}
}
return true;
}
private static void RestartUnityEditor()
{
if (unityRunningInBatchmode)
{
EditorApplication.Exit(0);
}
else
{
restartPending = true;
EditorApplication.OpenProject(GetCurrentProjectPath());
}
}
#region IOVRPluginInfoSupplier Implementation
// Test if the OVRPlugin/OpenXR plugin is currently activated, used by other editor utilities
public bool IsOVRPluginOpenXRActivated() => IsOVRPluginOpenXRActivatedInternal();
private static bool IsOVRPluginOpenXRActivatedInternal()
{
if (!unityVersionSupportsAndroidUniversal) // sanity check
{
return false;
}
PluginPackage enabledUtilsPluginPkg = GetEnabledUtilsPluginPkg();
return enabledUtilsPluginPkg != null && enabledUtilsPluginPkg.IsAndroidOpenXREnabled();
}
public bool IsOVRPluginUnityProvidedActivated()
{
PluginPackage enabledUtilsPluginPkg = GetEnabledUtilsPluginPkg();
return enabledUtilsPluginPkg != null && enabledUtilsPluginPkg.IsBundledPluginPackage();
}
#endregion
}
#endif