| using UnityEditor; | 
| using UnityEditor.IMGUI.Controls; | 
| using System.Collections.Generic; | 
| using System.IO; | 
| using System.Runtime.Serialization.Formatters.Binary; | 
|   | 
| using UnityEngine.AssetBundles.AssetBundleDataSource; | 
| using Assets.Editor.Tool; | 
| using HybridCLR.Editor.Commands; | 
| using HybridCLR.Editor.Settings; | 
| //using Mono.Cecil; | 
| using DG.Tweening.Plugins.Core.PathCore; | 
| using System; | 
| using Path = System.IO.Path; | 
| using HybridCLR.Editor.HotUpdate; | 
| using HybridCLR.Editor; | 
|   | 
| namespace UnityEngine.AssetBundles | 
| { | 
|     [System.Serializable] | 
|     public class AssetBundleBuildTab | 
|     { | 
|         const string k_BuildPrefPrefix = "ABBBuild:"; | 
|         // gui vars | 
|         //[SerializeField] | 
|         //private ValidBuildTarget m_BuildTarget = ValidBuildTarget.StandaloneWindows; | 
|         //[SerializeField] | 
|         //private CompressOptions m_Compression = CompressOptions.StandardCompression;         | 
|         //private string m_OutputPath = string.Empty; | 
|         //[SerializeField] | 
|         //private bool m_UseDefaultPath = true; | 
|         private string m_streamingPath | 
|         { | 
|             get | 
|             { | 
|                 switch (m_UserData.m_BuildTarget) | 
|                 { | 
|                     case ValidBuildTarget.Android: | 
|                         return StringUtility.Contact("Assets/StreamingAssets", "/android"); | 
|                     case ValidBuildTarget.iOS: | 
|                         return StringUtility.Contact("Assets/StreamingAssets", "/ios"); | 
|                     case ValidBuildTarget.StandaloneWindows: | 
|                     case ValidBuildTarget.StandaloneWindows64: | 
|                         return StringUtility.Contact("Assets/StreamingAssets", "/standalone"); | 
|                     default: | 
|                         return "Assets/StreamingAssets"; | 
|                 } | 
|             } | 
|         } | 
|   | 
|         [SerializeField] | 
|         private bool m_AdvancedSettings; | 
|   | 
|         [SerializeField] | 
|         private Vector2 m_ScrollPosition; | 
|   | 
|   | 
|         class ToggleData | 
|         { | 
|             public ToggleData(bool s, | 
|                 string title, | 
|                 string tooltip, | 
|                 List<string> onToggles, | 
|                 BuildAssetBundleOptions opt = BuildAssetBundleOptions.None) | 
|             { | 
|                 if (onToggles.Contains(title)) | 
|                     state = true; | 
|                 else | 
|                     state = s; | 
|                 content = new GUIContent(title, tooltip); | 
|                 option = opt; | 
|             } | 
|             //public string prefsKey | 
|             //{ get { return k_BuildPrefPrefix + content.text; } } | 
|             public bool state; | 
|             public GUIContent content; | 
|             public BuildAssetBundleOptions option; | 
|         } | 
|   | 
|         [SerializeField] | 
|         private BuildTabData m_UserData; | 
|   | 
|         [SerializeField] int m_Version; | 
|   | 
|         public string ApkOutputPath | 
|         { | 
|             get { return LocalSave.GetString("APKOutPutPath"); } | 
|             set { LocalSave.SetString("APKOutPutPath", value); } | 
|         } | 
|   | 
|         public string publishers | 
|         { | 
|             get { return LocalSave.GetString("APKPublishers"); } | 
|             set { LocalSave.SetString("APKPublishers", value); } | 
|         } | 
|   | 
|         List<ToggleData> m_ToggleData; | 
|         ToggleData m_ForceRebuild; | 
|         ToggleData m_CopyToStreaming; | 
|         GUIContent m_TargetContent; | 
|         GUIContent m_CompressionContent; | 
|         public enum CompressOptions | 
|         { | 
|             Uncompressed = 0, | 
|             StandardCompression, | 
|             ChunkBasedCompression, | 
|         } | 
|         GUIContent[] m_CompressionOptions = | 
|         { | 
|             new GUIContent("No Compression"), | 
|             new GUIContent("Standard Compression (LZMA)"), | 
|             new GUIContent("Chunk Based Compression (LZ4)") | 
|         }; | 
|         int[] m_CompressionValues = { 0, 1, 2 }; | 
|   | 
|         int rechargeSkin = 1; | 
|         string createRoleLevel = "001"; | 
|   | 
|         public AssetBundleBuildTab() | 
|         { | 
|             m_AdvancedSettings = false; | 
|             m_UserData = new BuildTabData(); | 
|             m_UserData.m_OnToggles = new List<string>(); | 
|             m_UserData.m_UseDefaultPath = true; | 
|         } | 
|   | 
|         public void OnDisable() | 
|         { | 
|             var dataPath = System.IO.Path.GetFullPath("."); | 
|             dataPath = dataPath.Replace("\\", "/"); | 
|             dataPath += "/Library/AssetBundleBrowserBuild.dat"; | 
|   | 
|             BinaryFormatter bf = new BinaryFormatter(); | 
|             FileStream file = File.Create(dataPath); | 
|   | 
|             bf.Serialize(file, m_UserData); | 
|             file.Close(); | 
|   | 
|         } | 
|         public void OnEnable(Rect pos, EditorWindow parent) | 
|         { | 
|   | 
|             //LoadData... | 
|             var dataPath = System.IO.Path.GetFullPath("."); | 
|             dataPath = dataPath.Replace("\\", "/"); | 
|             dataPath += "/Library/AssetBundleBrowserBuild.dat"; | 
|   | 
|             if (File.Exists(dataPath)) | 
|             { | 
|                 BinaryFormatter bf = new BinaryFormatter(); | 
|                 FileStream file = File.Open(dataPath, FileMode.Open); | 
|                 var data = bf.Deserialize(file) as BuildTabData; | 
|                 if (data != null) | 
|                     m_UserData = data; | 
|                 file.Close(); | 
|             } | 
|   | 
|             m_ToggleData = new List<ToggleData>(); | 
|             m_ToggleData.Add(new ToggleData( | 
|                 false, | 
|                 "Exclude Type Information", | 
|                 "不包含类型信息。发布web平台时,不能使用该选项。", | 
|                 m_UserData.m_OnToggles, | 
|                 BuildAssetBundleOptions.DisableWriteTypeTree)); | 
|             m_ToggleData.Add(new ToggleData( | 
|                 false, | 
|                 "Force Rebuild", | 
|                 "强制重新build所有ab包。", | 
|                 m_UserData.m_OnToggles, | 
|                 BuildAssetBundleOptions.ForceRebuildAssetBundle)); | 
|             m_ToggleData.Add(new ToggleData( | 
|                 false, | 
|                 "Ignore Type Tree Changes", | 
|                 "忽略typetree的变化,不能与DisableWriteTypeTree同时使用。", | 
|                 m_UserData.m_OnToggles, | 
|                 BuildAssetBundleOptions.IgnoreTypeTreeChanges)); | 
|             m_ToggleData.Add(new ToggleData( | 
|                 false, | 
|                 "Append Hash", | 
|                 "附加hash到assetbundle名字中。", | 
|                 m_UserData.m_OnToggles, | 
|                 BuildAssetBundleOptions.AppendHashToAssetBundleName)); | 
|             m_ToggleData.Add(new ToggleData( | 
|                 false, | 
|                 "Strict Mode", | 
|                 "使用严格模式build ab, 有任何非致命的error都不会build成功。", | 
|                 m_UserData.m_OnToggles, | 
|                 BuildAssetBundleOptions.StrictMode)); | 
|             m_ToggleData.Add(new ToggleData( | 
|                 false, | 
|                 "Dry Run Build", | 
|                 "Do a dry run build.", | 
|                 m_UserData.m_OnToggles, | 
|                 BuildAssetBundleOptions.DryRunBuild)); | 
|   | 
|   | 
|             m_ForceRebuild = new ToggleData( | 
|                 false, | 
|                 "Rebuild", | 
|                 "选中后会清空所有旧的资源,全部重新打包(建议测试时不勾选可加快打包速度)", | 
|                 m_UserData.m_OnToggles); | 
|             m_CopyToStreaming = new ToggleData( | 
|                 false, | 
|                 "Copy to StreamingAssets", | 
|                 "资源打包完成后,会将所有资源拷贝至:" + m_streamingPath + " for use in stand-alone player.", | 
|                 m_UserData.m_OnToggles); | 
|   | 
|             m_TargetContent = new GUIContent("Build Target", "Choose target platform to build for."); | 
|             m_CompressionContent = new GUIContent("Compression", "Choose no compress, standard (LZMA), or chunk based (LZ4)"); | 
|   | 
|             if (m_UserData.m_UseDefaultPath) | 
|             { | 
|                 ResetPathToDefault(); | 
|             } | 
|         } | 
|   | 
|         public void OnGUI(Rect pos) | 
|         { | 
|             m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition); | 
|             bool newState = false; | 
|             var centeredStyle = GUI.skin.GetStyle("Label"); | 
|             centeredStyle.alignment = TextAnchor.UpperCenter; | 
|             GUILayout.Label(new GUIContent("Example build setup"), centeredStyle); | 
|             //basic options | 
|             EditorGUILayout.Space(); | 
|             GUILayout.BeginVertical(); | 
|   | 
|             // build target | 
|             using (new EditorGUI.DisabledScope(!AssetBundleModel.Model.DataSource.CanSpecifyBuildTarget)) | 
|             { | 
|                 ValidBuildTarget tgt = (ValidBuildTarget)EditorGUILayout.EnumPopup(m_TargetContent, m_UserData.m_BuildTarget); | 
|                 if (tgt != m_UserData.m_BuildTarget) | 
|                 { | 
|                     m_UserData.m_BuildTarget = tgt; | 
|                     if (m_UserData.m_UseDefaultPath) | 
|                     { | 
|                         m_UserData.m_OutputPath = "AssetBundles/"; | 
|                         m_UserData.m_OutputPath += m_UserData.m_BuildTarget.ToString(); | 
|                         //EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath); | 
|                     } | 
|                 } | 
|             } | 
|   | 
|   | 
|             ////output path | 
|             using (new EditorGUI.DisabledScope(!AssetBundleModel.Model.DataSource.CanSpecifyBuildOutputDirectory)) | 
|             { | 
|                 EditorGUILayout.Space(); | 
|                 GUILayout.BeginHorizontal(); | 
|                 var newPath = EditorGUILayout.TextField("Output Path", m_UserData.m_OutputPath); | 
|                 if ((newPath != m_UserData.m_OutputPath) && | 
|                      (newPath != string.Empty)) | 
|                 { | 
|                     m_UserData.m_UseDefaultPath = false; | 
|                     m_UserData.m_OutputPath = newPath; | 
|                     //EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath); | 
|                 } | 
|                 GUILayout.EndHorizontal(); | 
|                 GUILayout.BeginHorizontal(); | 
|                 GUILayout.FlexibleSpace(); | 
|                 if (GUILayout.Button("Browse", GUILayout.MaxWidth(75f))) | 
|                     BrowseForFolder(); | 
|                 if (GUILayout.Button("Reset", GUILayout.MaxWidth(75f))) | 
|                     ResetPathToDefault(); | 
|                 //if (string.IsNullOrEmpty(m_OutputPath)) | 
|                 //    m_OutputPath = EditorUserBuildSettings.GetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath"); | 
|                 GUILayout.EndHorizontal(); | 
|                 EditorGUILayout.Space(); | 
|   | 
|                 newState = GUILayout.Toggle( | 
|                     m_ForceRebuild.state, | 
|                     m_ForceRebuild.content); | 
|                 if (newState != m_ForceRebuild.state) | 
|                 { | 
|                     if (newState) | 
|                         m_UserData.m_OnToggles.Add(m_ForceRebuild.content.text); | 
|                     else | 
|                         m_UserData.m_OnToggles.Remove(m_ForceRebuild.content.text); | 
|                     m_ForceRebuild.state = newState; | 
|                 } | 
|                 newState = GUILayout.Toggle( | 
|                     m_CopyToStreaming.state, | 
|                     m_CopyToStreaming.content); | 
|                 if (newState != m_CopyToStreaming.state) | 
|                 { | 
|                     if (newState) | 
|                         m_UserData.m_OnToggles.Add(m_CopyToStreaming.content.text); | 
|                     else | 
|                         m_UserData.m_OnToggles.Remove(m_CopyToStreaming.content.text); | 
|                     m_CopyToStreaming.state = newState; | 
|                 } | 
|             } | 
|   | 
|             // advanced options | 
|             using (new EditorGUI.DisabledScope(!AssetBundleModel.Model.DataSource.CanSpecifyBuildOptions)) | 
|             { | 
|                 EditorGUILayout.Space(); | 
|                 m_AdvancedSettings = EditorGUILayout.Foldout(m_AdvancedSettings, "Advanced Settings"); | 
|                 if (m_AdvancedSettings) | 
|                 { | 
|                     var indent = EditorGUI.indentLevel; | 
|                     EditorGUI.indentLevel = 1; | 
|                     CompressOptions cmp = (CompressOptions)EditorGUILayout.IntPopup( | 
|                         m_CompressionContent, | 
|                         (int)m_UserData.m_Compression, | 
|                         m_CompressionOptions, | 
|                         m_CompressionValues); | 
|   | 
|                     if (cmp != m_UserData.m_Compression) | 
|                     { | 
|                         m_UserData.m_Compression = cmp; | 
|                     } | 
|                     foreach (var tog in m_ToggleData) | 
|                     { | 
|                         newState = EditorGUILayout.ToggleLeft( | 
|                             tog.content, | 
|                             tog.state); | 
|                         if (newState != tog.state) | 
|                         { | 
|   | 
|                             if (newState) | 
|                                 m_UserData.m_OnToggles.Add(tog.content.text); | 
|                             else | 
|                                 m_UserData.m_OnToggles.Remove(tog.content.text); | 
|                             tog.state = newState; | 
|                         } | 
|                     } | 
|                     EditorGUILayout.Space(); | 
|                     EditorGUI.indentLevel = indent; | 
|                 } | 
|             } | 
|             if (GUILayout.Button("HybridclrBuild(不能热更)")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildHybridclrBuild; | 
|             } | 
|             // build. | 
|             EditorGUILayout.Space(); | 
|             if (GUILayout.Button("Build All Assets")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteBuildAll; | 
|             } | 
|   | 
|             EditorGUILayout.BeginHorizontal(); | 
|   | 
|             if (GUILayout.Button("Config")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildConfig; | 
|             } | 
|   | 
|             if (GUILayout.Button("UI")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildUI; | 
|             } | 
|   | 
|             if (GUILayout.Button("BuiltIn")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildBuiltIn; | 
|             } | 
|   | 
|             if (GUILayout.Button("Audio")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildAudio; | 
|             } | 
|   | 
|             if (GUILayout.Button("Video")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildVideo; | 
|             } | 
|   | 
|             if (GUILayout.Button("Levels")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildLevels; | 
|             } | 
|   | 
|             if (GUILayout.Button("MobEffectShader")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildMobEffectShader; | 
|             }  | 
|   | 
|             if (GUILayout.Button("HybridclrUpdate")) | 
|             { | 
|                 EditorApplication.delayCall += ExcuteBuildHybridclrUpdate; | 
|             } | 
|             EditorGUILayout.EndHorizontal(); | 
|   | 
|             EditorGUILayout.Space(); | 
|   | 
|   | 
|             EditorGUILayout.Space(); | 
|   | 
|             EditorGUILayout.BeginHorizontal(); | 
|   | 
|             if (GUILayout.Button("Make VersionFile")) | 
|             { | 
|                 EditorApplication.delayCall += MakeAssetsVersionFile; | 
|             } | 
|   | 
|             if (GUILayout.Button("Copy to StreamingAssets")) | 
|             { | 
|                 EditorApplication.delayCall += CopyToStreamingAssets; | 
|             } | 
|   | 
|             EditorGUILayout.EndHorizontal(); | 
|   | 
|             EditorGUILayout.Space(); | 
|             EditorGUILayout.Space(); | 
|             EditorGUILayout.Space(); | 
| #if UNITY_ANDROID | 
|             GUILayout.BeginHorizontal(); | 
|             EditorGUILayout.TextField("Apk Output Path", ApkOutputPath); | 
|             if (GUILayout.Button("Browse", GUILayout.MaxWidth(75f))) | 
|             { | 
|                 BrowseForApkOutput(); | 
|             } | 
|             GUILayout.EndHorizontal(); | 
|   | 
|             EditorGUILayout.Space(); | 
| #endif | 
|   | 
| #if UNITY_STANDALONE | 
|             GUILayout.BeginHorizontal(); | 
|             EditorGUILayout.TextField("EXE Output Path", ApkOutputPath); | 
|             if (GUILayout.Button("Browse", GUILayout.MaxWidth(75f))) | 
|             { | 
|                 BrowseForApkOutput(); | 
|             } | 
|             GUILayout.EndHorizontal(); | 
|   | 
|             EditorGUILayout.Space(); | 
| #endif | 
|   | 
|             GUILayout.BeginHorizontal(); | 
|             EditorGUILayout.TextField("SDK Project Path", ClientPackage.SDK_PLUGIN_PROJECT); | 
|             if (GUILayout.Button("Browse", GUILayout.MaxWidth(75f))) | 
|             { | 
|                 BrowseForSDKProject(); | 
|             } | 
|             GUILayout.EndHorizontal(); | 
|   | 
|             EditorGUILayout.Space(); | 
|   | 
| #if UNITY_IOS | 
|             ClientPackage.auditOutTime = EditorGUILayout.TextField("AppStore OutTime", ClientPackage.auditOutTime, GUILayout.Height(20)); | 
|             EditorGUILayout.Space(); | 
| #endif | 
|             GUILayout.BeginHorizontal(); | 
|   | 
|             ClientPackage.AssetPrior = EditorGUILayout.IntField("AssetPrior", ClientPackage.AssetPrior, GUILayout.Height(50), GUILayout.Width(250)); | 
|             publishers = EditorGUILayout.TextField("Publishers", publishers, GUILayout.Height(50)); | 
|             GUILayout.EndHorizontal(); | 
|   | 
|             EditorGUILayout.Space(); | 
|             GUILayout.BeginHorizontal(); | 
|   | 
|             ClientPackage.includeConfig = EditorGUILayout.Toggle("Include Config ", ClientPackage.includeConfig, GUILayout.Width(250)); | 
|             ClientPackage.includeUI = EditorGUILayout.Toggle("Include UI ", ClientPackage.includeUI, GUILayout.Width(250)); | 
|   | 
|             GUILayout.EndHorizontal(); | 
|             EditorGUILayout.Space(); | 
|             GUILayout.BeginHorizontal(); | 
|   | 
|             ClientPackage.obfuscatorEnabled = EditorGUILayout.Toggle("Obfuscator Enable ", ClientPackage.obfuscatorEnabled, GUILayout.Width(250)); | 
|   | 
| #if UNITY_STANDALONE | 
|             if (GUILayout.Button("EXE")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteBuildClientPackageStandalone; | 
|             } | 
| #elif UNITY_ANDROID | 
|             if (GUILayout.Button("APK")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteBuildClientPackageApk; | 
|             } | 
| #elif UNITY_IOS | 
|             if (GUILayout.Button("IPA_Append ")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteBuildClientPackageIpaAppend; | 
|             } | 
| #endif | 
|   | 
| #if UNITY_STANDALONE | 
|             if (GUILayout.Button("EXE Development ")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteBuildClientPackageStandaloneDevelopment; | 
|             } | 
| #elif UNITY_ANDROID | 
|             if (GUILayout.Button("APK Development")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteBuildClientPackageDevelopApk; | 
|             } | 
| #elif UNITY_IOS | 
|             if (GUILayout.Button("IPA_Replace")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteBuildClientPackageIpaReplace; | 
|             } | 
| #endif | 
|   | 
|             GUILayout.EndHorizontal(); | 
|   | 
|             GUILayout.Space(20); | 
|             if (GUILayout.Button("SwitchVersionConfig")) | 
|             { | 
|                 EditorApplication.delayCall += ExecuteSwitchVersionConfig; | 
|             } | 
|   | 
|             GUILayout.Space(20); | 
|             GUILayout.BeginHorizontal(); | 
|             rechargeSkin = EditorGUILayout.IntField("Recharge Skin", rechargeSkin, GUILayout.Width(250)); | 
|             if (GUILayout.Button("Switch")) | 
|             { | 
|                 UpdateSpriteSetting.SetRechargeSkin(rechargeSkin); | 
|                 AssetDatabase.Refresh(); | 
|                 UpdateSpritePackingSetting.UpdateAllSpritePackingSetting(); | 
|             } | 
|   | 
|             createRoleLevel = EditorGUILayout.TextField("CreateRole Level", createRoleLevel, GUILayout.Width(250)); | 
|             if (GUILayout.Button("Switch")) | 
|             { | 
|                 UpdateLevelSetting.SetCreateRoleLevel(createRoleLevel); | 
|                 AssetDatabase.Refresh(); | 
|             } | 
|             GUILayout.EndHorizontal(); | 
|   | 
|             GUILayout.EndVertical(); | 
|             EditorGUILayout.EndScrollView(); | 
|         } | 
|   | 
|         private void CopyToStreamingAssets() | 
|         { | 
|             if (Directory.Exists(m_streamingPath)) | 
|                 Directory.Delete(m_streamingPath, true); | 
|             DirectoryCopy(m_UserData.m_OutputPath, m_streamingPath); | 
|         } | 
|   | 
|         private void ExecuteBuildAll() | 
|         { | 
|   | 
|             if (AssetBundleModel.Model.DataSource.CanSpecifyBuildOutputDirectory) | 
|             { | 
|                 if (string.IsNullOrEmpty(m_UserData.m_OutputPath)) | 
|                 { | 
|                     BrowseForFolder(); | 
|                 } | 
|   | 
|                 if (string.IsNullOrEmpty(m_UserData.m_OutputPath)) //in case they hit "cancel" on the open browser | 
|                 { | 
|                     Debug.LogError("AssetBundle Build: No valid output path for build."); | 
|                     return; | 
|                 } | 
|   | 
|                 if (m_ForceRebuild.state) | 
|                 { | 
|                     try | 
|                     { | 
|                         if (Directory.Exists(m_UserData.m_OutputPath)) | 
|                         { | 
|                             Directory.Delete(m_UserData.m_OutputPath, true); | 
|                         } | 
|   | 
|                         if (m_CopyToStreaming.state) | 
|                         { | 
|                             if (Directory.Exists(m_streamingPath)) | 
|                             { | 
|                                 Directory.Delete(m_streamingPath, true); | 
|                             } | 
|                         } | 
|                     } | 
|                     catch (System.Exception e) | 
|                     { | 
|                         Debug.LogException(e); | 
|                     } | 
|                 } | 
|   | 
|                 if (!Directory.Exists(m_UserData.m_OutputPath)) | 
|                 { | 
|                     Directory.CreateDirectory(m_UserData.m_OutputPath); | 
|                 } | 
|             } | 
|   | 
|             ExcuteBuildAudio(); | 
|             ExcuteBuildVideo(); | 
|             ExcuteBuildMobEffectShader(); | 
|             ExcuteBuildConfig(); | 
|             ExcuteBuildLevels(); | 
|             ExcuteBuildUI(); | 
|             ExcuteBuildBuiltIn(); | 
|             ExcuteBuildHybridclrUpdate(); | 
|   | 
|             AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); | 
|   | 
|             MakeAssetsVersionFile(); | 
|   | 
|             if (m_CopyToStreaming.state) | 
|             { | 
|                 if (Directory.Exists(m_streamingPath)) | 
|                     Directory.Delete(m_streamingPath, true); | 
|                 DirectoryCopy(m_UserData.m_OutputPath, m_streamingPath); | 
|             } | 
|         } | 
|   | 
|         private void ExcuteBuildAsset(string _category, bool uncompressed = false) | 
|         { | 
|             BuildAssetBundleOptions opt = BuildAssetBundleOptions.None; | 
|             if (AssetBundleModel.Model.DataSource.CanSpecifyBuildOptions) | 
|             { | 
|                 if (m_UserData.m_Compression == CompressOptions.Uncompressed || uncompressed) | 
|                 { | 
|                     opt |= BuildAssetBundleOptions.UncompressedAssetBundle; | 
|                 } | 
|                 else if (m_UserData.m_Compression == CompressOptions.ChunkBasedCompression) | 
|                 { | 
|                     opt |= BuildAssetBundleOptions.ChunkBasedCompression; | 
|                 } | 
|   | 
|                 opt |= BuildAssetBundleOptions.DeterministicAssetBundle; | 
|   | 
|                 foreach (var tog in m_ToggleData) | 
|                 { | 
|                     if (tog.state) | 
|                     { | 
|                         opt |= tog.option; | 
|                     } | 
|                 } | 
|             } | 
|   | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             AssetBundleBuildExtersion.Build(outputPath, _category, opt, (BuildTarget)m_UserData.m_BuildTarget, m_ForceRebuild.state); | 
|         } | 
|   | 
|         private void ExcuteBuildBuiltIn() | 
|         { | 
|             BuiltInResourceSetting.SetLaunchBackGround(publishers.Split('|')[0], (BuildTarget)m_UserData.m_BuildTarget); | 
|             BuiltInResourceSetting.SetLoginBackGround(publishers.Split('|')[0], (BuildTarget)m_UserData.m_BuildTarget); | 
|             BuiltInResourceSetting.SetLoginLogo(publishers.Split('|')[0], (BuildTarget)m_UserData.m_BuildTarget); | 
|             UpdateBuiltInSetting.SetBuiltinAssetBundleName(); | 
|             ExcuteBuildAsset("builtin"); | 
|         } | 
|   | 
|         private void ExcuteBuildAudio() | 
|         { | 
|             UpdateAudioSetting.SetAllAudioAssetBundleName(); | 
|             ExcuteBuildAsset("audio"); | 
|         } | 
|   | 
|         private void ExcuteBuildVideo() | 
|         { | 
|             UpdateVideoSetting.SetAllVideoAssetBundleName(); | 
|             ExcuteBuildAsset("video"); | 
|         } | 
|   | 
|         private void ExcuteBuildMobEffectShader() | 
|         { | 
|             UpdateEffectPrefabSetting.SetAllEffectPrefabAssetBundleName(); | 
|             UpdateMobSetting.SetAllMobAssetBundleName(); | 
|             UpdateShaderSetting.SetAllShaderAssetBundleName(); | 
|             ExcuteBuildAsset("mobeffectshader"); | 
|         } | 
|   | 
|         private void ExcuteBuildConfig() | 
|         { | 
|             UpdateScriptableObjectsSetting.SetAllScriptableObjectAssetBundleName(); | 
|             ExcuteBuildAsset("config"); | 
|             TableTool.CopyConfigsToOutPutPath(StringUtility.Contact(m_UserData.m_OutputPath, "/config")); | 
|         } | 
|         //发包时获取热更dll和裁剪AOT | 
|         private void ExcuteBuildHybridclrBuild() | 
|         { | 
|             //重新生成热更dll和裁剪AOT | 
|             PrebuildCommand.GenerateAll(); | 
|             // 输出到AssetBundles目录 | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             outputPath = StringUtility.Contact(outputPath, "/logicbytes"); | 
|             if (Directory.Exists(outputPath)) | 
|                 Directory.Delete(outputPath, true); | 
|             //复制新生成的AOT dll到指定路径 | 
|             CopyAOTDataDll(outputPath); | 
|             //复制热更dll到指定路径 | 
|             CopyHotUpdateDll(outputPath); | 
|             AssetDatabase.Refresh(); | 
|         } | 
|         //热更新时获取热更dll | 
|         private void ExcuteBuildHybridclrUpdate() | 
|         { | 
|             //生成热更dll | 
|             CompileDllCommand.CompileDll(EditorUserBuildSettings.activeBuildTarget); | 
|             //判断当前的dll有没有使用了被裁剪的aot dll | 
|             if (IsAccessMissingMetadata()) | 
|             { | 
|                 DebugEx.LogError("当前热更代码使用了被裁剪的aot dll,请使用HybridclrBuild重新生成,重新出包"); | 
|                 return; | 
|             } | 
|             // 输出到AssetBundles目录 | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             outputPath = StringUtility.Contact(outputPath, "/logicbytes"); | 
|             CopyHotUpdateDll(outputPath); | 
|             MakeBytesVersionFile(); | 
|             AssetDatabase.Refresh(); | 
|         } | 
|   | 
|         private void MakeBytesVersionFile() | 
|         { | 
|             var fileInfos = new List<FileInfo>(); | 
|             FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(m_UserData.m_OutputPath, "/logicbytes"), fileInfos); | 
|             BytesVersionMaker.WriteAssetsVersionFile(Path.Combine(Directory.GetParent(Application.dataPath).FullName, m_UserData.m_OutputPath), fileInfos); | 
|             Debug.Log("热更新代码更新完毕,生成md5文件"); | 
|         } | 
|   | 
|         //复制裁剪AOT到指定目录 | 
|         void CopyAOTDataDll(string outputPath) | 
|         { | 
|             //项目根目录 | 
|             string rootDir = Directory.GetParent(Application.dataPath).FullName.Replace(@"\", @"/"); | 
|             //当前构建的平台名称 | 
|             string platformName = "/" + EditorUserBuildSettings.activeBuildTarget + "/"; | 
|             //上次出包时使用的AOT所在路径 | 
|             string checkAotDir = rootDir + "/HybridCLRData/CheckAssembliesPostIl2CppStrip" + platformName; | 
|             //HybridCLR Settings面板上设置的裁减后AOT dll输出根目录 | 
|             string strippedAOTDllOutputRootDir = "/" + HybridCLRSettings.Instance.strippedAOTDllOutputRootDir; | 
|             //重新生成的AOT所在路径 | 
|             string aotDir = StringUtility.Contact(rootDir, strippedAOTDllOutputRootDir, platformName); | 
|   | 
|             if (Directory.Exists(checkAotDir)) | 
|             { | 
|                 Directory.Delete(checkAotDir, true); | 
|                 Directory.CreateDirectory(checkAotDir); | 
|             } | 
|             //复制一份出包时使用的AOT | 
|             CopyDirectoryToPath(aotDir, checkAotDir); | 
|   | 
|             for (int i = 0; i < AOTGenericReferences.PatchedAOTAssemblyList.Count; i++) | 
|             { | 
|                 string dllFile = StringUtility.Contact(aotDir, AOTGenericReferences.PatchedAOTAssemblyList[i]); | 
|                 var outDllFile = outputPath + "/" + AOTGenericReferences.PatchedAOTAssemblyList[i] + ".bytes"; | 
|                 if (!File.Exists(dllFile)) | 
|                 { | 
|                     DebugEx.LogErrorFormat("错误:{0} 不存在", dllFile); | 
|                     return; | 
|                 } | 
|   | 
|                 FileExtersion.MakeSureDirectory(outDllFile); | 
|                 File.Copy(dllFile, outDllFile, true); | 
|             } | 
|         } | 
|   | 
|         //复制热更dll到指定目录 | 
|         void CopyHotUpdateDll(string outputPath) | 
|         { | 
|             //项目根目录 | 
|             string rootDir = Directory.GetParent(Application.dataPath).FullName.Replace(@"\", @"/"); | 
|             //当前构建的平台名称 | 
|             string platformName = "/" + EditorUserBuildSettings.activeBuildTarget + "/"; | 
|             //HybridCLR Settings面板上设置的热更新dll编译输出根目录 | 
|             string hotUpdateDllCompileOutputRootDir = "/" + HybridCLRSettings.Instance.hotUpdateDllCompileOutputRootDir; | 
|             //热更DLL生成目录 | 
|             string hotDllDir = StringUtility.Contact(rootDir, hotUpdateDllCompileOutputRootDir, platformName); | 
|             //HybridCLR的Settings面板上设置的热更新Assembly Definitions 资源 | 
|             var assemblyDefinitionAsset = HybridCLRSettings.Instance.hotUpdateAssemblyDefinitions; | 
|             for (int i = 0; i < assemblyDefinitionAsset.Length; i++) | 
|             { | 
|                 string assemblyPath = AssetDatabase.GetAssetPath(assemblyDefinitionAsset[i]); | 
|                 string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); | 
|   | 
|                 string dllFile = StringUtility.Contact(hotDllDir, assemblyName, ".dll"); | 
|                 var outDllFile = outputPath + "/" + assemblyName + ".dll.bytes"; | 
|                 if (!File.Exists(dllFile)) | 
|                 { | 
|                     DebugEx.LogErrorFormat("错误:{0} 不存在", dllFile); | 
|                     return; | 
|                 } | 
|                 FileExtersion.MakeSureDirectory(outDllFile); | 
|                 File.Copy(dllFile, outDllFile, true); | 
|             } | 
|   | 
|             //HybridCLR的Settings面板上设置的要热更的DLL资源 | 
|             string[] hotUpdateAssemblies = HybridCLRSettings.Instance.hotUpdateAssemblies; | 
|             for (int i = 0; i < hotUpdateAssemblies.Length; i++) | 
|             { | 
|                 string dllFile = StringUtility.Contact(hotDllDir, hotUpdateAssemblies[i], ".dll"); | 
|                 var outDllFile = outputPath + "/" + hotUpdateAssemblies[i] + ".dll.bytes"; | 
|                 if (!File.Exists(dllFile)) | 
|                 { | 
|                     DebugEx.LogErrorFormat("错误:{0} 不存在", dllFile); | 
|                     return; | 
|                 } | 
|                 FileExtersion.MakeSureDirectory(outDllFile); | 
|                 File.Copy(dllFile, outDllFile, true); | 
|             } | 
|   | 
|             //HybridCLR的Settings面板上设置的预留的热更新dlls | 
|             string[] preserveHotUpdateAssemblies = HybridCLRSettings.Instance.preserveHotUpdateAssemblies; | 
|             for (int i = 0; i < preserveHotUpdateAssemblies.Length; i++) | 
|             { | 
|                 string dllFile = StringUtility.Contact(hotDllDir, preserveHotUpdateAssemblies[i], ".dll"); | 
|                 var outDllFile = outputPath + "/" + preserveHotUpdateAssemblies[i] + ".dll.bytes"; | 
|                 if (!File.Exists(dllFile)) | 
|                 { | 
|                     DebugEx.LogWarningFormat("警告:预留的热更新dll: {0} 不存在", dllFile); | 
|                     continue; | 
|                 } | 
|                 FileExtersion.MakeSureDirectory(outDllFile); | 
|                 File.Copy(dllFile, outDllFile, true); | 
|             } | 
|         } | 
|   | 
|         //检查目标文件夹下是否有文件 | 
|         bool IsFolderNotEmpty(string dir) | 
|         { | 
|             if (Directory.Exists(dir)) | 
|             { | 
|                 string[] files = Directory.GetFiles(dir); | 
|                 if (files.Length > 0) | 
|                     return true; | 
|             } | 
|             return false; | 
|         } | 
|   | 
|         //检查热更新代码中是否引用了被裁剪的类型或函数 | 
|         bool IsAccessMissingMetadata() | 
|         { | 
|             //项目根目录 | 
|             string rootDir = Directory.GetParent(Application.dataPath).FullName.Replace(@"\", @"/"); | 
|             //当前构建的平台名称 | 
|             BuildTarget target = EditorUserBuildSettings.activeBuildTarget; | 
|             string platformName = "/" + target + "/"; | 
|             //上次出包时使用的AOT所在路径 | 
|             string checkAotDir = rootDir + "/HybridCLRData/CheckAssembliesPostIl2CppStrip" + platformName; | 
|   | 
|             //上次打包时保存的AOT所在文件夹不存在或没有dll文件 | 
|             if (!IsFolderNotEmpty(checkAotDir)) | 
|                 return true; | 
|             var checker = new MissingMetadataChecker(checkAotDir, new List<string>()); | 
|             string hotUpdateDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target); | 
|             for (int i = 0; i < SettingsUtil.HotUpdateAssemblyFilesExcludePreserved.Count; i++) | 
|             { | 
|                 string dllPath = hotUpdateDir + "/" + SettingsUtil.HotUpdateAssemblyFilesExcludePreserved[i]; | 
|                 bool notAnyMissing = checker.Check(dllPath); | 
|                 if (!notAnyMissing) | 
|                 { | 
|                     return true; | 
|                 } | 
|             } | 
|             return false; | 
|         } | 
|         private void CopyDirectoryToPath(string sourceDir, string destinationDir) | 
|         { | 
|             // 如果目标路径不存在,则创建它 | 
|             if (!Directory.Exists(destinationDir)) | 
|                 Directory.CreateDirectory(destinationDir); | 
|             // 获取所有文件并复制 | 
|             string[] files = Directory.GetFiles(sourceDir); | 
|             for (int i = 0; i < files.Length; i++) | 
|             { | 
|                 string dest = Path.Combine(destinationDir, Path.GetFileName(files[i])); | 
|                 File.Copy(files[i], dest, true); // true表示如果目标存在,则覆盖 | 
|             } | 
|         } | 
|   | 
|         private void ExcuteBuildLevels() | 
|         { | 
|             UpdateLevelSetting.SetAllLevelAssetBundleName(); | 
|             ExcuteBuildAsset("maps"); | 
|         } | 
|   | 
|         private void ExcuteBuildUI() | 
|         { | 
|             AssetSource.allFromEditor = true; | 
|             //CheckFontSwitch.CheckAndReplaceFontSwitch(); | 
|             UpdateUIPrefabSetting.SetAllUIPrefabAssetBundleName(); | 
|             UpdateUIWindowSetting.SetAllUIWindowAssetBundleName(); | 
|             UpdateSpriteSetting.SetAllSpriteAssetBundleName(); | 
|             ExcuteBuildAsset("ui"); | 
|         } | 
|   | 
|         private void SetAssetsVersion() | 
|         { | 
|             var fileInfos = new List<FileInfo>(); | 
|             FileExtersion.GetAllDirectoryFileInfos(m_UserData.m_OutputPath, fileInfos); | 
|             for (int i = 0; i < fileInfos.Count; i++) | 
|             { | 
|                 var fileInfo = fileInfos[i]; | 
|                 var fullName = FileExtersion.RemoveVersionFromFileFullName(fileInfo.FullName); | 
|                 var newFullName = FileExtersion.AddVersionToFileFullName(fullName, m_Version); | 
|                 if (fullName != newFullName) | 
|                 { | 
|                     File.Copy(fullName, newFullName, true); | 
|                     File.Delete(fullName); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         private void RemoveAssetsVersion() | 
|         { | 
|             var fileInfos = new List<FileInfo>(); | 
|             FileExtersion.GetAllDirectoryFileInfos(m_UserData.m_OutputPath, fileInfos); | 
|             for (int i = 0; i < fileInfos.Count; i++) | 
|             { | 
|                 var fileInfo = fileInfos[i]; | 
|                 var fullName = FileExtersion.RemoveVersionFromFileFullName(fileInfo.FullName); | 
|                 if (fullName != fileInfo.FullName) | 
|                 { | 
|                     File.Copy(fileInfo.FullName, fullName, true); | 
|                     File.Delete(fileInfo.FullName); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         private void MakeAssetsVersionFile() | 
|         { | 
|             var fileInfos = new List<FileInfo>(); | 
|             FileExtersion.GetAllDirectoryFileInfos(m_UserData.m_OutputPath, fileInfos); | 
|             AssetsVersionMaker.WriteAssetsVersionFile(Path.Combine(Directory.GetParent(Application.dataPath).FullName, m_UserData.m_OutputPath), fileInfos); | 
|             Debug.Log("生成AssetsVersion.txt文件完毕"); | 
|         } | 
|   | 
|         static int packageIndex | 
|         { | 
|             get { return LocalSave.GetInt("ClientPackageIndex", 1); } | 
|             set { LocalSave.SetInt("ClientPackageIndex", value); } | 
|         } | 
|   | 
|         private void ExecuteBuildClientPackageIpaAppend() | 
|         { | 
|             packageIndex++; | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             ClientPackage.BuildPublishers(ClientPackage.SDK_PLUGIN_PROJECT, outputPath, ApkOutputPath, publishers, packageIndex, false, false); | 
|         } | 
|   | 
|         private void ExecuteBuildClientPackageIpaReplace() | 
|         { | 
|             packageIndex++; | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             ClientPackage.BuildPublishers(ClientPackage.SDK_PLUGIN_PROJECT, outputPath, ApkOutputPath, publishers, packageIndex, false, true); | 
|         } | 
|   | 
|         private void ExecuteBuildClientPackageApk() | 
|         { | 
|             packageIndex++; | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             ClientPackage.BuildPublishers(ClientPackage.SDK_PLUGIN_PROJECT, outputPath, ApkOutputPath, publishers, packageIndex, false, false); | 
|         } | 
|   | 
|         private void ExecuteBuildClientPackageDevelopApk() | 
|         { | 
|             packageIndex++; | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             ClientPackage.BuildPublishers(ClientPackage.SDK_PLUGIN_PROJECT, outputPath, ApkOutputPath, publishers, packageIndex, true, false); | 
|         } | 
|   | 
|         private void ExecuteBuildClientPackageStandalone() | 
|         { | 
|             packageIndex++; | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             ClientPackage_Standalone.Build(new ClientPackage_Standalone.BuildParams() | 
|             { | 
|                 assetBundle = outputPath, | 
|                 output = ApkOutputPath, | 
|                 buildIndex = packageIndex, | 
|                 development = false, | 
|                 publisher = publishers, | 
|             }); | 
|         } | 
|   | 
|         private void ExecuteBuildClientPackageStandaloneDevelopment() | 
|         { | 
|             packageIndex++; | 
|             var outputPath = Application.dataPath.Replace("Assets", m_UserData.m_OutputPath); | 
|             ClientPackage_Standalone.Build(new ClientPackage_Standalone.BuildParams() | 
|             { | 
|                 assetBundle = outputPath, | 
|                 output = ApkOutputPath, | 
|                 buildIndex = packageIndex, | 
|                 development = true, | 
|                 publisher = publishers, | 
|             }); | 
|         } | 
|   | 
|         private void ExecuteSwitchVersionConfig() | 
|         { | 
|             var newVersionConfigPath = StringUtility.Contact("Assets/Resources/ScriptableObject/Config/VersionConfig", ".asset"); | 
|             var versionsFilePath = Application.dataPath + Path.DirectorySeparatorChar + "Editor/VersionConfigs/Versions.txt"; | 
|   | 
|             var lines = File.ReadAllLines(versionsFilePath); | 
|             for (int i = 2; i < lines.Length; i++) | 
|             { | 
|                 var line = lines[i]; | 
|                 var lineStrings = line.Split('\t'); | 
|                 if (lineStrings[0] == publishers) | 
|                 { | 
|                     VersionConfig.Get().Read(line); | 
|                     break; | 
|                 } | 
|             } | 
|         } | 
|   | 
|         private static void DirectoryCopy(string sourceDirName, string destDirName, string excludeEx = null) | 
|         { | 
|             // Get the subdirectories for the specified directory. | 
|             DirectoryInfo dir = new DirectoryInfo(sourceDirName); | 
|   | 
|             // If the destination directory doesn't exist, create it. | 
|             if (!Directory.Exists(destDirName)) | 
|             { | 
|                 Directory.CreateDirectory(destDirName); | 
|             } | 
|   | 
|             // Get the files in the directory and copy them to the new location. | 
|             FileInfo[] files = dir.GetFiles(); | 
|             foreach (FileInfo file in files) | 
|             { | 
|                 string temppath = Path.Combine(destDirName, file.Name); | 
|                 if (excludeEx == null || file.Extension != excludeEx) | 
|                     file.CopyTo(temppath, false); | 
|             } | 
|   | 
|             DirectoryInfo[] dirs = dir.GetDirectories(); | 
|             foreach (DirectoryInfo subdir in dirs) | 
|             { | 
|                 string temppath = Path.Combine(destDirName, subdir.Name); | 
|                 DirectoryCopy(subdir.FullName, temppath); | 
|             } | 
|         } | 
|   | 
|         private void BrowseForFolder() | 
|         { | 
|             m_UserData.m_UseDefaultPath = false; | 
|             var newPath = EditorUtility.OpenFolderPanel("Bundle Folder", m_UserData.m_OutputPath, string.Empty); | 
|             if (!string.IsNullOrEmpty(newPath)) | 
|             { | 
|                 var gamePath = System.IO.Path.GetFullPath("."); | 
|                 gamePath = gamePath.Replace("\\", "/"); | 
|                 if (newPath.StartsWith(gamePath) && newPath.Length > gamePath.Length) | 
|                     newPath = newPath.Remove(0, gamePath.Length + 1); | 
|                 m_UserData.m_OutputPath = newPath; | 
|                 //EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath); | 
|             } | 
|         } | 
|   | 
|         private void BrowseForApkOutput() | 
|         { | 
|             var newPath = EditorUtility.OpenFolderPanel("Apk Folder", ApkOutputPath, string.Empty); | 
|             if (!string.IsNullOrEmpty(newPath)) | 
|             { | 
|                 var gamePath = System.IO.Path.GetFullPath("."); | 
|                 gamePath = gamePath.Replace("\\", "/"); | 
|                 if (newPath.StartsWith(gamePath) && newPath.Length > gamePath.Length) | 
|                     newPath = newPath.Remove(0, gamePath.Length + 1); | 
|                 ApkOutputPath = newPath; | 
|             } | 
|         } | 
|   | 
|         private void BrowseForSDKProject() | 
|         { | 
|             var newPath = EditorUtility.OpenFolderPanel("Apk Folder", ClientPackage.SDK_PLUGIN_PROJECT, string.Empty); | 
|             if (!string.IsNullOrEmpty(newPath)) | 
|             { | 
|                 var gamePath = System.IO.Path.GetFullPath("."); | 
|                 gamePath = gamePath.Replace("\\", "/"); | 
|                 if (newPath.StartsWith(gamePath) && newPath.Length > gamePath.Length) | 
|                     newPath = newPath.Remove(0, gamePath.Length + 1); | 
|                 ClientPackage.SDK_PLUGIN_PROJECT = newPath; | 
|             } | 
|         } | 
|   | 
|         private void ResetPathToDefault() | 
|         { | 
|             m_UserData.m_UseDefaultPath = true; | 
|             m_UserData.m_OutputPath = "AssetBundles/"; | 
|             m_UserData.m_OutputPath += m_UserData.m_BuildTarget.ToString(); | 
|             //EditorUserBuildSettings.SetPlatformSettings(EditorUserBuildSettings.activeBuildTarget.ToString(), "AssetBundleOutputPath", m_OutputPath); | 
|         } | 
|   | 
|         //Note: this is the provided BuildTarget enum with some entries removed as they are invalid in the dropdown | 
|         public enum ValidBuildTarget | 
|         { | 
|             //NoTarget = -2,        --doesn't make sense | 
|             //iPhone = -1,          --deprecated | 
|             //BB10 = -1,            --deprecated | 
|             //MetroPlayer = -1,     --deprecated | 
|             StandaloneOSXUniversal = 2, | 
|             StandaloneOSXIntel = 4, | 
|             StandaloneWindows = 5, | 
|             WebPlayer = 6, | 
|             WebPlayerStreamed = 7, | 
|             iOS = 9, | 
|             PS3 = 10, | 
|             XBOX360 = 11, | 
|             Android = 13, | 
|             StandaloneLinux = 17, | 
|             StandaloneWindows64 = 19, | 
|             WebGL = 20, | 
|             WSAPlayer = 21, | 
|             StandaloneLinux64 = 24, | 
|             StandaloneLinuxUniversal = 25, | 
|             WP8Player = 26, | 
|             StandaloneOSXIntel64 = 27, | 
|             BlackBerry = 28, | 
|             Tizen = 29, | 
|             PSP2 = 30, | 
|             PS4 = 31, | 
|             PSM = 32, | 
|             XboxOne = 33, | 
|             SamsungTV = 34, | 
|             N3DS = 35, | 
|             WiiU = 36, | 
|             tvOS = 37, | 
|             Switch = 38 | 
|         } | 
|   | 
|         [System.Serializable] | 
|         public class BuildTabData | 
|         { | 
|             public List<string> m_OnToggles; | 
|             public ValidBuildTarget m_BuildTarget = ValidBuildTarget.StandaloneWindows; | 
|             public CompressOptions m_Compression = CompressOptions.StandardCompression; | 
|             public string m_OutputPath = string.Empty; | 
|             public bool m_UseDefaultPath = true; | 
|         } | 
|     } | 
|   | 
| } |