#if UNITY_EDITOR using System; using System.IO; using UnityEditor; namespace UnityEngine.InputSystem { /// Provides convenience functions for creating and managing assets for test purposes. /// Note that all returned paths are converted to Unix paths when running on Windows /// for consistency and to avoid mixed path names. public static class AssetDatabaseUtils { private const string kAssetPath = "Assets"; private const string kTestPath = "TestFiles"; private const string kMetaExtension = ".meta"; private const string kDefaultAssetExtension = "asset"; // Perform an operation equivalent to a file delete operation outside of Unity Editor. // Note that meta file is also removed to avoid generating warnings about non-clean delete. public static void ExternalDeleteFileOrDirectory(string path) { FileUtil.DeleteFileOrDirectory(path); FileUtil.DeleteFileOrDirectory(path + kMetaExtension); } // Perform an operation equivalent to a file move operation outside of Unity Editor. // Note that meta file is also moved to avoid generating warnings about non-clean move. public static void ExternalMoveFileOrDirectory(string source, string dest) { FileUtil.MoveFileOrDirectory(source, dest); FileUtil.MoveFileOrDirectory(source + kMetaExtension, dest + kMetaExtension); } // Create an asset at the given path containing the given text content. private static T CreateAssetAtPath(string path, string content) where T : UnityEngine.Object { Debug.Assert(!File.Exists(path)); T obj; try { CreateDirectories(Path.GetDirectoryName(path)); File.WriteAllText(path, content); AssetDatabase.ImportAsset(path); obj = AssetDatabase.LoadAssetAtPath(path); if (obj == null) throw new Exception($"Failed to create asset at \"{path}\""); } catch (Exception) { AssetDatabase.DeleteAsset(path); throw; } return obj; } private static string SanitizePath(string path) { return path?.Replace("\\", "/"); } private static void CreateRootDirectory() { CreateDirectories(RootPath()); } // Creates all directories (including intermediate) defined in path. private static string CreateDirectories(string path) { if (Directory.Exists(path)) return SanitizePath(path); var parentFolder = kAssetPath; path = path.Replace("\\", "/"); // Make sure we only get '/' separators. var directories = path.Split('/'); if (directories[0] != kAssetPath) throw new ArgumentException(path); for (var i = 1; i < directories.Length; ++i) { var guid = AssetDatabase.CreateFolder(parentFolder, directories[i]); if (guid == string.Empty) throw new Exception("Failed to create path \"" + path + "\""); parentFolder = SanitizePath(Path.Combine(parentFolder, directories[i])); } AssetDatabase.Refresh(); return SanitizePath(path); } // Creates a random test directory within asset folder that is automatically removed after test run. public static string CreateDirectory() { return CreateDirectories(RandomDirectoryPath()); } // Creates an asset in the given directory path with an explicit or random file name containing the // given content or the default content based on type. public static T CreateAsset(string directoryPath, string filename = null, string content = null) where T : UnityEngine.Object { Debug.Assert(directoryPath == null || directoryPath.Contains(RootPath())); Debug.Assert(filename == null || !filename.Contains("/")); if (directoryPath == null) directoryPath = RootPath(); string path; if (filename != null) { path = SanitizePath(Path.Combine(directoryPath, filename)); if (File.Exists(path)) throw new Exception($"File already exists: {path}"); } else { path = RandomAssetFilePath(directoryPath, AssetFileExtensionFromType(typeof(T))); } return CreateAsset(path: path, content: content); } // Creates an asset at the given path containing the specified content. // If path is null, a unique random file name is assigned, if content is null the default content based // on type (extension) is used. public static T CreateAsset(string path = null, string content = null) where T : UnityEngine.Object { if (path == null) path = RandomAssetFilePath(RootPath(), AssetFileExtensionFromType(typeof(T))); if (content == null) content = DefaultContentFromType(typeof(T)); return CreateAssetAtPath(path, content); } public static void Restore() { var root = RootPath(); // Delete all files in test folder if (!Directory.Exists(root)) return; foreach (var asset in AssetDatabase.FindAssets("", new string[] { root })) { var path = AssetDatabase.GUIDToAssetPath(asset); AssetDatabase.DeleteAsset(path); } AssetDatabase.DeleteAsset(root); } private static string RandomName() { const double scale = int.MaxValue; double r = UnityEngine.Random.value; return "Test_" + (int)(Math.Floor(r * scale)); } private static string RandomAssetFilePath(string directoryPath = null) { return RandomAssetFilePath(directoryPath, AssetFileExtensionFromType(typeof(T))); } private static string RandomAssetFilePath(string directoryPath = null, string extension = null) { // Default to using test files root path if (directoryPath == null) directoryPath = RootPath(); // Default to default extension if (extension == null) extension = kDefaultAssetExtension; string path; do { path = SanitizePath(Path.Combine(directoryPath, RandomName() + "." + extension)); // EDIT } while (File.Exists(path)); return path; } private static string RootPath() { return SanitizePath(Path.Combine(kAssetPath, kTestPath)); } public static string RandomDirectoryPath() { string path; do { path = Path.Combine(RootPath(), RandomName()); } while (File.Exists(path)); return SanitizePath(path); } private static string AssetFileExtensionFromType(Type type) { if (type == typeof(InputActionAsset)) return InputActionAsset.Extension; return kDefaultAssetExtension; } private static string DefaultContentFromType(Type type) { if (type == typeof(InputActionAsset)) return "{}"; return string.Empty; } } } #endif // UNITY_EDITOR