上传设置分页,隐藏不必要显示的项目,之后移入打包配置分页中

This commit is contained in:
Alienjack 2025-09-03 17:21:50 +08:00
parent 3881ae8232
commit b7c90096f6
4 changed files with 314 additions and 311 deletions

View File

@ -21,7 +21,7 @@ MonoBehaviour:
- VersionFlow.Editors.PatchUpLoader_AliOSS - VersionFlow.Editors.PatchUpLoader_AliOSS
m_values: m_values:
- '{"UploadRoot":"./LocalPatch"}' - '{"UploadRoot":"./LocalPatch"}'
- '{"BucketName":"asdad","UploadPath":"asdasd","accessKeyId":"asdasd","accessKeySecret":"dasdad","endPoint":"asdasd"}' - '{"BucketName":"BUCKET","UploadPath":"Project_DEMO","accessKeyId":"00000000","accessKeySecret":"asdasdasd","endPoint":"oss.endpoint.com"}'
Options: 288 Options: 288
Groups: Groups:
- GroupName: Backpack - GroupName: Backpack

View File

@ -36,8 +36,6 @@ namespace VersionFlow.Editors
public override void OnInspectorGUI() public override void OnInspectorGUI()
{ {
base.OnInspectorGUI();
DrawUploader(); DrawUploader();
var builder = target as BuilderConfig; var builder = target as BuilderConfig;

View File

@ -21,6 +21,7 @@ namespace VersionFlow.Editors
private void OnEnable() private void OnEnable()
{ {
titleContent = new GUIContent("VersionFlow");
m_builder = PatchUploaderUtility.FindBuilderInProject(); m_builder = PatchUploaderUtility.FindBuilderInProject();
m_builderEditor = Editor.CreateEditor(m_builder); m_builderEditor = Editor.CreateEditor(m_builder);

View File

@ -1,234 +1,238 @@
#if UNITY_EDITOR #if UNITY_EDITOR
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
using VersionFlow.Runtime.Builder; using VersionFlow.Runtime.Builder;
namespace VersionFlow.Runtime namespace VersionFlow.Runtime
{ {
[CreateAssetMenu(fileName = "Builder", menuName = "CreateBuilder")] [CreateAssetMenu(fileName = "Builder", menuName = "CreateBuilder")]
public class BuilderConfig : ScriptableObject public class BuilderConfig : ScriptableObject
{ {
public static bool ShowBuilderMarker public static bool ShowBuilderMarker
{ {
get => EditorPrefs.GetBool("ShowBuilderMarker", true); get => EditorPrefs.GetBool("ShowBuilderMarker", true);
set => EditorPrefs.SetBool("ShowBuilderMarker", value); set => EditorPrefs.SetBool("ShowBuilderMarker", value);
} }
[SerializeField]
internal VersionFlowSetting vfSetting;
[SerializeField]
internal StyleSheet debugGraphBackgroundStyle;
[SerializeField] [SerializeField]
[HideInInspector] [HideInInspector]
internal string uploaderClassName; internal VersionFlowSetting vfSetting;
[SerializeField] [SerializeField]
[HideInInspector] [HideInInspector]
internal UploaderCfgDict UploaderCfgDict; internal StyleSheet debugGraphBackgroundStyle;
public BuildAssetBundleOptions Options; [SerializeField]
[HideInInspector] [HideInInspector]
public List<BuildEntity> Groups; internal string uploaderClassName;
public ShaderVariantCollection SVC; [SerializeField]
[HideInInspector]
[HideInInspector] internal UploaderCfgDict UploaderCfgDict;
public bool DuplicateBundleBeInstallBundle;
[HideInInspector] [HideInInspector]
public bool ShaderBundleBeInstallBundle; public BuildAssetBundleOptions Options;
[HideInInspector]
public delegate void OnCalcBundleHashHandle(string bundleOutputPath, List<AssetBundleBuild> buildInfoList, Dictionary<string, BundleExtraInfo> bundleExtraInfo, AssetBundleManifest report); public List<BuildEntity> Groups;
public OnCalcBundleHashHandle OnCalcBundleHash; [HideInInspector]
public ShaderVariantCollection SVC;
public BundleManifest Build(string version, out string outputPath, out Dictionary<string, BundleExtraInfo> bundleExtraInfo)
{ [HideInInspector]
Dictionary<string, Asset> assetsToBuild = CollectAssetsToBuild(out var shaderGroup); public bool DuplicateBundleBeInstallBundle;
bundleExtraInfo = new Dictionary<string, BundleExtraInfo>(); [HideInInspector]
var duplicateBuilds = CalcDuplicateBuild(assetsToBuild, shaderGroup, ref bundleExtraInfo, DuplicateBundleBeInstallBundle); public bool ShaderBundleBeInstallBundle;
List<AssetBundleBuild> buildInfoList = CalcNormalBuild(assetsToBuild, ref bundleExtraInfo);
public delegate void OnCalcBundleHashHandle(string bundleOutputPath, List<AssetBundleBuild> buildInfoList, Dictionary<string, BundleExtraInfo> bundleExtraInfo, AssetBundleManifest report);
buildInfoList.AddRange(duplicateBuilds); public OnCalcBundleHashHandle OnCalcBundleHash;
public BundleManifest Build(string version, out string outputPath, out Dictionary<string, BundleExtraInfo> bundleExtraInfo)
outputPath = $"./Output/Bundles/{VersionFlowX.PlatformFoldName}"; {
Dictionary<string, Asset> assetsToBuild = CollectAssetsToBuild(out var shaderGroup);
bundleExtraInfo = new Dictionary<string, BundleExtraInfo>();
var duplicateBuilds = CalcDuplicateBuild(assetsToBuild, shaderGroup, ref bundleExtraInfo, DuplicateBundleBeInstallBundle);
List<AssetBundleBuild> buildInfoList = CalcNormalBuild(assetsToBuild, ref bundleExtraInfo);
buildInfoList.AddRange(duplicateBuilds);
outputPath = $"./Output/Bundles/{VersionFlowX.PlatformFoldName}";
Directory.CreateDirectory(outputPath); Directory.CreateDirectory(outputPath);
var report = BuildPipeline.BuildAssetBundles(outputPath, buildInfoList.ToArray(), Options, EditorUserBuildSettings.activeBuildTarget); var report = BuildPipeline.BuildAssetBundles(outputPath, buildInfoList.ToArray(), Options, EditorUserBuildSettings.activeBuildTarget);
if (report != null) if (report != null)
OnCalcBundleHash.Invoke(outputPath, buildInfoList, bundleExtraInfo, report); OnCalcBundleHash.Invoke(outputPath, buildInfoList, bundleExtraInfo, report);
var manifest = BundleManifest.Create(version, bundleExtraInfo, report, outputPath); var manifest = BundleManifest.Create(version, bundleExtraInfo, report, outputPath);
return manifest; return manifest;
} }
public List<BundleCompare> CompareBundleManifest(BundleManifest @new, BundleManifest old) public List<BundleCompare> CompareBundleManifest(BundleManifest @new, BundleManifest old)
{ {
List<BundleCompare> result = new List<BundleCompare>(); List<BundleCompare> result = new List<BundleCompare>();
foreach (var bundle in @new.Bundles) foreach (var bundle in @new.Bundles)
{
var oldBundle = old?.GetBundleByName(bundle.BundleName);
result.Add(new BundleCompare(bundle, oldBundle));
}
//收集被移除的bundle
if (old != null && old.Bundles != null)
{
foreach (var oldBundle in old.Bundles)
{
var newBundle = @new.GetBundleByName(oldBundle.BundleName);
if (newBundle == null)
result.Add(new BundleCompare(null, oldBundle));
}
}
return result;
}
private static List<AssetBundleBuild> CalcNormalBuild(Dictionary<string, Asset> assetsToBuild, ref Dictionary<string, BundleExtraInfo> bundleExtraInfo)
{
Dictionary<string, HashSet<string>> willBuilds = new Dictionary<string, HashSet<string>>();
foreach (var item in assetsToBuild)
{
var assetInfo = item.Value;
if (!willBuilds.ContainsKey(assetInfo.BundleName))
{
willBuilds[assetInfo.BundleName] = new HashSet<string>();
}
BundleExtraInfo info = new BundleExtraInfo();
if (!bundleExtraInfo.TryGetValue(assetInfo.BundleName, out info))
{
info = new BundleExtraInfo();
bundleExtraInfo[assetInfo.BundleName] = info;
//记录Bundle所属Group
info.GroupName = assetInfo.Group.GroupName;
//如果资源所属Group设置了可选Bundle,则标记Asset所在Bundle为可选下载Bundle
info.IsOptionBundle = assetInfo.Group.OptionBundle;
//如果资源所属Group设置了ShaderOnly,则标记Asset所在Bundle为ShaderBundle
info.ShaderBundle = assetInfo.Group.ShaderBundle;
//如果资源所属Group设置了随包资源标记,则标记Asset所在Bundle为随包资源
info.IsInstallBundle = assetInfo.Group.InstallReady;
}
willBuilds[assetInfo.BundleName].Add(assetInfo.FullName);
}
List<AssetBundleBuild> buildInfoList = new List<AssetBundleBuild>();
foreach (var item in willBuilds)
{
var buildInfo = new AssetBundleBuild { assetBundleName = item.Key };
List<string> assetPaths = new List<string>();
foreach (var assetPath in item.Value)
{
assetPaths.Add(assetPath);
}
buildInfo.assetNames = assetPaths.ToArray();
buildInfoList.Add(buildInfo);
}
return buildInfoList;
}
private static List<AssetBundleBuild> CalcDuplicateBuild(Dictionary<string, Asset> assetsToBuild, BuildEntity shaderGroup, ref Dictionary<string, BundleExtraInfo> bundleExtraInfo, bool DuplicateBundleBeInstallBundle)
{
Dictionary<string, int> dependencyAssetsNotBuild = new Dictionary<string, int>();
foreach (var asset in assetsToBuild.Values)
{
foreach (var depAsset in asset.dependencyAssets)
{
if (assetsToBuild.ContainsKey(depAsset)) continue;//跳过原本就会打包的Asset
if (dependencyAssetsNotBuild.ContainsKey(depAsset))
dependencyAssetsNotBuild[depAsset]++;
else
dependencyAssetsNotBuild[depAsset] = 1;
}
}
AssetBundleBuild duplicateBuild = new AssetBundleBuild { assetBundleName = "duplicate.bundle" };
bundleExtraInfo[duplicateBuild.assetBundleName] = new BundleExtraInfo
{
BundleName = duplicateBuild.assetBundleName.ToLower(),
GroupName = null,
IsOptionBundle = false,
ShaderBundle = false,
IsInstallBundle = DuplicateBundleBeInstallBundle,
};
List<string> duplicateAssets = new List<string>();
//重复依赖资源生成打包配置
foreach (var item in dependencyAssetsNotBuild)
{
var assetPath = item.Key;
var assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
//shader类型资源进shaderbundle,而不进duplicate.bundle
if (assetType == typeof(Shader) || assetType == typeof(ShaderVariantCollection))
{
var shaderAsset = new Asset(assetPath);
shaderAsset.Group = shaderGroup;
shaderAsset.BundleName = "ShaderFromSVC_Together.bundle".ToLower();
assetsToBuild[assetPath] = shaderAsset;
continue;
}
if (item.Value == 1) continue; //只有一次依赖的跳过
duplicateAssets.Add(assetPath);
}
duplicateBuild.assetNames = duplicateAssets.ToArray();
return new List<AssetBundleBuild> { duplicateBuild };
}
private Dictionary<string, Asset> CollectAssetsToBuild(out BuildEntity shaderGroup)
{
Dictionary<string, Asset> assetsToBuild = new Dictionary<string, Asset>();
int totalCount = Groups.Count;
int step = 0;
foreach (var group in Groups)
{ {
EditorUtility.DisplayProgressBar($"收集打包资源{step}/{totalCount}", $"{group.GroupName}", step * 1f / totalCount); var oldBundle = old?.GetBundleByName(bundle.BundleName);
result.Add(new BundleCompare(bundle, oldBundle));
}
//收集被移除的bundle
if (old != null && old.Bundles != null)
{
foreach (var oldBundle in old.Bundles)
{
var newBundle = @new.GetBundleByName(oldBundle.BundleName);
if (newBundle == null)
result.Add(new BundleCompare(null, oldBundle));
}
}
return result;
}
private static List<AssetBundleBuild> CalcNormalBuild(Dictionary<string, Asset> assetsToBuild, ref Dictionary<string, BundleExtraInfo> bundleExtraInfo)
{
Dictionary<string, HashSet<string>> willBuilds = new Dictionary<string, HashSet<string>>();
foreach (var item in assetsToBuild)
{
var assetInfo = item.Value;
if (!willBuilds.ContainsKey(assetInfo.BundleName))
{
willBuilds[assetInfo.BundleName] = new HashSet<string>();
}
BundleExtraInfo info = new BundleExtraInfo();
if (!bundleExtraInfo.TryGetValue(assetInfo.BundleName, out info))
{
info = new BundleExtraInfo();
bundleExtraInfo[assetInfo.BundleName] = info;
//记录Bundle所属Group
info.GroupName = assetInfo.Group.GroupName;
//如果资源所属Group设置了可选Bundle,则标记Asset所在Bundle为可选下载Bundle
info.IsOptionBundle = assetInfo.Group.OptionBundle;
//如果资源所属Group设置了ShaderOnly,则标记Asset所在Bundle为ShaderBundle
info.ShaderBundle = assetInfo.Group.ShaderBundle;
//如果资源所属Group设置了随包资源标记,则标记Asset所在Bundle为随包资源
info.IsInstallBundle = assetInfo.Group.InstallReady;
}
willBuilds[assetInfo.BundleName].Add(assetInfo.FullName);
}
List<AssetBundleBuild> buildInfoList = new List<AssetBundleBuild>();
foreach (var item in willBuilds)
{
var buildInfo = new AssetBundleBuild { assetBundleName = item.Key };
List<string> assetPaths = new List<string>();
foreach (var assetPath in item.Value)
{
assetPaths.Add(assetPath);
}
buildInfo.assetNames = assetPaths.ToArray();
buildInfoList.Add(buildInfo);
}
return buildInfoList;
}
private static List<AssetBundleBuild> CalcDuplicateBuild(Dictionary<string, Asset> assetsToBuild, BuildEntity shaderGroup, ref Dictionary<string, BundleExtraInfo> bundleExtraInfo, bool DuplicateBundleBeInstallBundle)
{
Dictionary<string, int> dependencyAssetsNotBuild = new Dictionary<string, int>();
foreach (var asset in assetsToBuild.Values)
{
foreach (var depAsset in asset.dependencyAssets)
{
if (assetsToBuild.ContainsKey(depAsset)) continue;//跳过原本就会打包的Asset
if (dependencyAssetsNotBuild.ContainsKey(depAsset))
dependencyAssetsNotBuild[depAsset]++;
else
dependencyAssetsNotBuild[depAsset] = 1;
}
}
AssetBundleBuild duplicateBuild = new AssetBundleBuild { assetBundleName = "duplicate.bundle" };
bundleExtraInfo[duplicateBuild.assetBundleName] = new BundleExtraInfo
{
BundleName = duplicateBuild.assetBundleName.ToLower(),
GroupName = null,
IsOptionBundle = false,
ShaderBundle = false,
IsInstallBundle = DuplicateBundleBeInstallBundle,
};
List<string> duplicateAssets = new List<string>();
//重复依赖资源生成打包配置
foreach (var item in dependencyAssetsNotBuild)
{
var assetPath = item.Key;
var assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
//shader类型资源进shaderbundle,而不进duplicate.bundle
if (assetType == typeof(Shader) || assetType == typeof(ShaderVariantCollection))
{
var shaderAsset = new Asset(assetPath);
shaderAsset.Group = shaderGroup;
shaderAsset.BundleName = "ShaderFromSVC_Together.bundle".ToLower();
assetsToBuild[assetPath] = shaderAsset;
continue;
}
if (item.Value == 1) continue; //只有一次依赖的跳过
duplicateAssets.Add(assetPath);
}
duplicateBuild.assetNames = duplicateAssets.ToArray();
return new List<AssetBundleBuild> { duplicateBuild };
}
private Dictionary<string, Asset> CollectAssetsToBuild(out BuildEntity shaderGroup)
{
Dictionary<string, Asset> assetsToBuild = new Dictionary<string, Asset>();
int totalCount = Groups.Count;
int step = 0;
foreach (var group in Groups)
{
EditorUtility.DisplayProgressBar($"收集打包资源{step}/{totalCount}", $"{group.GroupName}", step * 1f / totalCount);
group.OnHandleAsset = (asset) => group.OnHandleAsset = (asset) =>
{ {
EditorUtility.DisplayProgressBar($"收集打包资源{step}/{totalCount}", $"{asset.FullName}@{group.GroupName}", step * 1f / totalCount); EditorUtility.DisplayProgressBar($"收集打包资源{step}/{totalCount}", $"{asset.FullName}@{group.GroupName}", step * 1f / totalCount);
}; };
group.CollectionAsset(assetsToBuild); group.CollectionAsset(assetsToBuild);
step++; step++;
} }
shaderGroup = new BuildEntity(); shaderGroup = new BuildEntity();
shaderGroup.OptionBundle = false; shaderGroup.OptionBundle = false;
shaderGroup.FolderList = new List<DefaultAsset>(); shaderGroup.FolderList = new List<DefaultAsset>();
shaderGroup.BuildMode = BuildEntity.EnumBuildMode.PackTogether; shaderGroup.BuildMode = BuildEntity.EnumBuildMode.PackTogether;
shaderGroup.GroupName = "ShaderFromSVC"; shaderGroup.GroupName = "ShaderFromSVC";
shaderGroup.ShaderBundle = true; shaderGroup.ShaderBundle = true;
shaderGroup.InstallReady = ShaderBundleBeInstallBundle; shaderGroup.InstallReady = ShaderBundleBeInstallBundle;
if (SVC != null) if (SVC != null)
{ {
var path = AssetDatabase.GetAssetPath(SVC); var path = AssetDatabase.GetAssetPath(SVC);
foreach (var depPath in AssetDatabase.GetDependencies(path)) foreach (var depPath in AssetDatabase.GetDependencies(path))
{ {
var depAssetType = AssetDatabase.GetMainAssetTypeAtPath(depPath); var depAssetType = AssetDatabase.GetMainAssetTypeAtPath(depPath);
if (depAssetType == typeof(Shader) || depAssetType == typeof(ShaderVariantCollection)) if (depAssetType == typeof(Shader) || depAssetType == typeof(ShaderVariantCollection))
{ {
var asset = new Asset(depPath); var asset = new Asset(depPath);
asset.Group = shaderGroup; asset.Group = shaderGroup;
asset.BundleName = "ShaderFromSVC_Together.bundle".ToLower(); asset.BundleName = "ShaderFromSVC_Together.bundle".ToLower();
assetsToBuild[depPath] = asset; assetsToBuild[depPath] = asset;
} }
} }
} }
return assetsToBuild; return assetsToBuild;
} }
} }
[Serializable] [Serializable]
public class UploaderCfgDict : SerializableDictionary<string, string> public class UploaderCfgDict : SerializableDictionary<string, string>
{ {
public string GetUploaderCfg(Type uploaderCfg) public string GetUploaderCfg(Type uploaderCfg)
{ {
TryGetValue(uploaderCfg.FullName, out var json); TryGetValue(uploaderCfg.FullName, out var json);
@ -239,94 +243,94 @@ namespace VersionFlow.Runtime
{ {
this[type.FullName] = json; this[type.FullName] = json;
} }
} }
public class BundleExtraInfo public class BundleExtraInfo
{ {
public string BundleName { get; internal set; } public string BundleName { get; internal set; }
public bool IsOptionBundle { get; internal set; } public bool IsOptionBundle { get; internal set; }
public string GroupName { get; internal set; } public string GroupName { get; internal set; }
public bool ShaderBundle { get; internal set; } public bool ShaderBundle { get; internal set; }
public Hash128 BundleHash { get; internal set; } public Hash128 BundleHash { get; internal set; }
public bool IsInstallBundle { get; internal set; } public bool IsInstallBundle { get; internal set; }
} }
public class BundleCompare public class BundleCompare
{ {
public BundleCompare(Bundle @new, Bundle old) public BundleCompare(Bundle @new, Bundle old)
{ {
New = @new; New = @new;
Old = old; Old = old;
} }
public Bundle New { get; private set; } public Bundle New { get; private set; }
public Bundle Old { get; private set; } public Bundle Old { get; private set; }
public EnumCompare Result public EnumCompare Result
{ {
get get
{ {
if (Old == null) return EnumCompare.Add; if (Old == null) return EnumCompare.Add;
if (New == null) return EnumCompare.Delete; if (New == null) return EnumCompare.Delete;
if (Old.Hash == New.Hash) return EnumCompare.Same; if (Old.Hash == New.Hash) return EnumCompare.Same;
return EnumCompare.Modified; return EnumCompare.Modified;
} }
} }
public override string ToString() public override string ToString()
{ {
var bundleName = New == null ? Old.BundleName : New.BundleName; var bundleName = New == null ? Old.BundleName : New.BundleName;
switch (Result) switch (Result)
{ {
case EnumCompare.Same: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]"; case EnumCompare.Same: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]";
case EnumCompare.Modified: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]"; case EnumCompare.Modified: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]";
case EnumCompare.Add: return $"{bundleName} []->[{New.Hash}]"; case EnumCompare.Add: return $"{bundleName} []->[{New.Hash}]";
case EnumCompare.Delete: return $"{bundleName} [{Old.Hash}]->[]"; case EnumCompare.Delete: return $"{bundleName} [{Old.Hash}]->[]";
default: return $"{bundleName} []->[]"; default: return $"{bundleName} []->[]";
} }
} }
public enum EnumCompare public enum EnumCompare
{ {
Delete, Delete,
Add, Add,
Modified, Modified,
Same, Same,
} }
} }
public class Asset public class Asset
{ {
public string FullName; public string FullName;
public HashSet<string> dependencyAssets; public HashSet<string> dependencyAssets;
public string BundleName { get; internal set; } public string BundleName { get; internal set; }
public BuildEntity Group { get; internal set; } public BuildEntity Group { get; internal set; }
public Asset(string path) public Asset(string path)
{ {
FullName = path; FullName = path;
dependencyAssets = new HashSet<string>(); dependencyAssets = new HashSet<string>();
foreach (var dependPath in AssetDatabase.GetDependencies(FullName)) foreach (var dependPath in AssetDatabase.GetDependencies(FullName))
{ {
if (dependPath == FullName) continue; if (dependPath == FullName) continue;
if (dependPath.EndsWith(".cs")) continue; if (dependPath.EndsWith(".cs")) continue;
dependencyAssets.Add(dependPath); dependencyAssets.Add(dependPath);
} }
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return FullName.GetHashCode(); return FullName.GetHashCode();
} }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return GetHashCode() == obj.GetHashCode(); return GetHashCode() == obj.GetHashCode();
} }
} }
} }
#endif #endif