| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #include "CodeEditor/BsCodeEditor.h"
- #include "BsEditorApplication.h"
- #include "Library/BsProjectLibrary.h"
- #include "Library/BsProjectResourceMeta.h"
- #include "Resources/BsScriptCodeImportOptions.h"
- #include "Build/BsBuildManager.h"
- #include "CodeEditor/BsMDCodeEditor.h"
- #if BS_PLATFORM == BS_PLATFORM_WIN32
- #include "Private/Win32/BsVSCodeEditor.h"
- #else
- // Add implementations for code editors on other platforms.
- #endif
- namespace bs
- {
- CodeEditorManager::CodeEditorManager()
- :mActiveEditor(nullptr), mActiveEditorType(CodeEditorType::None)
- {
- #if BS_PLATFORM == BS_PLATFORM_WIN32
- VSCodeEditorFactory* vsCodeEditorFactory = bs_new<VSCodeEditorFactory>();
- Vector<CodeEditorType> vsEditors = vsCodeEditorFactory->getAvailableEditors();
- for(auto& editor : vsEditors)
- {
- mFactoryPerEditor[editor] = vsCodeEditorFactory;
- mEditors.push_back(editor);
- }
- mFactories.push_back(vsCodeEditorFactory);
- #else
- // Add implementations for code editors on other platforms.
- #endif
- MDCodeEditorFactory* mdCodeEditorFactory = bs_new<MDCodeEditorFactory>();
- Vector<CodeEditorType> mdEditors = mdCodeEditorFactory->getAvailableEditors();
- for(auto& editor : mdEditors)
- {
- mFactoryPerEditor[editor] = mdCodeEditorFactory;
- mEditors.push_back(editor);
- }
- mFactories.push_back(mdCodeEditorFactory);
- }
- CodeEditorManager::~CodeEditorManager()
- {
- for (auto& factory : mFactories)
- bs_delete(factory);
- if (mActiveEditor != nullptr)
- bs_delete(mActiveEditor);
- }
- void CodeEditorManager::setActive(CodeEditorType editor)
- {
- if (mActiveEditor != nullptr)
- {
- bs_delete(mActiveEditor);
- mActiveEditor = nullptr;
- }
- auto findIter = mFactoryPerEditor.find(editor);
- if (findIter == mFactoryPerEditor.end())
- return;
- mActiveEditor = findIter->second->create(editor);
- mActiveEditorType = editor;
- }
- void CodeEditorManager::openFile(const Path& path, UINT32 lineNumber) const
- {
- if (mActiveEditor == nullptr)
- return;
- Path filePath = path;
- if (!path.isAbsolute())
- filePath.makeAbsolute(gProjectLibrary().getResourcesFolder());
- mActiveEditor->openFile(getSolutionPath(), filePath, lineNumber);
- }
- void CodeEditorManager::syncSolution(const String& gameProjectName, const CodeProjectReference& engineAssemblyRef,
- const CodeProjectReference& editorAssemblyRef) const
- {
- if (mActiveEditor == nullptr)
- return;
- CodeSolutionData slnData;
- slnData.name = gEditorApplication().getProjectName();
- Vector<UINT32> scriptTypeIds =
- {
- TID_ScriptCode, TID_PlainText, TID_Shader, TID_ShaderInclude
- };
- Vector<ProjectLibrary::LibraryEntry*> libraryEntries = gProjectLibrary().search("*", scriptTypeIds);
-
- PlatformType activePlatform = BuildManager::instance().getActivePlatform();
- Vector<String> frameworkAssemblies = BuildManager::instance().getFrameworkAssemblies(activePlatform);
- slnData.projects.push_back(CodeProjectData());
- slnData.projects.push_back(CodeProjectData());
- // Game project
- CodeProjectData& gameProject = slnData.projects[0];
- gameProject.name = gameProjectName;
- gameProject.defines = BuildManager::instance().getDefines(activePlatform);
-
- //// Add references
- gameProject.assemblyReferences.push_back(engineAssemblyRef);
- for (auto& assemblyName : frameworkAssemblies)
- gameProject.assemblyReferences.push_back(CodeProjectReference{ assemblyName, Path::BLANK });
- // Editor project
- CodeProjectData& editorProject = slnData.projects[1];
- editorProject.name = String(SCRIPT_EDITOR_ASSEMBLY);
- //// Add references
- editorProject.assemblyReferences.push_back(engineAssemblyRef);
- editorProject.assemblyReferences.push_back(editorAssemblyRef);
- for (auto& assemblyName : frameworkAssemblies)
- gameProject.assemblyReferences.push_back(CodeProjectReference{ assemblyName, Path::BLANK });
- editorProject.projectReferences.push_back(CodeProjectReference{ gameProject.name, Path::BLANK });
- //// Add files for both projects
- for (auto& entry : libraryEntries)
- {
- if (entry->type != ProjectLibrary::LibraryEntryType::File)
- continue;
- ProjectLibrary::FileEntry* resEntry = static_cast<ProjectLibrary::FileEntry*>(entry);
- if (resEntry->meta->hasTypeId(TID_ScriptCode))
- {
- SPtr<ScriptCodeImportOptions> scriptIO = std::static_pointer_cast<ScriptCodeImportOptions>(resEntry->meta->getImportOptions());
- bool isEditorScript = false;
- if (scriptIO != nullptr)
- isEditorScript = scriptIO->isEditorScript();
- if (isEditorScript)
- editorProject.codeFiles.push_back(resEntry->path);
- else
- gameProject.codeFiles.push_back(resEntry->path);
- }
- else
- gameProject.nonCodeFiles.push_back(resEntry->path);
- }
- mActiveEditor->syncSolution(slnData, gEditorApplication().getProjectPath());
- }
- Path CodeEditorManager::getSolutionPath() const
- {
- Path path = gEditorApplication().getProjectPath();
- path.append(gEditorApplication().getProjectName() + ".sln");
- return path;
- }
- const String CSProject::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
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution{2}
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- EndGlobal
- )";
- const String CSProject::PROJ_ENTRY_TEMPLATE =
- R"(
- Project("\{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC\}") = "{0}", "{1}", "\{{2}\}"
- EndProject)";
- const String CSProject::PROJ_PLATFORM_TEMPLATE =
- R"(
- \{{0}\}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- \{{0}\}.Debug|Any CPU.Build.0 = Debug|Any CPU
- \{{0}\}.Release|Any CPU.ActiveCfg = Release|Any CPU
- \{{0}\}.Release|Any CPU.Build.0 = Release|Any CPU)";
- const String CSProject::PROJ_TEMPLATE =
- R"literal(<?xml version="1.0" encoding="utf-8"?>
- <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')" />
- <PropertyGroup>
- <Configuration Condition = " '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition = " '$(Platform)' == '' ">AnyCPU</Platform>
- <ProjectGuid>\{{1}\}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace></RootNamespace>
- <AssemblyName>{2}</AssemblyName>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <BaseDirectory>Resources</BaseDirectory>
- <SchemaVersion>2.0</SchemaVersion>
- </PropertyGroup>
- <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>Internal\\Temp\\Assemblies\\Debug\\</OutputPath>
- <BaseIntermediateOutputPath>Internal\\Temp\\Assemblies\\</BaseIntermediateOutputPath>
- <DefineConstants>DEBUG;TRACE;{3}</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel >
- </PropertyGroup>
- <PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>Internal\\Temp\\Assemblies\\Release\\</OutputPath>
- <BaseIntermediateOutputPath>Internal\\Temp\\Assemblies\\</BaseIntermediateOutputPath>
- <DefineConstants>TRACE;{3}</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <ItemGroup>{4}
- </ItemGroup>
- <ItemGroup>{5}
- </ItemGroup>
- <ItemGroup>{6}
- </ItemGroup>
- <ItemGroup>{7}
- </ItemGroup>
- <Import Project = "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"/>
- </Project>)literal";
- const String CSProject::REFERENCE_ENTRY_TEMPLATE =
- R"(
- <Reference Include="{0}"/>)";
- const String CSProject::REFERENCE_PATH_ENTRY_TEMPLATE =
- R"(
- <Reference Include="{0}">
- <HintPath>{1}</HintPath>
- </Reference>)";
- const String CSProject::REFERENCE_PROJECT_ENTRY_TEMPLATE =
- R"(
- <ProjectReference Include="{0}.csproj">
- <Project>\{{1}\}</Project>
- <Name>{0}</Name>
- </ProjectReference>)";
- const String CSProject::CODE_ENTRY_TEMPLATE =
- R"(
- <Compile Include="{0}"/>)";
- const String CSProject::NON_CODE_ENTRY_TEMPLATE =
- R"(
- <None Include="{0}"/>)";
- /** Generates a C# project GUID from the project name. */
- String getProjectGUID(const String& projectName)
- {
- static const String guidTemplate = "{0}-{1}-{2}-{3}-{4}";
- 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 output;
- }
- String CSProject::writeSolution(CSProjectVersion version, const CodeSolutionData& data)
- {
- struct VersionData
- {
- String formatVersion;
- };
- Map<CSProjectVersion, VersionData> versionData =
- {
- { CSProjectVersion::VS2008, { "10.00" } },
- { CSProjectVersion::VS2010, { "11.00" } },
- { CSProjectVersion::VS2012, { "12.00" } },
- { CSProjectVersion::VS2013, { "12.00" } },
- { CSProjectVersion::VS2015, { "12.00" } },
- { CSProjectVersion::VS2017, { "12.00" } },
- { CSProjectVersion::MonoDevelop, { "12.00" } }
- };
- StringStream projectEntriesStream;
- StringStream projectPlatformsStream;
- for (auto& project : data.projects)
- {
- String guid = getProjectGUID(project.name);
- String projectName = project.name;
- projectEntriesStream << StringUtil::format(PROJ_ENTRY_TEMPLATE, projectName, projectName + ".csproj", guid);
- projectPlatformsStream << StringUtil::format(PROJ_PLATFORM_TEMPLATE, guid);
- }
- String projectEntries = projectEntriesStream.str();
- String projectPlatforms = projectPlatformsStream.str();
- return StringUtil::format(SLN_TEMPLATE, versionData[version].formatVersion, projectEntries, projectPlatforms);
- }
- String CSProject::writeProject(CSProjectVersion version, const CodeProjectData& projectData)
- {
- struct VersionData
- {
- String toolsVersion;
- };
- Map<CSProjectVersion, VersionData> versionData =
- {
- { CSProjectVersion::VS2008, { "3.5" } },
- { CSProjectVersion::VS2010, { "4.0" } },
- { CSProjectVersion::VS2012, { "4.0" } },
- { CSProjectVersion::VS2013, { "12.0" } },
- { CSProjectVersion::VS2015, { "13.0" } },
- { CSProjectVersion::VS2017, { "15.0" } },
- { CSProjectVersion::MonoDevelop, { "14.0" } }
- };
- StringStream tempStream;
- for (auto& codeEntry : projectData.codeFiles)
- tempStream << StringUtil::format(CODE_ENTRY_TEMPLATE, codeEntry.toString());
- String codeEntries = tempStream.str();
- tempStream.str("");
- tempStream.clear();
- for (auto& nonCodeEntry : projectData.nonCodeFiles)
- tempStream << StringUtil::format(NON_CODE_ENTRY_TEMPLATE, nonCodeEntry.toString());
- String nonCodeEntries = tempStream.str();
- tempStream.str("");
- tempStream.clear();
- for (auto& referenceEntry : projectData.assemblyReferences)
- {
- String referenceName = referenceEntry.name;
- if (referenceEntry.path.isEmpty())
- tempStream << StringUtil::format(REFERENCE_ENTRY_TEMPLATE, referenceName);
- else
- tempStream << StringUtil::format(REFERENCE_PATH_ENTRY_TEMPLATE, referenceName, referenceEntry.path.toString());
- }
- String referenceEntries = tempStream.str();
- tempStream.str("");
- tempStream.clear();
- for (auto& referenceEntry : projectData.projectReferences)
- {
- String referenceName = referenceEntry.name;
- String projectGUID = getProjectGUID(referenceEntry.name);
- tempStream << StringUtil::format(REFERENCE_PROJECT_ENTRY_TEMPLATE, referenceName, projectGUID);
- }
- String projectReferenceEntries = tempStream.str();
- tempStream.str("");
- tempStream.clear();
- tempStream << projectData.defines;
- String defines = tempStream.str();
- String projectGUID = getProjectGUID(projectData.name);
- return StringUtil::format(PROJ_TEMPLATE, versionData[version].toolsVersion, projectGUID,
- projectData.name, defines, referenceEntries, projectReferenceEntries, codeEntries, nonCodeEntries);
- }
- }
|