diff --git a/Assets/TEngine/Editor/Resource.meta b/Assets/TEngine/Editor/Resource.meta
new file mode 100644
index 00000000..e836b2bd
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 88744e5c17541134884ec72227b3f36b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset.meta b/Assets/TEngine/Editor/Resource/YooAsset.meta
new file mode 100644
index 00000000..8ec971e3
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: be031d8b7b27267479e77a19628ac202
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder.meta b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder.meta
new file mode 100644
index 00000000..c1b5f4bc
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1fdecc5500229d44887425ce619352fc
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilder.cs b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilder.cs
new file mode 100644
index 00000000..88b82e0b
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilder.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class AssetBundleBuilder
+ {
+ private readonly BuildContext _buildContext = new BuildContext();
+
+ ///
+ /// 开始构建
+ ///
+ public BuildResult Run(BuildParameters buildParameters)
+ {
+ // 清空旧数据
+ _buildContext.ClearAllContext();
+
+ // 检测构建参数是否为空
+ if (buildParameters == null)
+ throw new Exception($"{nameof(buildParameters)} is null !");
+
+ // 检测可编程构建管线参数
+ if (buildParameters.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
+ {
+ if (buildParameters.SBPParameters == null)
+ throw new Exception($"{nameof(BuildParameters.SBPParameters)} is null !");
+
+ if (buildParameters.BuildMode == EBuildMode.DryRunBuild)
+ throw new Exception($"{nameof(EBuildPipeline.ScriptableBuildPipeline)} not support {nameof(EBuildMode.DryRunBuild)} build mode !");
+
+ if (buildParameters.BuildMode == EBuildMode.ForceRebuild)
+ throw new Exception($"{nameof(EBuildPipeline.ScriptableBuildPipeline)} not support {nameof(EBuildMode.ForceRebuild)} build mode !");
+ }
+
+ // 构建参数
+ var buildParametersContext = new BuildParametersContext(buildParameters);
+ _buildContext.SetContextObject(buildParametersContext);
+
+ // 创建构建节点
+ List pipeline;
+ if (buildParameters.BuildPipeline == EBuildPipeline.BuiltinBuildPipeline)
+ {
+ pipeline = new List
+ {
+ new TaskPrepare(), //前期准备工作
+ new TaskGetBuildMap(), //获取构建列表
+ new TaskBuilding(), //开始执行构建
+ new TaskCopyRawFile(), //拷贝原生文件
+ new TaskVerifyBuildResult(), //验证构建结果
+ new TaskEncryption(), //加密资源文件
+ new TaskUpdateBundleInfo(), //更新资源包信息
+ new TaskCreateManifest(), //创建清单文件
+ new TaskCreateReport(), //创建报告文件
+ new TaskCreatePackage(), //制作包裹
+ new TaskCopyBuildinFiles(), //拷贝内置文件
+ };
+ }
+ else if (buildParameters.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
+ {
+ pipeline = new List
+ {
+ new TaskPrepare(), //前期准备工作
+ new TaskGetBuildMap(), //获取构建列表
+ new TaskBuilding_SBP(), //开始执行构建
+ new TaskCopyRawFile(), //拷贝原生文件
+ new TaskVerifyBuildResult_SBP(), //验证构建结果
+ new TaskEncryption(), //加密资源文件
+ new TaskUpdateBundleInfo(), //更新补丁信息
+ new TaskCreateManifest(), //创建清单文件
+ new TaskCreateReport(), //创建报告文件
+ new TaskCreatePackage(), //制作补丁包
+ new TaskCopyBuildinFiles(), //拷贝内置文件
+ };
+ }
+ else
+ {
+ throw new NotImplementedException();
+ }
+
+ // 初始化日志
+ BuildLogger.InitLogger(buildParameters.EnableLog);
+
+ // 执行构建流程
+ var buildResult = BuildRunner.Run(pipeline, _buildContext);
+ if (buildResult.Success)
+ {
+ buildResult.OutputPackageDirectory = buildParametersContext.GetPackageOutputDirectory();
+ BuildLogger.Log($"{buildParameters.BuildMode} pipeline build succeed !");
+ }
+ else
+ {
+ BuildLogger.Warning($"{buildParameters.BuildMode} pipeline build failed !");
+ BuildLogger.Error($"Build task failed : {buildResult.FailedTask}");
+ BuildLogger.Error($"Build task error : {buildResult.FailedInfo}");
+ }
+
+ return buildResult;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilder.cs.meta b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilder.cs.meta
new file mode 100644
index 00000000..8060114a
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilder.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: de7563040250b4e4a835d1fc90238e38
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderHelper.cs b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderHelper.cs
new file mode 100644
index 00000000..ab0f9336
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderHelper.cs
@@ -0,0 +1,62 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public static class AssetBundleBuilderHelper
+ {
+ ///
+ /// 获取默认的输出根路录
+ ///
+ public static string GetDefaultOutputRoot()
+ {
+ string projectPath = EditorTools.GetProjectPath();
+ return $"{projectPath}/Bundles";
+ }
+
+ ///
+ /// 获取流文件夹路径
+ ///
+ public static string GetStreamingAssetsFolderPath()
+ {
+ return $"{Application.dataPath}/StreamingAssets/{YooAssetSettings.StreamingAssetsBuildinFolder}/";
+ }
+
+ ///
+ /// 清空流文件夹
+ ///
+ public static void ClearStreamingAssetsFolder()
+ {
+ string streamingFolderPath = GetStreamingAssetsFolderPath();
+ EditorTools.ClearFolder(streamingFolderPath);
+ }
+
+ ///
+ /// 删除流文件夹内无关的文件
+ /// 删除.manifest文件和.meta文件
+ ///
+ public static void DeleteStreamingAssetsIgnoreFiles()
+ {
+ string streamingFolderPath = GetStreamingAssetsFolderPath();
+ if (Directory.Exists(streamingFolderPath))
+ {
+ string[] files = Directory.GetFiles(streamingFolderPath, "*.manifest", SearchOption.AllDirectories);
+ foreach (var file in files)
+ {
+ FileInfo info = new FileInfo(file);
+ info.Delete();
+ }
+
+ files = Directory.GetFiles(streamingFolderPath, "*.meta", SearchOption.AllDirectories);
+ foreach (var item in files)
+ {
+ FileInfo info = new FileInfo(item);
+ info.Delete();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderHelper.cs.meta b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderHelper.cs.meta
new file mode 100644
index 00000000..2cbe1606
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f48abdec05f0dbe438a83e181fe6bc93
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSetting.cs b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSetting.cs
new file mode 100644
index 00000000..19f23d49
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSetting.cs
@@ -0,0 +1,48 @@
+using System;
+using UnityEngine;
+
+namespace YooAsset.Editor
+{
+ public class AssetBundleBuilderSetting : ScriptableObject
+ {
+ ///
+ /// 构建管线
+ ///
+ public EBuildPipeline BuildPipeline = EBuildPipeline.BuiltinBuildPipeline;
+
+ ///
+ /// 构建模式
+ ///
+ public EBuildMode BuildMode = EBuildMode.ForceRebuild;
+
+ ///
+ /// 构建的包裹名称
+ ///
+ public string BuildPackage = string.Empty;
+
+ ///
+ /// 压缩方式
+ ///
+ public ECompressOption CompressOption = ECompressOption.LZ4;
+
+ ///
+ /// 输出文件名称样式
+ ///
+ public EOutputNameStyle OutputNameStyle = EOutputNameStyle.HashName;
+
+ ///
+ /// 首包资源文件的拷贝方式
+ ///
+ public ECopyBuildinFileOption CopyBuildinFileOption = ECopyBuildinFileOption.None;
+
+ ///
+ /// 首包资源文件的标签集合
+ ///
+ public string CopyBuildinFileTags = string.Empty;
+
+ ///
+ /// 加密类名称
+ ///
+ public string EncyptionClassName = string.Empty;
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSetting.cs.meta b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSetting.cs.meta
new file mode 100644
index 00000000..a8a559c2
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSetting.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 09788b4733bab2d4792fdd5d28e7653c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSettingData.cs b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSettingData.cs
new file mode 100644
index 00000000..353931b6
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSettingData.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+
+namespace YooAsset.Editor
+{
+ public class AssetBundleBuilderSettingData
+ {
+ private static AssetBundleBuilderSetting _setting = null;
+ public static AssetBundleBuilderSetting Setting
+ {
+ get
+ {
+ if (_setting == null)
+ LoadSettingData();
+ return _setting;
+ }
+ }
+
+ ///
+ /// 配置数据是否被修改
+ ///
+ public static bool IsDirty { set; get; } = false;
+
+ ///
+ /// 加载配置文件
+ ///
+ private static void LoadSettingData()
+ {
+ _setting = SettingLoader.LoadSettingData();
+ }
+
+ ///
+ /// 存储文件
+ ///
+ public static void SaveFile()
+ {
+ if (Setting != null)
+ {
+ IsDirty = false;
+ EditorUtility.SetDirty(Setting);
+ AssetDatabase.SaveAssets();
+ Debug.Log($"{nameof(AssetBundleBuilderSetting)}.asset is saved!");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSettingData.cs.meta b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSettingData.cs.meta
new file mode 100644
index 00000000..4d7c62ec
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderSettingData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 24698266f028e4a47bb88f091fd64547
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderTools.cs b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderTools.cs
new file mode 100644
index 00000000..2216fc4f
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderTools.cs
@@ -0,0 +1,215 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using UnityEditor.Animations;
+
+namespace YooAsset.Editor
+{
+ public static class AssetBundleBuilderTools
+ {
+ ///
+ /// 检测所有损坏的预制体文件
+ ///
+ public static void CheckCorruptionPrefab(List searchDirectorys)
+ {
+ if (searchDirectorys.Count == 0)
+ throw new Exception("路径列表不能为空!");
+
+ // 获取所有资源列表
+ int checkCount = 0;
+ int invalidCount = 0;
+ string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Prefab, searchDirectorys.ToArray());
+ foreach (string assetPath in findAssets)
+ {
+ UnityEngine.Object prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object));
+ if (prefab == null)
+ {
+ invalidCount++;
+ Debug.LogError($"发现损坏预制件:{assetPath}");
+ }
+ EditorTools.DisplayProgressBar("检测预制件文件是否损坏", ++checkCount, findAssets.Length);
+ }
+ EditorTools.ClearProgressBar();
+
+ if (invalidCount == 0)
+ Debug.Log($"没有发现损坏预制件");
+ }
+
+ ///
+ /// 检测所有动画控制器的冗余状态
+ ///
+ public static void FindRedundantAnimationState(List searchDirectorys)
+ {
+ if (searchDirectorys.Count == 0)
+ throw new Exception("路径列表不能为空!");
+
+ // 获取所有资源列表
+ int checkCount = 0;
+ int findCount = 0;
+ string[] findAssets = EditorTools.FindAssets(EAssetSearchType.RuntimeAnimatorController, searchDirectorys.ToArray());
+ foreach (string assetPath in findAssets)
+ {
+ AnimatorController animator= AssetDatabase.LoadAssetAtPath(assetPath);
+ if (FindRedundantAnimationState(animator))
+ {
+ findCount++;
+ Debug.LogWarning($"发现冗余的动画控制器:{assetPath}");
+ }
+ EditorTools.DisplayProgressBar("检测冗余的动画控制器", ++checkCount, findAssets.Length);
+ }
+ EditorTools.ClearProgressBar();
+
+ if (findCount == 0)
+ Debug.Log($"没有发现冗余的动画控制器");
+ else
+ AssetDatabase.SaveAssets();
+ }
+
+ ///
+ /// 清理所有材质球的冗余属性
+ ///
+ public static void ClearMaterialUnusedProperty(List searchDirectorys)
+ {
+ if (searchDirectorys.Count == 0)
+ throw new Exception("路径列表不能为空!");
+
+ // 获取所有资源列表
+ int checkCount = 0;
+ int removedCount = 0;
+ string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Material, searchDirectorys.ToArray());
+ foreach (string assetPath in findAssets)
+ {
+ Material mat = AssetDatabase.LoadAssetAtPath(assetPath);
+ if (ClearMaterialUnusedProperty(mat))
+ {
+ removedCount++;
+ Debug.LogWarning($"材质球已被处理:{assetPath}");
+ }
+ EditorTools.DisplayProgressBar("清理冗余的材质球", ++checkCount, findAssets.Length);
+ }
+ EditorTools.ClearProgressBar();
+
+ if (removedCount == 0)
+ Debug.Log($"没有发现冗余的材质球");
+ else
+ AssetDatabase.SaveAssets();
+ }
+
+
+ ///
+ /// 清理无用的材质球属性
+ ///
+ private static bool ClearMaterialUnusedProperty(Material mat)
+ {
+ bool removeUnused = false;
+ SerializedObject so = new SerializedObject(mat);
+ SerializedProperty sp = so.FindProperty("m_SavedProperties");
+
+ sp.Next(true);
+ do
+ {
+ if (sp.isArray == false)
+ continue;
+
+ for (int i = sp.arraySize - 1; i >= 0; --i)
+ {
+ var p1 = sp.GetArrayElementAtIndex(i);
+ if (p1.isArray)
+ {
+ for (int ii = p1.arraySize - 1; ii >= 0; --ii)
+ {
+ var p2 = p1.GetArrayElementAtIndex(ii);
+ var val = p2.FindPropertyRelative("first");
+ if (mat.HasProperty(val.stringValue) == false)
+ {
+ Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
+ p1.DeleteArrayElementAtIndex(ii);
+ removeUnused = true;
+ }
+ }
+ }
+ else
+ {
+ var val = p1.FindPropertyRelative("first");
+ if (mat.HasProperty(val.stringValue) == false)
+ {
+ Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
+ sp.DeleteArrayElementAtIndex(i);
+ removeUnused = true;
+ }
+ }
+ }
+ }
+ while (sp.Next(false));
+ so.ApplyModifiedProperties();
+ return removeUnused;
+ }
+
+ ///
+ /// 查找动画控制器里冗余的动画状态机
+ ///
+ private static bool FindRedundantAnimationState(AnimatorController animatorController)
+ {
+ if (animatorController == null)
+ return false;
+
+ string assetPath = AssetDatabase.GetAssetPath(animatorController);
+
+ // 查找使用的状态机名称
+ List usedStateNames = new List();
+ foreach (var layer in animatorController.layers)
+ {
+ foreach (var state in layer.stateMachine.states)
+ {
+ usedStateNames.Add(state.state.name);
+ }
+ }
+
+ List allLines = new List();
+ List stateIndexList = new List();
+ using (StreamReader reader = File.OpenText(assetPath))
+ {
+ string content;
+ while (null != (content = reader.ReadLine()))
+ {
+ allLines.Add(content);
+ if (content.StartsWith("AnimatorState:"))
+ {
+ stateIndexList.Add(allLines.Count - 1);
+ }
+ }
+ }
+
+ List allStateNames = new List();
+ foreach (var index in stateIndexList)
+ {
+ for (int i = index; i < allLines.Count; i++)
+ {
+ string content = allLines[i];
+ content = content.Trim();
+ if (content.StartsWith("m_Name"))
+ {
+ string[] splits = content.Split(':');
+ string name = splits[1].TrimStart(' '); //移除前面的空格
+ allStateNames.Add(name);
+ break;
+ }
+ }
+ }
+
+ bool foundRedundantState = false;
+ foreach (var stateName in allStateNames)
+ {
+ if (usedStateNames.Contains(stateName) == false)
+ {
+ Debug.LogWarning($"发现冗余的动画文件:{assetPath}={stateName}");
+ foundRedundantState = true;
+ }
+ }
+ return foundRedundantState;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderTools.cs.meta b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderTools.cs.meta
new file mode 100644
index 00000000..769e38e0
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderTools.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fe50795c51a46884088139b840c1557f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderWindow.cs b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderWindow.cs
new file mode 100644
index 00000000..9e4b8eae
--- /dev/null
+++ b/Assets/TEngine/Editor/Resource/YooAsset/AssetBundleBuilder/AssetBundleBuilderWindow.cs
@@ -0,0 +1,358 @@
+#if UNITY_2019_4_OR_NEWER
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+using UnityEditor.UIElements;
+using UnityEngine.UIElements;
+
+namespace YooAsset.Editor
+{
+ public class AssetBundleBuilderWindow : EditorWindow
+ {
+ [MenuItem("YooAsset/AssetBundle Builder", false, 102)]
+ public static void ShowExample()
+ {
+ AssetBundleBuilderWindow window = GetWindow("资源包构建工具", true, WindowsDefine.DockedWindowTypes);
+ window.minSize = new Vector2(800, 600);
+ }
+
+ private BuildTarget _buildTarget;
+ private List _encryptionServicesClassTypes;
+ private List _encryptionServicesClassNames;
+ private List _buildPackageNames;
+
+ private Button _saveButton;
+ private TextField _buildOutputField;
+ private EnumField _buildPipelineField;
+ private EnumField _buildModeField;
+ private TextField _buildVersionField;
+ private PopupField _buildPackageField;
+ private PopupField _encryptionField;
+ private EnumField _compressionField;
+ private EnumField _outputNameStyleField;
+ private EnumField _copyBuildinFileOptionField;
+ private TextField _copyBuildinFileTagsField;
+
+ public void CreateGUI()
+ {
+ try
+ {
+ VisualElement root = this.rootVisualElement;
+
+ // 加载布局文件
+ var visualAsset = UxmlLoader.LoadWindowUXML();
+ if (visualAsset == null)
+ return;
+
+ visualAsset.CloneTree(root);
+
+ // 配置保存按钮
+ _saveButton = root.Q