360 lines
12 KiB
C#
360 lines
12 KiB
C#
|
using System;
|
|||
|
using System.IO;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
|
|||
|
namespace YooAsset
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 清单文件
|
|||
|
/// </summary>
|
|||
|
[Serializable]
|
|||
|
internal class PackageManifest
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 文件版本
|
|||
|
/// </summary>
|
|||
|
public string FileVersion;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 启用可寻址资源定位
|
|||
|
/// </summary>
|
|||
|
public bool EnableAddressable;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源定位地址大小写不敏感
|
|||
|
/// </summary>
|
|||
|
public bool LocationToLower;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 包含资源GUID数据
|
|||
|
/// </summary>
|
|||
|
public bool IncludeAssetGUID;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 文件名称样式
|
|||
|
/// </summary>
|
|||
|
public int OutputNameStyle;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 构建管线名称
|
|||
|
/// </summary>
|
|||
|
public string BuildPipeline;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源包裹名称
|
|||
|
/// </summary>
|
|||
|
public string PackageName;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源包裹的版本信息
|
|||
|
/// </summary>
|
|||
|
public string PackageVersion;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源列表(主动收集的资源列表)
|
|||
|
/// </summary>
|
|||
|
public List<PackageAsset> AssetList = new List<PackageAsset>();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源包列表
|
|||
|
/// </summary>
|
|||
|
public List<PackageBundle> BundleList = new List<PackageBundle>();
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源包集合(提供BundleName获取PackageBundle)
|
|||
|
/// </summary>
|
|||
|
[NonSerialized]
|
|||
|
public Dictionary<string, PackageBundle> BundleDic1;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源包集合(提供FileName获取PackageBundle)
|
|||
|
/// </summary>
|
|||
|
[NonSerialized]
|
|||
|
public Dictionary<string, PackageBundle> BundleDic2;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源包集合(提供BundleGUID获取PackageBundle)
|
|||
|
/// </summary>
|
|||
|
[NonSerialized]
|
|||
|
public Dictionary<string, PackageBundle> BundleDic3;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源映射集合(提供AssetPath获取PackageAsset)
|
|||
|
/// </summary>
|
|||
|
[NonSerialized]
|
|||
|
public Dictionary<string, PackageAsset> AssetDic;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源路径映射集合(提供Location获取AssetPath)
|
|||
|
/// </summary>
|
|||
|
[NonSerialized]
|
|||
|
public Dictionary<string, string> AssetPathMapping1;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源路径映射集合(提供AssetGUID获取AssetPath)
|
|||
|
/// </summary>
|
|||
|
[NonSerialized]
|
|||
|
public Dictionary<string, string> AssetPathMapping2;
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 尝试映射为资源路径
|
|||
|
/// </summary>
|
|||
|
public string TryMappingToAssetPath(string location)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(location))
|
|||
|
return string.Empty;
|
|||
|
|
|||
|
if (LocationToLower)
|
|||
|
location = location.ToLower();
|
|||
|
|
|||
|
if (AssetPathMapping1.TryGetValue(location, out string assetPath))
|
|||
|
return assetPath;
|
|||
|
else
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取主资源包
|
|||
|
/// 注意:传入的资源路径一定合法有效!
|
|||
|
/// </summary>
|
|||
|
public PackageBundle GetMainPackageBundle(string assetPath)
|
|||
|
{
|
|||
|
if (AssetDic.TryGetValue(assetPath, out PackageAsset packageAsset))
|
|||
|
{
|
|||
|
int bundleID = packageAsset.BundleID;
|
|||
|
if (bundleID >= 0 && bundleID < BundleList.Count)
|
|||
|
{
|
|||
|
var packageBundle = BundleList[bundleID];
|
|||
|
return packageBundle;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
throw new Exception($"Invalid bundle id : {bundleID} Asset path : {assetPath}");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
throw new Exception("Should never get here !");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取资源依赖列表
|
|||
|
/// 注意:传入的资源路径一定合法有效!
|
|||
|
/// </summary>
|
|||
|
public PackageBundle[] GetAllDependencies(string assetPath)
|
|||
|
{
|
|||
|
var packageBundle = GetMainPackageBundle(assetPath);
|
|||
|
List<PackageBundle> result = new List<PackageBundle>(packageBundle.DependIDs.Length);
|
|||
|
foreach (var dependID in packageBundle.DependIDs)
|
|||
|
{
|
|||
|
if (dependID >= 0 && dependID < BundleList.Count)
|
|||
|
{
|
|||
|
var dependBundle = BundleList[dependID];
|
|||
|
result.Add(dependBundle);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
throw new Exception($"Invalid bundle id : {dependID} Asset path : {assetPath}");
|
|||
|
}
|
|||
|
}
|
|||
|
return result.ToArray();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 尝试获取包裹的资源
|
|||
|
/// </summary>
|
|||
|
public bool TryGetPackageAsset(string assetPath, out PackageAsset result)
|
|||
|
{
|
|||
|
return AssetDic.TryGetValue(assetPath, out result);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 尝试获取包裹的资源包
|
|||
|
/// </summary>
|
|||
|
public bool TryGetPackageBundleByBundleName(string bundleName, out PackageBundle result)
|
|||
|
{
|
|||
|
return BundleDic1.TryGetValue(bundleName, out result);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 尝试获取包裹的资源包
|
|||
|
/// </summary>
|
|||
|
public bool TryGetPackageBundleByFileName(string fileName, out PackageBundle result)
|
|||
|
{
|
|||
|
return BundleDic2.TryGetValue(fileName, out result);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 尝试获取包裹的资源包
|
|||
|
/// </summary>
|
|||
|
public bool TryGetPackageBundleByBundleGUID(string bundleGUID, out PackageBundle result)
|
|||
|
{
|
|||
|
return BundleDic3.TryGetValue(bundleGUID, out result);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否包含资源文件
|
|||
|
/// </summary>
|
|||
|
public bool IsIncludeBundleFile(string bundleGUID)
|
|||
|
{
|
|||
|
return BundleDic3.ContainsKey(bundleGUID);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取资源信息列表
|
|||
|
/// </summary>
|
|||
|
public AssetInfo[] GetAssetsInfoByTags(string[] tags)
|
|||
|
{
|
|||
|
List<AssetInfo> result = new List<AssetInfo>(100);
|
|||
|
foreach (var packageAsset in AssetList)
|
|||
|
{
|
|||
|
if (packageAsset.HasTag(tags))
|
|||
|
{
|
|||
|
AssetInfo assetInfo = new AssetInfo(PackageName, packageAsset, null);
|
|||
|
result.Add(assetInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
return result.ToArray();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源定位地址转换为资源信息。
|
|||
|
/// </summary>
|
|||
|
/// <returns>如果转换失败会返回一个无效的资源信息类</returns>
|
|||
|
public AssetInfo ConvertLocationToAssetInfo(string location, System.Type assetType)
|
|||
|
{
|
|||
|
DebugCheckLocation(location);
|
|||
|
|
|||
|
string assetPath = ConvertLocationToAssetInfoMapping(location);
|
|||
|
if (TryGetPackageAsset(assetPath, out PackageAsset packageAsset))
|
|||
|
{
|
|||
|
AssetInfo assetInfo = new AssetInfo(PackageName, packageAsset, assetType);
|
|||
|
return assetInfo;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string error;
|
|||
|
if (string.IsNullOrEmpty(location))
|
|||
|
error = $"The location is null or empty !";
|
|||
|
else
|
|||
|
error = $"The location is invalid : {location}";
|
|||
|
AssetInfo assetInfo = new AssetInfo(PackageName, error);
|
|||
|
return assetInfo;
|
|||
|
}
|
|||
|
}
|
|||
|
private string ConvertLocationToAssetInfoMapping(string location)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(location))
|
|||
|
{
|
|||
|
YooLogger.Error("Failed to mapping location to asset path, The location is null or empty.");
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
|
|||
|
if (LocationToLower)
|
|||
|
location = location.ToLower();
|
|||
|
|
|||
|
if (AssetPathMapping1.TryGetValue(location, out string assetPath))
|
|||
|
{
|
|||
|
return assetPath;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
YooLogger.Warning($"Failed to mapping location to asset path : {location}");
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 资源GUID转换为资源信息。
|
|||
|
/// </summary>
|
|||
|
/// <returns>如果转换失败会返回一个无效的资源信息类</returns>
|
|||
|
public AssetInfo ConvertAssetGUIDToAssetInfo(string assetGUID, System.Type assetType)
|
|||
|
{
|
|||
|
if (IncludeAssetGUID == false)
|
|||
|
{
|
|||
|
YooLogger.Warning("Package manifest not include asset guid ! Please check asset bundle collector settings.");
|
|||
|
AssetInfo assetInfo = new AssetInfo(PackageName, "AssetGUID data is empty !");
|
|||
|
return assetInfo;
|
|||
|
}
|
|||
|
|
|||
|
string assetPath = ConvertAssetGUIDToAssetInfoMapping(assetGUID);
|
|||
|
if (TryGetPackageAsset(assetPath, out PackageAsset packageAsset))
|
|||
|
{
|
|||
|
AssetInfo assetInfo = new AssetInfo(PackageName, packageAsset, assetType);
|
|||
|
return assetInfo;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string error;
|
|||
|
if (string.IsNullOrEmpty(assetGUID))
|
|||
|
error = $"The assetGUID is null or empty !";
|
|||
|
else
|
|||
|
error = $"The assetGUID is invalid : {assetGUID}";
|
|||
|
AssetInfo assetInfo = new AssetInfo(PackageName, error);
|
|||
|
return assetInfo;
|
|||
|
}
|
|||
|
}
|
|||
|
private string ConvertAssetGUIDToAssetInfoMapping(string assetGUID)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(assetGUID))
|
|||
|
{
|
|||
|
YooLogger.Error("Failed to mapping assetGUID to asset path, The assetGUID is null or empty.");
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
|
|||
|
if (AssetPathMapping2.TryGetValue(assetGUID, out string assetPath))
|
|||
|
{
|
|||
|
return assetPath;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
YooLogger.Warning($"Failed to mapping assetGUID to asset path : {assetGUID}");
|
|||
|
return string.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取资源包内的主资源列表
|
|||
|
/// </summary>
|
|||
|
public string[] GetBundleIncludeAssets(string assetPath)
|
|||
|
{
|
|||
|
List<string> assetList = new List<string>();
|
|||
|
if (TryGetPackageAsset(assetPath, out PackageAsset result))
|
|||
|
{
|
|||
|
foreach (var packageAsset in AssetList)
|
|||
|
{
|
|||
|
if (packageAsset.BundleID == result.BundleID)
|
|||
|
{
|
|||
|
assetList.Add(packageAsset.AssetPath);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return assetList.ToArray();
|
|||
|
}
|
|||
|
|
|||
|
#region 调试方法
|
|||
|
[Conditional("DEBUG")]
|
|||
|
private void DebugCheckLocation(string location)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(location) == false)
|
|||
|
{
|
|||
|
// 检查路径末尾是否有空格
|
|||
|
int index = location.LastIndexOf(' ');
|
|||
|
if (index != -1)
|
|||
|
{
|
|||
|
if (location.Length == index + 1)
|
|||
|
YooLogger.Warning($"Found blank character in location : \"{location}\"");
|
|||
|
}
|
|||
|
|
|||
|
if (location.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0)
|
|||
|
YooLogger.Warning($"Found illegal character in location : \"{location}\"");
|
|||
|
}
|
|||
|
}
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|