using System; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Serialization; namespace UnityEditor.AddressableAssets.Settings { using Object = UnityEngine.Object; /// /// Collection of AddressableAssetGroupSchema objects /// [Serializable] public class AddressableAssetGroupSchemaSet { [FormerlySerializedAs("m_schemas")] [SerializeField] List m_Schemas = new List(); /// /// List of schemas for this group. /// public List Schemas { get { return m_Schemas; } } /// /// Get the list of schema types. /// public List Types { get { var types = new List(m_Schemas.Count); foreach (var s in m_Schemas) types.Add(s.GetType()); return types; } } /// /// Adds a copy of the provided schema object. /// /// The schema to copy. /// A function that returns the path where this method can save the schema asset. Set to null to not create an in-project asset. /// The created schema object. public AddressableAssetGroupSchema AddSchema(AddressableAssetGroupSchema schema, Func pathFunc) { if (schema == null) { Debug.LogWarning("Cannot add null Schema object."); return null; } var type = schema.GetType(); if (GetSchema(type) != null) { Debug.LogWarningFormat("Cannot add multiple schemas of the same type: {0}.", type.FullName); return null; } if (pathFunc == null) { m_Schemas.Add(schema); return schema; } var assetName = pathFunc(type); if (File.Exists(assetName)) { Debug.LogWarningFormat("Schema asset already exists at path {0}, relinking.", assetName); var existingSchema = AssetDatabase.LoadAssetAtPath(assetName, type) as AddressableAssetGroupSchema; m_Schemas.Add(existingSchema); return existingSchema; } var newSchema = Object.Instantiate(schema); if (!string.IsNullOrEmpty(assetName)) { var dir = Path.GetDirectoryName(assetName); if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir); AssetDatabase.CreateAsset(newSchema, assetName); } m_Schemas.Add(newSchema); return newSchema; } /// /// Creates and adds a schema of a given type to this group. The schema asset will be created in the GroupSchemas directory relative to the settings asset. /// /// The schema type. This type must not already be added. /// A function that returns the path where this method can save the schema asset. Set to null to not create an in-project asset. /// The created schema object. public AddressableAssetGroupSchema AddSchema(Type type, Func pathFunc) { if (type == null) { Debug.LogWarning("Cannot add null Schema type."); return null; } if (!typeof(AddressableAssetGroupSchema).IsAssignableFrom(type)) { Debug.LogWarningFormat("Invalid Schema type {0}. Schemas must inherit from AddressableAssetGroupSchema.", type.FullName); return null; } var existing = GetSchema(type); if (existing != null) { Debug.LogWarningFormat("Cannot add multiple schemas of the same type: {0}.", existing.GetType().FullName); return existing; } var assetName = pathFunc(type); if (File.Exists(assetName)) { Debug.LogWarningFormat("Schema asset already exists at path {0}, relinking.", assetName); var existingSchema = AssetDatabase.LoadAssetAtPath(assetName, type) as AddressableAssetGroupSchema; m_Schemas.Add(existingSchema); return existingSchema; } var schema = ScriptableObject.CreateInstance(type) as AddressableAssetGroupSchema; if (!string.IsNullOrEmpty(assetName)) { var dir = Path.GetDirectoryName(assetName); if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir); AssetDatabase.CreateAsset(schema, assetName); } m_Schemas.Add(schema); return schema; } /// /// Remove a given schema from this group. /// /// The schema type. /// True if the schema was found and removed, false otherwise. public bool RemoveSchema(Type type) { for (int i = 0; i < m_Schemas.Count; i++) { var s = m_Schemas[i]; if (s.GetType() == type) { m_Schemas.RemoveAt(i); string guid; long lfid; if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(s, out guid, out lfid)) AssetDatabase.DeleteAsset(AssetDatabase.GUIDToAssetPath(guid)); return true; } } return false; } /// /// Gets an added schema of the specified type. /// /// The schema type. /// The schema if found, otherwise null. public AddressableAssetGroupSchema GetSchema(Type type) { if (type == null) { Debug.LogWarning("Cannot get schema with null type."); return null; } if (!typeof(AddressableAssetGroupSchema).IsAssignableFrom(type)) { Debug.LogWarningFormat("Invalid Schema type {0}. Schemas must inherit from AddressableAssetGroupSchema.", type.FullName); return null; } foreach (var s in m_Schemas) if (type == s.GetType()) return s; return null; } /// /// Removes all schemas and optionally deletes the assets associated with them. /// /// If true, the schema assets will also be deleted. public void ClearSchemas(bool deleteAssets) { if (deleteAssets) { for (int i = 0; i < m_Schemas.Count; i++) { var s = m_Schemas[i]; string guid; long lfid; if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(s, out guid, out lfid)) { var path = AssetDatabase.GUIDToAssetPath(guid); if (File.Exists(path)) AssetDatabase.DeleteAsset(path); } } } m_Schemas.Clear(); } internal bool RenameSchemaAssets(Func pathFunc) { bool result = true; foreach (var schema in m_Schemas) { string guid; if (!AssetDatabase.TryGetGUIDAndLocalFileIdentifier(schema, out guid, out long lfid)) continue; string path = AssetDatabase.GUIDToAssetPath(guid); if (string.IsNullOrEmpty(path)) continue; string newPath = pathFunc(schema.GetType()); if (path == newPath) continue; string setPath = AssetDatabase.MoveAsset(path, newPath); if (!string.IsNullOrEmpty(setPath)) result = false; } return result; } } }