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

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
m_values:
- '{"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
Groups:
- GroupName: Backpack

View File

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

View File

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

View File

@ -1,234 +1,238 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using VersionFlow.Runtime.Builder;
namespace VersionFlow.Runtime
{
[CreateAssetMenu(fileName = "Builder", menuName = "CreateBuilder")]
public class BuilderConfig : ScriptableObject
{
public static bool ShowBuilderMarker
{
get => EditorPrefs.GetBool("ShowBuilderMarker", true);
set => EditorPrefs.SetBool("ShowBuilderMarker", value);
}
[SerializeField]
internal VersionFlowSetting vfSetting;
[SerializeField]
internal StyleSheet debugGraphBackgroundStyle;
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using VersionFlow.Runtime.Builder;
namespace VersionFlow.Runtime
{
[CreateAssetMenu(fileName = "Builder", menuName = "CreateBuilder")]
public class BuilderConfig : ScriptableObject
{
public static bool ShowBuilderMarker
{
get => EditorPrefs.GetBool("ShowBuilderMarker", true);
set => EditorPrefs.SetBool("ShowBuilderMarker", value);
}
[SerializeField]
[HideInInspector]
internal string uploaderClassName;
[HideInInspector]
internal VersionFlowSetting vfSetting;
[SerializeField]
[HideInInspector]
internal UploaderCfgDict UploaderCfgDict;
public BuildAssetBundleOptions Options;
[HideInInspector]
public List<BuildEntity> Groups;
public ShaderVariantCollection SVC;
[HideInInspector]
public bool DuplicateBundleBeInstallBundle;
[HideInInspector]
public bool ShaderBundleBeInstallBundle;
public delegate void OnCalcBundleHashHandle(string bundleOutputPath, List<AssetBundleBuild> buildInfoList, Dictionary<string, BundleExtraInfo> bundleExtraInfo, AssetBundleManifest report);
public OnCalcBundleHashHandle OnCalcBundleHash;
public BundleManifest Build(string version, out string outputPath, out Dictionary<string, BundleExtraInfo> bundleExtraInfo)
{
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}";
[HideInInspector]
internal StyleSheet debugGraphBackgroundStyle;
[SerializeField]
[HideInInspector]
internal string uploaderClassName;
[SerializeField]
[HideInInspector]
internal UploaderCfgDict UploaderCfgDict;
[HideInInspector]
public BuildAssetBundleOptions Options;
[HideInInspector]
public List<BuildEntity> Groups;
[HideInInspector]
public ShaderVariantCollection SVC;
[HideInInspector]
public bool DuplicateBundleBeInstallBundle;
[HideInInspector]
public bool ShaderBundleBeInstallBundle;
public delegate void OnCalcBundleHashHandle(string bundleOutputPath, List<AssetBundleBuild> buildInfoList, Dictionary<string, BundleExtraInfo> bundleExtraInfo, AssetBundleManifest report);
public OnCalcBundleHashHandle OnCalcBundleHash;
public BundleManifest Build(string version, out string outputPath, out Dictionary<string, BundleExtraInfo> bundleExtraInfo)
{
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);
var report = BuildPipeline.BuildAssetBundles(outputPath, buildInfoList.ToArray(), Options, EditorUserBuildSettings.activeBuildTarget);
var report = BuildPipeline.BuildAssetBundles(outputPath, buildInfoList.ToArray(), Options, EditorUserBuildSettings.activeBuildTarget);
if (report != null)
OnCalcBundleHash.Invoke(outputPath, buildInfoList, bundleExtraInfo, report);
var manifest = BundleManifest.Create(version, bundleExtraInfo, report, outputPath);
return manifest;
}
public List<BundleCompare> CompareBundleManifest(BundleManifest @new, BundleManifest old)
{
List<BundleCompare> result = new List<BundleCompare>();
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)
OnCalcBundleHash.Invoke(outputPath, buildInfoList, bundleExtraInfo, report);
var manifest = BundleManifest.Create(version, bundleExtraInfo, report, outputPath);
return manifest;
}
public List<BundleCompare> CompareBundleManifest(BundleManifest @new, BundleManifest old)
{
List<BundleCompare> result = new List<BundleCompare>();
foreach (var bundle in @new.Bundles)
{
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) =>
{
EditorUtility.DisplayProgressBar($"收集打包资源{step}/{totalCount}", $"{asset.FullName}@{group.GroupName}", step * 1f / totalCount);
};
group.CollectionAsset(assetsToBuild);
step++;
}
shaderGroup = new BuildEntity();
shaderGroup.OptionBundle = false;
shaderGroup.FolderList = new List<DefaultAsset>();
shaderGroup.BuildMode = BuildEntity.EnumBuildMode.PackTogether;
shaderGroup.GroupName = "ShaderFromSVC";
shaderGroup.ShaderBundle = true;
shaderGroup.InstallReady = ShaderBundleBeInstallBundle;
if (SVC != null)
{
var path = AssetDatabase.GetAssetPath(SVC);
foreach (var depPath in AssetDatabase.GetDependencies(path))
{
var depAssetType = AssetDatabase.GetMainAssetTypeAtPath(depPath);
if (depAssetType == typeof(Shader) || depAssetType == typeof(ShaderVariantCollection))
{
var asset = new Asset(depPath);
asset.Group = shaderGroup;
asset.BundleName = "ShaderFromSVC_Together.bundle".ToLower();
assetsToBuild[depPath] = asset;
}
}
}
return assetsToBuild;
group.CollectionAsset(assetsToBuild);
step++;
}
shaderGroup = new BuildEntity();
shaderGroup.OptionBundle = false;
shaderGroup.FolderList = new List<DefaultAsset>();
shaderGroup.BuildMode = BuildEntity.EnumBuildMode.PackTogether;
shaderGroup.GroupName = "ShaderFromSVC";
shaderGroup.ShaderBundle = true;
shaderGroup.InstallReady = ShaderBundleBeInstallBundle;
if (SVC != null)
{
var path = AssetDatabase.GetAssetPath(SVC);
foreach (var depPath in AssetDatabase.GetDependencies(path))
{
var depAssetType = AssetDatabase.GetMainAssetTypeAtPath(depPath);
if (depAssetType == typeof(Shader) || depAssetType == typeof(ShaderVariantCollection))
{
var asset = new Asset(depPath);
asset.Group = shaderGroup;
asset.BundleName = "ShaderFromSVC_Together.bundle".ToLower();
assetsToBuild[depPath] = asset;
}
}
}
return assetsToBuild;
}
}
[Serializable]
}
[Serializable]
public class UploaderCfgDict : SerializableDictionary<string, string>
{
{
public string GetUploaderCfg(Type uploaderCfg)
{
TryGetValue(uploaderCfg.FullName, out var json);
@ -239,94 +243,94 @@ namespace VersionFlow.Runtime
{
this[type.FullName] = json;
}
}
public class BundleExtraInfo
{
public string BundleName { get; internal set; }
public bool IsOptionBundle { get; internal set; }
public string GroupName { get; internal set; }
public bool ShaderBundle { get; internal set; }
public Hash128 BundleHash { get; internal set; }
public bool IsInstallBundle { get; internal set; }
}
public class BundleCompare
{
public BundleCompare(Bundle @new, Bundle old)
{
New = @new;
Old = old;
}
public Bundle New { get; private set; }
public Bundle Old { get; private set; }
public EnumCompare Result
{
get
{
if (Old == null) return EnumCompare.Add;
if (New == null) return EnumCompare.Delete;
if (Old.Hash == New.Hash) return EnumCompare.Same;
return EnumCompare.Modified;
}
}
public override string ToString()
{
var bundleName = New == null ? Old.BundleName : New.BundleName;
switch (Result)
{
case EnumCompare.Same: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]";
case EnumCompare.Modified: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]";
case EnumCompare.Add: return $"{bundleName} []->[{New.Hash}]";
case EnumCompare.Delete: return $"{bundleName} [{Old.Hash}]->[]";
default: return $"{bundleName} []->[]";
}
}
public enum EnumCompare
{
Delete,
Add,
Modified,
Same,
}
}
public class Asset
{
public string FullName;
public HashSet<string> dependencyAssets;
public string BundleName { get; internal set; }
public BuildEntity Group { get; internal set; }
public Asset(string path)
{
FullName = path;
dependencyAssets = new HashSet<string>();
foreach (var dependPath in AssetDatabase.GetDependencies(FullName))
{
if (dependPath == FullName) continue;
if (dependPath.EndsWith(".cs")) continue;
dependencyAssets.Add(dependPath);
}
}
public override int GetHashCode()
{
return FullName.GetHashCode();
}
public override bool Equals(object obj)
{
return GetHashCode() == obj.GetHashCode();
}
}
}
public class BundleExtraInfo
{
public string BundleName { get; internal set; }
public bool IsOptionBundle { get; internal set; }
public string GroupName { get; internal set; }
public bool ShaderBundle { get; internal set; }
public Hash128 BundleHash { get; internal set; }
public bool IsInstallBundle { get; internal set; }
}
public class BundleCompare
{
public BundleCompare(Bundle @new, Bundle old)
{
New = @new;
Old = old;
}
public Bundle New { get; private set; }
public Bundle Old { get; private set; }
public EnumCompare Result
{
get
{
if (Old == null) return EnumCompare.Add;
if (New == null) return EnumCompare.Delete;
if (Old.Hash == New.Hash) return EnumCompare.Same;
return EnumCompare.Modified;
}
}
public override string ToString()
{
var bundleName = New == null ? Old.BundleName : New.BundleName;
switch (Result)
{
case EnumCompare.Same: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]";
case EnumCompare.Modified: return $"{bundleName} [{Old.Hash}]->[{New.Hash}]";
case EnumCompare.Add: return $"{bundleName} []->[{New.Hash}]";
case EnumCompare.Delete: return $"{bundleName} [{Old.Hash}]->[]";
default: return $"{bundleName} []->[]";
}
}
public enum EnumCompare
{
Delete,
Add,
Modified,
Same,
}
}
public class Asset
{
public string FullName;
public HashSet<string> dependencyAssets;
public string BundleName { get; internal set; }
public BuildEntity Group { get; internal set; }
public Asset(string path)
{
FullName = path;
dependencyAssets = new HashSet<string>();
foreach (var dependPath in AssetDatabase.GetDependencies(FullName))
{
if (dependPath == FullName) continue;
if (dependPath.EndsWith(".cs")) continue;
dependencyAssets.Add(dependPath);
}
}
public override int GetHashCode()
{
return FullName.GetHashCode();
}
public override bool Equals(object obj)
{
return GetHashCode() == obj.GetHashCode();
}
}
}
#endif