using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
namespace Unity.VisualScripting
{
public static class PathUtility
{
public static string TryPathsForFile(string fileName, IEnumerable<string> directories)
{
return directories.Select(directory => Path.Combine(directory, fileName)).FirstOrDefault(File.Exists);
}
public static string TryPathsForFile(string fileName, params string[] directories)
{
return TryPathsForFile(fileName, (IEnumerable<string>)directories);
}
public static string GetRelativePath(string path, string directory)
{
Ensure.That(nameof(path)).IsNotNull(path);
Ensure.That(nameof(directory)).IsNotNull(directory);
if (!directory.EndsWith(Path.DirectorySeparatorChar))
{
directory += Path.DirectorySeparatorChar;
}
try
{
// Optimization: Try a simple substring if possible
path = path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
directory = directory.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
if (path.StartsWith(directory, StringComparison.Ordinal))
{
return path.Substring(directory.Length);
}
// Otherwise, use the URI library
var pathUri = new Uri(path);
var folderUri = new Uri(directory);
return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString()
.Replace('/', Path.DirectorySeparatorChar));
}
catch (UriFormatException ufex)
{
throw new UriFormatException($"Failed to get relative path.\nPath: {path}\nDirectory:{directory}\n{ufex}");
}
}
public static string FromEditorResources(string path)
{
return GetRelativePath(path, Paths.editorDefaultResources);
}
public static string FromAssets(string path)
{
return GetRelativePath(path, Paths.assets);
}
public static string FromProject(string path)
{
return GetRelativePath(path, Paths.project);
}
public static void CreateParentDirectoryIfNeeded(string path)
{
CreateDirectoryIfNeeded(Directory.GetParent(path).FullName);
}
public static void CreateDirectoryIfNeeded(string path)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
public static void DeleteDirectoryIfExists(string path)
{
if (Directory.Exists(path))
{
Directory.Delete(path, true);
}
var metaFilePath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileName(path) + ".meta");
if (File.Exists(metaFilePath))
{
File.Delete(metaFilePath);
}
}
public static void DeleteProjectFileIfExists(string filePath, bool checkoutInVersionControl = false)
{
if (File.Exists(filePath))
{
string metaFilePath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileName(filePath) + ".meta");
if (checkoutInVersionControl)
{
VersionControlUtility.Unlock(filePath);
VersionControlUtility.Unlock(metaFilePath);
}
File.Delete(filePath);
File.Delete(metaFilePath);
}
}
public static string MakeSafeFilename(string filename, char replace)
{
foreach (var c in Path.GetInvalidFileNameChars())
{
filename = filename.Replace(c, replace);
}
return filename;
}
public static string GetPackageRootPath()
{
// This bit of code is so that we can find out Bolt package folder wherever it lives, as long as its accessible to the AssetDatabase
const string packageEditorFolderGuid = "ee9f54d6cd5a17045a3f1c9877d4b7e6";
var packageEditorAssetPath = AssetDatabase.GUIDToAssetPath(packageEditorFolderGuid);
if (packageEditorAssetPath == string.Empty)
{
throw new FileNotFoundException($"Couldn't find Visual Scripting package folder.");
}
// The root VS folder path is 1 directories up from our Editor folder
return Path.GetDirectoryName(packageEditorAssetPath);
}
}
}