Explorar o código

When opening windows don't activate them (helps when app is in background and progress bar opens)
Open new windows in the center of the main application window

BearishSun %!s(int64=10) %!d(string=hai) anos
pai
achega
e60129bba4

+ 37 - 28
BansheeCore/Source/Win32/BsWin32Platform.cpp

@@ -515,49 +515,58 @@ namespace BansheeEngine
 			SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams));
 
 			RenderWindowCore* newWindow = (RenderWindowCore*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			if (newWindow != nullptr && newWindow->getProperties().isModal())
+			if (newWindow != nullptr)
 			{
-				if(!mData->mModalWindowStack.empty())
-				{
-					RenderWindowCore* curModalWindow = mData->mModalWindowStack.back();
+				const RenderWindowProperties& props = newWindow->getProperties();
+				if (!props.isHidden())
+					ShowWindow(hWnd, SW_SHOWNOACTIVATE);
 
-					UINT64 curHwnd;
-					curModalWindow->getCustomAttribute("WINDOW", &curHwnd);
-					EnableWindow((HWND)curHwnd, FALSE);
-				}
-				else
+				if (props.isModal())
 				{
-					Vector<RenderWindowCore*> renderWindows = RenderWindowCoreManager::instance().getRenderWindows();
-					for(auto& renderWindow : renderWindows)
+					if (!mData->mModalWindowStack.empty())
 					{
-						if(renderWindow == newWindow)
-							continue;
+						RenderWindowCore* curModalWindow = mData->mModalWindowStack.back();
 
 						UINT64 curHwnd;
-						renderWindow->getCustomAttribute("WINDOW", &curHwnd);
+						curModalWindow->getCustomAttribute("WINDOW", &curHwnd);
 						EnableWindow((HWND)curHwnd, FALSE);
 					}
-				}
+					else
+					{
+						Vector<RenderWindowCore*> renderWindows = RenderWindowCoreManager::instance().getRenderWindows();
+						for (auto& renderWindow : renderWindows)
+						{
+							if (renderWindow == newWindow)
+								continue;
 
-				mData->mModalWindowStack.push_back(newWindow);
-			}
-			else
-			{
-				// A non-modal window was opened while another modal one is open:
-				// immediately deactivate it and make sure the modal windows stay on top
-				if (!mData->mModalWindowStack.empty())
-				{
-					EnableWindow((HWND)hWnd, FALSE);
+							UINT64 curHwnd;
+							renderWindow->getCustomAttribute("WINDOW", &curHwnd);
+							EnableWindow((HWND)curHwnd, FALSE);
+						}
+					}
 
-					for (auto window : mData->mModalWindowStack)
+					mData->mModalWindowStack.push_back(newWindow);
+				}
+				else
+				{
+					// A non-modal window was opened while another modal one is open:
+					// immediately deactivate it and make sure the modal windows stay on top
+					if (!mData->mModalWindowStack.empty())
 					{
-						UINT64 curHwnd;
-						window->getCustomAttribute("WINDOW", &curHwnd);
+						EnableWindow((HWND)hWnd, FALSE);
+
+						for (auto window : mData->mModalWindowStack)
+						{
+							UINT64 curHwnd;
+							window->getCustomAttribute("WINDOW", &curHwnd);
 
-						BringWindowToTop((HWND)curHwnd);
+							BringWindowToTop((HWND)curHwnd);
+						}
 					}
 				}
 			}
+			else
+				ShowWindow(hWnd, SW_SHOWNOACTIVATE);
 
 			return 0;
 		}

+ 0 - 3
BansheeCore/Source/Win32/BsWin32Window.cpp

@@ -24,9 +24,6 @@ namespace BansheeEngine
 		{
 			m->style = WS_CLIPCHILDREN;
 
-			if (!desc.hidden)
-				m->style |= WS_VISIBLE;
-
 			INT32 left = desc.left;
 			INT32 top = desc.top;
 

+ 20 - 4
BansheeEditor/Source/BsEditorWindowBase.cpp

@@ -1,8 +1,9 @@
 #include "BsEditorWindowBase.h"
-#include "BsCoreApplication.h"
+#include "BsEditorApplication.h"
 #include "BsCoreThread.h"
 #include "BsSceneObject.h"
 #include "BsRenderWindow.h"
+#include "BsMainEditorWindow.h"
 
 #include "BsEditorWindowManager.h"
 #include "BsCCamera.h"
@@ -14,16 +15,31 @@ namespace BansheeEngine
 	EditorWindowBase::EditorWindowBase(bool isModal)
 		:mOwnsRenderWindow(true), mIsModal(isModal)
 	{
+		UINT32 width = 200;
+		UINT32 height = 200;
+
+		INT32 left = -1;
+		INT32 top = -1;
+
+		// If possible open the window in the center of the main editor window
+		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
+		if(mainWindow != nullptr)
+		{
+			left = mainWindow->getLeft() + mainWindow->getWidth() / 2 - width / 2;
+			top = mainWindow->getTop() + mainWindow->getHeight() / 2 - height / 2;
+		}
+
+
 		RENDER_WINDOW_DESC renderWindowDesc;
-		renderWindowDesc.videoMode = VideoMode(200, 200);
+		renderWindowDesc.videoMode = VideoMode(width, height);
 		renderWindowDesc.title = "EditorWindow";
 		renderWindowDesc.fullscreen = false;
 		renderWindowDesc.border = WindowBorder::None;
 		renderWindowDesc.toolWindow = true;
 		renderWindowDesc.modal = isModal;
 		renderWindowDesc.hideUntilSwap = true;
-		renderWindowDesc.left = -1;
-		renderWindowDesc.top = -1;
+		renderWindowDesc.left = left;
+		renderWindowDesc.top = top;
 
 		mRenderWindow = RenderWindow::create(renderWindowDesc, gCoreApplication().getPrimaryWindow());
 

+ 514 - 514
MBansheeEditor/ProjectLibrary.cs

@@ -1,514 +1,514 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Runtime.CompilerServices;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// 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.
-    /// </summary>
-    public sealed class ProjectLibrary : ScriptObject
-    {
-        /// <summary>
-        /// Root entry of the project library, referencing the top level resources folder.
-        /// </summary>
-        public static DirectoryEntry Root { get { return Internal_GetRoot(); } }
-
-        /// <summary>
-        /// Absolute path to the current project's project library resource folder.
-        /// </summary>
-        public static string ResourceFolder { get { return Internal_GetResourceFolder(); } }
-
-        /// <summary>
-        /// Triggered when a new entry is added to the project library. Provided path relative to the project library 
-        /// resources folder.
-        /// </summary>
-        public static event Action<string> OnEntryAdded;
-
-        /// <summary>
-        /// Triggered when an entry is removed from the project library. Provided path relative to the project library 
-        /// resources folder.
-        /// </summary>
-        public static event Action<string> OnEntryRemoved;
-
-        /// <summary>
-        /// Triggered when an entry is (re)imported in the project library. Provided path relative to the project library 
-        /// resources folder.
-        /// </summary>
-        public static event Action<string> OnEntryImported;
-
-        private static HashSet<string> queuedForImport = new HashSet<string>();
-        private static int numImportedFiles;
-        private static int totalFilesToImport;
-        private static bool importInProgress;
-
-        private const float TIME_SLICE_SECONDS = 0.030f;
-
-        /// <summary>
-        /// Checks the project library folder for any modifications and reimports the required resources.
-        /// </summary>
-        /// <param name="synchronous">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.</param>
-        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;
-            }
-        }
-
-        /// <summary>
-        /// Checks the specified folder for any modifications and reimports the required resources.
-        /// </summary>
-        /// <param name="path">Path to a file or folder to refresh. Relative to the project library resources folder or 
-        ///                    absolute.</param>
-        public static void Refresh(string path)
-        {
-            string[] modifiedPaths = Internal_Refresh(path, false);
-            foreach (var modifiedPath in modifiedPaths)
-            {
-                if (queuedForImport.Add(modifiedPath))
-                    totalFilesToImport++;
-            }
-        }
-
-        /// <summary>
-        /// Registers a new resource in the library.
-        /// </summary>
-        /// <param name="resource">Resource instance to add to the library. A copy of the resource will be saved at the 
-        ///                        provided path.</param>
-        /// <param name="path">Path where where to store the resource. Absolute or relative to the resources folder.</param>
-        public static void Create(Resource resource, string path)
-        {
-            Internal_Create(resource, path);
-        }
-
-        /// <summary>
-        /// Updates a resource that is already in the library.
-        /// </summary>
-        /// <param name="resource">Resource to save.</param>
-        public static void Save(Resource resource)
-        {
-            Internal_Save(resource);
-        }
-
-        /// <summary>
-        /// Loads a resource from the project library.
-        /// </summary>
-        /// <typeparam name="T">Type of the resource to load.</typeparam>
-        /// <param name="path">Path of the resource to load. Absolute or relative to the resources folder.</param>
-        /// <returns>Instance of the loaded resource, or null if not found.</returns>
-        public static T Load<T>(string path) where T : Resource
-        {
-            return (T) Internal_Load(path);
-        }
-
-        /// <summary>
-        /// Triggers a reimport of a resource using the provided import options, if needed.
-        /// </summary>
-        /// <param name="path">Path to the resource to reimport, absolute or relative to resources folder.</param>
-        /// <param name="options">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.</param>
-        /// <param name="force">Should the resource be reimported even if no changes are detected.</param>
-        public static void Reimport(string path, ImportOptions options = null, bool force = false)
-        {
-            Internal_Reimport(path, options, force);
-        }
-
-        /// <summary>
-        /// Checks does the project library contain a resource at the specified path.
-        /// </summary>
-        /// <param name="path">Path to the resource to check, absolute or relative to resources folder.</param>
-        /// <returns>True if the resourc exists, false otherwise.</returns>
-        public static bool Exists(string path)
-        {
-            return GetEntry(path) != null;
-        }
-
-        /// <summary>
-        /// Attempts to locate a library entry that describes a file or a folder in the project library.
-        /// </summary>
-        /// <param name="path">Path to the entry to retrieve, absolute or relative to resources folder.</param>
-        /// <returns>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.</returns>
-        public static LibraryEntry GetEntry(string path)
-        {
-            return Internal_GetEntry(path);
-        }
-
-        /// <summary>
-        /// Searches the library for a pattern and returns all entries matching it.
-        /// </summary>
-        /// <param name="pattern">Pattern to search for. Use wildcard * to match any character(s).</param>
-        /// <param name="types">Type of resources to search for. If null all entries will be searched.</param>
-        /// <returns>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.</returns>
-        public static LibraryEntry[] Search(string pattern, ResourceType[] types = null)
-        {
-            return Internal_Search(pattern, types);
-        }
-
-        /// <summary>
-        /// Returns a path to a resource stored in the project library.
-        /// </summary>
-        /// <param name="resource">Resource to find the path for.</param>
-        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
-        ///          </returns>
-        public static string GetPath(Resource resource)
-        {
-            return Internal_GetPath(resource);
-        }
-
-        /// <summary>
-        /// Returns a path to a resource with the specified UUID stored in the project library.
-        /// </summary>
-        /// <param name="uuid">Unique identifier of the resources to retrieve the path of.</param>
-        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
-        ///          </returns>
-        public static string GetPath(string uuid)
-        {
-            return Internal_GetPathFromUUID(uuid);
-        }
-
-        /// <summary>
-        /// Deletes a resource in the project library.
-        /// </summary>
-        /// <param name="path">Path to the entry to delete, absolute or relative to resources folder.</param>
-        public static void Delete(string path)
-        {
-            Internal_Delete(path);
-        }
-
-        /// <summary>
-        /// Creates a new folder in the library.
-        /// </summary>
-        /// <param name="path">Path of the folder to create. Absolute or relative to the resources folder.</param>
-        public static void CreateFolder(string path)
-        {
-            Internal_CreateFolder(path);
-        }
-
-        /// <summary>
-        /// Renames an entry in the project library.
-        /// </summary>
-        /// <param name="path">Path of the entry to rename, absolute or relative to resources folder.</param>
-        /// <param name="name">New name of the entry with an extension.</param>
-        /// <param name="overwrite">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.</param>
-        public static void Rename(string path, string name, bool overwrite = false)
-        {
-            Internal_Rename(path, name, false);
-        }
-
-        /// <summary>
-        /// Moves an entry in the project library from one path to another.
-        /// </summary>
-        /// <param name="oldPath">Source path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="newPath">Destination path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="overwrite">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.</param>
-        public static void Move(string oldPath, string newPath, bool overwrite = false)
-        {
-            Internal_Move(oldPath, newPath, overwrite);
-        }
-
-        /// <summary>
-        /// Copies an entry in the project library from one path to another.
-        /// </summary>
-        /// <param name="source">Source path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="destination">Destination path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="overwrite">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.</param>
-        public static void Copy(string source, string destination, bool overwrite = false)
-        {
-            Internal_Copy(source, destination, overwrite);
-        }
-
-        /// <summary>
-        /// Controls should a resource be included an a build. All dependant resources will also be included.
-        /// </summary>
-        /// <param name="path">Path of the resource to include, absolute or relative to resources folder.</param>
-        /// <param name="include">True if it should be included, false otherwise.</param>
-        public static void SetIncludeInBuild(string path, bool include)
-        {
-            Internal_SetIncludeInBuild(path, include);
-        }
-
-        /// <summary>
-        /// Triggers reimport for queued resource. Should be called once per frame.
-        /// </summary>
-        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<string> toRemove = new List<string>();
-
-                    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<string> 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, pct);
-                }
-
-                importInProgress = true;
-            }
-            else
-                importInProgress = false;
-        }
-
-        /// <summary>
-        /// Triggered internally by the runtime when a new entry is added to the project library.
-        /// </summary>
-        /// <param name="path">Path relative to the project library resources folder.</param>
-        private static void Internal_DoOnEntryAdded(string path)
-        {
-            if (OnEntryAdded != null)
-                OnEntryAdded(path);
-        }
-
-        /// <summary>
-        /// Triggered internally by the runtime when an entry is removed from the project library.
-        /// </summary>
-        /// <param name="path">Path relative to the project library resources folder.</param>
-        private static void Internal_DoOnEntryRemoved(string path)
-        {
-            if (OnEntryRemoved != null)
-                OnEntryRemoved(path);
-        }
-
-        /// <summary>
-        /// Triggered internally by the runtime when an entry is (re)imported in the project library.
-        /// </summary>
-        /// <param name="path">Path relative to the project library resources folder.</param>
-        private static void Internal_DoOnEntryImported(string path)
-        {
-            if (OnEntryImported != null)
-                OnEntryImported(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);
-    }
-
-    /// <summary>
-    /// Type of project library entries.
-    /// </summary>
-    public enum LibraryEntryType // Note: Must match the C++ enum ProjectLibrary::LibraryEntryType
-    {
-        File, Directory
-    }
-
-    /// <summary>
-    /// Type of resources supported by the project library.
-    /// </summary>
-    public enum ResourceType // Note: Must match the C++ enum ScriptResourceType
-    {
-        Texture, SpriteTexture, Mesh, Font, Shader, ShaderInclude, Material, Prefab, PlainText, 
-        ScriptCode, StringTable, GUISkin, Undefined
-    }
-
-    /// <summary>
-    /// A generic project library entry that may be a file or a folder.
-    /// </summary>
-    public class LibraryEntry : ScriptObject
-    {
-        /// <summary>
-        /// Path of the library entry, relative to the project library resources folder.
-        /// </summary>
-        public string Path { get { return Internal_GetPath(mCachedPtr); } }
-
-        /// <summary>
-        /// Name of the library entry.
-        /// </summary>
-        public string Name { get { return Internal_GetName(mCachedPtr); } }
-
-        /// <summary>
-        /// Type of the library entry.
-        /// </summary>
-        public LibraryEntryType Type { get { return Internal_GetType(mCachedPtr); } }
-
-        /// <summary>
-        /// Directory entry that contains this entry. This may be null for the root entry.
-        /// </summary>
-        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);
-    }
-
-    /// <summary>
-    /// A project library entry representing a directory that contains other entries.
-    /// </summary>
-    public class DirectoryEntry : LibraryEntry
-    {
-        /// <summary>
-        /// A set of entries contained in this entry.
-        /// </summary>
-        public LibraryEntry[] Children { get { return Internal_GetChildren(mCachedPtr); } }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern LibraryEntry[] Internal_GetChildren(IntPtr thisPtr);
-    }
-
-    /// <summary>
-    /// A library entry representing a resource.
-    /// </summary>
-    public class FileEntry : LibraryEntry
-    {
-        /// <summary>
-        /// Import options used for importing the resource.
-        /// </summary>
-        public ImportOptions Options { get { return Internal_GetImportOptions(mCachedPtr); } }
-
-        /// <summary>
-        /// Unique identifier of the resource.
-        /// </summary>
-        public string UUID { get { return Internal_GetUUID(mCachedPtr); } }
-
-        /// <summary>
-        /// Custom icon for the resource to display in the editor, if the resource has one.
-        /// </summary>
-        public Texture2D Icon { get { return Internal_GetIcon(mCachedPtr); } }
-
-        /// <summary>
-        /// Type of the resource referenced by this entry.
-        /// </summary>
-        public ResourceType ResType { get { return Internal_GetResourceType(mCachedPtr); } }
-
-        /// <summary>
-        /// Determines will the resource be included in the project build.
-        /// </summary>
-        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);
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// 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.
+    /// </summary>
+    public sealed class ProjectLibrary : ScriptObject
+    {
+        /// <summary>
+        /// Root entry of the project library, referencing the top level resources folder.
+        /// </summary>
+        public static DirectoryEntry Root { get { return Internal_GetRoot(); } }
+
+        /// <summary>
+        /// Absolute path to the current project's project library resource folder.
+        /// </summary>
+        public static string ResourceFolder { get { return Internal_GetResourceFolder(); } }
+
+        /// <summary>
+        /// Triggered when a new entry is added to the project library. Provided path relative to the project library 
+        /// resources folder.
+        /// </summary>
+        public static event Action<string> OnEntryAdded;
+
+        /// <summary>
+        /// Triggered when an entry is removed from the project library. Provided path relative to the project library 
+        /// resources folder.
+        /// </summary>
+        public static event Action<string> OnEntryRemoved;
+
+        /// <summary>
+        /// Triggered when an entry is (re)imported in the project library. Provided path relative to the project library 
+        /// resources folder.
+        /// </summary>
+        public static event Action<string> OnEntryImported;
+
+        private static HashSet<string> queuedForImport = new HashSet<string>();
+        private static int numImportedFiles;
+        private static int totalFilesToImport;
+        private static bool importInProgress;
+
+        private const float TIME_SLICE_SECONDS = 0.030f;
+
+        /// <summary>
+        /// Checks the project library folder for any modifications and reimports the required resources.
+        /// </summary>
+        /// <param name="synchronous">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.</param>
+        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;
+            }
+        }
+
+        /// <summary>
+        /// Checks the specified folder for any modifications and reimports the required resources.
+        /// </summary>
+        /// <param name="path">Path to a file or folder to refresh. Relative to the project library resources folder or 
+        ///                    absolute.</param>
+        public static void Refresh(string path)
+        {
+            string[] modifiedPaths = Internal_Refresh(path, false);
+            foreach (var modifiedPath in modifiedPaths)
+            {
+                if (queuedForImport.Add(modifiedPath))
+                    totalFilesToImport++;
+            }
+        }
+
+        /// <summary>
+        /// Registers a new resource in the library.
+        /// </summary>
+        /// <param name="resource">Resource instance to add to the library. A copy of the resource will be saved at the 
+        ///                        provided path.</param>
+        /// <param name="path">Path where where to store the resource. Absolute or relative to the resources folder.</param>
+        public static void Create(Resource resource, string path)
+        {
+            Internal_Create(resource, path);
+        }
+
+        /// <summary>
+        /// Updates a resource that is already in the library.
+        /// </summary>
+        /// <param name="resource">Resource to save.</param>
+        public static void Save(Resource resource)
+        {
+            Internal_Save(resource);
+        }
+
+        /// <summary>
+        /// Loads a resource from the project library.
+        /// </summary>
+        /// <typeparam name="T">Type of the resource to load.</typeparam>
+        /// <param name="path">Path of the resource to load. Absolute or relative to the resources folder.</param>
+        /// <returns>Instance of the loaded resource, or null if not found.</returns>
+        public static T Load<T>(string path) where T : Resource
+        {
+            return (T) Internal_Load(path);
+        }
+
+        /// <summary>
+        /// Triggers a reimport of a resource using the provided import options, if needed.
+        /// </summary>
+        /// <param name="path">Path to the resource to reimport, absolute or relative to resources folder.</param>
+        /// <param name="options">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.</param>
+        /// <param name="force">Should the resource be reimported even if no changes are detected.</param>
+        public static void Reimport(string path, ImportOptions options = null, bool force = false)
+        {
+            Internal_Reimport(path, options, force);
+        }
+
+        /// <summary>
+        /// Checks does the project library contain a resource at the specified path.
+        /// </summary>
+        /// <param name="path">Path to the resource to check, absolute or relative to resources folder.</param>
+        /// <returns>True if the resourc exists, false otherwise.</returns>
+        public static bool Exists(string path)
+        {
+            return GetEntry(path) != null;
+        }
+
+        /// <summary>
+        /// Attempts to locate a library entry that describes a file or a folder in the project library.
+        /// </summary>
+        /// <param name="path">Path to the entry to retrieve, absolute or relative to resources folder.</param>
+        /// <returns>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.</returns>
+        public static LibraryEntry GetEntry(string path)
+        {
+            return Internal_GetEntry(path);
+        }
+
+        /// <summary>
+        /// Searches the library for a pattern and returns all entries matching it.
+        /// </summary>
+        /// <param name="pattern">Pattern to search for. Use wildcard * to match any character(s).</param>
+        /// <param name="types">Type of resources to search for. If null all entries will be searched.</param>
+        /// <returns>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.</returns>
+        public static LibraryEntry[] Search(string pattern, ResourceType[] types = null)
+        {
+            return Internal_Search(pattern, types);
+        }
+
+        /// <summary>
+        /// Returns a path to a resource stored in the project library.
+        /// </summary>
+        /// <param name="resource">Resource to find the path for.</param>
+        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
+        ///          </returns>
+        public static string GetPath(Resource resource)
+        {
+            return Internal_GetPath(resource);
+        }
+
+        /// <summary>
+        /// Returns a path to a resource with the specified UUID stored in the project library.
+        /// </summary>
+        /// <param name="uuid">Unique identifier of the resources to retrieve the path of.</param>
+        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
+        ///          </returns>
+        public static string GetPath(string uuid)
+        {
+            return Internal_GetPathFromUUID(uuid);
+        }
+
+        /// <summary>
+        /// Deletes a resource in the project library.
+        /// </summary>
+        /// <param name="path">Path to the entry to delete, absolute or relative to resources folder.</param>
+        public static void Delete(string path)
+        {
+            Internal_Delete(path);
+        }
+
+        /// <summary>
+        /// Creates a new folder in the library.
+        /// </summary>
+        /// <param name="path">Path of the folder to create. Absolute or relative to the resources folder.</param>
+        public static void CreateFolder(string path)
+        {
+            Internal_CreateFolder(path);
+        }
+
+        /// <summary>
+        /// Renames an entry in the project library.
+        /// </summary>
+        /// <param name="path">Path of the entry to rename, absolute or relative to resources folder.</param>
+        /// <param name="name">New name of the entry with an extension.</param>
+        /// <param name="overwrite">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.</param>
+        public static void Rename(string path, string name, bool overwrite = false)
+        {
+            Internal_Rename(path, name, false);
+        }
+
+        /// <summary>
+        /// Moves an entry in the project library from one path to another.
+        /// </summary>
+        /// <param name="oldPath">Source path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="newPath">Destination path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="overwrite">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.</param>
+        public static void Move(string oldPath, string newPath, bool overwrite = false)
+        {
+            Internal_Move(oldPath, newPath, overwrite);
+        }
+
+        /// <summary>
+        /// Copies an entry in the project library from one path to another.
+        /// </summary>
+        /// <param name="source">Source path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="destination">Destination path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="overwrite">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.</param>
+        public static void Copy(string source, string destination, bool overwrite = false)
+        {
+            Internal_Copy(source, destination, overwrite);
+        }
+
+        /// <summary>
+        /// Controls should a resource be included an a build. All dependant resources will also be included.
+        /// </summary>
+        /// <param name="path">Path of the resource to include, absolute or relative to resources folder.</param>
+        /// <param name="include">True if it should be included, false otherwise.</param>
+        public static void SetIncludeInBuild(string path, bool include)
+        {
+            Internal_SetIncludeInBuild(path, include);
+        }
+
+        /// <summary>
+        /// Triggers reimport for queued resource. Should be called once per frame.
+        /// </summary>
+        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<string> toRemove = new List<string>();
+
+                    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<string> 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, pct);
+                }
+
+                importInProgress = true;
+            }
+            else
+                importInProgress = false;
+        }
+
+        /// <summary>
+        /// Triggered internally by the runtime when a new entry is added to the project library.
+        /// </summary>
+        /// <param name="path">Path relative to the project library resources folder.</param>
+        private static void Internal_DoOnEntryAdded(string path)
+        {
+            if (OnEntryAdded != null)
+                OnEntryAdded(path);
+        }
+
+        /// <summary>
+        /// Triggered internally by the runtime when an entry is removed from the project library.
+        /// </summary>
+        /// <param name="path">Path relative to the project library resources folder.</param>
+        private static void Internal_DoOnEntryRemoved(string path)
+        {
+            if (OnEntryRemoved != null)
+                OnEntryRemoved(path);
+        }
+
+        /// <summary>
+        /// Triggered internally by the runtime when an entry is (re)imported in the project library.
+        /// </summary>
+        /// <param name="path">Path relative to the project library resources folder.</param>
+        private static void Internal_DoOnEntryImported(string path)
+        {
+            if (OnEntryImported != null)
+                OnEntryImported(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);
+    }
+
+    /// <summary>
+    /// Type of project library entries.
+    /// </summary>
+    public enum LibraryEntryType // Note: Must match the C++ enum ProjectLibrary::LibraryEntryType
+    {
+        File, Directory
+    }
+
+    /// <summary>
+    /// Type of resources supported by the project library.
+    /// </summary>
+    public enum ResourceType // Note: Must match the C++ enum ScriptResourceType
+    {
+        Texture, SpriteTexture, Mesh, Font, Shader, ShaderInclude, Material, Prefab, PlainText, 
+        ScriptCode, StringTable, GUISkin, Undefined
+    }
+
+    /// <summary>
+    /// A generic project library entry that may be a file or a folder.
+    /// </summary>
+    public class LibraryEntry : ScriptObject
+    {
+        /// <summary>
+        /// Path of the library entry, relative to the project library resources folder.
+        /// </summary>
+        public string Path { get { return Internal_GetPath(mCachedPtr); } }
+
+        /// <summary>
+        /// Name of the library entry.
+        /// </summary>
+        public string Name { get { return Internal_GetName(mCachedPtr); } }
+
+        /// <summary>
+        /// Type of the library entry.
+        /// </summary>
+        public LibraryEntryType Type { get { return Internal_GetType(mCachedPtr); } }
+
+        /// <summary>
+        /// Directory entry that contains this entry. This may be null for the root entry.
+        /// </summary>
+        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);
+    }
+
+    /// <summary>
+    /// A project library entry representing a directory that contains other entries.
+    /// </summary>
+    public class DirectoryEntry : LibraryEntry
+    {
+        /// <summary>
+        /// A set of entries contained in this entry.
+        /// </summary>
+        public LibraryEntry[] Children { get { return Internal_GetChildren(mCachedPtr); } }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern LibraryEntry[] Internal_GetChildren(IntPtr thisPtr);
+    }
+
+    /// <summary>
+    /// A library entry representing a resource.
+    /// </summary>
+    public class FileEntry : LibraryEntry
+    {
+        /// <summary>
+        /// Import options used for importing the resource.
+        /// </summary>
+        public ImportOptions Options { get { return Internal_GetImportOptions(mCachedPtr); } }
+
+        /// <summary>
+        /// Unique identifier of the resource.
+        /// </summary>
+        public string UUID { get { return Internal_GetUUID(mCachedPtr); } }
+
+        /// <summary>
+        /// Custom icon for the resource to display in the editor, if the resource has one.
+        /// </summary>
+        public Texture2D Icon { get { return Internal_GetIcon(mCachedPtr); } }
+
+        /// <summary>
+        /// Type of the resource referenced by this entry.
+        /// </summary>
+        public ResourceType ResType { get { return Internal_GetResourceType(mCachedPtr); } }
+
+        /// <summary>
+        /// Determines will the resource be included in the project build.
+        /// </summary>
+        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);
+    }
+}