瀏覽代碼

Fixed an issue with folder monitor where 64bit pointers were being truncated
Project library now saves entry paths as relative in order to support project folder being moved
Improved layout for ProjectWindow
Added error messages to file decoder/encoder when file open fails
Added temp folder path to file system
MonoUtil wstring to mono conversion now properly handles UTF32
Fixed a crash with GUIInputBox that happened when starting drag on the input box without selecting it previously

BearishSun 10 年之前
父節點
當前提交
d715c4b2ad

+ 3 - 3
BansheeCore/Source/Win32/BsWin32FolderMonitor.cpp

@@ -77,7 +77,7 @@ namespace BansheeEngine
 			BS_LOCK_MUTEX_NAMED(mStatusMutex, lock);
 
 			mState = MonitorState::Starting;
-			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (DWORD)this, &mOverlapped);
+			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (ULONG_PTR)this, &mOverlapped);
 
 			while(mState != MonitorState::Monitoring)
 				BS_THREAD_WAIT(mStartStopEvent, mStatusMutex, lock);
@@ -102,7 +102,7 @@ namespace BansheeEngine
 			BS_LOCK_MUTEX_NAMED(mStatusMutex, lock);
 
 			mState = MonitorState::Shutdown;
-			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (DWORD)this, &mOverlapped);
+			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (ULONG_PTR)this, &mOverlapped);
 
 			while(mState != MonitorState::Inactive)
 				BS_THREAD_WAIT(mStartStopEvent, mStatusMutex, lock);
@@ -364,7 +364,7 @@ namespace BansheeEngine
 		mPimpl->mFoldersToWatch.push_back(bs_new<FolderWatchInfo>(folderPath, dirHandle, subdirectories, filterFlags));
 		FolderWatchInfo* watchInfo = mPimpl->mFoldersToWatch.back();
 
-		mPimpl->mCompPortHandle = CreateIoCompletionPort(dirHandle, mPimpl->mCompPortHandle, (DWORD)watchInfo, 0);
+		mPimpl->mCompPortHandle = CreateIoCompletionPort(dirHandle, mPimpl->mCompPortHandle, (ULONG_PTR)watchInfo, 0);
 
 		if(mPimpl->mCompPortHandle == nullptr)
 		{

+ 11 - 0
BansheeEditor/Include/BsProjectLibrary.h

@@ -379,6 +379,17 @@ namespace BansheeEngine
 		 */
 		void queueDependantForReimport(const ResourceEntry* entry);
 
+		/**
+		 * @brief	Makes all library entry paths relative to the current resources folder.
+		 */
+		void makeEntriesRelative();
+
+		/**
+		 * @brief	Makes all library entry paths absolute by appending them to the current resources folder.
+		 *			Entries must have previously been made relative by calling ::makeEntriesRelative.
+		 */
+		void makeEntriesAbsolute();
+
 		static const WString LIBRARY_ENTRIES_FILENAME;
 		static const WString RESOURCE_MANIFEST_FILENAME;
 

+ 1 - 1
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -1403,7 +1403,7 @@ namespace BansheeEngine
 		selectableLabelStyle.minWidth = 10;
 		selectableLabelStyle.font = font;
 		selectableLabelStyle.fontSize = DefaultFontSize;
-		selectableLabelStyle.textHorzAlign = THA_Center;
+		selectableLabelStyle.textHorzAlign = THA_Left;
 
 		skin->setStyle("SelectableLabel", selectableLabelStyle);
 

+ 10 - 10
BansheeEditor/Source/BsEditorApplication.cpp

@@ -160,23 +160,23 @@ namespace BansheeEngine
 
 		mTestShader = Importer::instance().import<Shader>(testShaderLoc);
 
-		gResources().save(mTestShader, L"C:\\testShader.asset", true);
+		gResources().save(mTestShader, L"E:\\testShader.asset", true);
 		gResources().unload(mTestShader);
-		mTestShader = gResources().load<Shader>(L"C:\\testShader.asset");
+		mTestShader = gResources().load<Shader>(L"E:\\testShader.asset");
 
 		mTestMaterial = Material::create(mTestShader);
 
 		mTestTexRef = static_resource_cast<Texture>(Importer::instance().import(RUNTIME_DATA_PATH + L"Examples\\Dragon.tga"));
 		mDbgMeshRef = static_resource_cast<Mesh>(Importer::instance().import(RUNTIME_DATA_PATH + L"Examples\\Dragon.fbx"));
 
-		gResources().save(mTestTexRef, L"C:\\ExportTest.tex", true);
-		gResources().save(mDbgMeshRef, L"C:\\ExportMesh.mesh", true);
+		gResources().save(mTestTexRef, L"E:\\ExportTest.tex", true);
+		gResources().save(mDbgMeshRef, L"E:\\ExportMesh.mesh", true);
 
 		gResources().unload(mTestTexRef);
 		gResources().unload(mDbgMeshRef);
 
-		mTestTexRef = static_resource_cast<Texture>(gResources().loadAsync(L"C:\\ExportTest.tex"));
-		mDbgMeshRef = static_resource_cast<Mesh>(gResources().loadAsync(L"C:\\ExportMesh.mesh"));
+		mTestTexRef = static_resource_cast<Texture>(gResources().loadAsync(L"E:\\ExportTest.tex"));
+		mDbgMeshRef = static_resource_cast<Mesh>(gResources().loadAsync(L"E:\\ExportMesh.mesh"));
 
 		mDbgMeshRef.blockUntilLoaded();
 		mDbgMeshRef->blockUntilCoreInitialized();
@@ -184,14 +184,14 @@ namespace BansheeEngine
 		mTestTexRef->blockUntilCoreInitialized();
 
 		mTestMaterial->setTexture("tex", mTestTexRef);
-		gResources().save(mTestShader, L"C:\\ExportShader.asset", true);
-		gResources().save(mTestMaterial, L"C:\\ExportMaterial.mat", true);
+		gResources().save(mTestShader, L"E:\\ExportShader.asset", true);
+		gResources().save(mTestMaterial, L"E:\\ExportMaterial.mat", true);
 
 		gResources().unload(mTestMaterial);
 		gResources().unload(mTestShader);
 
-		mTestShader = gResources().load<Shader>(L"C:\\ExportShader.asset");
-		mTestMaterial = gResources().load<Material>(L"C:\\ExportMaterial.mat");
+		mTestShader = gResources().load<Shader>(L"E:\\ExportShader.asset");
+		mTestMaterial = gResources().load<Material>(L"E:\\ExportMaterial.mat");
 
 		testRenderable->setMesh(mDbgMeshRef);
 		testRenderable->setMaterial(0, mTestMaterial);

+ 4 - 2
BansheeEditor/Source/BsEditorTestSuite.cpp

@@ -12,6 +12,7 @@
 #include "BsResources.h"
 #include "BsPrefabDiff.h"
 #include "BsFrameAlloc.h"
+#include "BsFileSystem.h"
 
 namespace BansheeEngine
 {
@@ -627,8 +628,9 @@ namespace BansheeEngine
 
 		GameObjectHandle<TestComponentD> cmp2 = so2->addComponent<TestComponentD>();
 
+		Path prefabPath = Path::combine(FileSystem::getTempDirectoryPath(), "testprefab.asset");
 		HPrefab prefab = Prefab::create(root);
-		gResources().save(prefab, "C:\\testprefab.asset", true);
+		gResources().save(prefab, prefabPath, true);
 
 		// Perform modifications
 		GameObjectHandle<TestComponentC> cmp1_3;
@@ -663,7 +665,7 @@ namespace BansheeEngine
 
 		SPtr<PrefabDiff> prefabDiff = PrefabDiff::create(prefab->getRoot(), root);
 
-		prefab = gResources().load<Prefab>("C:\\testprefab.asset");
+		prefab = gResources().load<Prefab>(prefabPath);
 		HSceneObject newRoot = prefab->instantiate();
 		prefabDiff->apply(newRoot);
 

+ 47 - 0
BansheeEditor/Source/BsProjectLibrary.cpp

@@ -1026,11 +1026,52 @@ namespace BansheeEngine
 		mIsLoaded = false;
 	}
 
+	void ProjectLibrary::makeEntriesRelative()
+	{
+		// Make all paths relative before saving
+		std::function<void(LibraryEntry*, const Path&)> makeRelative =
+			[&](LibraryEntry* entry, const Path& root)
+		{
+			entry->path.makeRelative(root);
+
+			if (entry->type == LibraryEntryType::Directory)
+			{
+				DirectoryEntry* dirEntry = static_cast<DirectoryEntry*>(entry);
+				for (auto& child : dirEntry->mChildren)
+					makeRelative(child, root);
+			}
+		};
+
+		Path root = getResourcesFolder();
+		makeRelative(mRootEntry, root);
+	}
+
+	void ProjectLibrary::makeEntriesAbsolute()
+	{
+		std::function<void(LibraryEntry*, const Path&)> makeAbsolute =
+			[&](LibraryEntry* entry, const Path& root)
+		{
+			entry->path.makeAbsolute(root);
+
+			if (entry->type == LibraryEntryType::Directory)
+			{
+				DirectoryEntry* dirEntry = static_cast<DirectoryEntry*>(entry);
+				for (auto& child : dirEntry->mChildren)
+					makeAbsolute(child, root);
+			}
+		};
+
+		Path root = getResourcesFolder();
+		makeAbsolute(mRootEntry, root);
+	}
+
 	void ProjectLibrary::saveLibrary()
 	{
 		if (!mIsLoaded)
 			return;
 
+		// Make all paths relative before saving
+		makeEntriesRelative();		
 		std::shared_ptr<ProjectLibraryEntries> libEntries = ProjectLibraryEntries::create(*mRootEntry);
 
 		Path libraryEntriesPath = mProjectFolder;
@@ -1040,6 +1081,9 @@ namespace BansheeEngine
 		FileEncoder fs(libraryEntriesPath);
 		fs.encode(libEntries.get());
 
+		// Restore absolute entry paths
+		makeEntriesAbsolute();
+
 		Path resourceManifestPath = mProjectFolder;
 		resourceManifestPath.append(INTERNAL_RESOURCES_DIR);
 		resourceManifestPath.append(RESOURCE_MANIFEST_FILENAME);
@@ -1073,6 +1117,9 @@ namespace BansheeEngine
 			mRootEntry->parent = nullptr;
 		}
 
+		// Entries are stored relative to project folder, but we want their absolute paths now
+		makeEntriesAbsolute();
+
 		// Load resource manifest
 		Path resourceManifestPath = mProjectFolder;
 		resourceManifestPath.append(INTERNAL_RESOURCES_DIR);

+ 17 - 20
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -452,30 +452,27 @@ namespace BansheeEngine
 		}
 		else if(ev.getType() == GUIMouseEventType::MouseDown && ev.getButton() == GUIMouseButton::Left)
 		{
-			if(mHasFocus)
+			if(ev.isShiftDown())
 			{
-				if(ev.isShiftDown())
-				{
-					if(!mSelectionShown)
-						showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
-				}
-				else
-				{
-					clearSelection();
-					showCaret();
-				}
+				if(!mSelectionShown)
+					showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
+			}
+			else
+			{
+				clearSelection();
+				showCaret();
+			}
 
-				if(mText.size() > 0)
-					gGUIManager().getInputCaretTool()->moveCaretToPos(ev.getPosition());
-				else
-					gGUIManager().getInputCaretTool()->moveCaretToStart();
+			if(mText.size() > 0)
+				gGUIManager().getInputCaretTool()->moveCaretToPos(ev.getPosition());
+			else
+				gGUIManager().getInputCaretTool()->moveCaretToStart();
 
-				if(ev.isShiftDown())
-					gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
+			if(ev.isShiftDown())
+				gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
 
-				scrollTextToCaret();
-				_markContentAsDirty();
-			}
+			scrollTextToCaret();
+			_markContentAsDirty();
 
 			return true;
 		}

+ 15 - 1
BansheeMono/Include/BsMonoUtil.h

@@ -5,6 +5,7 @@
 #include "BsDebug.h"
 #include "BsMonoArray.h"
 #include <mono/jit/jit.h>
+#include <codecvt>
 
 namespace BansheeEngine
 {
@@ -56,7 +57,20 @@ namespace BansheeEngine
 		 */
 		static MonoString* wstringToMono(MonoDomain* domain, const WString& str)
 		{
-			return mono_string_from_utf16((mono_unichar2*)str.c_str());
+			if (sizeof(wchar_t) == 2) // Assuming UTF-16
+				return mono_string_from_utf16((mono_unichar2*)str.c_str());
+			else // Assuming UTF-32
+			{
+				const std::codecvt_mode convMode = (std::codecvt_mode)(std::little_endian);
+				typedef std::codecvt_utf16<char32_t, 1114111, convMode> utf16utf32;
+
+				std::wstring_convert<utf16utf32, char32_t> conversion("?");
+				char32_t* start = (char32_t*)str.data();
+				char32_t* end = (start + (str.size() - 1) / 4);
+
+				mono_unichar2* convertedStr = (mono_unichar2*)conversion.to_bytes(start, end).c_str();
+				return mono_string_from_utf16(convertedStr);
+			}
 		}
 
 		/**

+ 5 - 0
BansheeUtility/Include/BsFileSystem.h

@@ -129,5 +129,10 @@ namespace BansheeEngine
 		 * @brief	Returns the path to the currently working directory.
 		 */
 		static Path getWorkingDirectoryPath();
+
+		/**
+		 * @brief	Returns the path to a directory where temporary files may be stored.
+		 */
+		static Path getTempDirectoryPath();
 	};
 }

+ 10 - 1
BansheeUtility/Source/BsFileSerializer.cpp

@@ -4,7 +4,7 @@
 #include "BsIReflectable.h"
 #include "BsBinarySerializer.h"
 #include "BsFileSystem.h"
-
+#include "BsDebug.h"
 #include <numeric>
 
 using namespace std::placeholders;
@@ -21,6 +21,10 @@ namespace BansheeEngine
 			FileSystem::createDir(parentDir);
 
 		mOutputStream.open(fileLocation.toString().c_str(), std::ios::out | std::ios::binary);
+		if (mOutputStream.fail())
+		{
+			LOGWRN("Failed to save file: \"" + fileLocation.toString() + "\". Error: " + strerror(errno) + ".");
+		}
 	}
 
 	FileEncoder::~FileEncoder()
@@ -56,6 +60,11 @@ namespace BansheeEngine
 	{
 		mInputStream.open(fileLocation.toString().c_str(), std::ios::in | std::ios::ate | std::ios::binary);
 
+		if (mInputStream.fail())
+		{
+			LOGWRN("Failed to open file: \"" + fileLocation.toString() + "\". Error: " + strerror(errno) + ".");
+		}
+
 		std::streamoff fileSize = mInputStream.tellg();
 		if (fileSize > std::numeric_limits<UINT32>::max())
 		{

+ 29 - 0
BansheeUtility/Source/Win32/BsFileSystem.cpp

@@ -76,6 +76,30 @@ namespace BansheeEngine
 		return StringUtil::WBLANK;
 	}
 
+	WString win32_getTempDirectory()
+	{
+		DWORD len = GetTempPathW(0, NULL);
+		if (len > 0)
+		{
+			wchar_t* buffer = (wchar_t*)bs_alloc(len * sizeof(wchar_t));
+
+			DWORD n = GetTempPathW(len, buffer);
+			if (n > 0 && n <= len)
+			{
+				WString result(buffer);
+				if (result[result.size() - 1] != '\\')
+					result.append(L"\\");
+
+				bs_free(buffer);
+				return result;
+			}
+
+			bs_free(buffer);
+		}
+
+		return StringUtil::WBLANK;
+	}
+
 	bool win32_pathExists(const WString& path)
 	{
 		DWORD attr = GetFileAttributesW(path.c_str());
@@ -565,4 +589,9 @@ namespace BansheeEngine
 	{
 		return Path(win32_getCurrentDirectory());
 	}
+
+	Path FileSystem::getTempDirectoryPath()
+	{
+		return Path(win32_getTempDirectory());
+	}
 }

+ 3 - 0
Dependencies.txt

@@ -44,6 +44,9 @@ BansheeD3D11RenderAPI & BansheeD3D9RenderAPI (both optional) rely on:
  - Microsoft DirectX SDK June 2010
   - http://www.microsoft.com/en-us/download/details.aspx?id=6812
   - After installing the SDK make sure DXSDK_DIR environment variable is set up pointing to the installation path
+ - Windows SDK 
+  - Needed for DirectX 11 debug layer
+  - This also contains DirectX SDK so you don't need to install it separately.
 
 BansheeSL (optional) relies on:
  - Bison 2.7

+ 4 - 0
MBansheeEditor/EditorApplication.cs

@@ -109,7 +109,11 @@ namespace BansheeEditor
                 string projectPath = EditorSettings.LastOpenProject;
                 if (Internal_IsValidProject(projectPath))
                     LoadProject(projectPath);
+                else
+                    ProjectWindow.Open();
             }
+            else
+                ProjectWindow.Open();
         }
 
         private static void OnAssetModified(string path)

+ 9 - 6
MBansheeEditor/ProjectWindow.cs

@@ -38,6 +38,7 @@ namespace BansheeEditor
             GUILayout firstRow = vertLayout.AddLayoutX();
             vertLayout.AddFlexibleSpace();
             GUILayout secondRow = vertLayout.AddLayoutX();
+            vertLayout.AddSpace(15);
             GUILayout thirdRow = vertLayout.AddLayoutX();
             vertLayout.AddFlexibleSpace();
             GUILayout fourthRow = vertLayout.AddLayoutX();
@@ -61,10 +62,10 @@ namespace BansheeEditor
             secondRow.AddElement(recentProjectsLabel);
             secondRow.AddFlexibleSpace();
 
-            recentProjectsArea = new GUIScrollArea(GUIOption.FixedWidth(425), GUIOption.FixedHeight(150));
-            thirdRow.AddSpace(5);
+            recentProjectsArea = new GUIScrollArea(GUIOption.FixedWidth(405), GUIOption.FixedHeight(140));
+            thirdRow.AddSpace(5 + 10);
             thirdRow.AddElement(recentProjectsArea);
-            thirdRow.AddSpace(15);
+            thirdRow.AddSpace(15 + 10);
 
             GUILayout browseBtnLayout = thirdRow.AddLayoutY();
             GUIButton browseBtn = new GUIButton(new LocEdString("Browse"), GUIOption.FixedWidth(50));
@@ -98,9 +99,11 @@ namespace BansheeEditor
 
             Rect2I bounds = vertLayout.Bounds;
             Rect2I scrollAreaBounds = recentProjectsArea.Bounds;
-            Debug.Log(scrollAreaBounds + " - " + vertLayout.Bounds);
-            scrollAreaBounds.y += bounds.y;
-            scrollAreaBounds.height += 2;
+
+            scrollAreaBounds.x -= 10;
+            scrollAreaBounds.y += bounds.y - 10;
+            scrollAreaBounds.height += 20;
+            scrollAreaBounds.width += 20;
 
             scrollAreaBgTex.Bounds = scrollAreaBounds;
         }

+ 5 - 1
SBansheeEditor/Source/BsScriptEditorSettings.cpp

@@ -182,7 +182,11 @@ namespace BansheeEngine
 
 		for (UINT32 i = 0; i < numEntries; i++)
 		{
-			MonoString* monoPath = MonoUtil::wstringToMono(MonoManager::instance().getDomain(), recentProjects[i].path.toWString());
+			// Duplicate all slashes as mono seems to remove them during conversion to MonoString
+			WString projectPath = recentProjects[i].path.toWString();
+			projectPath = StringUtil::replaceAll(projectPath, L"\\", L"\\\\");
+
+			MonoString* monoPath = MonoUtil::wstringToMono(MonoManager::instance().getDomain(), projectPath);
 
 			outputPaths.set(i, monoPath);
 			outputTimeStamps.set(i, recentProjects[i].accessTimestamp);