IEnumerable <string> GetAllValidAssetPathsFromDirectory(string path, bool recurseAll) { var files = from file in Directory.EnumerateFiles(path, "*.*", recurseAll ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly) where AddressableAssetUtility.IsPathValidForEntry(file) let convertedPath = file.Replace('\\', '/') where !BuiltinSceneCache.Contains(convertedPath) select convertedPath; return(files); }
/// <summary> /// Gets an entry for this folder entry /// </summary> /// <param name="subAssetGuid"></param> /// <param name="subAssetPath"></param> /// <returns></returns> /// <remarks>Assumes that this asset entry is a valid folder asset</remarks> internal AddressableAssetEntry GetFolderSubEntry(string subAssetGuid, string subAssetPath) { string assetPath = AssetPath; if (string.IsNullOrEmpty(assetPath) || !subAssetPath.StartsWith(assetPath)) { return(null); } var settings = parentGroup.Settings; AddressableAssetEntry assetEntry = settings.FindAssetEntry(subAssetGuid); if (assetEntry != null) { if (assetEntry.IsSubAsset && assetEntry.ParentEntry == this) { return(assetEntry); } return(null); } string relativePath = subAssetPath.Remove(0, assetPath.Length + 1); string[] splitRelativePath = relativePath.Split('/'); string folderPath = assetPath; for (int i = 0; i < splitRelativePath.Length - 1; ++i) { folderPath = folderPath + "/" + splitRelativePath[i]; string folderGuid = AssetDatabase.AssetPathToGUID(folderPath); if (!AddressableAssetUtility.IsPathValidForEntry(folderPath)) { return(null); } var folderEntry = settings.CreateSubEntryIfUnique(folderGuid, address + "/" + folderPath.Remove(assetPath.Length), this); if (folderEntry != null) { folderEntry.IsInResources = IsInResources; folderEntry.m_Labels = m_Labels; folderEntry.IsFolder = true; } else { return(null); } } assetEntry = settings.CreateSubEntryIfUnique(subAssetGuid, address + relativePath, this); if (assetEntry == null || assetEntry.IsSubAsset == false) { return(null); } return(assetEntry); }
internal void CreateCatalogEntriesInternal(List <ContentCatalogDataEntry> entries, bool isBundled, string providerType, IEnumerable <object> dependencies, object extraData, Dictionary <GUID, AssetLoadInfo> depInfo, HashSet <Type> providerTypes, bool includeAddress, bool includeGUID, bool includeLabels, HashSet <string> assetsInBundle) { if (string.IsNullOrEmpty(AssetPath)) { return; } string assetPath = GetAssetLoadPath(isBundled, assetsInBundle); List <object> keyList = CreateKeyList(includeAddress, includeGUID, includeLabels); if (keyList.Count == 0) { return; } //The asset may have previously been invalid. Since then, it may have been re-imported. //This can occur in particular when using ScriptedImporters with complex, multi-step behavior. //Double-check the type here in case the asset has been imported correctly after we cached its type. if (MainAssetType == typeof(DefaultAsset)) { m_cachedMainAssetType = null; } Type mainType = AddressableAssetUtility.MapEditorTypeToRuntimeType(MainAssetType, false); if ((mainType == null || mainType == typeof(DefaultAsset)) && !IsInResources) { var t = MainAssetType; Debug.LogWarningFormat("Type {0} is in editor assembly {1}. Asset location with internal id {2} will be stripped.", t.Name, t.Assembly.FullName, assetPath); return; } Type runtimeProvider = GetRuntimeProviderType(providerType, mainType); if (runtimeProvider != null) { providerTypes.Add(runtimeProvider); } if (!IsScene) { ObjectIdentifier[] ids = depInfo != null ? depInfo[new GUID(guid)].includedObjects.ToArray() : ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(guid), EditorUserBuildSettings.activeBuildTarget); foreach (var t in GatherSubObjectTypes(ids, guid)) { entries.Add(new ContentCatalogDataEntry(t, assetPath, providerType, keyList, dependencies, extraData)); } } else if (mainType != null && mainType != typeof(DefaultAsset)) { entries.Add(new ContentCatalogDataEntry(mainType, assetPath, providerType, keyList, dependencies, extraData)); } }
/// <summary> /// Marks the object as modified. /// </summary> /// <param name="modificationEvent">The event type that is changed.</param> /// <param name="eventData">The object data that corresponds to the event.</param> /// <param name="postEvent">If true, the event is propagated to callbacks.</param> public void SetDirty(AddressableAssetSettings.ModificationEvent modificationEvent, object eventData, bool postEvent) { if (Settings != null) { if (Settings.IsPersisted && this != null) { EditorUtility.SetDirty(this); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(this); } Settings.SetDirty(modificationEvent, eventData, postEvent, false); } }
static void SetDirty(Object obj) { UnityEngine.GUI.changed = true; // To support EditorGUI.BeginChangeCheck() / EditorGUI.EndChangeCheck() EditorUtility.SetDirty(obj); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(obj); var comp = obj as Component; if (comp != null && comp.gameObject != null && comp.gameObject.activeInHierarchy) { EditorSceneManager.MarkSceneDirty(comp.gameObject.scene); } }
internal void GatherResourcesEntries(List <AddressableAssetEntry> assets, bool recurseAll, Func <AddressableAssetEntry, bool> entryFilter) { var settings = parentGroup.Settings; var pd = parentGroup.GetSchema <GroupSchemas.PlayerDataGroupSchema>(); if (pd.IncludeResourcesFolders) { foreach (var resourcesDir in GetResourceDirectories()) { foreach (var file in Directory.GetFiles(resourcesDir, "*.*", recurseAll ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) { if (AddressableAssetUtility.IsPathValidForEntry(file)) { var g = AssetDatabase.AssetPathToGUID(file); var addr = GetResourcesPath(file); var entry = settings.CreateSubEntryIfUnique(g, addr, this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInResources = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } if (!recurseAll) { foreach (var folder in Directory.GetDirectories(resourcesDir)) { if (AssetDatabase.IsValidFolder(folder)) { var entry = settings.CreateSubEntryIfUnique(AssetDatabase.AssetPathToGUID(folder), GetResourcesPath(folder), this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInResources = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } } } }
/// <summary> /// Updates the CCD buckets and badges with the data source settings /// </summary> /// <param name="projectId">Project Id connected to Unity Services</param> /// <param name="showInfoLog">Whether or not to show debug logs or not</param> /// <returns>List of ProfileGroupType</returns> public static async Task <List <ProfileGroupType> > UpdateCCDDataSourcesAsync(string projectId, bool showInfoLog) { if (showInfoLog) { Addressables.Log("Syncing CCD Buckets and Badges."); } var settings = GetSettings(); var profileGroupTypes = new List <ProfileGroupType>(); profileGroupTypes.AddRange(CreateDefaultGroupTypes()); await CCDManagementAPIService.SetConfigurationAuthHeader(CloudProjectSettings.accessToken); var bucketDictionary = await GetAllBucketsAsync(projectId); foreach (var kvp in bucketDictionary) { var bucket = kvp.Value; var badges = await GetAllBadgesAsync(projectId, bucket.Id.ToString()); if (badges.Count == 0) { badges.Add(new CcdBadge(name: "latest")); } foreach (var badge in badges) { var groupType = new ProfileGroupType($"CCD{ProfileGroupType.k_PrefixSeparator}{projectId}{ProfileGroupType.k_PrefixSeparator}{bucket.Id}{ProfileGroupType.k_PrefixSeparator}{badge.Name}"); groupType.AddVariable(new ProfileGroupType.GroupTypeVariable($"{nameof(CcdBucket)}{nameof(CcdBucket.Name)}", bucket.Name)); groupType.AddVariable(new ProfileGroupType.GroupTypeVariable($"{nameof(CcdBucket)}{nameof(CcdBucket.Id)}", bucket.Id.ToString())); groupType.AddVariable(new ProfileGroupType.GroupTypeVariable($"{nameof(CcdBadge)}{nameof(CcdBadge.Name)}", badge.Name)); groupType.AddVariable(new ProfileGroupType.GroupTypeVariable(nameof(CcdBucket.Attributes.PromoteOnly), bucket.Attributes.PromoteOnly.ToString())); string buildPath = $"{AddressableAssetSettings.kCCDBuildDataPath}/{bucket.Id}/{badge.Name}"; groupType.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kBuildPath, buildPath)); string loadPath = $"https://{projectId}.client-api.unity3dusercontent.com/client_api/v1/buckets/{bucket.Id}/release_by_badge/{badge.Name}/entry_by_path/content/?path="; groupType.AddVariable(new ProfileGroupType.GroupTypeVariable(AddressableAssetSettings.kLoadPath, loadPath)); profileGroupTypes.Add(groupType); } } settings.profileGroupTypes = profileGroupTypes; if (showInfoLog) { Addressables.Log("Successfully synced CCD Buckets and Badges."); } EditorUtility.SetDirty(settings); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(settings); return(settings.profileGroupTypes); }
internal void CreateCatalogEntriesInternal(List <ContentCatalogDataEntry> entries, bool isBundled, string providerType, IEnumerable <object> dependencies, object extraData, Dictionary <GUID, AssetLoadInfo> depInfo) { if (string.IsNullOrEmpty(AssetPath)) { return; } string assetPath = GetAssetLoadPath(isBundled); List <object> keyList = CreateKeyList(); Type mainType = AddressableAssetUtility.MapEditorTypeToRuntimeType(MainAssetType, false); if (mainType == null && !IsInResources) { var t = MainAssetType; Debug.LogWarningFormat("Type {0} is in editor assembly {1}. Asset location with internal id {2} will be stripped.", t.Name, t.Assembly.FullName, assetPath); return; } if (mainType != null) { entries.Add(new ContentCatalogDataEntry(mainType, assetPath, providerType, keyList, dependencies, extraData)); } if (!IsScene) { ObjectIdentifier[] ids = depInfo != null ? depInfo[new GUID(guid)].includedObjects.ToArray() : ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(guid), EditorUserBuildSettings.activeBuildTarget); if (ids.Length > 1) { Type [] typesForObjs = ContentBuildInterface.GetTypeForObjects(ids); HashSet <Type> typesSeen = new HashSet <Type>(); typesSeen.Add(mainType); foreach (var objType in typesForObjs) { if (typeof(Component).IsAssignableFrom(objType)) { continue; } Type rtType = AddressableAssetUtility.MapEditorTypeToRuntimeType(objType, false); if (rtType != null && !typesSeen.Contains(rtType)) { entries.Add(new ContentCatalogDataEntry(rtType, assetPath, providerType, keyList, dependencies, extraData)); typesSeen.Add(rtType); } } } } }
/// <summary> /// Used to notify the addressables settings that data has been modified. This must be called by subclasses to ensure proper cache invalidation. /// </summary> /// <param name="postEvent">Determines if this method call will post an event to the internal addressables event system</param> protected void SetDirty(bool postEvent) { if (m_Group != null) { if (m_Group.Settings != null && m_Group.Settings.IsPersisted) { EditorUtility.SetDirty(this); AddressableAssetUtility.OpenAssetIfUsingVCIntegration(this); } if (m_Group != null) { m_Group.SetDirty(AddressableAssetSettings.ModificationEvent.GroupSchemaModified, this, postEvent, false); } } }
static IEnumerable <string> GetResourceDirectories() { foreach (string path in GetResourceDirectoriesatPath("Assets")) { yield return(path); } List <PackageManager.PackageInfo> packages = AddressableAssetUtility.GetPackages(); foreach (PackageManager.PackageInfo package in packages) { foreach (string path in GetResourceDirectoriesatPath(package.assetPath)) { yield return(path); } } }
internal void CreateCatalogEntriesInternal(List <ContentCatalogDataEntry> entries, bool isBundled, string providerType, IEnumerable <object> dependencies, object extraData, Dictionary <GUID, AssetLoadInfo> depInfo, HashSet <Type> providerTypes, bool includeAddress, bool includeGUID, bool includeLabels, HashSet <string> assetsInBundle) { if (string.IsNullOrEmpty(AssetPath)) { return; } string assetPath = GetAssetLoadPath(isBundled, assetsInBundle); List <object> keyList = CreateKeyList(includeAddress, includeGUID, includeLabels); if (keyList.Count == 0) { return; } Type mainType = AddressableAssetUtility.MapEditorTypeToRuntimeType(MainAssetType, false); if (mainType == null && !IsInResources) { var t = MainAssetType; Debug.LogWarningFormat("Type {0} is in editor assembly {1}. Asset location with internal id {2} will be stripped.", t.Name, t.Assembly.FullName, assetPath); return; } Type runtimeProvider = GetRuntimeProviderType(providerType, mainType); if (runtimeProvider != null) { providerTypes.Add(runtimeProvider); } if (!IsScene) { ObjectIdentifier[] ids = depInfo != null ? depInfo[new GUID(guid)].includedObjects.ToArray() : ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(guid), EditorUserBuildSettings.activeBuildTarget); foreach (var t in GatherSubObjectTypes(ids, guid)) { entries.Add(new ContentCatalogDataEntry(t, assetPath, providerType, keyList, dependencies, extraData)); } } else if (mainType != null) { entries.Add(new ContentCatalogDataEntry(mainType, assetPath, providerType, keyList, dependencies, extraData)); } }
static void GatherEntryLocations(AddressableAssetEntry entry, Type type, IList <IResourceLocation> locations, AddressableAssetTree assetTree) { if (!string.IsNullOrEmpty(entry.address) && entry.address.Contains("[") && entry.address.Contains("]")) { Debug.LogErrorFormat("Address '{0}' cannot contain '[ ]'.", entry.address); return; } using (new AddressablesFileEnumerationScope(assetTree)) { entry.GatherAllAssets(null, true, true, false, e => { if (e.IsScene) { if (type == null || type == typeof(SceneInstance) || AddressableAssetUtility.MapEditorTypeToRuntimeType(e.MainAssetType, false) == type) { locations.Add(new ResourceLocationBase(e.address, e.AssetPath, typeof(SceneProvider).FullName, typeof(SceneInstance))); } } else if (type == null || type.IsAssignableFrom(e.MainAssetType)) { locations.Add(new ResourceLocationBase(e.address, e.AssetPath, typeof(AssetDatabaseProvider).FullName, e.MainAssetType)); return(true); } else { ObjectIdentifier[] ids = ContentBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(e.guid), EditorUserBuildSettings.activeBuildTarget); if (ids.Length > 1) { foreach (var t in AddressableAssetEntry.GatherSubObjectTypes(ids, e.guid)) { if (type.IsAssignableFrom(t)) { locations.Add(new ResourceLocationBase(e.address, e.AssetPath, typeof(AssetDatabaseProvider).FullName, t)); } } return(true); } } return(false); }); } }
internal static void AddLocations(IList <IResourceLocation> locations, Type type, string keyStr, string internalId) { if (!string.IsNullOrEmpty(internalId) && !string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(internalId))) { if (type == m_SpriteType && AssetDatabase.GetMainAssetTypeAtPath(internalId) == m_SpriteAtlasType) { locations.Add(new ResourceLocationBase(keyStr, internalId, typeof(AssetDatabaseProvider).FullName, m_SpriteAtlasType)); } else { foreach (var obj in AssetDatabaseProvider.LoadAssetsWithSubAssets(internalId)) { var rtt = AddressableAssetUtility.MapEditorTypeToRuntimeType(obj.GetType(), false); if (type.IsAssignableFrom(rtt)) { locations.Add(new ResourceLocationBase(keyStr, internalId, typeof(AssetDatabaseProvider).FullName, rtt)); } } } } }
static internal IEnumerable <Type> GatherSubObjectTypes(ObjectIdentifier[] ids, string guid) { if (ids.Length > 0) { Type[] typesForObjs = ContentBuildInterface.GetTypeForObjects(ids); HashSet <Type> typesSeen = new HashSet <Type>(); foreach (var objType in typesForObjs) { if (typeof(Component).IsAssignableFrom(objType)) { continue; } Type rtType = AddressableAssetUtility.MapEditorTypeToRuntimeType(objType, false); if (rtType != null && !typesSeen.Contains(rtType)) { yield return(rtType); typesSeen.Add(rtType); } } } }
/// <summary> /// Create all entries for this addressable asset. This will expand subassets (Sprites, Meshes, etc) and also different representations. /// </summary> /// <param name="entries">The list of entries to fill in.</param> /// <param name="isBundled">Whether the entry is bundles or not. This will affect the load path.</param> /// <param name="providerType">The provider type for the main entry.</param> /// <param name="dependencies">Keys of dependencies</param> /// <param name="extraData">Extra data to append to catalog entries.</param> /// <param name="providerTypes">Any unknown provider types are added to this set in order to ensure they are not stripped.</param> public void CreateCatalogEntries(List <ContentCatalogDataEntry> entries, bool isBundled, string providerType, IEnumerable <object> dependencies, object extraData, HashSet <Type> providerTypes) { if (string.IsNullOrEmpty(AssetPath)) { return; } var assetPath = GetAssetLoadPath(isBundled); var keyList = CreateKeyList(); var mainType = AddressableAssetUtility.RemapToRuntimeType(MainAssetType); if (mainType == null && !IsInResources) { var t = MainAssetType; Debug.LogWarningFormat("Type {0} is in editor assembly {1}. Asset location with internal id {2} will be stripped.", t.Name, t.Assembly.FullName, assetPath); return; } if (mainType != null) { entries.Add(new ContentCatalogDataEntry(mainType, assetPath, providerType, keyList, dependencies, extraData)); } if (mainType == typeof(SpriteAtlas)) { var atlas = AssetDatabase.LoadAssetAtPath <SpriteAtlas>(AssetPath); var sprites = new Sprite[atlas.spriteCount]; atlas.GetSprites(sprites); for (int i = 0; i < atlas.spriteCount; i++) { var spriteName = sprites[i].name; if (spriteName.EndsWith("(Clone)")) { spriteName = spriteName.Replace("(Clone)", ""); } var namedAddress = string.Format("{0}[{1}]", address, spriteName); var guidAddress = string.Format("{0}[{1}]", guid, spriteName); entries.Add(new ContentCatalogDataEntry(typeof(Sprite), spriteName, typeof(AtlasSpriteProvider).FullName, new object[] { namedAddress, guidAddress }, new object[] { keyList[0] }, extraData)); } providerTypes.Add(typeof(AtlasSpriteProvider)); } HashSet <Type> typesSeen = new HashSet <Type>(); typesSeen.Add(mainType); var objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(AssetPath); for (int i = 0; i < objs.Length; i++) { var o = objs[i]; var t = AddressableAssetUtility.RemapToRuntimeType(o.GetType()); if (t == null) { continue; } var internalId = string.Format("{0}[{1}]", assetPath, o.name); var namedAddress = string.Format("{0}[{1}]", address, o.name); var guidAddress = string.Format("{0}[{1}]", guid, o.name); entries.Add(new ContentCatalogDataEntry(t, internalId, providerType, new object[] { namedAddress, guidAddress }, dependencies, extraData)); if (!typesSeen.Contains(t)) { entries.Add(new ContentCatalogDataEntry(t, assetPath, providerType, keyList, dependencies, extraData)); typesSeen.Add(t); } } }
public void GatherAllAssets(List <AddressableAssetEntry> assets, bool includeSelf, bool recurseAll, Func <AddressableAssetEntry, bool> entryFilter = null) { var settings = parentGroup.Settings; if (guid == EditorSceneListName) { foreach (var s in BuiltinSceneCache.scenes) { if (s.enabled) { var entry = settings.CreateSubEntryIfUnique(s.guid.ToString(), Path.GetFileNameWithoutExtension(s.path), this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInSceneList = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } else if (guid == ResourcesName) { foreach (var resourcesDir in Directory.GetDirectories("Assets", "Resources", SearchOption.AllDirectories)) { foreach (var file in Directory.GetFiles(resourcesDir, "*.*", recurseAll ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) { if (AddressableAssetUtility.IsPathValidForEntry(file)) { var g = AssetDatabase.AssetPathToGUID(file); var addr = GetResourcesPath(file); var entry = settings.CreateSubEntryIfUnique(g, addr, this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInResources = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } if (!recurseAll) { foreach (var folder in Directory.GetDirectories(resourcesDir)) { if (AssetDatabase.IsValidFolder(folder)) { var entry = settings.CreateSubEntryIfUnique(AssetDatabase.AssetPathToGUID(folder), GetResourcesPath(folder), this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInResources = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } } } else { var path = AssetDatabase.GUIDToAssetPath(guid); if (string.IsNullOrEmpty(path)) { return; } if (AssetDatabase.IsValidFolder(path)) { foreach (var fi in Directory.GetFiles(path, "*.*", recurseAll ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) { var file = fi.Replace('\\', '/'); if (AddressableAssetUtility.IsPathValidForEntry(file)) { var subGuid = AssetDatabase.AssetPathToGUID(file); if (!BuiltinSceneCache.Contains(new GUID(subGuid))) { var entry = settings.CreateSubEntryIfUnique(subGuid, address + GetRelativePath(file, path), this); if (entry != null) { entry.IsInResources = IsInResources; //if this is a sub-folder of Resources, copy it on down entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } if (!recurseAll) { foreach (var fo in Directory.GetDirectories(path, "*.*", SearchOption.TopDirectoryOnly)) { var folder = fo.Replace('\\', '/'); if (AssetDatabase.IsValidFolder(folder)) { var entry = settings.CreateSubEntryIfUnique(AssetDatabase.AssetPathToGUID(folder), address + GetRelativePath(folder, path), this); if (entry != null) { entry.IsInResources = IsInResources; //if this is a sub-folder of Resources, copy it on down entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } } else { if (AssetDatabase.GetMainAssetTypeAtPath(path) == typeof(AddressableAssetEntryCollection)) { var col = AssetDatabase.LoadAssetAtPath <AddressableAssetEntryCollection>(AssetPath); if (col != null) { foreach (var e in col.Entries) { var entry = settings.CreateSubEntryIfUnique(e.guid, e.address, this); if (entry != null) { entry.IsInResources = e.IsInResources; foreach (var l in e.labels) { entry.SetLabel(l, true, false); } foreach (var l in m_Labels) { entry.SetLabel(l, true, false); } if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } else { if (includeSelf) { if (entryFilter == null || entryFilter(this)) { assets.Add(this); } } } } } }
/// <summary> /// Gathers all asset entries. Each explicit entry may contain multiple sub entries. For example, addressable folders create entries for each asset contained within. /// </summary> /// <param name="assets">The generated list of entries. For simple entries, this will contain just the entry itself if specified.</param> /// <param name="includeSelf">Determines if the entry should be contained in the result list or just sub entries.</param> /// <param name="recurseAll">Determines if full recursion should be done when gathering entries.</param> /// <param name="includeSubObjects">Determines if sub objects such as sprites should be included.</param> /// <param name="entryFilter">Optional predicate to run against each entry, only returning those that pass. A null filter will return all entries</param> public void GatherAllAssets(List <AddressableAssetEntry> assets, bool includeSelf, bool recurseAll, bool includeSubObjects, Func <AddressableAssetEntry, bool> entryFilter = null) { var settings = parentGroup.Settings; if (guid == EditorSceneListName) { foreach (var s in BuiltinSceneCache.scenes) { if (s.enabled) { var entry = settings.CreateSubEntryIfUnique(s.guid.ToString(), Path.GetFileNameWithoutExtension(s.path), this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInSceneList = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } else if (guid == ResourcesName) { foreach (var resourcesDir in Directory.GetDirectories("Assets", "Resources", SearchOption.AllDirectories)) { foreach (var file in Directory.GetFiles(resourcesDir, "*.*", recurseAll ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) { if (AddressableAssetUtility.IsPathValidForEntry(file)) { var g = AssetDatabase.AssetPathToGUID(file); var addr = GetResourcesPath(file); var entry = settings.CreateSubEntryIfUnique(g, addr, this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInResources = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } if (!recurseAll) { foreach (var folder in Directory.GetDirectories(resourcesDir)) { if (AssetDatabase.IsValidFolder(folder)) { var entry = settings.CreateSubEntryIfUnique(AssetDatabase.AssetPathToGUID(folder), GetResourcesPath(folder), this); if (entry != null) //TODO - it's probably really bad if this is ever null. need some error detection { entry.IsInResources = true; entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } } } else { var path = AssetPath; if (string.IsNullOrEmpty(path)) { return; } if (AssetDatabase.IsValidFolder(path)) { foreach (var fi in Directory.GetFiles(path, "*.*", recurseAll ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)) { var file = fi.Replace('\\', '/'); if (AddressableAssetUtility.IsPathValidForEntry(file)) { var subGuid = AssetDatabase.AssetPathToGUID(file); if (!BuiltinSceneCache.Contains(new GUID(subGuid))) { var entry = settings.CreateSubEntryIfUnique(subGuid, address + GetRelativePath(file, path), this); if (entry != null) { entry.IsInResources = IsInResources; //if this is a sub-folder of Resources, copy it on down entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } if (!recurseAll) { foreach (var fo in Directory.GetDirectories(path, "*.*", SearchOption.TopDirectoryOnly)) { var folder = fo.Replace('\\', '/'); if (AssetDatabase.IsValidFolder(folder)) { var entry = settings.CreateSubEntryIfUnique(AssetDatabase.AssetPathToGUID(folder), address + GetRelativePath(folder, path), this); if (entry != null) { entry.IsInResources = IsInResources; //if this is a sub-folder of Resources, copy it on down entry.m_Labels = m_Labels; if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } } else { if (MainAssetType == typeof(AddressableAssetEntryCollection)) { var col = AssetDatabase.LoadAssetAtPath <AddressableAssetEntryCollection>(AssetPath); if (col != null) { foreach (var e in col.Entries) { var entry = settings.CreateSubEntryIfUnique(e.guid, e.address, this); if (entry != null) { entry.IsInResources = e.IsInResources; foreach (var l in e.labels) { entry.SetLabel(l, true, false); } foreach (var l in m_Labels) { entry.SetLabel(l, true, false); } if (entryFilter == null || entryFilter(entry)) { assets.Add(entry); } } } } } else { if (includeSelf) { if (entryFilter == null || entryFilter(this)) { assets.Add(this); } } if (includeSubObjects) { var mainType = AssetDatabase.GetMainAssetTypeAtPath(AssetPath); if (mainType == typeof(SpriteAtlas)) { var atlas = AssetDatabase.LoadAssetAtPath <SpriteAtlas>(AssetPath); var sprites = new Sprite[atlas.spriteCount]; atlas.GetSprites(sprites); for (int i = 0; i < atlas.spriteCount; i++) { var spriteName = sprites[i].name; if (spriteName.EndsWith("(Clone)")) { spriteName = spriteName.Replace("(Clone)", ""); } var namedAddress = string.Format("{0}[{1}]", address, spriteName); var newEntry = new AddressableAssetEntry("", namedAddress, parentGroup, true); newEntry.IsSubAsset = true; newEntry.ParentEntry = this; newEntry.IsInResources = IsInResources; assets.Add(newEntry); } } var objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(AssetPath); for (int i = 0; i < objs.Length; i++) { var o = objs[i]; var t = o.GetType(); var namedAddress = string.Format("{0}[{1}]", address, o.name); var newEntry = new AddressableAssetEntry("", namedAddress, parentGroup, true); newEntry.IsSubAsset = true; newEntry.ParentEntry = this; newEntry.IsInResources = IsInResources; assets.Add(newEntry); } } } } } }