using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEngine;
using UnityEngine.Rendering;
using Wheels.Unity;
[InitializeOnLoad]
public partial class IssueFix : EditorWindow
{
static ARSDKConfig sdkConfig;
static Texture2D logo;
static bool allFixed = true;
///
/// 目标系统平台,必须是Android
///
static bool targetPlatform;
///
/// SDK是否为C/S架构,如果是的话需要向ScriptingDefineSymbols添加CS符号,否则移除
///
static bool clientServerMode;
///
/// GraphicsAPI必须是OpenGLES3或OpenGLES2,否则为false
///
static bool graphicsAPIOK;
///
/// Android最小支持sdk版本,大于等于27为true
///
static bool minimum_API_Level;
///
/// 编译此项目用到的sdk版本
///
static bool target_API_Level;
///
/// 是Mono还是IL2CPP,IL2CPP为true
///
static bool scripting_Backend;
///
/// 目标平台为ARM64为true
///
static bool target_Architectures;
///
/// 允许unsafe为true
///
static bool allow_Unsafe_Code;
///
/// 禁用MultiThreadedRendering为true
///
static bool disableMultiThreadedRendering;
static IssueFix()
{
AssetDatabase.importPackageCompleted -= AssetDatabase_importPackageCompleted;
AssetDatabase.importPackageCompleted += AssetDatabase_importPackageCompleted;
}
private void OnEnable()
{
Init();
FixTags();
}
private static void AssetDatabase_importPackageCompleted(string packageName)
{
if (packageName.Contains("EZXR_ARGlass_SDK"))
{
string filePath = "EZXR_CICD.cfg";
if (File.Exists(filePath))
{
FixAllIssues();
File.WriteAllText(filePath, "AllFixed");
}
else
{
ShowWindow();
}
}
}
[MenuItem("ARSDK/Project Settings", false, 50)]
public static void ShowWindow()
{
EditorWindow window = EditorWindow.GetWindow(typeof(IssueFix), false, "Project Settings");
window.minSize = new Vector2(300, 300);
}
[DidReloadScripts]
///
/// 进行所有代码之前必须先执行的初始化操作,取到ARSDK的配置文件
///
static void Init()
{
string filePath = "Assets/EZXRGlassSDK/Editor/ARSDKConfig.asset";
if ((AssetDatabase.LoadAssetAtPath(filePath, typeof(ARSDKConfig)) as ARSDKConfig) == null)
{
filePath = AssetDatabase.GUIDToAssetPath("2c84fdf00cdace44ba329395d9e29d08");
}
sdkConfig = AssetDatabase.LoadAssetAtPath(filePath, typeof(ARSDKConfig)) as ARSDKConfig;
if (sdkConfig != null)
{
SetAbilitiesSymbols();
CheckAllIssues();
if (!allFixed)
{
ShowWindow();
}
}
}
partial void OnGUI_X1();
static bool foldout_IssueFix = true;
GUIStyle label_Red;
//static bool foldout_Settings = true;
void OnGUI()
{
if (logo == null)
{
logo = Resources.Load("ezxr_logo");
}
GUILayout.Button(logo, GUILayout.Height(200));
EditorGUILayout.Separator();
CheckAllIssues();
UnityEditorGUI.DrawLine();
foldout_IssueFix = EditorGUILayout.Foldout(foldout_IssueFix, "Project IssueFix");
if (foldout_IssueFix)
{
label_Red = new GUIStyle(EditorStyles.label);
label_Red.normal.textColor = Color.red;
if (allFixed)
{
EditorGUILayout.HelpBox("Everything is OK!", MessageType.Info);
}
else
{
EditorGUILayout.HelpBox("For AR Glass Project, all issues below must be fixed, or your project cannot run on AR Glass devices!", MessageType.Warning);
}
EditorGUILayout.Separator();
#region 通用修复项
if (!targetPlatform)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Platform:");
GUILayout.FlexibleSpace();
GUILayout.Label("Should be 'Android'", label_Red);
if (GUILayout.Button("Fix"))
{
FixTargetPlatform();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!clientServerMode)
{
GUILayout.BeginHorizontal();
GUILayout.Label("C/S:");
GUILayout.FlexibleSpace();
GUILayout.Label("Should be Fixed", label_Red);
if (GUILayout.Button("Fix"))
{
FixClientServerMode();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!graphicsAPIOK)
{
GUILayout.BeginHorizontal();
GUILayout.Label("GraphicsAPI Status:");
GUILayout.FlexibleSpace();
GUILayout.Label("Should be 'OpenGLES3 or OpenGLES2'", label_Red);
if (GUILayout.Button("Fix"))
{
FixGraphicsAPI();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!minimum_API_Level)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Minimum API Level:");
GUILayout.FlexibleSpace();
GUILayout.Label("Recommend be '" + (AndroidSdkVersions)sdkConfig.recommendedAPILevel + "'", label_Red);
if (GUILayout.Button("Fix"))
{
FixMinimumAPILevel();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!target_API_Level)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Target API Level: ");
GUILayout.FlexibleSpace();
GUILayout.Label("Recommend be '" + sdkConfig.recommendedAPILevel + "'", label_Red);
if (GUILayout.Button("Fix"))
{
FixTargetAPILevel();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!scripting_Backend)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Scripting Backend: ");
GUILayout.FlexibleSpace();
GUILayout.Label("Should be 'IL2CPP'", label_Red);
if (GUILayout.Button("Fix"))
{
FixScriptingBackend();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!target_Architectures)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Target Architectures: ");
GUILayout.FlexibleSpace();
GUILayout.Label("Should be 'ARM64'", label_Red);
if (GUILayout.Button("Fix"))
{
FixTargetArchitectures();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!allow_Unsafe_Code)
{
GUILayout.BeginHorizontal();
GUILayout.Label("Allow Unsafe Code: ");
GUILayout.FlexibleSpace();
GUILayout.Label("Should be 'Checked'", label_Red);
if (GUILayout.Button("Fix"))
{
FixAllowUnsafeCode();
}
GUILayout.EndHorizontal();
EditorGUILayout.Separator();
}
if (!disableMultiThreadedRendering)
{
GUILayout.BeginHorizontal();
GUILayout.Label("MultiThreadedRendering: ");
GUILayout.FlexibleSpace();
GUILayout.Label("MultiThreadedRendering must be 'Disabled'", label_Red);
if (GUILayout.Button("Fix"))
{
FixMultiThreadedRendering();
}
GUILayout.EndHorizontal();
}
#endregion
OnGUI_X1();
}
UnityEditorGUI.DrawLine();
//foldout_Settings = EditorGUILayout.Foldout(foldout_Settings, "Project XR Abilities");
//if (foldout_Settings)
//{
// EditorGUILayout.BeginVertical(EditorStyles.helpBox);
// EditorGUILayout.BeginHorizontal();
// projectConfig.spatialTracking = EditorGUILayout.ToggleLeft("spatialTracking", projectConfig.spatialTracking, GUILayout.Width(150));
// projectConfig.planeDetection = EditorGUILayout.ToggleLeft("planeDetection", projectConfig.planeDetection, GUILayout.Width(150));
// projectConfig.imageDetection = EditorGUILayout.ToggleLeft("imageDetection", projectConfig.imageDetection, GUILayout.Width(150));
// EditorGUILayout.EndHorizontal();
// EditorGUILayout.BeginHorizontal();
// projectConfig.spatialMesh = EditorGUILayout.ToggleLeft("spatialMesh", projectConfig.spatialMesh, GUILayout.Width(150));
// projectConfig.handTracking = EditorGUILayout.ToggleLeft("handTracking", projectConfig.handTracking, GUILayout.Width(150));
// projectConfig.spatialPositioning = EditorGUILayout.ToggleLeft("spatialPositioning", projectConfig.spatialPositioning, GUILayout.Width(150));
// EditorGUILayout.EndHorizontal();
// projectConfig.miraCast = EditorGUILayout.ToggleLeft("MiraCast", projectConfig.miraCast, GUILayout.Width(150));
// EditorGUILayout.BeginHorizontal();
// EditorGUILayout.EndHorizontal();
// EditorGUILayout.EndVertical();
//}
}
static partial void CheckAllIssues_X1();
static void CheckAllIssues()
{
#region 通用修复项
//目标系统平台必须是Android
BuildTarget buildTarget = EditorUserBuildSettings.activeBuildTarget;
if (buildTarget == BuildTarget.Android)
{
targetPlatform = true;
allFixed &= targetPlatform;
}
else
{
targetPlatform = false;
allFixed &= targetPlatform;
}
string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
if (sdkConfig.clientServerMode)
{
if (string.IsNullOrEmpty(symbols))
{
clientServerMode = false;
}
else if (symbols.Contains("EZXRCS"))
{
clientServerMode = true;
}
else
{
clientServerMode = false;
}
}
else
{
if (string.IsNullOrEmpty(symbols))
{
clientServerMode = true;
}
else if (symbols.Contains("EZXRCS"))
{
clientServerMode = false;
}
else
{
clientServerMode = true;
}
}
//GraphicsAPI必须是OpenGLES3或OpenGLES2,否则为false
GraphicsDeviceType[] graphicsAPIs = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android);
foreach (GraphicsDeviceType item in graphicsAPIs)
{
if (item != GraphicsDeviceType.OpenGLES3 && item != GraphicsDeviceType.OpenGLES2)
{
graphicsAPIOK = false;
allFixed &= graphicsAPIOK;
break;
}
else
{
graphicsAPIOK = true;
allFixed &= graphicsAPIOK;
}
}
//Android最小支持sdk版本
AndroidSdkVersions androidSdkVersions = PlayerSettings.Android.minSdkVersion;
if ((int)androidSdkVersions >= sdkConfig.recommendedAPILevel)
{
minimum_API_Level = true;
allFixed &= minimum_API_Level;
}
else
{
minimum_API_Level = false;
allFixed &= minimum_API_Level;
}
//用于编译项目的sdk版本
AndroidSdkVersions targetAndroidSdkVersions = PlayerSettings.Android.targetSdkVersion;
if ((int)targetAndroidSdkVersions >= sdkConfig.recommendedAPILevel)
{
target_API_Level = true;
allFixed &= target_API_Level;
}
else
{
target_API_Level = false;
allFixed &= target_API_Level;
}
//脚本backend
if (PlayerSettings.GetScriptingBackend(BuildTargetGroup.Android) == ScriptingImplementation.IL2CPP)
{
scripting_Backend = true;
allFixed &= scripting_Backend;
}
else
{
scripting_Backend = false;
allFixed &= scripting_Backend;
}
//cpu架构
if (PlayerSettings.Android.targetArchitectures == AndroidArchitecture.ARM64)
{
target_Architectures = true;
allFixed &= target_Architectures;
}
else
{
target_Architectures = false;
allFixed &= target_Architectures;
}
//是否允许unsafe代码
if (PlayerSettings.allowUnsafeCode)
{
allow_Unsafe_Code = true;
allFixed &= allow_Unsafe_Code;
}
else
{
allow_Unsafe_Code = false;
allFixed &= allow_Unsafe_Code;
}
//是否禁用MultiThreadedRendering
if (PlayerSettings.GetMobileMTRendering(BuildTargetGroup.Android))
{
disableMultiThreadedRendering = false;
allFixed &= disableMultiThreadedRendering;
}
else
{
disableMultiThreadedRendering = true;
allFixed &= disableMultiThreadedRendering;
}
#endregion
CheckAllIssues_X1();
}
#region 通用修复项
static void FixTags()
{
string[] tags = new string[] { "SpatialObject", "SpatialUI", "SpatialUI(NoInteractable)", "SpatialHandler" };
Object tagManagerObject = AssetDatabase.LoadAssetAtPath("ProjectSettings/TagManager.asset", typeof(Object));
if (tagManagerObject == null)
{
return;
}
SerializedObject tagManager = new SerializedObject(tagManagerObject);
SerializedProperty tagsProp = tagManager.FindProperty("tags");
//Debug.Log("TagsPorp Size:" + tagsProp.arraySize);
List tagsExists = new List();
for (int i = 0; i < tagsProp.arraySize; i++)
{
tagsExists.Add(tagsProp.GetArrayElementAtIndex(i).stringValue);
}
foreach (string tag in tags)
{
if (!tagsExists.Contains(tag))
{
tagsExists.Add(tag);
}
}
tagsProp.ClearArray();
foreach (string tag in tagsExists)
{
tagsProp.InsertArrayElementAtIndex(Mathf.Clamp(0, tagsProp.arraySize - 1, 128));
tagsProp.GetArrayElementAtIndex(tagsProp.arraySize - 1).stringValue = tag;
}
tagManager.ApplyModifiedProperties();
}
static void FixTargetPlatform()
{
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);
}
static void FixClientServerMode()
{
if (sdkConfig.clientServerMode)
{
//向ScriptingDefineSymbols添加EZXRCS
var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
if (!symbols.Contains("EZXRCS"))
{
symbols += ";EZXRCS";
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, symbols);
}
}
else
{
//去掉ScriptingDefineSymbols中的EZXRCS,避免移除package的时候会因为引用丢失而报错
string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
if (symbols.Contains("EZXRCS;"))
{
symbols = symbols.Replace("EZXRCS;", "");
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, symbols);
}
else if (symbols.Contains("EZXRCS"))
{
symbols = symbols.Replace("EZXRCS", "");
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, symbols);
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
static void FixGraphicsAPI()
{
PlayerSettings.SetUseDefaultGraphicsAPIs(BuildTarget.Android, false);
PlayerSettings.SetGraphicsAPIs(BuildTarget.Android, new GraphicsDeviceType[] { GraphicsDeviceType.OpenGLES3 });
}
static void FixMinimumAPILevel()
{
PlayerSettings.Android.minSdkVersion = (AndroidSdkVersions)sdkConfig.recommendedAPILevel;
}
static void FixTargetAPILevel()
{
PlayerSettings.Android.targetSdkVersion = (AndroidSdkVersions)sdkConfig.recommendedAPILevel;
}
static void FixScriptingBackend()
{
PlayerSettings.SetScriptingBackend(BuildTargetGroup.Android, ScriptingImplementation.IL2CPP);
}
static void FixTargetArchitectures()
{
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
}
static void FixAllowUnsafeCode()
{
PlayerSettings.allowUnsafeCode = true;
}
static void FixMultiThreadedRendering()
{
PlayerSettings.SetMobileMTRendering(BuildTargetGroup.Android, false);
}
///
/// 将sdk所带的功能名配置到全局符号定义,主要用于类似XRMan这种会涉及到多模块的脚本做#if用
///
static void SetAbilitiesSymbols()
{
if (sdkConfig.spatialMesh)
{
AddSymbol("SpatialMesh");
}
else
{
RemoveSymbol("SpatialMesh");
}
if (sdkConfig.spatialComputing)
{
AddSymbol("SpatialComputing");
}
else
{
RemoveSymbol("SpatialComputing");
}
if (sdkConfig.imageTracking)
{
AddSymbol("Tracking2D");
}
else
{
RemoveSymbol("Tracking2D");
}
if (sdkConfig.objectDetection)
{
AddSymbol("Tracking3D");
}
else
{
RemoveSymbol("Tracking3D");
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
///
/// 向ScriptingDefineSymbols添加symbol
///
///
static void AddSymbol(string symbol)
{
var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
if (!symbols.Contains(symbol))
{
symbols += ";" + symbol;
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, symbols);
}
}
///
/// 从ScriptingDefineSymbols中去掉symbol
///
///
static void RemoveSymbol(string symbol)
{
string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android);
if (symbols.Contains(symbol + ";"))
{
symbols = symbols.Replace(symbol + ";", "");
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, symbols);
}
else if (symbols.Contains(symbol))
{
symbols = symbols.Replace(symbol, "");
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, symbols);
}
}
//Note: 这里每添加一条,都应该在下方的FixAllIssues中添加一行执行代码
#endregion
static partial void Fix_X1();
public static void FixAllIssues()
{
Init();
#region 通用修复项
FixTags();
FixTargetPlatform();
FixClientServerMode();
FixGraphicsAPI();
FixMinimumAPILevel();
FixTargetAPILevel();
FixScriptingBackend();
FixTargetArchitectures();
FixAllowUnsafeCode();
FixMultiThreadedRendering();
SetAbilitiesSymbols();
#endregion
Fix_X1();
}
}