Files
plugin-library/Assets/00.BuildOriginality/Editor/ArtBuild/BuildArtAssetWindow.cs
zhangzheng f055116d4d 111
2026-01-05 18:26:50 +08:00

423 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/****************************************************
文件BuildAssetWindow.cs
作者xosmo_
邮箱:
日期2025/3/10 10:43:20
功能:
*****************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sirenix.OdinInspector;
using Sirenix.OdinInspector.Editor;
using UnityEditor;
using UnityEngine;
using YooAsset;
using YooAsset.Editor;
namespace Stary.Evo.Editor
{
public class BuildArtAssetWindow : OdinEditorWindow
{
public static OdinEditorWindow window;
private HotfixMainResDomain hotfixMainResDomain;
[MenuItem("Evo/Art/Art资源打包工具", false, 1)]
static void ShowWindows()
{
window = (BuildArtAssetWindow)EditorWindow.GetWindow(typeof(BuildArtAssetWindow));
window.Show();
}
protected override void OnDisable()
{
base.OnDisable();
EditorUtility.ClearProgressBar();
packageName = "";
}
protected override async void Initialize()
{
base.Initialize();
GetBuildPackageNames();
//初始化打包管线
_buildPipelineViewer = new ScriptableBuildPipelineViewer(packageName,
EBuildPipeline.ScriptableBuildPipeline.ToString(), _packageVersion);
_buildPipelineViewer.clearBuildCacheToggle = true;
_buildPipelineViewer.useAssetDependencyDBToggle = false;
_buildPipelineViewer.SetBuildCacheToggle();
_buildPipelineViewer.SetUseAssetDependencyDB();
}
public static void RemoveBuildAssetWindow()
{
if (window != null)
window.Close();
}
[BoxGroup("Build", showLabel: false)]
[Title("包裹列表", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("Build/BuildPipeline"), HideLabel]
[ValueDropdown("GetBuildPackageNames")]
[OnValueChanged("SetBuildPackageNames")]
public string selectedPackageNames;
[BoxGroup("Build", showLabel: false)]
[Title("当前打包平台", titleAlignment: TitleAlignments.Centered)]
[ReadOnly]
[HorizontalGroup("Build/BuildPipeline"), HideLabel]
public string buildTarget;
private static string packageName;
[Title("版本号", titleAlignment: TitleAlignments.Centered)]
[HorizontalGroup("Build/PackageVersion"), HideLabel]
[OnValueChanged("OnPackageValueChanged")]
public string _packageVersion;
private string PackageVersion
{
get { return _packageVersion; }
set
{
_packageVersion = value;
if (_buildPipelineViewer != null)
_buildPipelineViewer.SetBuildPackagePackageVersion(_packageVersion);
}
}
private AbstractBuildPipelineViewer _buildPipelineViewer;
#region BuildAsset
public void OnPackageValueChanged()
{
if (_buildPipelineViewer != null)
_buildPipelineViewer.SetBuildPackageData(packageName, EBuildPipeline.ScriptableBuildPipeline.ToString(),
_packageVersion);
}
/// <summary>
/// 检测当前所有包裹
/// </summary>
/// <returns></returns>
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var name in ArtLoadAssetLocal.GetLocalDomainAllName())
{
result.Add(name);
}
if (selectedPackageNames.IsNullOrEmpty())
{
if (result.Count > 0)
{
selectedPackageNames = result[0];
}
else
{
selectedPackageNames = "";
}
}
SetBuildPackageNames();
return result;
}
/// <summary>
/// 获取当前包裹
/// </summary>
/// <returns></returns>
public static string GetBuildPackageName()
{
return packageName;
}
/// <summary>
/// 设置当前包裹
/// </summary>
/// <returns></returns>
private void SetBuildPackageNames()
{
if (selectedPackageNames != packageName)
{
GetHostBuildPackageVersion();
Init();
}
packageName = selectedPackageNames;
OnPackageValueChanged();
}
#endregion
#region Update
[BoxGroup("Build", showLabel: false)]
[Title("打包本地资源", titleAlignment: TitleAlignments.Centered)]
[HideLabel]
public BuildAssetEntity onBuildPipelineEntity;
[BoxGroup("Build", showLabel: false)]
[Title("上传资源", titleAlignment: TitleAlignments.Centered)]
[HideLabel]
public BuildAssetEntity onUpdateBuildPipelineEntity;
private void OnBuildPipeline()
{
if (EditorUtility.DisplayDialog("提示",
$"开始构建资源包[{selectedPackageNames}],版本号为[{_buildPipelineViewer.packageVersion}]", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
MarkAdressable.AddArtMark(() => { EditorApplication.delayCall += _buildPipelineViewer.ExecuteBuild; });
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
private async void OnUpdateBuildPipeline()
{
if (EditorUtility.DisplayDialog("提示",
$"开始上传至服务器[{selectedPackageNames}],,版本号为[{_buildPipelineViewer.packageVersion}", "Yes", "No"))
{
// 新增打包为zip的逻辑
string zipFilePath = BuildZip();
await UpdateFileDataResDomain(zipFilePath);
await Task.Delay(1000);
EditorUtility.ClearProgressBar();
}
else
{
EditorUtility.ClearProgressBar();
EditorUtility.DisplayDialog("提示", "Update] 上传已经取消", "确定");
Debug.LogWarning("[Update] 上传已经取消");
}
}
public string BuildZip()
{
EditorUtility.DisplayProgressBar("提示", $"开始上传{packageName}(打包zip)", 0.0f);
// 新增打包为zip的逻辑
string zipFileName =
$"{packageName}_{_packageVersion}.zip";
//原yooAsset目录
var outputPackageDirectory =
$"{AssetBundleBuilderHelper.GetDefaultBuildOutputRoot()}/{EditorUserBuildSettings.activeBuildTarget}/{packageName}";
//拷贝目录
string outFilePath = $"{outputPackageDirectory}/{_packageVersion}";
var copyPackageDirectory =
$"{Application.streamingAssetsPath}/{YooAssetSettingsData.GetDefaultYooFolderName()}/{packageName}";
//拷贝BuildinCatalog文件
CreateBuildinCatalogFile("BuildinCatalog.json", copyPackageDirectory, outFilePath);
CreateBuildinCatalogFile("BuildinCatalog.bytes", copyPackageDirectory, outFilePath);
//输出目录
string zipFilePath = Path.Combine(outputPackageDirectory, zipFileName);
try
{
using (FileStream zipStream = new FileStream(zipFilePath, FileMode.Create))
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create))
{
// 指定需要压缩的后缀(例如:只压缩.json和.dll文件
//string[] targetExtensions = { ".bundle" };
// 遍历目录下所有文件
// foreach (string filePath in Directory.GetFiles(outFilePath, "*.*", SearchOption.AllDirectories)
// .Where(f => targetExtensions.Contains(Path.GetExtension(f),
// StringComparer.OrdinalIgnoreCase)))
foreach (string filePath in Directory.GetFiles(outFilePath, "*.*", SearchOption.AllDirectories))
{
// 获取文件在压缩包中的相对路径
string entryName = Path.GetRelativePath(outFilePath, filePath);
// 创建zip条目
ZipArchiveEntry entry = archive.CreateEntry(entryName,
System.IO.Compression.CompressionLevel.Optimal);
// 写入文件内容
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (Stream entryStream = entry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
Debug.Log($"成功打包为zip{zipFilePath}");
EditorUtility.DisplayProgressBar("提示", $"开始上传{packageName}(打包zip)", 0.25f);
return zipFilePath;
}
catch (Exception ex)
{
Debug.LogError($"打包zip失败{ex.Message}");
EditorUtility.ClearProgressBar();
return default;
}
}
private static void CreateBuildinCatalogFile(string fileName, string copyPackageDirectory, string outFilePath)
{
// 假设 BuildinCatalog 文件名为 BuildinCatalog.json
string sourcePath = Path.Combine(copyPackageDirectory, fileName); // 源文件路径
string destinationPath = Path.Combine(outFilePath, fileName); // 目标文件路径
// 如果目标文件已存在,则覆盖
if (File.Exists(destinationPath))
{
File.Delete(destinationPath);
}
// 执行拷贝操作
File.Copy(sourcePath, destinationPath);
}
public async Task UpdateFileDataResDomain(string zipFilePath)
{
string ip = EditorPrefs.GetString("ip");
var messageEntity = await WebRequestSystem.PostFile(ip + "/FileLoad/UpLoadFile", new[] { zipFilePath });
EditorUtility.DisplayProgressBar("提示", $"开始上传{packageName}(上传zip文件)", 0.5f);
if (messageEntity.code == 200)
{
List<ResultMessageEntity> resultMessageEntities =
JsonConvert.DeserializeObject<List<ResultMessageEntity>>(messageEntity.data.ToString());
if (resultMessageEntities.Count > 0)
{
EditorUtility.DisplayProgressBar("提示", "开始上传(更新数据库)", 0.75f);
foreach (var resultMessageEntity in resultMessageEntities)
{
var data = JsonConvert.DeserializeObject(resultMessageEntity.data.ToString()) as JObject;
string fileId = data["id"].ToString();
ResDmainAddRequst resDmainAddRequst = new ResDmainAddRequst()
{
ProductName = Application.identifier,
DomainName = packageName,
Platform = EditorUserBuildSettings.activeBuildTarget.ToString(),
PackageVersion = _packageVersion,
DocumentFileId = fileId
};
var resResultMessage = await WebRequestSystem.Post(ip + "/ResDomain/AddResDomain",
JsonConvert.SerializeObject(resDmainAddRequst));
//如果低于服务器版本,更新版本号
if (resResultMessage.code == 4100)
{
ResDmainVersionResponse dmainVersionResponse =
JsonConvert.DeserializeObject<ResDmainVersionResponse>(resResultMessage.data
.ToString());
if (dmainVersionResponse.PackageVersion == _packageVersion)
{
EditorUtility.DisplayDialog("提示",
$"上传失败,版本号{_packageVersion}跟服务器版本重复,请修改版本号后,重新打包上传",
"确定");
EditorUtility.ClearProgressBar();
return;
}
}
else if (resResultMessage.code == 200)
{
EditorUtility.DisplayDialog("提示",
$"上传成功,已更新为{_packageVersion}",
"确定");
}
}
EditorUtility.DisplayProgressBar("提示", $"开始上传{packageName}(更新数据库)", 1f);
}
}
else
{
EditorUtility.DisplayProgressBar("提示", $"{messageEntity.message}", 1f);
}
await Task.Delay(1000);
EditorUtility.ClearProgressBar();
return;
}
/// <summary>
/// 获取服务器上版本号
/// </summary>
private async void GetHostBuildPackageVersion()
{
var resDmainAddRequst = new ResDmainRequst()
{
ProductName = Application.identifier,
DomainName = selectedPackageNames,
Platform = EditorUserBuildSettings.activeBuildTarget.ToString(),
};
string ip = EditorPrefs.GetString("ip");
var resResultMessage = await WebRequestSystem.Post(ip + "/ResDomain/GetResDomainByDomain",
JsonConvert.SerializeObject(resDmainAddRequst));
//如果低于服务器版本,更新版本号
if (resResultMessage.code != 1011)
{
if (resResultMessage.data != null)
{
ResDmainResponse domainResponse =
JsonConvert.DeserializeObject<ResDmainResponse>(resResultMessage.data
.ToString());
PackageVersion = domainResponse.PackageVersion;
}
else
{
Debug.LogError($"UnityEvo获取服务器版本失败,resResultMessage.data为空");
}
}
else
{
EditorUtility.DisplayDialog("提示",
$"{resResultMessage.message},默认test_1.0版本 ", "确定");
PackageVersion = "test_1.0";
}
}
#endregion
protected void Init()
{
//Update
buildTarget = EditorUserBuildSettings.activeBuildTarget.ToString();
onBuildPipelineEntity =
new BuildAssetEntity("打包", $"打包资源包【版本:{_packageVersion}】", OnBuildPipeline);
onUpdateBuildPipelineEntity =
new BuildAssetEntity("更新", $"更新至服务器【版本:{_packageVersion}】",
OnUpdateBuildPipeline);
}
private Vector2 scroll;
protected override void DrawEditor(int index)
{
scroll = GUILayout.BeginScrollView(scroll);
{
base.DrawEditor(index);
}
GUILayout.EndScrollView();
UpdateBuildPipelineButtonName();
}
public void UpdateBuildPipelineButtonName()
{
onBuildPipelineEntity.SetButtonName($"打包资源包【版本:{_packageVersion}】");
onUpdateBuildPipelineEntity.SetButtonName($"更新至服务器【版本:{_packageVersion}】");
}
}
}