using System;
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine.ProBuilder;
using Object = UnityEngine.Object;
namespace UnityEditor.ProBuilder
{
///
/// Helper functions for working with files and directories.
///
static class FileUtility
{
// ProBuilder folder path.
static string s_ProBuilderFolderPath = "Packages/com.unity.probuilder/";
static string s_ProBuilderDataPath = "Assets/ProBuilder Data/";
// The order is important - always search for the package manager installed version first
static readonly string[] k_PossibleInstallDirectories = new string[]
{
"Packages/com.unity.probuilder/",
"UnityPackageManager/com.unity.probuilder/",
"Assets/",
};
///
/// Check that the directory contains a valid ProBuilder install.
///
/// Directory to check
///
internal static bool ValidateProBuilderRoot(string dir)
{
return !string.IsNullOrEmpty(dir) &&
Directory.Exists(dir + "/Editor/EditorCore") &&
Directory.Exists(dir + "/Runtime/Core") &&
Directory.Exists(dir + "/Runtime/MeshOperations");
}
///
/// Return a relative path to the ProBuilder directory. Can be in the packages cache or Assets folder.
/// If the project is in the packman cache it is immutable.
///
///
internal static string GetProBuilderInstallDirectory()
{
if (ValidateProBuilderRoot(s_ProBuilderFolderPath))
return s_ProBuilderFolderPath;
foreach (var install in k_PossibleInstallDirectories)
{
s_ProBuilderFolderPath = install;
if (ValidateProBuilderRoot(s_ProBuilderFolderPath))
return s_ProBuilderFolderPath;
}
// It's not in any of the usual haunts, start digging through Assets until we find it (likely an A$ install)
s_ProBuilderFolderPath = FindAssetStoreProBuilderInstall();
if (Directory.Exists(s_ProBuilderFolderPath))
return s_ProBuilderFolderPath;
// Things are dire. ProBuilder was nowhere to be found in the Assets directory, which means either the user
// has renamed the folder, or something very spooky is going on.
// Either way, just create a new ProBuilder folder in Assets and return that so at the very least
// local preferences and the material/color palettes will still work.
Log.Warning("Creating a new ProBuilder directory... was the ProBuilder folder renamed?\nIcons & preferences may not work in this state.");
s_ProBuilderFolderPath = "Assets/ProBuilder";
Directory.CreateDirectory(s_ProBuilderFolderPath);
return s_ProBuilderFolderPath;
}
///
/// Scan the Assets directory for an install of ProBuilder.
///
///
internal static string FindAssetStoreProBuilderInstall()
{
string dir = null;
string[] matches = Directory.GetDirectories("Assets", "ProBuilder", SearchOption.AllDirectories);
foreach (var match in matches)
{
dir = match.Replace("\\", "/") + "/";
if (dir.Contains("ProBuilder") && ValidateProBuilderRoot(dir))
break;
}
return dir;
}
///
/// Get the path to the local ProBuilder/Data folder
///
///
internal static string GetLocalDataDirectory(bool initializeIfMissing = false)
{
if (Directory.Exists(s_ProBuilderDataPath))
return s_ProBuilderDataPath;
string root = GetProBuilderInstallDirectory();
if (root.StartsWith("Assets"))
{
// Installed from Asset Store or manual package import
s_ProBuilderDataPath = root + "Data/";
}
else
{
// Scan project for ProBuilder Data folder
// none found? create one at root
string[] matches = Directory.GetDirectories("Assets", "ProBuilder Data", SearchOption.AllDirectories);
s_ProBuilderDataPath = matches.Length > 0 ? matches[0] : "Assets/ProBuilder Data/";
}
if (!Directory.Exists(s_ProBuilderDataPath) && initializeIfMissing)
Directory.CreateDirectory(s_ProBuilderDataPath);
return s_ProBuilderDataPath;
}
internal static string[] FindAssets(string pattern) where T : UnityEngine.Object
{
return AssetDatabase.FindAssets("t:" + typeof(T).ToString() + " " + pattern);
}
internal static T[] FindAndLoadAssets() where T : UnityEngine.Object
{
return AssetDatabase.FindAssets("t:" + typeof(T).ToString())
.Select(x => AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(x))).ToArray();
}
internal static T FindAssetOfType() where T : UnityEngine.Object
{
foreach (var i in AssetDatabase.FindAssets("t:" + typeof(T).ToString()))
{
T o = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(i));
if (o != null)
return o;
}
return null;
}
///
/// Get the selected directory relative to project root.
///
///
internal static string GetSelectedDirectory()
{
Object o = Selection.activeObject;
if (o != null)
{
string path = AssetDatabase.GetAssetPath(o.GetInstanceID());
if (!string.IsNullOrEmpty(path))
{
if (Directory.Exists(path))
return GetRelativePath(Path.GetFullPath(path));
string res = Path.GetDirectoryName(path);
if (!string.IsNullOrEmpty(res) && Directory.Exists(res))
return GetRelativePath(Path.GetFullPath(res));
}
}
return "Assets";
}
///
/// Get a file or folder path relative to the Unity project directory.
///
/// File or directory path, either relative or absolute.
/// A new path relative to the current project root.
public static string GetRelativePath(string path)
{
string full = Path.GetFullPath(path).Replace("\\", "/");
string cur = Directory.GetCurrentDirectory().Replace("\\", "/");
if (!cur.EndsWith("/"))
cur += "/";
return full.Replace(cur, "");
}
///
/// Check if a file or folder exists at path.
///
///
///
public static bool Exists(string path)
{
return Directory.Exists(path) || File.Exists(path);
}
///
/// Load an internal asset relative to the ProBuilder directory.
///
///
///
///
internal static T LoadInternalAsset(string path) where T : Object
{
string full = string.Format("{0}{1}", GetProBuilderInstallDirectory(), path);
return Load(full);
}
///
/// Fetch a default asset from path. If not found, a new one is created.
///
///
///
///
internal static T LoadRequired(string path) where T : ScriptableObject, IHasDefault
{
T asset = Load(path);
if (asset == null)
{
asset = ScriptableObject.CreateInstance();
asset.SetDefaultValues();
UnityEditor.EditorUtility.SetDirty(asset);
string folder = Path.GetDirectoryName(path);
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
AssetDatabase.CreateAsset(asset, path);
}
return asset;
}
static T Load(string path) where T : Object
{
return AssetDatabase.LoadAssetAtPath(path);
}
///
/// Write contents to a file path.
///
///
///
[System.Obsolete("Use WriteAllText")]
public static void WriteFile(string path, string contents)
{
WriteAllText(path, contents);
}
///
/// Write contents to a file path, creating a new directory if necessary.
///
///
///
public static void WriteAllText(string path, string contents)
{
string dir = Path.GetDirectoryName(path);
if (string.IsNullOrEmpty(dir))
{
Log.Error("Cannot write file to \"{0}\", invalid path.", path);
return;
}
if (!Directory.Exists(path))
Directory.CreateDirectory(dir);
File.WriteAllText(path, contents);
}
///
/// Save an image to the specified path.
///
///
///
/// True on success, false if operation failed.
internal static bool SaveTexture(Texture2D texture, string path)
{
byte[] bytes = texture.EncodeToPNG();
if (string.IsNullOrEmpty(path))
return false;
System.IO.File.WriteAllBytes(path, bytes);
AssetDatabase.Refresh();
return true;
}
}
}