private bool mCurSaveBinary; //是否保存二进制文件

        private void OnEnable()
        {
            if (VFS_Platform != null)
            {
                flag_platform_from_param = true;
                platform_from_param      = VFS_Platform.Value;

                //如果参数给的是平台,那么要倒推出,当前该平台可用的分支
                string[] main_package_branches = VFSManagerEditor.VersionManager.GetBranchNamesByMainPackage(platform_from_param);
                if (main_package_branches != null && main_package_branches.Length > 0)
                {
                    match_branches_from_param.AddRange(main_package_branches);
                }
                string   platform_name = XPlatformUtil.GetNameText(platform_from_param);
                string   source_packages_folder_path = Path.Combine(VFSEditorConst.PROJECT_VFS_SOURCE_PACKAGES_ROOT_PATH, platform_name);
                string[] extension_groups_in_source_package_folder = VFSUtil.GetValidExtensionGroupNames(VFSUtil.GetExtensionPackageRootFolderInPackages(source_packages_folder_path));
                foreach (var groupName in extension_groups_in_source_package_folder)
                {
                    string[] group_branches = VFSManagerEditor.VersionManager.GetBranchNamesByExtensionGroup(platform_from_param, groupName);
                    if (group_branches != null && group_branches.Length > 0)
                    {
                        match_branches_from_param.AddRange(group_branches);
                    }
                }
                match_branches_from_param_arr = match_branches_from_param.ToArray();
            }

            if (!BranchName.IsNullOrEmpty())
            {
                flag_branchName_from_param = true;
                branchName_from_param      = BranchName;
                isBrancNameFromParamValid  = VFSManagerEditor.VersionManager.TryGetVersionBranch(branchName_from_param, out mCurBranch);
                mCurSelectBranchName       = BranchName;
            }
        }
        public bool AddBranch(string branchName, VersionBranch.BranchType type, XRuntimePlatform platform, string desc = null, string extGroupName = null)
        {
            if (!branchName.IsValidFileName())
            {
                return(false);
            }
            if (this.IsBranchExists(branchName))
            {
                return(false);
            }
            if (type == VersionBranch.BranchType.ExtensionGroup && extGroupName.IsNullOrEmpty())
            {
                return(false);
            }
            mVersionMainData.Branches_ReadWrite.Add(branchName);
            var branch = new VersionBranch();

            branch.BranchName         = branchName;
            branch.BType              = type;
            branch.Desc               = desc;
            branch.ExtensionGroupName = extGroupName;
            branch.Platform           = platform;

            if (mDict_Branches.ContainsKey(branchName))
            {
                mDict_Branches[branchName] = branch;
            }
            else
            {
                mDict_Branches.Add(branchName, branch);
            }
            SaveVersionMainData(ref mVersionMainData, mVersionMainFilePath);
            SaveBranchFile(ref branch);
            return(true);
        }
        public string[] GetBranchNamesByExtensionGroup(XRuntimePlatform platform, string extensionGroupName)
        {
            List <string> result = new List <string>();

            foreach (var item in mDict_Branches)
            {
                if (item.Value.BType == VersionBranch.BranchType.ExtensionGroup && item.Value.Platform == platform && item.Value.ExtensionGroupName == extensionGroupName)
                {
                    result.Add(item.Key);
                }
            }
            return(result.ToArray());
        }
        public string[] GetBranchNamesByMainPackage(XRuntimePlatform platform)
        {
            List <string> result = new List <string>();

            foreach (var item in mDict_Branches)
            {
                if (item.Value.BType == VersionBranch.BranchType.MainPackage && item.Value.Platform == platform)
                {
                    result.Add(item.Key);
                }
            }
            return(result.ToArray());
        }
Example #5
0
        private void SaveExtensionGroupInfo(string group_path, string group_name, XRuntimePlatform platform, long mainPackageVersionLimit, string ab_ext_name)
        {
            string file_path = VFSUtil.GetExtensionGroup_GroupInfo_Path_InGroupPath(group_path);
            var    obj       = new ExtensionGroupInfo
            {
                Platform  = platform,
                GroupName = group_name,
                MainPackageVersionLimit = mainPackageVersionLimit,
                AssetBundleExtension    = ab_ext_name
            };

            XConfig.SaveJson(obj, file_path, AssetLoadType.SystemIO);
        }
Example #6
0
        public void Build(XRuntimePlatform platform, AssetCompressType compressType)
        {
            Debug.Log("[TinaX.VFS] Start build assets...");
            if (ClearAssetBundleSignBeforeBuild)
            {
                VFSEditorUtil.RemoveAllAssetbundleSigns();
            }
            Debug.Log("    handle assetbundle signs...");
            RefreshAssetBundleSign();
            Debug.Log("    build assetbundles by unity editor.");

            string packages_root_path;  //VFS存放相关文件的根目录
            string output_temp_path;    //Unity自身打包后直接输出的目录

            BuildAssetBundle(platform, compressType, out packages_root_path, out output_temp_path);

            #region 加载Build得到的AssetbundleManifest文件
            string      abmanifest_file_name = Path.GetFileName(output_temp_path);
            string      abmanifest_path      = Path.Combine(output_temp_path, abmanifest_file_name);
            AssetBundle ab_mainifest         = AssetBundle.LoadFromFile(abmanifest_path);
            mAssetBundleManifest = ab_mainifest.LoadAsset <AssetBundleManifest>("AssetBundleManifest");
            #endregion

            HandleVFSFiles(packages_root_path, output_temp_path, platform);
            SaveAssetHashFiles(Path.Combine(packages_root_path, VFSEditorConst.PROJECT_VFS_FILE_FOLDER_DATA));
            MakeEditorBuildInfo(packages_root_path);
            MakeBuildInfo(packages_root_path);
            MakeVFSConfig(packages_root_path, Config);

            if (CopyToStreamingAssetsFolder)
            {
                CopyToStreamingAssets(packages_root_path, XPlatformUtil.GetNameText(platform));
            }

            if (ClearAssetBundleSignAfterBuild)
            {
                VFSEditorUtil.RemoveAllAssetbundleSigns();
            }

            Debug.Log("[TinaX.VFS] Build Finished.");
        }
Example #7
0
        public static UnityEditor.BuildTarget GetBuildTarget(XRuntimePlatform xPlatform)
        {
            switch (xPlatform) // !! Visual Studio 会给这地方建议改成C#8的模式匹配表达式,不要动,Unity目前只支持C#7.2语法!!
            {
            default:
                return(UnityEditor.BuildTarget.NoTarget);

            case XRuntimePlatform.Windows:
                return(UnityEditor.BuildTarget.StandaloneWindows64);

            case XRuntimePlatform.UniversalWindowsPlatform:
                return(UnityEditor.BuildTarget.WSAPlayer);

            case XRuntimePlatform.Linux:
                return(UnityEditor.BuildTarget.StandaloneLinux64);

            case XRuntimePlatform.OSX:
                return(UnityEditor.BuildTarget.StandaloneOSX);

            case XRuntimePlatform.iOS:
                return(UnityEditor.BuildTarget.iOS);

            case XRuntimePlatform.Android:
                return(UnityEditor.BuildTarget.Android);

            case XRuntimePlatform.XBox:
                return(UnityEditor.BuildTarget.XboxOne);

            case XRuntimePlatform.PS4:
                return(UnityEditor.BuildTarget.PS4);

            case XRuntimePlatform.NSwitch:
                return(UnityEditor.BuildTarget.Switch);

            case XRuntimePlatform.Windows32:
                return(UnityEditor.BuildTarget.StandaloneWindows);
            }
        }
Example #8
0
        public static string GetNameText(XRuntimePlatform xPlatform)
        {
            switch (xPlatform)
            {
            default:
                return(xPlatform.ToString().ToLower());

            case XRuntimePlatform.Windows:
                return("windows_amd64");    //标注amd64, 区别于Windows后搞出来的arm64

            case XRuntimePlatform.UniversalWindowsPlatform:
                return("uwp");

            case XRuntimePlatform.Linux:
                return("gnu_linux_64");

            case XRuntimePlatform.OSX:
                return("osx");

            case XRuntimePlatform.iOS:
                return("ios");

            case XRuntimePlatform.Android:
                return("android");

            case XRuntimePlatform.XBox:
                return("xbox");

            case XRuntimePlatform.PS4:
                return("ps4");

            case XRuntimePlatform.NSwitch:
                return("switch");

            case XRuntimePlatform.Windows32:
                return("windows_x86_32");
            }
        }
Example #9
0
        private void OnGUI()
        {
            GUILayout.Label(IsChinese ? "创建新分支" : "Create Branch");
            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(IsChinese ? "分支名" : "branchName", GUILayout.Width(100));
            mBranchName = EditorGUILayout.TextField(mBranchName);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(IsChinese ? "分支类型" : "BranchType", GUILayout.Width(100));
            mSelect_BranchType = (VersionBranch.BranchType)EditorGUILayout.EnumPopup(mSelect_BranchType);
            EditorGUILayout.EndHorizontal();

            if (mSelect_BranchType == VersionBranch.BranchType.ExtensionGroup)
            {
                if (flag_refreshExtGroupDatas == false)
                {
                    refreshExtensionGroupDatas();
                }

                if (ExtensionGroupNames.Length == 0)
                {
                    GUILayout.Label(IsChinese ? "没有可扩展组" : "No Extension Group.");
                }
                else
                {
                    EditorGUILayout.BeginHorizontal();
                    GUILayout.Label(IsChinese ? "扩展组" : "ExtensionGroup:", GUILayout.Width(100));
                    select_extGroup_index = EditorGUILayout.Popup(select_extGroup_index, ExtensionGroupNames);
                    EditorGUILayout.EndHorizontal();
                    mExtensionGroupName = ExtensionGroupNames[select_extGroup_index];
                }
            }

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(IsChinese ? "目标平台" : "Platform", GUILayout.Width(100));
            mSelect_platform = (XRuntimePlatform)EditorGUILayout.EnumPopup(mSelect_platform);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(IsChinese ? "分支描述" : "description", GUILayout.Width(100));
            mBranchDesc = EditorGUILayout.TextArea(mBranchDesc);
            EditorGUILayout.EndHorizontal();

            GUILayout.Space(15);
            if (GUILayout.Button(IsChinese ? "新建" : "Create"))
            {
                if (!mBranchName.IsValidFileName())
                {
                    EditorUtility.DisplayDialog(IsChinese ? "有点问题" : "Oops", IsChinese ? "输入的分支名是无效的" : "Branch name you input is invalid.", IsChinese ? "好吧" : "Okey");
                    return;
                }

                //分支名查重
                if (VFSManagerEditor.VersionManager.IsBranchExists(mBranchName))
                {
                    EditorUtility.DisplayDialog(IsChinese ? "有点问题" : "Oops", IsChinese ? "输入的分支名已存在" : "Branch name you input is exists.", IsChinese ? "好吧" : "Okey");
                    return;
                }

                //分支类型和名称确定
                if (mSelect_BranchType == VersionBranch.BranchType.ExtensionGroup && mExtensionGroupName.IsNullOrEmpty())
                {
                    EditorUtility.DisplayDialog(IsChinese ? "有点问题" : "Oops", IsChinese ? "扩展组名称无效" : "Extension group name you input is invalid.", IsChinese ? "好吧" : "Okey");
                    return;
                }

                if (!mBranchDesc.IsNullOrEmpty() && mBranchDesc.Length > 512)
                {
                    mBranchDesc = mBranchDesc.Substring(0, 512);
                }

                if (VFSManagerEditor.VersionManager.AddBranch(mBranchName, mSelect_BranchType, mSelect_platform, mBranchDesc, mExtensionGroupName))
                {
                    EditorUtility.DisplayDialog(IsChinese ? "完成" : "Success", IsChinese ? "创建成功" : "Create branch success.", IsChinese ? "好的" : "Ok");
                    this.Close();
                }
                else
                {
                    this.ShowNotification(new GUIContent(IsChinese ? "创建成功" : "创建失败"));
                }
            }
        }
Example #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="root_path">存放一系列VFS目录的根目录</param>
        /// <param name="build_root_path">Unity的Build结果输出目录</param>
        public void HandleVFSFiles(string root_path, string build_root_path, XRuntimePlatform platform)
        {
            mEditorBuildInfo = new EditorBuildInfo();
            List <VFSEditorGroup> groups  = VFSManagerEditor.GetGroups();
            string remote_files_root_path = Path.Combine(root_path, VFSEditorConst.PROJECT_VFS_FILE_FOLDER_REMOTE);
            string local_files_root_path  = Path.Combine(root_path, VFSEditorConst.PROJECT_VFS_FILES_FOLDER_MAIN);
            string source_packages_extension_root_folder = Path.Combine(root_path, VFSEditorConst.PROJECT_VFS_FILES_FOLDER_EXTENSION);

            XDirectory.DeleteIfExists(remote_files_root_path, true);
            XDirectory.DeleteIfExists(local_files_root_path, true);
            XDirectory.DeleteIfExists(source_packages_extension_root_folder, true);

            foreach (var group in groups)
            {
                //扩展组的判断
                if (group.ExtensionGroup)
                {
                    #region 处理扩展组
                    string extension_group_root_path = Path.Combine(source_packages_extension_root_folder, group.GroupName.ToLower());
                    bool   moved = CopyAssetBundleFilesByGroup(group, build_root_path, extension_group_root_path);
                    if (moved)
                    {
                        //manifest
                        group.MakeVFSManifest(root_path, mDict_Group_AssetBundleNames[group.GroupName], ref mAssetBundleManifest);
                        //给独立的组生成一份hash
                        group.MakeAssetBundleFilesHash(root_path, extension_group_root_path, mDict_Group_AssetBundleNames[group.GroupName]);
                        SaveExtensionGroupInfo(extension_group_root_path, group.GroupName, platform, group.ExtensionGroup_MainPackageVersionLimit, Config.AssetBundleFileExtension);
                        //保存Options
                        group.SaveGroupOptionFile(root_path);
                    }

                    #endregion

                    //登记
                    if (curProfile.IsDisabledGroup(group.GroupName))
                    {
                        mEditorBuildInfo.list_disable_extension.Add(group.GroupName);
                    }
                    else
                    {
                        mEditorBuildInfo.list_total_extension.Add(group.GroupName);

                        if (group.HandleMode == GroupHandleMode.LocalOrRemote)
                        {
                            if (curProfile.TryGetGroupLocation(group.GroupName, out var location))
                            {
                                if (location == ProfileRecord.E_GroupAssetsLocation.Local)
                                {
                                    mEditorBuildInfo.list_extension_local.Add(group.GroupName);
                                }
                                else if (location == ProfileRecord.E_GroupAssetsLocation.Remote)
                                {
                                    mEditorBuildInfo.list_extension_remote.Add(group.GroupName);
                                }
                            }
                            else
                            {
                                mEditorBuildInfo.list_extension_local.Add(group.GroupName);
                            }
                        }
                        else if (group.HandleMode == GroupHandleMode.RemoteOnly)
                        {
                            mEditorBuildInfo.list_extension_remote.Add(group.GroupName);
                        }
                        else
                        {
                            mEditorBuildInfo.list_extension_local.Add(group.GroupName);
                        }
                    }
                }
                else
                {
                    bool moveToRemote = false;
                    bool moveToLocal  = false;

                    if (group.HandleMode == GroupHandleMode.LocalOrRemote)
                    {
                        if (curProfile.TryGetGroupLocation(group.GroupName, out var location))
                        {
                            if (location == ProfileRecord.E_GroupAssetsLocation.Remote)
                            {
                                moveToRemote = true;
                            }
                            else
                            {
                                moveToLocal = true;
                            }
                        }
                        else
                        {
                            moveToLocal = true;
                        }
                    }
                    else if (group.HandleMode == GroupHandleMode.RemoteOnly)
                    {
                        moveToRemote = true;
                    }
                    else if (group.HandleMode == GroupHandleMode.LocalOnly || group.HandleMode == GroupHandleMode.LocalAndUpdatable)
                    {
                        moveToLocal = true;
                    }

                    //登记
                    mEditorBuildInfo.list_total_main_package.Add(group.GroupName);

                    if (moveToRemote)
                    {
                        //登记
                        mEditorBuildInfo.list_main_package_remote.Add(group.GroupName);
                        XDirectory.CreateIfNotExists(remote_files_root_path);
                        CopyAssetBundleFilesByGroup(group, build_root_path, remote_files_root_path);
                        //上一步copy的时候,开发者自定义的pipeline可以改变文件,所以制作assetbundle的hash信息的时候,必须使用上一步处理后的结果
                        group.MakeAssetBundleFilesHash(root_path, remote_files_root_path, mDict_Group_AssetBundleNames[group.GroupName]);
                    }
                    else if (moveToLocal)
                    {
                        //登记
                        mEditorBuildInfo.list_main_package_local.Add(group.GroupName);
                        XDirectory.CreateIfNotExists(local_files_root_path);
                        CopyAssetBundleFilesByGroup(group, build_root_path, local_files_root_path);
                        //上一步copy的时候,开发者自定义的pipeline可以改变文件,所以制作assetbundle的hash信息的时候,必须使用上一步处理后的结果
                        group.MakeAssetBundleFilesHash(root_path, local_files_root_path, mDict_Group_AssetBundleNames[group.GroupName]);
                    }


                    group.MakeVFSManifest(root_path, mDict_Group_AssetBundleNames[group.GroupName], ref mAssetBundleManifest);
                }
            }
        }
Example #11
0
        public void BuildAssetBundle(XRuntimePlatform platform, AssetCompressType compressType, out string output_folder, out string temp_output_folder)
        {
            var buildTarget = XPlatformEditorUtil.GetBuildTarget(platform);
            var target_name = XPlatformUtil.GetNameText(platform);

            output_folder = Path.Combine(VFSEditorConst.PROJECT_VFS_SOURCE_PACKAGES_ROOT_PATH, target_name);
            string build_output_folder = Path.Combine(output_folder, "build_temp");

            temp_output_folder = build_output_folder;

            if (ClearOutputFolder)
            {
                XDirectory.DeleteIfExists(output_folder, true);
            }
            XDirectory.CreateIfNotExists(output_folder);
            XDirectory.CreateIfNotExists(temp_output_folder);

            //压缩方法
            BuildAssetBundleOptions build_opt = BuildAssetBundleOptions.None;

            switch (compressType)
            {
            default:
            case AssetCompressType.LZ4:
                build_opt = BuildAssetBundleOptions.ChunkBasedCompression;
                break;

            case AssetCompressType.LZMA:
                build_opt = BuildAssetBundleOptions.None;
                break;

            case AssetCompressType.None:
                build_opt = BuildAssetBundleOptions.UncompressedAssetBundle;
                break;
            }

            //强制重新构建
            if (ForceRebuild)
            {
                build_opt = build_opt | BuildAssetBundleOptions.ForceRebuildAssetBundle;
            }
            //严格模式
            if (StrictMode)
            {
                build_opt = build_opt | BuildAssetBundleOptions.StrictMode;
            }
            //Hash保持一致
            build_opt = build_opt | BuildAssetBundleOptions.DeterministicAssetBundle;

            //叫Unity来打ab包
            BuildPipeline.BuildAssetBundles(build_output_folder, build_opt, buildTarget);

            //打包完了,把所有打包得到的AssetBundle文件记录下来
            string ab_extension = Config.AssetBundleFileExtension;

            if (!ab_extension.StartsWith("."))
            {
                ab_extension = "." + ab_extension;
            }

            string[] files = Directory.GetFiles(build_output_folder, $"*{ab_extension}", SearchOption.AllDirectories);

            #region temp下的目录完全hash
            //var hashBook = new FilesHashBook();
            //List<FilesHashBook.FileHash> temp_hash_list = new List<FilesHashBook.FileHash>();
            //int build_output_folder_len = build_output_folder.Length + 1;
            //foreach (var file in files)
            //{
            //    string pure_path = file.Substring(build_output_folder_len, file.Length - build_output_folder_len);
            //    if (pure_path.IndexOf("\\") != -1)
            //        pure_path = pure_path.Replace("\\", "/");
            //    temp_hash_list.Add(new FilesHashBook.FileHash()
            //    {
            //        p = pure_path,
            //        h = XFile.GetMD5(file, true)
            //    });
            //}
            //hashBook.Files = temp_hash_list.ToArray();
            //string hashBook_path = Path.Combine(build_output_folder, VFSConst.ABsHashFileName);
            //XFile.DeleteIfExists(hashBook_path);
            //string hashBook_json = JsonUtility.ToJson(hashBook);
            //File.WriteAllText(hashBook_path, hashBook_json, Encoding.UTF8);
            #endregion
        }
Example #12
0
 public void BuildAssetBundle(XRuntimePlatform platform, AssetCompressType compressType)
 {
     this.BuildAssetBundle(platform, compressType, out _, out _);
 }
Example #13
0
        private void OnGUI()
        {
            GUILayout.BeginVertical(style_body);

            #region Profile 选择

            if (xprofiles == null || (select_xprofile - 1) > xprofiles.Length)
            {
                refreshXprofilesCacheData();
            }
            if (mDevelopMode)
            {
                GUILayout.Label("[Develop Mode]", style_warning);
            }
            GUILayout.BeginHorizontal(style_profile_selector);
            GUILayout.Label("Profile:", GUILayout.Width(55));

            //select_xprofile = EditorGUILayout.Popup(select_xprofile, xprofiles);
            GUILayout.Label(xprofiles[select_xprofile]);
            if (GUILayout.Button(VFSBuilderI18N.SwitchProfile, GUILayout.Width(50)))
            {
                SettingsService.OpenProjectSettings(XEditorConst.ProjectSetting_CorePath);
            }
            GUILayout.EndHorizontal();

            #endregion
            if (xprofiles != null && xprofiles.Length > 0)
            {
                cur_select_xprofile_name = xprofiles[select_xprofile];
            }

            #region 平台选择
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.PlatformTarget, GUILayout.MaxWidth(100));
            cur_select_platform = (XRuntimePlatform)EditorGUILayout.EnumPopup(cur_select_platform);
            EditorGUILayout.EndHorizontal();
            #endregion

            #region 严格模式
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.strictMode, GUILayout.Width(100));
            cur_strictMode = EditorGUILayout.Toggle(cur_strictMode);
            EditorGUILayout.EndHorizontal();
            #endregion

            #region 压缩设置
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.AssetCompressType, GUILayout.MaxWidth(100));
            cur_select_compress = (AssetCompressType)EditorGUILayout.EnumPopup(cur_select_compress);
            EditorGUILayout.EndHorizontal();
            #endregion

            #region  制到StreamingAssets
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.CopyToStramingAssetPath, GUILayout.MaxWidth(200));
            cur_copyToStreamingAssetFolder = EditorGUILayout.Toggle(cur_copyToStreamingAssetFolder);
            EditorGUILayout.EndHorizontal();
            #endregion

            #region 在结束前清理AB标记
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.ClearAllABSignBeforeStart);
            cur_clearAllABSign = EditorGUILayout.Toggle(cur_clearAllABSign);
            EditorGUILayout.EndHorizontal();
            GUILayout.Label(VFSBuilderI18N.ClearAllABSignBeforeStart_Tips, EditorStyles.helpBox);
            #endregion

            #region 在结束后清理AB标记
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.ClearAllABSignAfterFinish);
            cur_clearAllABSignAfterFinish = EditorGUILayout.Toggle(cur_clearAllABSignAfterFinish);
            EditorGUILayout.EndHorizontal();
            #endregion

            #region 清理输出目录
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.ClearOutputFolders);
            cur_ClearOutputFolder = EditorGUILayout.Toggle(cur_ClearOutputFolder);
            EditorGUILayout.EndHorizontal();
            #endregion

            #region 强制重构建资源
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(VFSBuilderI18N.ForceRebuild);
            cur_ForceRebuild = EditorGUILayout.Toggle(cur_ForceRebuild);
            EditorGUILayout.EndHorizontal();
            #endregion

            #region 管线
            if (mPipeline_ready == false)
            {
                refreshBuildPipline();
            }
            if (mList_pipeline != null && mList_pipeline.Count > 0)
            {
                GUILayout.Space(15);
                TinaXEditor.Utils.EditorGUIUtil.HorizontalLine();
                GUILayout.Label("Builder Pipeline:");
                v2_scroll_pipeline = EditorGUILayout.BeginScrollView(v2_scroll_pipeline);
                foreach (var type in mList_pipeline)
                {
                    if (type.Namespace.IsNullOrEmpty())
                    {
                        GUILayout.Label($"- {type.FullName} [{type.Assembly.ManifestModule.Name}]");
                    }
                    else
                    {
                        GUILayout.Label($"- {type.Namespace}.{type.FullName} [{type.Assembly.ManifestModule.Name}]");
                    }
                }
                EditorGUILayout.EndScrollView();
            }

            #endregion

            //#region Preview
            //GUILayout.BeginVertical(style_preview);
            //GUILayout.Label("Build Priview", EditorStyles.centeredGreyMiniLabel);
            //GUILayout.Label("Build Group:");
            //GUILayout.FlexibleSpace();
            //GUILayout.EndVertical();

            //#endregion
            EditorGUILayout.Space();

            if (GUILayout.Button("Build", style_btn_build))
            {
                runBuild();
            }
            if (GUILayout.Button(VFSBuilderI18N.RemoveAllAssetBundleSign))
            {
                if (EditorUtility.DisplayDialog("Clear?", "Are you sure?", "yes", "no"))
                {
                    VFSEditorUtil.RemoveAllAssetbundleSigns(true);
                }
            }
            if (GUILayout.Button(VFSBuilderI18N.CreateVersionRecord))
            {
                CreateVersionRecordGUI.VFS_Platform = cur_select_platform;
                CreateVersionRecordGUI.OpenUI();
            }
            EditorGUILayout.Space();

            GUILayout.EndVertical();
        }