BsScriptBuildManager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. #include "BsScriptBuildManager.h"
  2. #include "BsMonoManager.h"
  3. #include "BsMonoClass.h"
  4. #include "BsMonoMethod.h"
  5. #include "BsMonoUtil.h"
  6. #include "BsScriptPlatformInfo.h"
  7. #include "BsFileSystem.h"
  8. #include "BsIconUtility.h"
  9. #include "BsCoreThread.h"
  10. #include "BsGameSettings.h"
  11. #include "BsFileSerializer.h"
  12. #include "BsProjectLibrary.h"
  13. #include "BsProjectResourceMeta.h"
  14. #include "BsResources.h"
  15. #include "BsPrefab.h"
  16. #include "BsEditorApplication.h"
  17. #include "BsResourceManifest.h"
  18. #include "BsBuiltinResources.h"
  19. #include "BsSceneObject.h"
  20. namespace BansheeEngine
  21. {
  22. ScriptBuildManager::ScriptBuildManager(MonoObject* instance)
  23. :ScriptObject(instance)
  24. { }
  25. void ScriptBuildManager::initRuntimeData()
  26. {
  27. metaData.scriptClass->addInternalCall("Internal_GetAvailablePlatforms", &ScriptBuildManager::internal_GetAvailablePlatforms);
  28. metaData.scriptClass->addInternalCall("Internal_GetActivePlatform", &ScriptBuildManager::internal_GetActivePlatform);
  29. metaData.scriptClass->addInternalCall("Internal_SetActivePlatform", &ScriptBuildManager::internal_SetActivePlatform);
  30. metaData.scriptClass->addInternalCall("Internal_GetActivePlatformInfo", &ScriptBuildManager::internal_GetActivePlatformInfo);
  31. metaData.scriptClass->addInternalCall("Internal_GetPlatformInfo", &ScriptBuildManager::internal_GetPlatformInfo);
  32. metaData.scriptClass->addInternalCall("Internal_GetFrameworkAssemblies", &ScriptBuildManager::internal_GetFrameworkAssemblies);
  33. metaData.scriptClass->addInternalCall("Internal_GetMainExecutable", &ScriptBuildManager::internal_GetMainExecutable);
  34. metaData.scriptClass->addInternalCall("Internal_GetDefines", &ScriptBuildManager::internal_GetDefines);
  35. metaData.scriptClass->addInternalCall("Internal_GetNativeBinaries", &ScriptBuildManager::internal_GetNativeBinaries);
  36. metaData.scriptClass->addInternalCall("Internal_GetBuildFolder", &ScriptBuildManager::internal_GetBuildFolder);
  37. metaData.scriptClass->addInternalCall("Internal_InjectIcons", &ScriptBuildManager::internal_InjectIcons);
  38. metaData.scriptClass->addInternalCall("Internal_PackageResources", &ScriptBuildManager::internal_PackageResources);
  39. metaData.scriptClass->addInternalCall("Internal_CreateStartupSettings", &ScriptBuildManager::internal_CreateStartupSettings);
  40. }
  41. MonoArray* ScriptBuildManager::internal_GetAvailablePlatforms()
  42. {
  43. const Vector<PlatformType>& availableType = BuildManager::instance().getAvailablePlatforms();
  44. ScriptArray outArray = ScriptArray::create<UINT32>((UINT32)availableType.size());
  45. UINT32 idx = 0;
  46. for (auto& type : availableType)
  47. outArray.set(idx++, type);
  48. return outArray.getInternal();
  49. }
  50. PlatformType ScriptBuildManager::internal_GetActivePlatform()
  51. {
  52. return BuildManager::instance().getActivePlatform();
  53. }
  54. void ScriptBuildManager::internal_SetActivePlatform(PlatformType value)
  55. {
  56. BuildManager::instance().setActivePlatform(value);
  57. }
  58. MonoObject* ScriptBuildManager::internal_GetActivePlatformInfo()
  59. {
  60. return ScriptPlatformInfo::create(BuildManager::instance().getActivePlatformInfo());
  61. }
  62. MonoObject* ScriptBuildManager::internal_GetPlatformInfo(PlatformType type)
  63. {
  64. return ScriptPlatformInfo::create(BuildManager::instance().getPlatformInfo(type));
  65. }
  66. MonoArray* ScriptBuildManager::internal_GetFrameworkAssemblies(PlatformType type)
  67. {
  68. Vector<WString> frameworkAssemblies = BuildManager::instance().getFrameworkAssemblies(type);
  69. ScriptArray outArray = ScriptArray::create<WString>((UINT32)frameworkAssemblies.size());
  70. UINT32 idx = 0;
  71. for (auto& assemblyName : frameworkAssemblies)
  72. outArray.set(idx++, MonoUtil::wstringToMono(MonoManager::instance().getDomain(), assemblyName));
  73. return outArray.getInternal();
  74. }
  75. MonoString* ScriptBuildManager::internal_GetMainExecutable(PlatformType type)
  76. {
  77. return MonoUtil::wstringToMono(MonoManager::instance().getDomain(), BuildManager::instance().getMainExecutable(type).toWString());
  78. }
  79. MonoString* ScriptBuildManager::internal_GetDefines(PlatformType type)
  80. {
  81. return MonoUtil::wstringToMono(MonoManager::instance().getDomain(), BuildManager::instance().getDefines(type));
  82. }
  83. MonoArray* ScriptBuildManager::internal_GetNativeBinaries(PlatformType type)
  84. {
  85. Vector<Path> paths = BuildManager::instance().getNativeBinaries(type);
  86. UINT32 numEntries = (UINT32)paths.size();
  87. ScriptArray outArray = ScriptArray::create<WString>(numEntries);
  88. for (UINT32 i = 0; i < numEntries; i++)
  89. {
  90. outArray.set(i, MonoUtil::wstringToMono(MonoManager::instance().getDomain(), paths[i].toWString()));
  91. }
  92. return outArray.getInternal();
  93. }
  94. MonoString* ScriptBuildManager::internal_GetBuildFolder(ScriptBuildFolder folder, PlatformType platform)
  95. {
  96. Path path;
  97. if (folder == ScriptBuildFolder::FrameworkAssemblies)
  98. {
  99. Path assemblyFolder = MonoManager::instance().getFrameworkAssembliesFolder();
  100. assemblyFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
  101. Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
  102. path = assemblyFolder.makeRelative(sourceFolder);
  103. }
  104. else if (folder == ScriptBuildFolder::Mono)
  105. {
  106. Path monoEtcFolder = MonoManager::instance().getMonoEtcFolder();
  107. monoEtcFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
  108. Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
  109. path = monoEtcFolder.makeRelative(sourceFolder);
  110. }
  111. else
  112. {
  113. BuildFolder nativeFolderType = BuildFolder::SourceRoot;
  114. switch (folder)
  115. {
  116. case ScriptBuildFolder::SourceRoot:
  117. nativeFolderType = BuildFolder::SourceRoot;
  118. break;
  119. case ScriptBuildFolder::DestinationRoot:
  120. nativeFolderType = BuildFolder::DestinationRoot;
  121. break;
  122. case ScriptBuildFolder::NativeBinaries:
  123. nativeFolderType = BuildFolder::NativeBinaries;
  124. break;
  125. case ScriptBuildFolder::BansheeAssemblies:
  126. nativeFolderType = BuildFolder::BansheeAssemblies;
  127. break;
  128. case ScriptBuildFolder::Data:
  129. nativeFolderType = BuildFolder::Data;
  130. break;
  131. }
  132. path = BuildManager::instance().getBuildFolder(nativeFolderType, platform);
  133. }
  134. return MonoUtil::wstringToMono(MonoManager::instance().getDomain(), path.toWString());
  135. }
  136. void ScriptBuildManager::internal_InjectIcons(MonoString* filePath, ScriptPlatformInfo* info)
  137. {
  138. if (info == nullptr)
  139. return;
  140. Path executablePath = MonoUtil::monoToWString(filePath);
  141. Map<UINT32, PixelDataPtr> icons;
  142. SPtr<PlatformInfo> platformInfo = info->getPlatformInfo();
  143. switch (platformInfo->type)
  144. {
  145. case PlatformType::Windows:
  146. {
  147. SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
  148. struct IconData
  149. {
  150. UINT32 size;
  151. HTexture texture;
  152. PixelDataPtr pixels;
  153. };
  154. IconData textures[] =
  155. {
  156. { 16, winPlatformInfo->icon16 },
  157. { 32, winPlatformInfo->icon32 },
  158. { 48, winPlatformInfo->icon48 },
  159. { 64, winPlatformInfo->icon64 },
  160. { 96, winPlatformInfo->icon96 },
  161. { 128, winPlatformInfo->icon128 },
  162. { 192, winPlatformInfo->icon192 },
  163. { 256, winPlatformInfo->icon256 }
  164. };
  165. for (auto& entry : textures)
  166. {
  167. auto& texProps = entry.texture->getProperties();
  168. entry.pixels = texProps.allocateSubresourceBuffer(0);
  169. entry.texture->readSubresource(gCoreAccessor(), 0, entry.pixels);
  170. icons[entry.size] = entry.pixels;
  171. }
  172. gCoreAccessor().submitToCoreThread(true);
  173. }
  174. break;
  175. }
  176. IconUtility::updateIconExe(executablePath, icons);
  177. }
  178. void ScriptBuildManager::internal_PackageResources(MonoString* buildFolder, ScriptPlatformInfo* info)
  179. {
  180. UnorderedSet<Path> usedResources;
  181. // Get all resources manually included in build
  182. Vector<ProjectLibrary::ResourceEntry*> buildResources = gProjectLibrary().getResourcesForBuild();
  183. for (auto& entry : buildResources)
  184. {
  185. if (entry->meta == nullptr)
  186. {
  187. LOGWRN("Cannot include resource in build, missing meta file for: " + entry->path.toString());
  188. continue;
  189. }
  190. Path resourcePath;
  191. if (gResources().getFilePathFromUUID(entry->meta->getUUID(), resourcePath))
  192. usedResources.insert(resourcePath);
  193. else
  194. LOGWRN("Cannot include resource in build, missing imported asset for: " + entry->path.toString());
  195. }
  196. // Include main scene
  197. SPtr<PlatformInfo> platformInfo;
  198. if (info != nullptr)
  199. platformInfo = info->getPlatformInfo();
  200. if (platformInfo != nullptr)
  201. {
  202. Path resourcePath;
  203. if (gResources().getFilePathFromUUID(platformInfo->mainScene.getUUID(), resourcePath))
  204. usedResources.insert(resourcePath);
  205. else
  206. LOGWRN("Cannot include main scene in build, missing imported asset.");
  207. }
  208. // Find dependencies of all resources
  209. Vector<Path> newResources;
  210. for (auto& entry : usedResources)
  211. newResources.push_back(entry);
  212. while (!newResources.empty())
  213. {
  214. Vector<Path> allDependencies;
  215. for (auto& entry : newResources)
  216. {
  217. Vector<String> curDependencies = gResources().getDependencies(entry);
  218. for (auto& entry : curDependencies)
  219. {
  220. Path resourcePath;
  221. if (gResources().getFilePathFromUUID(entry, resourcePath))
  222. {
  223. if (usedResources.find(resourcePath) == usedResources.end())
  224. {
  225. allDependencies.push_back(resourcePath);
  226. newResources.push_back(resourcePath);
  227. }
  228. }
  229. }
  230. }
  231. newResources = allDependencies;
  232. }
  233. // Copy resources
  234. Path outputPath = MonoUtil::monoToWString(buildFolder);
  235. outputPath.append(GAME_RESOURCES_FOLDER_NAME);
  236. FileSystem::createDir(outputPath);
  237. for (auto& entry : usedResources)
  238. {
  239. String uuid;
  240. BS_ASSERT(gResources().getUUIDFromFilePath(entry, uuid));
  241. Path sourcePath = gProjectLibrary().uuidToPath(uuid);
  242. ProjectLibrary::LibraryEntry* libEntry = gProjectLibrary().findEntry(sourcePath);
  243. assert(libEntry != nullptr && libEntry->type == ProjectLibrary::LibraryEntryType::File);
  244. ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(libEntry);
  245. Path destPath = outputPath;
  246. destPath.setFilename(entry.getFilename());
  247. // If resource is prefab make sure to update it in case any of the prefabs it is referencing changed
  248. if (resEntry->meta->getTypeID() == TID_Prefab)
  249. {
  250. bool reload = gResources().isLoaded(uuid);
  251. HPrefab prefab = static_resource_cast<Prefab>(gProjectLibrary().load(sourcePath));
  252. prefab->_updateChildInstances();
  253. // Clear prefab diffs as they're not used in standalone
  254. Stack<HSceneObject> todo;
  255. todo.push(prefab->_getRoot());
  256. while (!todo.empty())
  257. {
  258. HSceneObject current = todo.top();
  259. todo.pop();
  260. current->_clearPrefabDiff();
  261. UINT32 numChildren = current->getNumChildren();
  262. for (UINT32 i = 0; i < numChildren; i++)
  263. {
  264. HSceneObject child = current->getChild(i);
  265. todo.push(child);
  266. }
  267. }
  268. gResources().save(prefab, destPath, false);
  269. // Need to unload this one as we modified it in memory, and we don't want to persist those changes past
  270. // this point
  271. gResources().unload(prefab);
  272. if (reload)
  273. gProjectLibrary().load(sourcePath);
  274. }
  275. else
  276. FileSystem::copy(entry, destPath);
  277. }
  278. // Save icon
  279. Path iconFolder = FileSystem::getWorkingDirectoryPath();
  280. iconFolder.append(BuiltinResources::EngineIconFolder);
  281. Path sourceRoot = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platformInfo->type);
  282. iconFolder.makeRelative(sourceRoot);
  283. Path destRoot = BuildManager::instance().getBuildFolder(BuildFolder::DestinationRoot, platformInfo->type);
  284. Path destIconFile = destRoot;
  285. destIconFile.append(iconFolder);
  286. destIconFile.setFilename(BuiltinResources::IconTextureName + L".asset");
  287. switch (platformInfo->type)
  288. {
  289. case PlatformType::Windows:
  290. {
  291. SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
  292. gResources().save(winPlatformInfo->taskbarIcon, destIconFile, false);
  293. }
  294. };
  295. // Save manifest
  296. Path manifestPath = outputPath;
  297. manifestPath.append(GAME_RESOURCE_MANIFEST_NAME);
  298. Path internalResourcesFolder = gEditorApplication().getProjectPath();
  299. internalResourcesFolder.append(PROJECT_INTERNAL_DIR);
  300. ResourceManifestPtr manifest = gProjectLibrary()._getManifest();
  301. ResourceManifest::save(manifest, manifestPath, internalResourcesFolder);
  302. }
  303. void ScriptBuildManager::internal_CreateStartupSettings(MonoString* buildFolder, ScriptPlatformInfo* info)
  304. {
  305. SPtr<PlatformInfo> platformInfo;
  306. if (info != nullptr)
  307. platformInfo = info->getPlatformInfo();
  308. SPtr<GameSettings> gameSettings;
  309. if (platformInfo != nullptr)
  310. {
  311. gameSettings->mainSceneUUID = platformInfo->mainScene.getUUID();
  312. gameSettings->fullscreen = platformInfo->fullscreen;
  313. gameSettings->resolutionWidth = platformInfo->windowedWidth;
  314. gameSettings->resolutionWidth = platformInfo->windowedHeight;
  315. switch (platformInfo->type)
  316. {
  317. case(PlatformType::Windows) :
  318. {
  319. SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
  320. gameSettings->titleBarText = winPlatformInfo->titlebarText;
  321. }
  322. break;
  323. }
  324. }
  325. Path outputPath = MonoUtil::monoToWString(buildFolder);
  326. outputPath.append(GAME_SETTINGS_NAME);
  327. FileEncoder fe(outputPath);
  328. fe.encode(gameSettings.get());
  329. }
  330. }