using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using UnityEditor; using UnityEngine; using UnityObject = UnityEngine.Object; namespace Unity.VisualScripting { public static class AssetUtility { public static IEnumerable GetAllAssetsOfType() { if (typeof(UnityObject).IsAssignableFrom(typeof(T))) { return AssetDatabase.FindAssets($"t:{typeof(T).Name}") .Select(AssetDatabase.GUIDToAssetPath) .Select(AssetDatabase.LoadMainAssetAtPath) .OfType(); } else { // GetAllAssetPaths is undocumented and sometimes returns // paths that are outside the assets folder, hence the where filter. var result = AssetDatabase.GetAllAssetPaths() .Where(p => p.StartsWith("Assets")) .Select(AssetDatabase.LoadMainAssetAtPath) .OfType(); EditorUtility.UnloadUnusedAssetsImmediate(); return result; } } public static string GetSelectedFolderPath() { foreach (UnityObject uo in Selection.GetFiltered(typeof(UnityObject), SelectionMode.Assets)) { var assetPath = AssetDatabase.GetAssetPath(uo); if (AssetDatabase.IsValidFolder(assetPath)) { return Path.Combine(Paths.project, assetPath); } } return null; } public static int GetFileID(string @namespace, string name) { // Gets the fileID of a given type inside a DLL asset. // "Given a type t, the fileID is equal to the first four bytes of the MD4 of the string `"s\0\0\0" + t.Namespace + t.Name' as a little endian 32-byte integer." // https://forum.unity.com/threads/yaml-fileid-hash-function-for-dll-scripts.252075/#post-1695479 string toBeHashed = "s\0\0\0" + @namespace + name; using (var hash = new MD4()) { byte[] hashed = hash.ComputeHash(Encoding.UTF8.GetBytes(toBeHashed)); int result = 0; for (int i = 3; i >= 0; --i) { result <<= 8; result |= hashed[i]; } return result; } } public static int GetFileID(Type type) { Ensure.That(nameof(type)).IsNotNull(type); return GetFileID(type.Namespace, type.Name); } public static string GetPluginRuntimeGUID(Plugin plugin) { Ensure.That(nameof(plugin)).IsNotNull(plugin); return AssetDatabase.AssetPathToGUID(PathUtility.FromProject(plugin.runtimeAssembly.Location)); } public static bool TryLoadIfExists(string path, out T asset) where T : ScriptableObject { var assetDatabasePath = PathUtility.FromProject(path); if (File.Exists(path)) { // Try loading the existing asset file. asset = AssetDatabase.LoadAssetAtPath(assetDatabasePath); if (asset == null) { // The file exists, but it isn't a valid asset. // Warn and leave the asset as is to prevent losing its serialized contents // because we might be able to salvage them by deserializing later on. // Return a new empty instance in the mean time. Debug.LogWarning($"Loading {typeof(T).FullName} failed:\n{assetDatabasePath}"); asset = ScriptableObject.CreateInstance(); return false; } return true; } asset = default; return false; } public static bool TryLoad(string path, out T asset) where T : ScriptableObject { var assetDatabasePath = PathUtility.FromProject(path); if (File.Exists(path)) { // Try loading the existing asset file. asset = AssetDatabase.LoadAssetAtPath(assetDatabasePath); if (asset == null) { // The file exists, but it isn't a valid asset. // Warn and leave the asset as is to prevent losing its serialized contents // because we might be able to salvage them by deserializing later on. // Return a new empty instance in the mean time. Debug.LogWarning($"Loading {typeof(T).FullName} failed:\n{assetDatabasePath}"); asset = ScriptableObject.CreateInstance(); return false; } } else { // The file doesn't exist, so create a new asset and save it. asset = ScriptableObject.CreateInstance(); PathUtility.CreateParentDirectoryIfNeeded(path); AssetDatabase.CreateAsset(asset, assetDatabasePath); AssetDatabase.SaveAssets(); } return true; } } }