using System; using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; using BansheeEngine; namespace BansheeEditor { /// /// The primary location for interacting with all the resources in the current project. A complete hierarchy of /// resources is provided which can be interacted with by importing new ones, deleting them, moving, renaming and similar. /// public sealed class ProjectLibrary : ScriptObject { /// /// Root entry of the project library, referencing the top level resources folder. /// public static DirectoryEntry Root { get { return Internal_GetRoot(); } } /// /// Absolute path to the current project's project library resource folder. /// public static string ResourceFolder { get { return Internal_GetResourceFolder(); } } /// /// Triggered when a new entry is added to the project library. Provided path relative to the project library /// resources folder. /// public static event Action OnEntryAdded; /// /// Triggered when an entry is removed from the project library. Provided path relative to the project library /// resources folder. /// public static event Action OnEntryRemoved; private static HashSet queuedForImport = new HashSet(); private static int numImportedFiles; private static int totalFilesToImport; private static bool importInProgress; private const float TIME_SLICE_SECONDS = 0.030f; /// /// Checks the project library folder for any modifications and reimports the required resources. /// /// If true this method will block until the project library has done refreshing, /// otherwise the refresh will happen over the course of this and next frames. public static void Refresh(bool synchronous = false) { string[] modifiedPaths = Internal_Refresh(ResourceFolder, synchronous); if (!synchronous) { foreach (var modifiedPath in modifiedPaths) { if (queuedForImport.Add(modifiedPath)) totalFilesToImport++; } } else { foreach (var path in queuedForImport) Internal_Refresh(path, true); queuedForImport.Clear(); numImportedFiles = 0; totalFilesToImport = 0; } } /// /// Checks the specified folder for any modifications and reimports the required resources. /// /// Path to a file or folder to refresh. Relative to the project library resources folder or /// absolute. public static void Refresh(string path) { string[] modifiedPaths = Internal_Refresh(path, false); foreach (var modifiedPath in modifiedPaths) { if (queuedForImport.Add(modifiedPath)) totalFilesToImport++; } } /// /// Registers a new resource in the library. /// /// Resource instance to add to the library. A copy of the resource will be saved at the /// provided path. /// Path where where to store the resource. Absolute or relative to the resources folder. public static void Create(Resource resource, string path) { Internal_Create(resource, path); } /// /// Updates a resource that is already in the library. /// /// Resource to save. public static void Save(Resource resource) { Internal_Save(resource); } /// /// Loads a resource from the project library. /// /// Type of the resource to load. /// Path of the resource to load. Absolute or relative to the resources folder. /// Instance of the loaded resource, or null if not found. public static T Load(string path) where T : Resource { return (T) Internal_Load(path); } /// /// Triggers a reimport of a resource using the provided import options, if needed. /// /// Path to the resource to reimport, absolute or relative to resources folder. /// ptional import options to use when importing the resource. Caller must ensure the import /// options are of the correct type for the resource in question. If null is provided default /// import options are used. /// Should the resource be reimported even if no changes are detected. public static void Reimport(string path, ImportOptions options = null, bool force = false) { Internal_Reimport(path, options, force); } /// /// Checks does the project library contain a resource at the specified path. /// /// Path to the resource to check, absolute or relative to resources folder. /// True if the resourc exists, false otherwise. public static bool Exists(string path) { return GetEntry(path) != null; } /// /// Attempts to locate a library entry that describes a file or a folder in the project library. /// /// Path to the entry to retrieve, absolute or relative to resources folder. /// Library entry if found, null otherwise. This object can become invalid on the next library refresh /// and you are not meant to hold a permanent reference to it. public static LibraryEntry GetEntry(string path) { return Internal_GetEntry(path); } /// /// Searches the library for a pattern and returns all entries matching it. /// /// Pattern to search for. Use wildcard * to match any character(s). /// Type of resources to search for. If null all entries will be searched. /// A set of entries matching the pattern. These objects can become invalid on the next library refresh /// and you are not meant to hold a permanent reference to them. public static LibraryEntry[] Search(string pattern, ResourceType[] types = null) { return Internal_Search(pattern, types); } /// /// Returns a path to a resource stored in the project library. /// /// Resource to find the path for. /// Path to relative to the project library resources folder if resource was found, null otherwise. /// public static string GetPath(Resource resource) { return Internal_GetPath(resource); } /// /// Returns a path to a resource with the specified UUID stored in the project library. /// /// Unique identifier of the resources to retrieve the path of. /// Path to relative to the project library resources folder if resource was found, null otherwise. /// public static string GetPath(string uuid) { return Internal_GetPathFromUUID(uuid); } /// /// Deletes a resource in the project library. /// /// Path to the entry to delete, absolute or relative to resources folder. public static void Delete(string path) { Internal_Delete(path); } /// /// Creates a new folder in the library. /// /// Path of the folder to create. Absolute or relative to the resources folder. public static void CreateFolder(string path) { Internal_CreateFolder(path); } /// /// Renames an entry in the project library. /// /// Path of the entry to rename, absolute or relative to resources folder. /// New name of the entry with an extension. /// Determines should the entry be deleted if one with the provided name already exists. If /// this is false and an entry already exists, no rename operation will be performed. public static void Rename(string path, string name, bool overwrite = false) { Internal_Rename(path, name, false); } /// /// Moves an entry in the project library from one path to another. /// /// Source path of the entry, absolute or relative to resources folder. /// Destination path of the entry, absolute or relative to resources folder. /// Determines should the entry be deleted if one at the destination path already exists. If /// this is false and an entry already exists, no move operation will be performed. public static void Move(string oldPath, string newPath, bool overwrite = false) { Internal_Move(oldPath, newPath, overwrite); } /// /// Copies an entry in the project library from one path to another. /// /// Source path of the entry, absolute or relative to resources folder. /// Destination path of the entry, absolute or relative to resources folder. /// Determines should the entry be deleted if one at the destination path already exists. If /// this is false and an entry already exists, no copy operation will be performed. public static void Copy(string source, string destination, bool overwrite = false) { Internal_Copy(source, destination, overwrite); } /// /// Controls should a resource be included an a build. All dependant resources will also be included. /// /// Path of the resource to include, absolute or relative to resources folder. /// True if it should be included, false otherwise. public static void SetIncludeInBuild(string path, bool include) { Internal_SetIncludeInBuild(path, include); } /// /// Triggers reimport for queued resource. Should be called once per frame. /// internal static void Update() { if (queuedForImport.Count > 0) { // Skip first frame to get the progress bar a chance to show up if (importInProgress) { UInt64 start = Time.Precise; List toRemove = new List(); foreach (var entry in queuedForImport) { Internal_Refresh(entry, true); toRemove.Add(entry); numImportedFiles++; UInt64 end = Time.Precise; UInt64 elapsed = end - start; float elapsedSeconds = elapsed * Time.MicroToSecond; if (elapsedSeconds > TIME_SLICE_SECONDS) break; } foreach (var entry in toRemove) queuedForImport.Remove(entry); } if (queuedForImport.Count == 0) { numImportedFiles = 0; totalFilesToImport = 0; ProgressBar.Hide(); } else { IEnumerator enumerator = queuedForImport.GetEnumerator(); enumerator.MoveNext(); string displayName = enumerator.Current; displayName = displayName.Replace("\\", "\\\\"); if (displayName.Length > 60) { displayName = displayName.Remove(0, displayName.Length - 60); displayName = "..." + displayName; } float pct = numImportedFiles / (float)totalFilesToImport; ProgressBar.Show("Importing (" + numImportedFiles + "/" + totalFilesToImport + ")", displayName, 0.5f); } importInProgress = true; } else importInProgress = false; } /// /// Triggered internally by the runtime when a new entry is added to the project library. /// /// Path relative to the project library resources folder. private static void Internal_DoOnEntryAdded(string path) { if (OnEntryAdded != null) OnEntryAdded(path); } /// /// Triggered internally by the runtime when an entry is removed from the project library. /// /// Path relative to the project library resources folder. private static void Internal_DoOnEntryRemoved(string path) { if (OnEntryRemoved != null) OnEntryRemoved(path); } [MethodImpl(MethodImplOptions.InternalCall)] private static extern string[] Internal_Refresh(string path, bool import); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_Create(Resource resource, string path); [MethodImpl(MethodImplOptions.InternalCall)] private static extern Resource Internal_Load(string path); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_Save(Resource resource); [MethodImpl(MethodImplOptions.InternalCall)] private static extern DirectoryEntry Internal_GetRoot(); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_Reimport(string path, ImportOptions options, bool force); [MethodImpl(MethodImplOptions.InternalCall)] private static extern LibraryEntry Internal_GetEntry(string path); [MethodImpl(MethodImplOptions.InternalCall)] private static extern LibraryEntry[] Internal_Search(string path, ResourceType[] types); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string Internal_GetPath(Resource resource); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string Internal_GetPathFromUUID(string uuid); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_Delete(string path); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_CreateFolder(string path); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_Rename(string path, string name, bool overwrite); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_Move(string oldPath, string newPath, bool overwrite); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_Copy(string source, string destination, bool overwrite); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string Internal_GetResourceFolder(); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void Internal_SetIncludeInBuild(string path, bool force); } /// /// Type of project library entries. /// public enum LibraryEntryType // Note: Must match the C++ enum ProjectLibrary::LibraryEntryType { File, Directory } /// /// Type of resources supported by the project library. /// public enum ResourceType // Note: Must match the C++ enum ScriptResourceType { Texture, SpriteTexture, Mesh, Font, Shader, Material, Prefab, PlainText, ScriptCode, StringTable, GUISkin, Undefined } /// /// A generic project library entry that may be a file or a folder. /// public class LibraryEntry : ScriptObject { /// /// Path of the library entry, relative to the project library resources folder. /// public string Path { get { return Internal_GetPath(mCachedPtr); } } /// /// Name of the library entry. /// public string Name { get { return Internal_GetName(mCachedPtr); } } /// /// Type of the library entry. /// public LibraryEntryType Type { get { return Internal_GetType(mCachedPtr); } } /// /// Directory entry that contains this entry. This may be null for the root entry. /// public DirectoryEntry Parent { get { return Internal_GetParent(mCachedPtr); } } [MethodImpl(MethodImplOptions.InternalCall)] private static extern string Internal_GetPath(IntPtr thisPtr); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string Internal_GetName(IntPtr thisPtr); [MethodImpl(MethodImplOptions.InternalCall)] private static extern LibraryEntryType Internal_GetType(IntPtr thisPtr); [MethodImpl(MethodImplOptions.InternalCall)] private static extern DirectoryEntry Internal_GetParent(IntPtr thisPtr); } /// /// A project library entry representing a directory that contains other entries. /// public class DirectoryEntry : LibraryEntry { /// /// A set of entries contained in this entry. /// public LibraryEntry[] Children { get { return Internal_GetChildren(mCachedPtr); } } [MethodImpl(MethodImplOptions.InternalCall)] private static extern LibraryEntry[] Internal_GetChildren(IntPtr thisPtr); } /// /// A library entry representing a resource. /// public class FileEntry : LibraryEntry { /// /// Import options used for importing the resource. /// public ImportOptions Options { get { return Internal_GetImportOptions(mCachedPtr); } } /// /// Unique identifier of the resource. /// public string UUID { get { return Internal_GetUUID(mCachedPtr); } } /// /// Custom icon for the resource to display in the editor, if the resource has one. /// public Texture2D Icon { get { return Internal_GetIcon(mCachedPtr); } } /// /// Type of the resource referenced by this entry. /// public ResourceType ResType { get { return Internal_GetResourceType(mCachedPtr); } } /// /// Determines will the resource be included in the project build. /// public bool IncludeInBuild { get { return Internal_GetIncludeInBuild(mCachedPtr); } } [MethodImpl(MethodImplOptions.InternalCall)] private static extern ImportOptions Internal_GetImportOptions(IntPtr thisPtr); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string Internal_GetUUID(IntPtr thisPtr); [MethodImpl(MethodImplOptions.InternalCall)] private static extern Texture2D Internal_GetIcon(IntPtr thisPtr); [MethodImpl(MethodImplOptions.InternalCall)] private static extern ResourceType Internal_GetResourceType(IntPtr thisPtr); [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool Internal_GetIncludeInBuild(IntPtr thisPtr); } }