using System; using System.IO; using System.Diagnostics; using System.Collections; using System.Collections.Generic; namespace YooAsset { /// /// 清单文件 /// [Serializable] internal class PackageManifest { /// /// 文件版本 /// public string FileVersion; /// /// 启用可寻址资源定位 /// public bool EnableAddressable; /// /// 资源定位地址大小写不敏感 /// public bool LocationToLower; /// /// 包含资源GUID数据 /// public bool IncludeAssetGUID; /// /// 文件名称样式 /// public int OutputNameStyle; /// /// 构建资源包类型 /// public int BuildBundleType; /// /// 构建管线名称 /// public string BuildPipeline; /// /// 资源包裹名称 /// public string PackageName; /// /// 资源包裹的版本信息 /// public string PackageVersion; /// /// 资源包裹的备注信息 /// public string PackageNote; /// /// 资源列表(主动收集的资源列表) /// public List AssetList = new List(); /// /// 资源包列表 /// public List BundleList = new List(); /// /// 资源映射集合(提供AssetPath获取PackageAsset) /// [NonSerialized] public Dictionary AssetDic; /// /// 资源路径映射集合(提供Location获取AssetPath) /// [NonSerialized] public Dictionary AssetPathMapping1; /// /// 资源路径映射集合(提供AssetGUID获取AssetPath) /// [NonSerialized] public Dictionary AssetPathMapping2; /// /// 资源包集合(提供BundleName获取PackageBundle) /// [NonSerialized] public Dictionary BundleDic1; /// /// 资源包集合(提供FileName获取PackageBundle) /// [NonSerialized] public Dictionary BundleDic2; /// /// 资源包集合(提供BundleGUID获取PackageBundle) /// [NonSerialized] public Dictionary BundleDic3; /// /// 获取包裹的详细信息 /// public PackageDetails GetPackageDetails() { PackageDetails details = new PackageDetails(); details.FileVersion = FileVersion; details.EnableAddressable = EnableAddressable; details.LocationToLower = LocationToLower; details.IncludeAssetGUID = IncludeAssetGUID; details.OutputNameStyle = OutputNameStyle; details.BuildBundleType = BuildBundleType; details.BuildPipeline = BuildPipeline; details.PackageName = PackageName; details.PackageVersion = PackageVersion; details.PackageNote = PackageNote; details.AssetTotalCount = AssetList.Count; details.BundleTotalCount = BundleList.Count; return details; } /// /// 尝试映射为资源路径 /// public string TryMappingToAssetPath(string location) { if (string.IsNullOrEmpty(location)) return string.Empty; if (AssetPathMapping1.TryGetValue(location, out string assetPath)) return assetPath; else return string.Empty; } /// /// 获取主资源包 /// 注意:传入的资源包ID一定合法有效! /// public PackageBundle GetMainPackageBundle(int bundleID) { if (bundleID >= 0 && bundleID < BundleList.Count) { var packageBundle = BundleList[bundleID]; return packageBundle; } else { throw new Exception($"Invalid bundle id : {bundleID}"); } } /// /// 获取主资源包 /// 注意:传入的资源对象一定合法有效! /// public PackageBundle GetMainPackageBundle(PackageAsset packageAsset) { return GetMainPackageBundle(packageAsset.BundleID); } /// /// 获取依赖列表 /// 注意:传入的资源对象一定合法有效! /// public PackageBundle[] GetAllDependencies(PackageAsset packageAsset) { List result = new List(packageAsset.DependBundleIDs.Length); foreach (var dependID in packageAsset.DependBundleIDs) { var dependBundle = GetMainPackageBundle(dependID); result.Add(dependBundle); } return result.ToArray(); } /// /// 获取依赖列表 /// 注意:传入的资源包对象一定合法有效! /// public PackageBundle[] GetAllDependencies(PackageBundle packageBundle) { List result = new List(packageBundle.DependBundleIDs.Length); foreach (var dependID in packageBundle.DependBundleIDs) { var dependBundle = GetMainPackageBundle(dependID); result.Add(dependBundle); } return result.ToArray(); } /// /// 尝试获取包裹的资源 /// public bool TryGetPackageAsset(string assetPath, out PackageAsset result) { return AssetDic.TryGetValue(assetPath, out result); } /// /// 尝试获取包裹的资源包 /// public bool TryGetPackageBundleByBundleName(string bundleName, out PackageBundle result) { return BundleDic1.TryGetValue(bundleName, out result); } /// /// 尝试获取包裹的资源包 /// public bool TryGetPackageBundleByFileName(string fileName, out PackageBundle result) { return BundleDic2.TryGetValue(fileName, out result); } /// /// 尝试获取包裹的资源包 /// public bool TryGetPackageBundleByBundleGUID(string bundleGUID, out PackageBundle result) { return BundleDic3.TryGetValue(bundleGUID, out result); } /// /// 是否包含资源文件 /// public bool IsIncludeBundleFile(string bundleGUID) { return BundleDic3.ContainsKey(bundleGUID); } /// /// 获取所有的资源信息 /// public AssetInfo[] GetAllAssetInfos() { List result = new List(AssetList.Count); foreach (var packageAsset in AssetList) { AssetInfo assetInfo = new AssetInfo(PackageName, packageAsset, null); result.Add(assetInfo); } return result.ToArray(); } /// /// 获取资源信息列表 /// public AssetInfo[] GetAssetInfosByTags(string[] tags) { List result = new List(100); foreach (var packageAsset in AssetList) { if (packageAsset.HasTag(tags)) { AssetInfo assetInfo = new AssetInfo(PackageName, packageAsset, null); result.Add(assetInfo); } } return result.ToArray(); } /// /// 资源定位地址转换为资源信息。 /// /// 如果转换失败会返回一个无效的资源信息类 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 (AssetPathMapping1.TryGetValue(location, out string assetPath)) { return assetPath; } else { YooLogger.Warning($"Failed to mapping location to asset path : {location}"); return string.Empty; } } /// /// 资源GUID转换为资源信息。 /// /// 如果转换失败会返回一个无效的资源信息类 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; } } #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 } }