Browse Source

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 10 years ago
parent
commit
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);
+    }
+}