Browse Source

VS integration finished (for now)

Marko Pintera 10 years ago
parent
commit
3a73e65b09

+ 6 - 6
BansheeEditor/Include/BsCodeEditor.h

@@ -36,8 +36,8 @@ namespace BansheeEngine
 		CodeEditorManager();
 		CodeEditorManager();
 		~CodeEditorManager();
 		~CodeEditorManager();
 
 
-		const Vector<WString>& getAvailableEditors() const { return mEditors; }
-		void setActive(const WString& editor);
+		const Vector<CodeEditorType>& getAvailableEditors() const { return mEditors; }
+		void setActive(CodeEditorType editor);
 
 
 		void openFile(const Path& path, UINT32 lineNumber) const;
 		void openFile(const Path& path, UINT32 lineNumber) const;
 		void syncSolution() const;
 		void syncSolution() const;
@@ -46,8 +46,8 @@ namespace BansheeEngine
 		Path getSolutionPath() const;
 		Path getSolutionPath() const;
 
 
 		CodeEditor* mActiveEditor;
 		CodeEditor* mActiveEditor;
-		Map<WString, CodeEditorFactory*> mFactoryPerEditor;
-		Vector<WString> mEditors;
+		Map<CodeEditorType, CodeEditorFactory*> mFactoryPerEditor;
+		Vector<CodeEditorType> mEditors;
 		Vector<CodeEditorFactory*> mFactories;
 		Vector<CodeEditorFactory*> mFactories;
 	};
 	};
 
 
@@ -61,7 +61,7 @@ namespace BansheeEngine
 	class BS_ED_EXPORT CodeEditorFactory
 	class BS_ED_EXPORT CodeEditorFactory
 	{
 	{
 	public:
 	public:
-		virtual const Vector<WString>& getAvailableEditors() const = 0;
-		virtual CodeEditor* create(const WString& editor) const = 0;
+		virtual const Vector<CodeEditorType>& getAvailableEditors() const = 0;
+		virtual CodeEditor* create(CodeEditorType editor) const = 0;
 	};
 	};
 }
 }

+ 9 - 0
BansheeEditor/Include/BsEditorPrerequisites.h

@@ -83,6 +83,15 @@ namespace BansheeEngine
 		Resources = 10002
 		Resources = 10002
 	};
 	};
 
 
+	enum class CodeEditorType
+	{
+		VS2008,
+		VS2010,
+		VS2012,
+		VS2013,
+		VS2015
+	};
+
 	enum TypeID_BansheeEditor
 	enum TypeID_BansheeEditor
 	{
 	{
 		TID_ProjectResourceMeta = 40000,
 		TID_ProjectResourceMeta = 40000,

+ 5 - 5
BansheeEditor/Include/Win32/BsVSCodeEditor.h

@@ -33,8 +33,8 @@ namespace BansheeEngine
 	public:
 	public:
 		VSCodeEditorFactory();
 		VSCodeEditorFactory();
 
 
-		const Vector<WString>& getAvailableEditors() const override { return mAvailableEditors; }
-		CodeEditor* create(const WString& editor) const override;
+		const Vector<CodeEditorType>& getAvailableEditors() const override { return mAvailableEditors; }
+		CodeEditor* create(CodeEditorType editor) const override;
 
 
 	private:
 	private:
 		struct VSVersionInfo
 		struct VSVersionInfo
@@ -45,9 +45,9 @@ namespace BansheeEngine
 			VisualStudioVersion version;
 			VisualStudioVersion version;
 		};
 		};
 
 
-		Map<WString, VSVersionInfo> getAvailableVersions() const;
+		Map<CodeEditorType, VSVersionInfo> getAvailableVersions() const;
 
 
-		Map<WString, VSVersionInfo> mAvailableVersions;
-		Vector<WString> mAvailableEditors;
+		Map<CodeEditorType, VSVersionInfo> mAvailableVersions;
+		Vector<CodeEditorType> mAvailableEditors;
 	};
 	};
 }
 }

+ 17 - 10
BansheeEditor/Source/BsCodeEditor.cpp

@@ -17,7 +17,7 @@ namespace BansheeEngine
 	{
 	{
 #if BS_PLATFORM == BS_PLATFORM_WIN32
 #if BS_PLATFORM == BS_PLATFORM_WIN32
 		VSCodeEditorFactory* vsCodeEditorFactory = bs_new<VSCodeEditorFactory>();
 		VSCodeEditorFactory* vsCodeEditorFactory = bs_new<VSCodeEditorFactory>();
-		Vector<WString> vsEditors = vsCodeEditorFactory->getAvailableEditors();
+		Vector<CodeEditorType> vsEditors = vsCodeEditorFactory->getAvailableEditors();
 		for(auto& editor : vsEditors)
 		for(auto& editor : vsEditors)
 		{
 		{
 			mFactoryPerEditor[editor] = vsCodeEditorFactory;
 			mFactoryPerEditor[editor] = vsCodeEditorFactory;
@@ -39,7 +39,7 @@ namespace BansheeEngine
 			bs_delete(mActiveEditor);
 			bs_delete(mActiveEditor);
 	}
 	}
 
 
-	void CodeEditorManager::setActive(const WString& editor)
+	void CodeEditorManager::setActive(CodeEditorType editor)
 	{
 	{
 		if (mActiveEditor != nullptr)
 		if (mActiveEditor != nullptr)
 		{
 		{
@@ -56,8 +56,14 @@ namespace BansheeEngine
 
 
 	void CodeEditorManager::openFile(const Path& path, UINT32 lineNumber) const
 	void CodeEditorManager::openFile(const Path& path, UINT32 lineNumber) const
 	{
 	{
-		if (mActiveEditor != nullptr)
-			mActiveEditor->openFile(getSolutionPath(), path, lineNumber);
+		if (mActiveEditor == nullptr)
+			return;
+
+		Path filePath = path;
+		if (!path.isAbsolute())
+			filePath.makeAbsolute(gEditorApplication().getProjectPath());
+
+		mActiveEditor->openFile(getSolutionPath(), filePath, lineNumber);
 	}
 	}
 
 
 	void CodeEditorManager::syncSolution() const
 	void CodeEditorManager::syncSolution() const
@@ -75,9 +81,11 @@ namespace BansheeEngine
 
 
 		Vector<ProjectLibrary::LibraryEntry*> libraryEntries = ProjectLibrary::instance().search(L"*", scriptTypeIds);
 		Vector<ProjectLibrary::LibraryEntry*> libraryEntries = ProjectLibrary::instance().search(L"*", scriptTypeIds);
 		
 		
-		// Game project
 		slnData.projects.push_back(CodeProjectData());
 		slnData.projects.push_back(CodeProjectData());
-		CodeProjectData& gameProject = slnData.projects.back();
+		slnData.projects.push_back(CodeProjectData());
+
+		// Game project
+		CodeProjectData& gameProject = slnData.projects[0];
 		gameProject.name = toWString(SCRIPT_GAME_ASSEMBLY);
 		gameProject.name = toWString(SCRIPT_GAME_ASSEMBLY);
 		
 		
 		//// Add references
 		//// Add references
@@ -85,8 +93,7 @@ namespace BansheeEngine
 		gameProject.assemblyReferences.push_back(CodeProjectReference{ L"BansheeEngine", gApplication().getEngineAssemblyPath() });
 		gameProject.assemblyReferences.push_back(CodeProjectReference{ L"BansheeEngine", gApplication().getEngineAssemblyPath() });
 
 
 		// Editor project
 		// Editor project
-		slnData.projects.push_back(CodeProjectData());
-		CodeProjectData& editorProject = slnData.projects.back();
+		CodeProjectData& editorProject = slnData.projects[1];
 		editorProject.name = toWString(SCRIPT_EDITOR_ASSEMBLY);
 		editorProject.name = toWString(SCRIPT_EDITOR_ASSEMBLY);
 
 
 		//// Add references
 		//// Add references
@@ -94,7 +101,7 @@ namespace BansheeEngine
 		editorProject.assemblyReferences.push_back(CodeProjectReference{ L"BansheeEngine", gApplication().getEngineAssemblyPath() });
 		editorProject.assemblyReferences.push_back(CodeProjectReference{ L"BansheeEngine", gApplication().getEngineAssemblyPath() });
 		editorProject.assemblyReferences.push_back(CodeProjectReference{ L"BansheeEditor", gEditorApplication().getEditorAssemblyPath() });
 		editorProject.assemblyReferences.push_back(CodeProjectReference{ L"BansheeEditor", gEditorApplication().getEditorAssemblyPath() });
 
 
-		editorProject.projectReferences.push_back(CodeProjectReference{ gameProject.name, Path::BLANK});
+		editorProject.projectReferences.push_back(CodeProjectReference{ gameProject.name, Path::BLANK });
 
 
 		//// Add files for both projects
 		//// Add files for both projects
 		for (auto& entry : libraryEntries)
 		for (auto& entry : libraryEntries)
@@ -120,7 +127,7 @@ namespace BansheeEngine
 				gameProject.nonCodeFiles.push_back(resEntry->path);
 				gameProject.nonCodeFiles.push_back(resEntry->path);
 		}
 		}
 
 
-		mActiveEditor->syncSolution(slnData, getSolutionPath());
+		mActiveEditor->syncSolution(slnData, gEditorApplication().getProjectPath());
 	}
 	}
 
 
 	Path CodeEditorManager::getSolutionPath() const
 	Path CodeEditorManager::getSolutionPath() const

+ 124 - 114
BansheeEditor/Source/Win32/BsVSCodeEditor.cpp

@@ -32,16 +32,16 @@ namespace BansheeEngine
 	class VisualStudio
 	class VisualStudio
 	{
 	{
 	private:
 	private:
-		static const WString SLN_TEMPLATE;
-		static const WString PROJ_ENTRY_TEMPLATE;
-		static const WString PROJ_PLATFORM_TEMPLATE;
+		static const String SLN_TEMPLATE;
+		static const String PROJ_ENTRY_TEMPLATE;
+		static const String PROJ_PLATFORM_TEMPLATE;
 
 
-		static const WString PROJ_TEMPLATE;
-		static const WString REFERENCE_ENTRY_TEMPLATE;
-		static const WString REFERENCE_PROJECT_ENTRY_TEMPLATE;
-		static const WString REFERENCE_PATH_ENTRY_TEMPLATE;
-		static const WString CODE_ENTRY_TEMPLATE;
-		static const WString NON_CODE_ENTRY_TEMPLATE;
+		static const String PROJ_TEMPLATE;
+		static const String REFERENCE_ENTRY_TEMPLATE;
+		static const String REFERENCE_PROJECT_ENTRY_TEMPLATE;
+		static const String REFERENCE_PATH_ENTRY_TEMPLATE;
+		static const String CODE_ENTRY_TEMPLATE;
+		static const String NON_CODE_ENTRY_TEMPLATE;
 
 
 	public:
 	public:
 		static CComPtr<EnvDTE::_DTE> findRunningInstance(const CLSID& clsID, const Path& solutionPath)
 		static CComPtr<EnvDTE::_DTE> findRunningInstance(const CLSID& clsID, const Path& solutionPath)
@@ -173,150 +173,153 @@ namespace BansheeEngine
 			return true;
 			return true;
 		}
 		}
 
 
-		static String getSolutionGUID(const WString& solutionName)
-		{
-			static const String guidTemplate = "{0}-{1}-{2}-{3}-{4}";
-			String hash = md5(L"SLN_" + solutionName);
-
-			return StringUtil::format(guidTemplate, hash.substr(0, 8), hash.substr(8, 4), hash.substr(12, 4), hash.substr(16, 4), hash.substr(20, 12));
-		}
-
 		static String getProjectGUID(const WString& projectName)
 		static String getProjectGUID(const WString& projectName)
 		{
 		{
 			static const String guidTemplate = "{0}-{1}-{2}-{3}-{4}";
 			static const String guidTemplate = "{0}-{1}-{2}-{3}-{4}";
-			String hash = md5(L"PRJ_" + projectName);
+			String hash = md5(projectName);
+
+			String output = StringUtil::format(guidTemplate, hash.substr(0, 8),
+				hash.substr(8, 4), hash.substr(12, 4), hash.substr(16, 4), hash.substr(20, 12));
+			StringUtil::toUpperCase(output);
 
 
-			return StringUtil::format(guidTemplate, hash.substr(0, 8), hash.substr(8, 4), hash.substr(12, 4), hash.substr(16, 4), hash.substr(20, 12));
+			return output;
 		}
 		}
 
 
-		static WString writeSolution(VisualStudioVersion version, const CodeSolutionData& data)
+		static String writeSolution(VisualStudioVersion version, const CodeSolutionData& data)
 		{
 		{
 			struct VersionData
 			struct VersionData
 			{
 			{
-				WString formatVersion;
+				String formatVersion;
 			};
 			};
 
 
 			Map<VisualStudioVersion, VersionData> versionData =
 			Map<VisualStudioVersion, VersionData> versionData =
 			{
 			{
-				{ VisualStudioVersion::VS2008, { L"10.0" } },
-				{ VisualStudioVersion::VS2010, { L"11.0" } },
-				{ VisualStudioVersion::VS2012, { L"12.0" } },
-				{ VisualStudioVersion::VS2013, { L"12.0" } },
-				{ VisualStudioVersion::VS2015, { L"12.0" } }
+				{ VisualStudioVersion::VS2008, { "10.00" } },
+				{ VisualStudioVersion::VS2010, { "11.00" } },
+				{ VisualStudioVersion::VS2012, { "12.00" } },
+				{ VisualStudioVersion::VS2013, { "12.00" } },
+				{ VisualStudioVersion::VS2015, { "12.00" } }
 			};
 			};
 
 
-			WString solutionGUID = toWString(getSolutionGUID(data.name));
-
-			WStringStream projectEntriesStream;
-			WStringStream projectPlatformsStream;
+			StringStream projectEntriesStream;
+			StringStream projectPlatformsStream;
 			for (auto& project : data.projects)
 			for (auto& project : data.projects)
 			{
 			{
-				WString guid = toWString(getProjectGUID(project.name));
+				String guid = getProjectGUID(project.name);
+				String projectName = toString(project.name);
 
 
-				projectEntriesStream << StringUtil::format(PROJ_ENTRY_TEMPLATE, solutionGUID, project.name, project.name + L".csproj", guid) << std::endl;
-				projectPlatformsStream << StringUtil::format(PROJ_PLATFORM_TEMPLATE, guid) << std::endl;
+				projectEntriesStream << StringUtil::format(PROJ_ENTRY_TEMPLATE, projectName, projectName + ".csproj", guid);
+				projectPlatformsStream << StringUtil::format(PROJ_PLATFORM_TEMPLATE, guid);
 			}
 			}
 
 
-			WString projectEntries = projectEntriesStream.str();
-			WString projectPlatforms = projectPlatformsStream.str();
+			String projectEntries = projectEntriesStream.str();
+			String projectPlatforms = projectPlatformsStream.str();
 
 
 			return StringUtil::format(SLN_TEMPLATE, versionData[version].formatVersion, projectEntries, projectPlatforms);
 			return StringUtil::format(SLN_TEMPLATE, versionData[version].formatVersion, projectEntries, projectPlatforms);
 		}
 		}
 
 
-		static WString writeProject(VisualStudioVersion version, const CodeProjectData& projectData)
+		static String writeProject(VisualStudioVersion version, const CodeProjectData& projectData)
 		{
 		{
 			struct VersionData
 			struct VersionData
 			{
 			{
-				WString toolsVersion;
+				String toolsVersion;
 			};
 			};
 
 
 			Map<VisualStudioVersion, VersionData> versionData =
 			Map<VisualStudioVersion, VersionData> versionData =
 			{
 			{
-				{ VisualStudioVersion::VS2008, { L"3.5" } },
-				{ VisualStudioVersion::VS2010, { L"4.0" } },
-				{ VisualStudioVersion::VS2012, { L"4.0" } },
-				{ VisualStudioVersion::VS2013, { L"12.0" } },
-				{ VisualStudioVersion::VS2015, { L"13.0" } }
+				{ VisualStudioVersion::VS2008, { "3.5" } },
+				{ VisualStudioVersion::VS2010, { "4.0" } },
+				{ VisualStudioVersion::VS2012, { "4.0" } },
+				{ VisualStudioVersion::VS2013, { "12.0" } },
+				{ VisualStudioVersion::VS2015, { "13.0" } }
 			};
 			};
 
 
-			WStringStream tempStream;
+			StringStream tempStream;
 			for (auto& codeEntry : projectData.codeFiles)
 			for (auto& codeEntry : projectData.codeFiles)
-				tempStream << StringUtil::format(CODE_ENTRY_TEMPLATE, codeEntry.toWString()) << std::endl;
+				tempStream << StringUtil::format(CODE_ENTRY_TEMPLATE, codeEntry.toString());
 
 
-			WString codeEntries = tempStream.str();
-			tempStream.str(L"");
+			String codeEntries = tempStream.str();
+			tempStream.str("");
 			tempStream.clear();
 			tempStream.clear();
 
 
 			for (auto& nonCodeEntry : projectData.nonCodeFiles)
 			for (auto& nonCodeEntry : projectData.nonCodeFiles)
-				tempStream << StringUtil::format(NON_CODE_ENTRY_TEMPLATE, nonCodeEntry.toWString()) << std::endl;
+				tempStream << StringUtil::format(NON_CODE_ENTRY_TEMPLATE, nonCodeEntry.toString());
 
 
-			WString nonCodeEntries = tempStream.str();
-			tempStream.str(L"");
+			String nonCodeEntries = tempStream.str();
+			tempStream.str("");
 			tempStream.clear();
 			tempStream.clear();
 
 
 			for (auto& referenceEntry : projectData.assemblyReferences)
 			for (auto& referenceEntry : projectData.assemblyReferences)
 			{
 			{
+				String referenceName = toString(referenceEntry.name);
+
 				if (referenceEntry.path.isEmpty())
 				if (referenceEntry.path.isEmpty())
-					tempStream << StringUtil::format(REFERENCE_ENTRY_TEMPLATE, referenceEntry.name) << std::endl;
+					tempStream << StringUtil::format(REFERENCE_ENTRY_TEMPLATE, referenceName);
 				else
 				else
-					tempStream << StringUtil::format(REFERENCE_PATH_ENTRY_TEMPLATE, referenceEntry.name, referenceEntry.path.toWString()) << std::endl;
+					tempStream << StringUtil::format(REFERENCE_PATH_ENTRY_TEMPLATE, referenceName, referenceEntry.path.toString());
 			}
 			}
 
 
-			WString referenceEntries = tempStream.str();
-			tempStream.str(L"");
+			String referenceEntries = tempStream.str();
+			tempStream.str("");
 			tempStream.clear();
 			tempStream.clear();
 
 
 			for (auto& referenceEntry : projectData.projectReferences)
 			for (auto& referenceEntry : projectData.projectReferences)
 			{
 			{
-				WString projectGUID = toWString(getProjectGUID(referenceEntry.name));
-				tempStream << StringUtil::format(REFERENCE_PROJECT_ENTRY_TEMPLATE, referenceEntry.name, projectGUID) << std::endl;
+				String referenceName = toString(referenceEntry.name);
+				String projectGUID = getProjectGUID(referenceEntry.name);
+
+				tempStream << StringUtil::format(REFERENCE_PROJECT_ENTRY_TEMPLATE, referenceName, projectGUID);
 			}
 			}
 
 
-			WString projectReferenceEntries = tempStream.str();
-			tempStream.str(L"");
+			String projectReferenceEntries = tempStream.str();
+			tempStream.str("");
 			tempStream.clear();
 			tempStream.clear();
 
 
 			for (auto& define : projectData.defines)
 			for (auto& define : projectData.defines)
-				tempStream << define << L";";
+				tempStream << toString(define) << ";";
 
 
-			WString defines = tempStream.str();
-			WString projectGUID = toWString(getProjectGUID(projectData.name));
+			String defines = tempStream.str();
+			String projectGUID = getProjectGUID(projectData.name);
 
 
-			return StringUtil::format(PROJ_ENTRY_TEMPLATE, versionData[version].toolsVersion, projectGUID, 
-				projectData.name, defines, referenceEntries, projectReferenceEntries, codeEntries, nonCodeEntries);
+			return StringUtil::format(PROJ_TEMPLATE, versionData[version].toolsVersion, projectGUID, 
+				toString(projectData.name), defines, referenceEntries, projectReferenceEntries, codeEntries, nonCodeEntries);
 		}
 		}
 	};
 	};
 
 
-	const WString VisualStudio::SLN_TEMPLATE =
-		LR"(Microsoft Visual Studio Solution File, Format Version {0}
-{1}
+	const String VisualStudio::SLN_TEMPLATE =
+		R"(Microsoft Visual Studio Solution File, Format Version {0}
+# Visual Studio 2013
+VisualStudioVersion = 12.0.30723.0
+MinimumVisualStudioVersion = 10.0.40219.1{1}
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
 		Debug|Any CPU = Debug|Any CPU
 		Release|Any CPU = Release|Any CPU
 		Release|Any CPU = Release|Any CPU
 	EndGlobalSection
 	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{2}
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution{2}
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE
 	EndGlobalSection
 	EndGlobalSection
-EndGlobal)";
+EndGlobal
+)";
 
 
-	const WString VisualStudio::PROJ_ENTRY_TEMPLATE =
-		LR"(Project("\{{0}\}") = "{1}", "{2}", "\{{3}\}"
+	const String VisualStudio::PROJ_ENTRY_TEMPLATE =
+		R"(
+Project("\{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC\}") = "{0}", "{1}", "\{{2}\}"
 EndProject)";
 EndProject)";
 
 
-	const WString VisualStudio::PROJ_PLATFORM_TEMPLATE =
-		LR"(\{{0}\}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+	const String VisualStudio::PROJ_PLATFORM_TEMPLATE =
+		R"(
+		\{{0}\}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		\{{0}\}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		\{{0}\}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		\{{0}\}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		\{{0}\}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		\{{0}\}.Release|Any CPU.Build.0 = Release|Any CPU)";
 		\{{0}\}.Release|Any CPU.Build.0 = Release|Any CPU)";
 
 
-	const WString VisualStudio::PROJ_TEMPLATE =
-		LR"literal(<?xml version="1.0" encoding="utf-8"?>
+	const String VisualStudio::PROJ_TEMPLATE =
+		R"literal(<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="{0}" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="{0}" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')" />
   <PropertyGroup>
   <PropertyGroup>
     <Configuration Condition = " '$(Configuration)' == '' ">Debug</Configuration>
     <Configuration Condition = " '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition = " '$(Platform)' == '' ">AnyCPU</Platform>
     <Platform Condition = " '$(Platform)' == '' ">AnyCPU</Platform>
@@ -330,11 +333,12 @@ EndProject)";
     <BaseDirectory>Resources</BaseDirectory>
     <BaseDirectory>Resources</BaseDirectory>
     <SchemaVersion>2.0</SchemaVersion>
     <SchemaVersion>2.0</SchemaVersion>
   </PropertyGroup>
   </PropertyGroup>
-    <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
-    <OutputPath>Internal\Temp\Assemblies\Debug\</OutputPath>
+    <OutputPath>Internal\\Temp\\Assemblies\\Debug\\</OutputPath>
+    <BaseIntermediateOutputPath>Internal\\Temp\\Assemblies\\</BaseIntermediateOutputPath>
     <DefineConstants>DEBUG;TRACE;{3}</DefineConstants>
     <DefineConstants>DEBUG;TRACE;{3}</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel >
     <WarningLevel>4</WarningLevel >
@@ -342,45 +346,47 @@ EndProject)";
   <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
-    <OutputPath>Internal\Temp\Assemblies\Release\</OutputPath>
+    <OutputPath>Internal\\Temp\\Assemblies\\Release\\</OutputPath>
+	<BaseIntermediateOutputPath>Internal\\Temp\\Assemblies\\</BaseIntermediateOutputPath>
     <DefineConstants>TRACE;{3}</DefineConstants>
     <DefineConstants>TRACE;{3}</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   </PropertyGroup>
-  <ItemGroup>
-{4}
+  <ItemGroup>{4}
   </ItemGroup>
   </ItemGroup>
-  <ItemGroup>
-{5}
+  <ItemGroup>{5}
   </ItemGroup>
   </ItemGroup>
-  <ItemGroup>
-{6}
+  <ItemGroup>{6}
   </ItemGroup>
   </ItemGroup>
-  <ItemGroup>
-{7}
+  <ItemGroup>{7}
   </ItemGroup>
   </ItemGroup>
-  <Import Project = "$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
+  <Import Project = "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"/>
 </Project>)literal";
 </Project>)literal";
 
 
-	const WString VisualStudio::REFERENCE_ENTRY_TEMPLATE =
-		LR"(    <Reference Include="{0}"/>)";
+	const String VisualStudio::REFERENCE_ENTRY_TEMPLATE =
+		R"(
+    <Reference Include="{0}"/>)";
 
 
-	const WString VisualStudio::REFERENCE_PATH_ENTRY_TEMPLATE =
-		LR"(    <Reference Include="{0}">
+	const String VisualStudio::REFERENCE_PATH_ENTRY_TEMPLATE =
+		R"(
+    <Reference Include="{0}">
       <HintPath>{1}</HintPath>
       <HintPath>{1}</HintPath>
     </Reference>)";
     </Reference>)";
 
 
-	const WString VisualStudio::REFERENCE_PROJECT_ENTRY_TEMPLATE =
-		LR"(    <ProjectReference Include="{0}.csproj">
+	const String VisualStudio::REFERENCE_PROJECT_ENTRY_TEMPLATE =
+		R"(
+    <ProjectReference Include="{0}.csproj">
       <Project>\{{1}\}</Project>
       <Project>\{{1}\}</Project>
       <Name>{0}</Name>
       <Name>{0}</Name>
     </ProjectReference>)";
     </ProjectReference>)";
 
 
-	const WString VisualStudio::CODE_ENTRY_TEMPLATE =
-		LR"(    <Compile Include="{0}"/>)";
+	const String VisualStudio::CODE_ENTRY_TEMPLATE =
+		R"(
+    <Compile Include="{0}"/>)";
 
 
-	const WString VisualStudio::NON_CODE_ENTRY_TEMPLATE =
-		LR"(    <None Include="{0}"/>)";
+	const String VisualStudio::NON_CODE_ENTRY_TEMPLATE =
+		R"(
+    <None Include="{0}"/>)";
 
 
 	VSCodeEditor::VSCodeEditor(VisualStudioVersion version, const Path& execPath, const WString& CLSID)
 	VSCodeEditor::VSCodeEditor(VisualStudioVersion version, const Path& execPath, const WString& CLSID)
 		:mCLSID(CLSID), mExecPath(execPath), mVersion(version)
 		:mCLSID(CLSID), mExecPath(execPath), mVersion(version)
@@ -406,23 +412,26 @@ EndProject)";
 
 
 	void VSCodeEditor::syncSolution(const CodeSolutionData& data, const Path& outputPath) const
 	void VSCodeEditor::syncSolution(const CodeSolutionData& data, const Path& outputPath) const
 	{
 	{
-		WString solutionString = VisualStudio::writeSolution(mVersion, data);
+		String solutionString = VisualStudio::writeSolution(mVersion, data);
+		solutionString = StringUtil::replaceAll(solutionString, "\n", "\r\n");
 		Path solutionPath = outputPath;
 		Path solutionPath = outputPath;
 		solutionPath.append(data.name + L".sln");
 		solutionPath.append(data.name + L".sln");
 
 
 		for (auto& project : data.projects)
 		for (auto& project : data.projects)
 		{
 		{
-			WString projectString = VisualStudio::writeProject(mVersion, project);
+			String projectString = VisualStudio::writeProject(mVersion, project);
+			projectString = StringUtil::replaceAll(projectString, "\n", "\r\n");
+
 			Path projectPath = outputPath;
 			Path projectPath = outputPath;
 			projectPath.append(project.name + L".csproj");
 			projectPath.append(project.name + L".csproj");
 
 
 			DataStreamPtr projectStream = FileSystem::createAndOpenFile(projectPath);
 			DataStreamPtr projectStream = FileSystem::createAndOpenFile(projectPath);
-			projectStream->write(projectString.c_str(), projectString.size());
+			projectStream->write(projectString.c_str(), projectString.size() * sizeof(String::value_type));
 			projectStream->close();
 			projectStream->close();
 		}
 		}
 
 
 		DataStreamPtr solutionStream = FileSystem::createAndOpenFile(solutionPath);
 		DataStreamPtr solutionStream = FileSystem::createAndOpenFile(solutionPath);
-		solutionStream->write(solutionString.c_str(), solutionString.size());
+		solutionStream->write(solutionString.c_str(), solutionString.size() * sizeof(String::value_type));
 		solutionStream->close();
 		solutionStream->close();
 	}
 	}
 
 
@@ -433,7 +442,7 @@ EndProject)";
 			mAvailableEditors.push_back(version.first);
 			mAvailableEditors.push_back(version.first);
 	}
 	}
 
 
-	Map<WString, VSCodeEditorFactory::VSVersionInfo> VSCodeEditorFactory::getAvailableVersions() const
+	Map<CodeEditorType, VSCodeEditorFactory::VSVersionInfo> VSCodeEditorFactory::getAvailableVersions() const
 	{
 	{
 #if BS_ARCH_TYPE == BS_ARCHITECTURE_x86_64
 #if BS_ARCH_TYPE == BS_ARCHITECTURE_x86_64
 		bool is64bit = true;
 		bool is64bit = true;
@@ -444,12 +453,13 @@ EndProject)";
 
 
 		WString registryKeyRoot;
 		WString registryKeyRoot;
 		if (is64bit)
 		if (is64bit)
-			registryKeyRoot = L"SOFTWARE\\Microsoft";
+			registryKeyRoot = L"SOFTWARE\\Wow6432Node\\Microsoft"; 
 		else
 		else
-			registryKeyRoot = L"SOFTWARE\\Wow6432Node\\Microsoft";
+			registryKeyRoot = L"SOFTWARE\\Microsoft";
 
 
 		struct VersionData
 		struct VersionData
 		{
 		{
+			CodeEditorType type;
 			WString registryKey;
 			WString registryKey;
 			WString name;
 			WString name;
 			WString executable;
 			WString executable;
@@ -457,20 +467,20 @@ EndProject)";
 
 
 		Map<VisualStudioVersion, VersionData> versionToVersionNumber =
 		Map<VisualStudioVersion, VersionData> versionToVersionNumber =
 		{ 
 		{ 
-			{ VisualStudioVersion::VS2008, { L"VisualStudio\\9.0", L"Visual Studio 2008", L"devenv.exe" } },
-			{ VisualStudioVersion::VS2010, { L"VisualStudio\\10.0", L"Visual Studio 2010", L"devenv.exe" } },
-			{ VisualStudioVersion::VS2012, { L"VisualStudio\\11.0", L"Visual Studio 2012", L"devenv.exe" } },
-			{ VisualStudioVersion::VS2013, { L"VisualStudio\\12.0", L"Visual Studio 2013", L"devenv.exe" } },
-			{ VisualStudioVersion::VS2015, { L"VisualStudio\\13.0", L"Visual Studio 2015", L"devenv.exe" } }
+			{ VisualStudioVersion::VS2008, { CodeEditorType::VS2008, L"VisualStudio\\9.0", L"Visual Studio 2008", L"devenv.exe" } },
+			{ VisualStudioVersion::VS2010, { CodeEditorType::VS2010, L"VisualStudio\\10.0", L"Visual Studio 2010", L"devenv.exe" } },
+			{ VisualStudioVersion::VS2012, { CodeEditorType::VS2012, L"VisualStudio\\11.0", L"Visual Studio 2012", L"devenv.exe" } },
+			{ VisualStudioVersion::VS2013, { CodeEditorType::VS2013, L"VisualStudio\\12.0", L"Visual Studio 2013", L"devenv.exe" } },
+			{ VisualStudioVersion::VS2015, { CodeEditorType::VS2015, L"VisualStudio\\13.0", L"Visual Studio 2015", L"devenv.exe" } }
 		};
 		};
 
 
-		Map<WString, VSVersionInfo> versionInfo;
+		Map<CodeEditorType, VSVersionInfo> versionInfo;
 		for(auto version : versionToVersionNumber)
 		for(auto version : versionToVersionNumber)
 		{
 		{
 			WString registryKey = registryKeyRoot + L"\\" + version.second.registryKey;
 			WString registryKey = registryKeyRoot + L"\\" + version.second.registryKey;
 
 
 			HKEY regKey;
 			HKEY regKey;
-			LONG result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, registryKeyRoot.c_str(), 0, KEY_READ, &regKey);
+			LONG result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, registryKey.c_str(), 0, KEY_READ, &regKey);
 			if (result != ERROR_SUCCESS)
 			if (result != ERROR_SUCCESS)
 				continue;
 				continue;
 
 
@@ -488,7 +498,7 @@ EndProject)";
 			info.CLSID = clsID;
 			info.CLSID = clsID;
 			info.version = version.first;
 			info.version = version.first;
 
 
-			versionInfo[info.name] = info;
+			versionInfo[version.second.type] = info;
 		}
 		}
 
 
 		// TODO - Also query for VSExpress and VSCommunity (their registry keys are different)
 		// TODO - Also query for VSExpress and VSCommunity (their registry keys are different)
@@ -496,9 +506,9 @@ EndProject)";
 		return versionInfo;
 		return versionInfo;
 	}
 	}
 
 
-	CodeEditor* VSCodeEditorFactory::create(const WString& editor) const
+	CodeEditor* VSCodeEditorFactory::create(CodeEditorType type) const
 	{
 	{
-		auto findIter = mAvailableVersions.find(editor);
+		auto findIter = mAvailableVersions.find(type);
 		if (findIter == mAvailableVersions.end())
 		if (findIter == mAvailableVersions.end())
 			return nullptr;
 			return nullptr;
 
 

+ 10 - 7
BansheeUtility/Include/BsStringFormat.h

@@ -69,7 +69,7 @@ namespace BansheeEngine
 				if (source[i] == '\\' && !escaped && paramRangeWriteIdx < MAX_PARAM_REFERENCES)
 				if (source[i] == '\\' && !escaped && paramRangeWriteIdx < MAX_PARAM_REFERENCES)
 				{
 				{
 					escaped = true;
 					escaped = true;
-					paramRanges[paramRangeWriteIdx++] = FormatParamRange(charWriteIdx, 1, 0);
+					paramRanges[paramRangeWriteIdx++] = FormatParamRange(charWriteIdx, 1, (UINT32)-1);
 					continue;
 					continue;
 				}
 				}
 
 
@@ -96,8 +96,8 @@ namespace BansheeEngine
 							UINT32 paramIdx = strToInt(bracketChars);
 							UINT32 paramIdx = strToInt(bracketChars);
 							if (paramIdx < MAX_PARAMS && paramRangeWriteIdx < MAX_PARAM_REFERENCES) // Check if exceeded maximum parameter limit
 							if (paramIdx < MAX_PARAMS && paramRangeWriteIdx < MAX_PARAM_REFERENCES) // Check if exceeded maximum parameter limit
 							{
 							{
-								charWriteIdx += parameters[paramIdx].size;
 								paramRanges[paramRangeWriteIdx++] = FormatParamRange(charWriteIdx, numParamChars + 2, paramIdx);
 								paramRanges[paramRangeWriteIdx++] = FormatParamRange(charWriteIdx, numParamChars + 2, paramIdx);
+								charWriteIdx += parameters[paramIdx].size;
 
 
 								processedBracket = true;
 								processedBracket = true;
 							}
 							}
@@ -128,17 +128,20 @@ namespace BansheeEngine
 			{
 			{
 				const FormatParamRange& rangeInfo = paramRanges[i];
 				const FormatParamRange& rangeInfo = paramRanges[i];
 				UINT32 copySize = rangeInfo.start - copyDestIdx;
 				UINT32 copySize = rangeInfo.start - copyDestIdx;
-				UINT32 paramSize = parameters[rangeInfo.paramIdx].size;
-
-				memcpy(outputBuffer + copyDestIdx, source + copySourceIdx, copySize);
+				
+				memcpy(outputBuffer + copyDestIdx, source + copySourceIdx, copySize * sizeof(T));
 				copySourceIdx += copySize + rangeInfo.identifierSize;
 				copySourceIdx += copySize + rangeInfo.identifierSize;
 				copyDestIdx += copySize;
 				copyDestIdx += copySize;
 
 
-				memcpy(outputBuffer + copyDestIdx, parameters[rangeInfo.paramIdx].buffer, paramSize);
+				if (rangeInfo.paramIdx == (UINT32)-1)
+					continue;
+
+				UINT32 paramSize = parameters[rangeInfo.paramIdx].size;
+				memcpy(outputBuffer + copyDestIdx, parameters[rangeInfo.paramIdx].buffer, paramSize * sizeof(T));
 				copyDestIdx += paramSize;
 				copyDestIdx += paramSize;
 			}
 			}
 
 
-			memcpy(outputBuffer + copyDestIdx, source + copySourceIdx, finalStringSize - copyDestIdx);
+			memcpy(outputBuffer + copyDestIdx, source + copySourceIdx, (finalStringSize - copyDestIdx) * sizeof(T));
 
 
 			BasicString<T> outputStr(outputBuffer, finalStringSize);
 			BasicString<T> outputStr(outputBuffer, finalStringSize);
 			bs_free(outputBuffer);
 			bs_free(outputBuffer);

+ 17 - 13
BansheeUtility/Source/BsUtil.cpp

@@ -6,30 +6,34 @@ namespace BansheeEngine
 	String md5(const WString& source)
 	String md5(const WString& source)
 	{
 	{
 		MD5 md5;
 		MD5 md5;
-		md5.update((UINT8*)source.c_str(), (UINT32)source.length());
+		md5.update((UINT8*)source.c_str(), (UINT32)source.length() * sizeof(WString::value_type));
 		md5.finalize();
 		md5.finalize();
 
 
-		UINT8* digest = (UINT8*)bs_alloc(16);
-		md5.decdigest(digest, 16);
+		UINT8 digest[16];
+		md5.decdigest(digest, sizeof(digest));
 
 
-		String output((char*)digest);
-		bs_free(digest);
-
-		return output;
+		char buf[33];
+		for (int i = 0; i < 16; i++)
+			sprintf(buf + i * 2, "%02x", digest[i]);
+		buf[32] = 0;
+		
+		return String(buf);
 	}
 	}
 
 
 	String md5(const String& source)
 	String md5(const String& source)
 	{
 	{
 		MD5 md5;
 		MD5 md5;
-		md5.update((UINT8*)source.c_str(), (UINT32)source.length());
+		md5.update((UINT8*)source.c_str(), (UINT32)source.length() * sizeof(String::value_type));
 		md5.finalize();
 		md5.finalize();
 
 
-		UINT8* digest = (UINT8*)bs_alloc(16);
-		md5.decdigest(digest, 16);
+		UINT8 digest[16];
+		md5.decdigest(digest, sizeof(digest));
 
 
-		String output((char*)digest);
-		bs_free(digest);
+		char buf[33];
+		for (int i = 0; i < 16; i++)
+			sprintf(buf + i * 2, "%02x", digest[i]);
+		buf[32] = 0;
 
 
-		return output;
+		return String(buf);
 	}
 	}
 }
 }

+ 51 - 0
MBansheeEditor/CodeEditor.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    // Note: Must match C++ CodeEditorType enum
+    public enum CodeEditorType
+    {
+        VS2008,
+        VS2010,
+        VS2012,
+        VS2013,
+        VS2015
+    }
+
+    public static class CodeEditor
+    {
+        public static CodeEditorType ActiveEditor
+        {
+            set { Internal_SetActiveEditor(value); }
+        }
+
+        public static CodeEditorType[] AvailableEditors
+        {
+            get { return Internal_GetAvailableEditors(); }
+        }
+
+        public static void OpenFile(string path, UInt32 line)
+        {
+            Internal_OpenFile(path, line);
+        }
+
+        public static void SyncSolution()
+        {
+            Internal_SyncSolution();
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_SetActiveEditor(CodeEditorType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern CodeEditorType[] Internal_GetAvailableEditors();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_OpenFile(string path, UInt32 line);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_SyncSolution();
+    }
+}

+ 1 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -40,6 +40,7 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Compile Include="BrowseDialog.cs" />
     <Compile Include="BrowseDialog.cs" />
+    <Compile Include="CodeEditor.cs" />
     <Compile Include="ColorPicker.cs" />
     <Compile Include="ColorPicker.cs" />
     <Compile Include="DbgCustomInspector.cs" />
     <Compile Include="DbgCustomInspector.cs" />
     <Compile Include="DbgEditorWindow.cs" />
     <Compile Include="DbgEditorWindow.cs" />

+ 9 - 1
MBansheeEditor/ProjectLibrary.cs

@@ -48,6 +48,11 @@ namespace BansheeEditor
             return Internal_GetEntry(path);
             return Internal_GetEntry(path);
         }
         }
 
 
+        public LibraryEntry[] Search(string pattern, ResourceType[] types = null)
+        {
+            return Internal_Search(pattern, types);
+        }
+
         public static string GetPath(Resource resource)
         public static string GetPath(Resource resource)
         {
         {
             return Internal_GetPath(resource);
             return Internal_GetPath(resource);
@@ -108,6 +113,9 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern LibraryEntry Internal_GetEntry(string path);
         private static extern LibraryEntry Internal_GetEntry(string path);
 
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern LibraryEntry[] Internal_Search(string path, ResourceType[] types);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern string Internal_GetPath(Resource resource);
         private static extern string Internal_GetPath(Resource resource);
 
 
@@ -136,7 +144,7 @@ namespace BansheeEditor
     // Note: Must be the same as C++ enum ScriptResourceType
     // Note: Must be the same as C++ enum ScriptResourceType
     public enum ResourceType
     public enum ResourceType
     {
     {
-        Texture, SpriteTexture, Mesh, Font, GpuProgram, Undefined
+        Texture, SpriteTexture, Mesh, Font, GpuProgram, PlainText, ScriptCode, Undefined
     }
     }
 
 
     public class LibraryEntry : ScriptObject
     public class LibraryEntry : ScriptObject

+ 21 - 0
SBansheeEditor/Include/BsScriptCodeEditor.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BED_EXPORT ScriptCodeEditor : public ScriptObject<ScriptCodeEditor>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "CodeEditor")
+
+	private:
+		static void internal_SetActiveEditor(CodeEditorType type);
+		static MonoArray* internal_GetAvailableEditors();
+		static void internal_OpenFile(MonoString* path, UINT32 line);
+		static void internal_SyncSolution();
+
+		ScriptCodeEditor(MonoObject* instance);
+	};
+}

+ 1 - 0
SBansheeEditor/Include/BsScriptProjectLibrary.h

@@ -23,6 +23,7 @@ namespace BansheeEngine
 		static void internal_Reimport(MonoString* path, MonoObject* options, bool force);
 		static void internal_Reimport(MonoString* path, MonoObject* options, bool force);
 		static MonoObject* internal_GetEntry(MonoString* path);
 		static MonoObject* internal_GetEntry(MonoString* path);
 		static MonoString* internal_GetPath(MonoObject* resource);
 		static MonoString* internal_GetPath(MonoObject* resource);
+		static MonoArray* internal_Search(MonoString* pattern, MonoArray* types);
 		static void internal_Delete(MonoString* path);
 		static void internal_Delete(MonoString* path);
 		static void internal_CreateFolder(MonoString* path);
 		static void internal_CreateFolder(MonoString* path);
 		static void internal_Rename(MonoString* path, MonoString* name);
 		static void internal_Rename(MonoString* path, MonoString* name);

+ 2 - 0
SBansheeEditor/SBansheeEditor.vcxproj

@@ -237,6 +237,7 @@
     <ClInclude Include="Include\BsGUIPanelContainer.h" />
     <ClInclude Include="Include\BsGUIPanelContainer.h" />
     <ClInclude Include="Include\BsGUIResourceField.h" />
     <ClInclude Include="Include\BsGUIResourceField.h" />
     <ClInclude Include="Include\BsScriptBrowseDialog.h" />
     <ClInclude Include="Include\BsScriptBrowseDialog.h" />
+    <ClInclude Include="Include\BsScriptCodeEditor.h" />
     <ClInclude Include="Include\BsScriptDragDropManager.h" />
     <ClInclude Include="Include\BsScriptDragDropManager.h" />
     <ClInclude Include="Include\BsScriptEditorPrerequisites.h" />
     <ClInclude Include="Include\BsScriptEditorPrerequisites.h" />
     <ClInclude Include="Include\BsScriptEditorSettings.h" />
     <ClInclude Include="Include\BsScriptEditorSettings.h" />
@@ -271,6 +272,7 @@
     <ClInclude Include="Include\BsScriptSelection.h" />
     <ClInclude Include="Include\BsScriptSelection.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
+    <ClCompile Include="Source\BsScriptCodeEditor.cpp" />
     <ClCompile Include="Source\BsScriptDragDropManager.cpp" />
     <ClCompile Include="Source\BsScriptDragDropManager.cpp" />
     <ClCompile Include="Source\BsEditorScriptManager.cpp" />
     <ClCompile Include="Source\BsEditorScriptManager.cpp" />
     <ClCompile Include="Source\BsGUIGameObjectField.cpp" />
     <ClCompile Include="Source\BsGUIGameObjectField.cpp" />

+ 6 - 0
SBansheeEditor/SBansheeEditor.vcxproj.filters

@@ -126,6 +126,9 @@
     <ClInclude Include="Include\BsScriptImportOptions.h">
     <ClInclude Include="Include\BsScriptImportOptions.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptCodeEditor.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp">
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp">
@@ -239,5 +242,8 @@
     <ClCompile Include="Source\BsScriptImportOptions.cpp">
     <ClCompile Include="Source\BsScriptImportOptions.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptCodeEditor.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 54 - 0
SBansheeEditor/Source/BsScriptCodeEditor.cpp

@@ -0,0 +1,54 @@
+#include "BsScriptCodeEditor.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoMethod.h"
+#include "BsMonoManager.h"
+#include "BsMonoUtil.h"
+#include "BsCodeEditor.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	ScriptCodeEditor::ScriptCodeEditor(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptCodeEditor::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_SetActiveEditor", &ScriptCodeEditor::internal_SetActiveEditor);
+		metaData.scriptClass->addInternalCall("Internal_GetAvailableEditors", &ScriptCodeEditor::internal_GetAvailableEditors);
+		metaData.scriptClass->addInternalCall("Internal_OpenFile", &ScriptCodeEditor::internal_OpenFile);
+		metaData.scriptClass->addInternalCall("Internal_SyncSolution", &ScriptCodeEditor::internal_SyncSolution);
+	}
+
+	void ScriptCodeEditor::internal_SetActiveEditor(CodeEditorType type)
+	{
+		CodeEditorManager::instance().setActive(type);
+	}
+
+	MonoArray* ScriptCodeEditor::internal_GetAvailableEditors()
+	{
+		Vector<CodeEditorType> availableEditors = CodeEditorManager::instance().getAvailableEditors();
+
+		ScriptArray outArray = ScriptArray::create<UINT32>((UINT32)availableEditors.size());
+		UINT32 idx = 0;
+		for (auto& entry : availableEditors)
+			outArray.set(idx, (UINT32)entry);
+
+		return outArray.getInternal();
+	}
+
+	void ScriptCodeEditor::internal_OpenFile(MonoString* path, UINT32 line)
+	{
+		Path filePath = MonoUtil::monoToWString(path);
+
+		CodeEditorManager::instance().openFile(filePath, line);
+	}
+
+	void ScriptCodeEditor::internal_SyncSolution()
+	{
+		CodeEditorManager::instance().syncSolution();
+	}
+}

+ 33 - 0
SBansheeEditor/Source/BsScriptProjectLibrary.cpp

@@ -38,6 +38,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_Reimport", &ScriptProjectLibrary::internal_Reimport);
 		metaData.scriptClass->addInternalCall("Internal_Reimport", &ScriptProjectLibrary::internal_Reimport);
 		metaData.scriptClass->addInternalCall("Internal_GetEntry", &ScriptProjectLibrary::internal_GetEntry);
 		metaData.scriptClass->addInternalCall("Internal_GetEntry", &ScriptProjectLibrary::internal_GetEntry);
 		metaData.scriptClass->addInternalCall("Internal_GetPath", &ScriptProjectLibrary::internal_GetPath);
 		metaData.scriptClass->addInternalCall("Internal_GetPath", &ScriptProjectLibrary::internal_GetPath);
+		metaData.scriptClass->addInternalCall("Internal_Search", &ScriptProjectLibrary::internal_Search);
 		metaData.scriptClass->addInternalCall("Internal_Delete", &ScriptProjectLibrary::internal_Delete);
 		metaData.scriptClass->addInternalCall("Internal_Delete", &ScriptProjectLibrary::internal_Delete);
 		metaData.scriptClass->addInternalCall("Internal_CreateFolder", &ScriptProjectLibrary::internal_CreateFolder);
 		metaData.scriptClass->addInternalCall("Internal_CreateFolder", &ScriptProjectLibrary::internal_CreateFolder);
 		metaData.scriptClass->addInternalCall("Internal_Rename", &ScriptProjectLibrary::internal_Rename);
 		metaData.scriptClass->addInternalCall("Internal_Rename", &ScriptProjectLibrary::internal_Rename);
@@ -138,6 +139,38 @@ namespace BansheeEngine
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
+	MonoArray* ScriptProjectLibrary::internal_Search(MonoString* pattern, MonoArray* types)
+	{
+		WString strPattern = MonoUtil::monoToWString(pattern);
+
+		ScriptArray typeArray(types);
+		Vector<UINT32> typeIds;
+		for (UINT32 i = 0; i < typeArray.size(); i++)
+		{
+			UINT32 typeId = ScriptResource::getTypeIdFromType((ScriptResourceType)typeArray.get<UINT32>(i));
+			typeIds.push_back(typeId);
+		}
+
+		Vector<ProjectLibrary::LibraryEntry*> foundEntries = ProjectLibrary::instance().search(strPattern, typeIds);
+
+		UINT32 idx = 0;
+		ScriptArray outArray = ScriptArray::create<ScriptLibraryEntry>((UINT32)foundEntries.size());
+		for (auto& entry : foundEntries)
+		{
+			MonoObject* managedEntry = nullptr;
+
+			if (entry->type == ProjectLibrary::LibraryEntryType::File)
+				managedEntry = ScriptFileEntry::create(static_cast<ProjectLibrary::ResourceEntry*>(entry));
+			else
+				managedEntry = ScriptDirectoryEntry::create(static_cast<ProjectLibrary::DirectoryEntry*>(entry));
+
+			outArray.set(idx, managedEntry);
+			idx++;
+		}
+
+		return outArray.getInternal();
+	}
+
 	void ScriptProjectLibrary::internal_Delete(MonoString* path)
 	void ScriptProjectLibrary::internal_Delete(MonoString* path)
 	{
 	{
 		Path pathToDelete = MonoUtil::monoToWString(path);
 		Path pathToDelete = MonoUtil::monoToWString(path);

+ 2 - 2
SBansheeEngine/Include/BsScriptResource.h

@@ -7,7 +7,7 @@ namespace BansheeEngine
 {
 {
 	enum class ScriptResourceType
 	enum class ScriptResourceType
 	{
 	{
-		Texture, SpriteTexture, Mesh, Font, GpuProgram, Undefined
+		Texture, SpriteTexture, Mesh, Font, GpuProgram, PlainText, ScriptCode, Undefined
 	};
 	};
 
 
 	class BS_SCR_BE_EXPORT ScriptResourceBase : public PersistentScriptObjectBase
 	class BS_SCR_BE_EXPORT ScriptResourceBase : public PersistentScriptObjectBase
@@ -37,7 +37,7 @@ namespace BansheeEngine
 		static void initRuntimeData() { }
 		static void initRuntimeData() { }
 
 
 		static ScriptResourceType getTypeFromTypeId(UINT32 typeId);
 		static ScriptResourceType getTypeFromTypeId(UINT32 typeId);
-
+		static UINT32 getTypeIdFromType(ScriptResourceType type);
 	private:
 	private:
 		ScriptResource(MonoObject* instance)
 		ScriptResource(MonoObject* instance)
 			:ScriptObject(instance)
 			:ScriptObject(instance)

+ 27 - 0
SBansheeEngine/Source/BsScriptResource.cpp

@@ -34,8 +34,35 @@ namespace BansheeEngine
 			return ScriptResourceType::GpuProgram;
 			return ScriptResourceType::GpuProgram;
 		case TID_Font:
 		case TID_Font:
 			return ScriptResourceType::Font;
 			return ScriptResourceType::Font;
+		case TID_PlainText:
+			return ScriptResourceType::PlainText;
+		case TID_ScriptCode:
+			return ScriptResourceType::ScriptCode;
 		}
 		}
 
 
 		return ScriptResourceType::Undefined;
 		return ScriptResourceType::Undefined;
 	}
 	}
+
+	UINT32 ScriptResource::getTypeIdFromType(ScriptResourceType type)
+	{
+		switch (type)
+		{
+		case ScriptResourceType::Texture:
+			return TID_Texture;
+		case ScriptResourceType::SpriteTexture:
+			return TID_SpriteTexture;
+		case ScriptResourceType::Mesh:
+			return TID_Mesh;
+		case ScriptResourceType::GpuProgram:
+			return TID_GpuProgram;
+		case ScriptResourceType::Font:
+			return TID_Font;
+		case ScriptResourceType::PlainText:
+			return TID_PlainText;
+		case ScriptResourceType::ScriptCode:
+			return TID_ScriptCode;
+		}
+
+		return 0;
+	}
 }
 }

+ 3 - 8
TODO.txt

@@ -11,25 +11,20 @@ Project library
 
 
 Almost all of PRojectLibrary functionality is completely untested
 Almost all of PRojectLibrary functionality is completely untested
 
 
-ProjectLibrary needs a method that searches for all entries with a specific name (or a subset of a name), and all entries of a specific type
- - Can I make Library/Resource entries faster so I can do this properly from C#?
-
 Figure out how to create a C# BuiltinResources class. It should be able to load arbitrary resources from a non-project folder
 Figure out how to create a C# BuiltinResources class. It should be able to load arbitrary resources from a non-project folder
  - I should move all the GUI element style creation out of code and make it just pure data (once I have an editor for it)
  - I should move all the GUI element style creation out of code and make it just pure data (once I have an editor for it)
  - Will also need a debug button to reimport all the built-in resources
  - Will also need a debug button to reimport all the built-in resources
 
 
+My GUID generation is screwed up. If multiple GUIDs are generated in succession then the timestamp will remain
+the same and the only variable will be the 4byte random number, which can sometimes end up identical to the previous number.
+
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 VisualStudio integration
 VisualStudio integration
 
 
-None of the new VS functionality has been tested
 VS integration will likely not work with VSExpress or Community edition
 VS integration will likely not work with VSExpress or Community edition
  - VSExpress doesn't support EnvDTE so the only option is to open it using a shell command which doesn't seem to offer precise parameters
  - VSExpress doesn't support EnvDTE so the only option is to open it using a shell command which doesn't seem to offer precise parameters
  - Community edition should work similarily to Pro, but might have a different executable and/or registry paths
  - Community edition should work similarily to Pro, but might have a different executable and/or registry paths
 
 
-Test:
- - If string::format works
- - If VS open and sync works
-
 For later:
 For later:
  - Make sure that 3rd party assemblies can be imported in the project, and that they are properly referenced in VS project generation
  - Make sure that 3rd party assemblies can be imported in the project, and that they are properly referenced in VS project generation