1#include "BsApplication.h"
2#include "BsEngineConfig.h"
3#include "Resources/BsResources.h"
4#include "Resources/BsBuiltinResources.h"
5#include "BsBuiltinResourcesHelper.h"
6#include "FileSystem/BsFileSystem.h"
7#include "FileSystem/BsPath.h"
8#include "FileSystem/BsDataStream.h"
9#include "Resources/BsResourceManifest.h"
10#include "ThirdParty/json.hpp"
11#include "Utility/BsShapeMeshes3D.h"
12#include "Mesh/BsMesh.h"
13#include "Renderer/BsRendererMeshData.h"
14#include "Image/BsTexture.h"
15#include "RenderAPI/BsVertexDataDesc.h"
16#include "Serialization/BsFileSerializer.h"
17#include "Importer/BsImporter.h"
18#include "Importer/BsTextureImportOptions.h"
19
20namespace bs
21{
22 static constexpr const char* TIMESTAMP_NAME = u8"Timestamp.asset";
23 static constexpr const char* MANIFEST_NAME = u8"ResourceManifest.asset";
24 static constexpr const char* DEPENDENCIES_JSON_NAME = u8"ShaderDependencies.json";
25 static constexpr const char* DATA_LIST_JSON = u8"DataList.json";
26 static constexpr const char* GUI_SKIN_JSON = u8"GUISkin.json";
27
28 static Path sInputFolder;
29 static Path sOutputFolder;
30 static Path sManifestPath;
31 static SPtr<ResourceManifest> sManifest;
32
33 void processAssets(bool, bool, time_t);
34}
35
36int main(int argc, char * argv[])
37{
38 using namespace bs;
39
40 if(argc < 3)
41 return 2;
42
43 START_UP_DESC desc;
44 desc.renderAPI = BS_RENDER_API_MODULE;
45 desc.renderer = BS_RENDERER_MODULE;
46 desc.audio = BS_AUDIO_MODULE;
47 desc.physics = BS_PHYSICS_MODULE;
48
49 desc.importers.push_back("bsfFreeImgImporter");
50 desc.importers.push_back("bsfFBXImporter");
51 desc.importers.push_back("bsfFontImporter");
52 desc.importers.push_back("bsfSL");
53
54 desc.primaryWindowDesc.videoMode = VideoMode (64, 64);
55 desc.primaryWindowDesc.fullscreen = false;
56 desc.primaryWindowDesc.title = "bsf importer";
57 desc.primaryWindowDesc.hidden = true;
58
59 Application::startUp(desc);
60
61 sInputFolder = argv[1];
62 sOutputFolder = argv[2];
63 sManifestPath = sOutputFolder + MANIFEST_NAME;
64
65 bool generateGenerated = true;
66 bool forceImport = false;
67 for(int i = 3; i < argc; i++)
68 {
69 if(strcmp(argv[i], "--editor") == 0)
70 generateGenerated = false;
71 else if(strcmp(argv[i], "--force") == 0)
72 forceImport = true;
73 }
74
75 if (FileSystem::exists(sInputFolder))
76 {
77 time_t lastUpdateTime;
78 UINT32 modifications = BuiltinResourcesHelper::checkForModifications(
79 sInputFolder,
80 sOutputFolder + TIMESTAMP_NAME,
81 lastUpdateTime);
82
83 if(forceImport)
84 modifications = 2;
85
86 // Check if manifest needs to be rebuilt
87 if (modifications == 0 && !FileSystem::exists(sManifestPath))
88 modifications = 1;
89
90 if (modifications > 0)
91 {
92 const bool fullReimport = modifications == 2;
93
94 sManifest = ResourceManifest::create("BuiltinResources");
95 gResources().registerResourceManifest(sManifest);
96
97 processAssets(generateGenerated, fullReimport, lastUpdateTime);
98 BuiltinResourcesHelper::writeTimestamp(sOutputFolder + TIMESTAMP_NAME);
99
100 ResourceManifest::save(sManifest, sManifestPath, sOutputFolder);
101
102 Application::shutDown();
103 return 1;
104 }
105 }
106
107 Application::shutDown();
108 return 0;
109}
110
111namespace bs
112{
113 void generateTextures()
114 {
115 SPtr<PixelData> blackPixelData = PixelData::create(2, 2, 1, PF_RGBA8);
116 blackPixelData->setColorAt(Color::Black, 0, 0);
117 blackPixelData->setColorAt(Color::Black, 0, 1);
118 blackPixelData->setColorAt(Color::Black, 1, 0);
119 blackPixelData->setColorAt(Color::Black, 1, 1);
120
121 SPtr<Texture> blackTexture = Texture::_createPtr(blackPixelData);
122
123 SPtr<PixelData> whitePixelData = PixelData::create(2, 2, 1, PF_RGBA8);
124 whitePixelData->setColorAt(Color::White, 0, 0);
125 whitePixelData->setColorAt(Color::White, 0, 1);
126 whitePixelData->setColorAt(Color::White, 1, 0);
127 whitePixelData->setColorAt(Color::White, 1, 1);
128
129 SPtr<Texture> whiteTexture = Texture::_createPtr(whitePixelData);
130
131 SPtr<PixelData> normalPixelData = PixelData::create(2, 2, 1, PF_RGBA8);
132
133 Color encodedNormal(0.5f, 0.5f, 1.0f);
134 normalPixelData->setColorAt(encodedNormal, 0, 0);
135 normalPixelData->setColorAt(encodedNormal, 0, 1);
136 normalPixelData->setColorAt(encodedNormal, 1, 0);
137 normalPixelData->setColorAt(encodedNormal, 1, 1);
138
139 SPtr<Texture> normalTexture = Texture::_createPtr(normalPixelData);
140
141 // Save all textures
142 Path outputDir = sOutputFolder + BuiltinResources::TEXTURE_FOLDER;
143
144 auto saveTexture = [&](const Path& path, const SPtr<Texture>& texture, const String& uuid)
145 {
146 HResource textureResource = gResources()._createResourceHandle(texture, UUID(uuid));
147
148 gResources().save(textureResource, path, true);
149 sManifest->registerResource(textureResource.getUUID(), path);
150 };
151
152 Path whitePath = outputDir + BuiltinResources::TEXTURE_WHITE_FILE;
153 saveTexture(whitePath, whiteTexture, "1f7d0e3f-d81b-42ee-9d31-cb6c6fc55824");
154
155 Path blackPath = outputDir + BuiltinResources::TEXTURE_BLACK_FILE;
156 saveTexture(blackPath, blackTexture, "149a5c05-9570-4915-9dbd-69acf88b865b");
157
158 Path normalPath = outputDir + BuiltinResources::TEXTURE_NORMAL_FILE;
159 saveTexture(normalPath, normalTexture, "afb29163-1ef0-4440-9cfb-c1ebb3b3d452");
160 }
161
162 void generateMeshes()
163 {
164 SPtr<VertexDataDesc> vertexDesc = bs_shared_ptr_new<VertexDataDesc>();
165 vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
166 vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
167 vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
168 vertexDesc->addVertElem(VET_FLOAT4, VES_TANGENT);
169 vertexDesc->addVertElem(VET_COLOR, VES_COLOR);
170
171 UINT32 boxNumVertices = 0;
172 UINT32 boxNumIndices = 0;
173 ShapeMeshes3D::getNumElementsAABox(boxNumVertices, boxNumIndices);
174 SPtr<MeshData> boxMeshData = MeshData::create(boxNumVertices, boxNumIndices, vertexDesc);
175 AABox box(Vector3(-0.5f, -0.5f, -0.5f), Vector3(0.5f, 0.5f, 0.5f));
176
177 ShapeMeshes3D::solidAABox(box, boxMeshData, 0, 0);
178 SPtr<Mesh> boxMesh = Mesh::_createPtr(RendererMeshData::convert(boxMeshData));
179
180 UINT32 sphereNumVertices = 0;
181 UINT32 sphereNumIndices = 0;
182 ShapeMeshes3D::getNumElementsSphere(3, sphereNumVertices, sphereNumIndices);
183 SPtr<MeshData> sphereMeshData = bs_shared_ptr_new<MeshData>(sphereNumVertices, sphereNumIndices, vertexDesc);
184
185 ShapeMeshes3D::solidSphere(Sphere(Vector3::ZERO, 1.0f), sphereMeshData, 0, 0, 3);
186 SPtr<Mesh> sphereMesh = Mesh::_createPtr(RendererMeshData::convert(sphereMeshData));
187
188 UINT32 coneNumVertices = 0;
189 UINT32 coneNumIndices = 0;
190 ShapeMeshes3D::getNumElementsCone(10, coneNumVertices, coneNumIndices);
191 SPtr<MeshData> coneMeshData = bs_shared_ptr_new<MeshData>(coneNumVertices, coneNumIndices, vertexDesc);
192
193 ShapeMeshes3D::solidCone(Vector3::ZERO, Vector3::UNIT_Y, 1.0f, 1.0f, Vector2::ONE, coneMeshData, 0, 0);
194 SPtr<Mesh> coneMesh = Mesh::_createPtr(RendererMeshData::convert(coneMeshData));
195
196 UINT32 cylinderNumVertices = 0;
197 UINT32 cylinderNumIndices = 0;
198 ShapeMeshes3D::getNumElementsCylinder(10, cylinderNumVertices, cylinderNumIndices);
199 SPtr<MeshData> cylinderMeshData = bs_shared_ptr_new<MeshData>(cylinderNumVertices, cylinderNumIndices, vertexDesc);
200
201 ShapeMeshes3D::solidCylinder(Vector3::ZERO, Vector3::UNIT_Y, 1.0f, 1.0f, Vector2::ONE, cylinderMeshData, 0, 0);
202 SPtr<Mesh> cylinderMesh = Mesh::_createPtr(RendererMeshData::convert(cylinderMeshData));
203
204 UINT32 quadNumVertices = 8;
205 UINT32 quadNumIndices = 12;
206 ShapeMeshes3D::getNumElementsQuad(quadNumVertices, quadNumIndices);
207 SPtr<MeshData> quadMeshData = bs_shared_ptr_new<MeshData>(quadNumVertices, quadNumIndices, vertexDesc);
208
209 std::array<Vector3, 2> axes = {{ Vector3::UNIT_X, Vector3::UNIT_Z }};
210 std::array<float, 2> sizes = {{ 1.0f, 1.0f }};
211 Rect3 rect(Vector3::ZERO, axes, sizes);
212 ShapeMeshes3D::solidQuad(rect, quadMeshData, 0, 0);
213 SPtr<Mesh> quadMesh = Mesh::_createPtr(RendererMeshData::convert(quadMeshData));
214
215 UINT32 discNumVertices = 0;
216 UINT32 discNumIndices = 0;
217 ShapeMeshes3D::getNumElementsDisc(10, discNumVertices, discNumIndices);
218 SPtr<MeshData> discMeshData = bs_shared_ptr_new<MeshData>(discNumVertices, discNumIndices, vertexDesc);
219
220 ShapeMeshes3D::solidDisc(Vector3::ZERO, 1.0f, Vector3::UNIT_Y, discMeshData, 0, 0);
221 SPtr<Mesh> discMesh = Mesh::_createPtr(RendererMeshData::convert(discMeshData));
222
223 // Save all meshes
224 const Path outputDir = sOutputFolder + BuiltinResources::MESH_FOLDER;
225
226 auto saveMesh = [&](const Path& path, const SPtr<Mesh>& mesh, const String& uuid)
227 {
228 HResource meshResource = gResources()._createResourceHandle(mesh, UUID(uuid));
229
230 gResources().save(meshResource, path, true);
231 sManifest->registerResource(meshResource.getUUID(), path);
232 };
233
234 Path boxPath = outputDir + BuiltinResources::MESH_BOX_FILE;
235 saveMesh(boxPath, boxMesh, "bc1d20ca-7fe6-489b-8b5c-dbf798badc95");
236
237 Path spherePath = outputDir + BuiltinResources::MESH_SPHERE_FILE;
238 saveMesh(spherePath, sphereMesh, "040642f3-04d6-419e-9dba-f7824161c205");
239
240 Path conePath = outputDir + BuiltinResources::MESH_CONE_FILE;
241 saveMesh(conePath, coneMesh, "b8cf6db5-1736-47ac-852f-82ecd88b4d46");
242
243 Path cylinderPath = outputDir + BuiltinResources::MESH_CYLINDER_FILE;
244 saveMesh(cylinderPath, cylinderMesh, "e6b2b797-4e72-7e49-61ba-4e7275bd561d");
245
246 Path quadPath = outputDir + BuiltinResources::MESH_QUAD_FILE;
247 saveMesh(quadPath, quadMesh, "06592bf3-f82a-472e-a034-26a98225fbe1");
248
249 Path discPath = outputDir + BuiltinResources::MESH_DISC_FILE;
250 saveMesh(discPath, discMesh, "6f496313-344a-495c-83e8-152e3053c52d");
251 }
252
253 SPtr<GUISkin> generateGUISkin()
254 {
255 using nlohmann::json;
256
257 const Path skinFolder = sOutputFolder + BuiltinResources::SKIN_FOLDER + BuiltinResources::SPRITE_FOLDER;
258 BuiltinResourceGUIElementStyleLoader loader(sOutputFolder, skinFolder);
259
260 Path guiSkinPath = sInputFolder + GUI_SKIN_JSON;
261 SPtr<DataStream> guiSkinStream = FileSystem::openFile(guiSkinPath);
262 json guiSkinJSON = json::parse(guiSkinStream->getAsString().c_str());
263
264 SPtr<GUISkin> skin = GUISkin::_createPtr();
265
266 for(auto& entry : guiSkinJSON)
267 {
268 std::string name = entry["name"];
269
270 GUIElementStyle style = BuiltinResourcesHelper::loadGUIStyleFromJSON(entry, loader);
271 skin->setStyle(name.c_str(), style);
272 }
273
274 return skin;
275 }
276
277 void processAssets(bool generateGenerated, bool forceImport, time_t lastUpdateTime)
278 {
279 using nlohmann::json;
280
281 // Hidden dependency: Textures need to be generated before shaders as they may use the default textures
282 if(generateGenerated)
283 {
284 generateTextures();
285 generateMeshes();
286 }
287
288 const Path dataListsFilePath = sInputFolder + DATA_LIST_JSON;
289 SPtr<DataStream> dataListStream = FileSystem::openFile(dataListsFilePath);
290 json dataListJSON = json::parse(dataListStream->getAsString().c_str());
291
292 json skinJSON = dataListJSON["Skin"];
293 json animatedSpritesJSON = dataListJSON["AnimatedSprites"];
294 json cursorsJSON = dataListJSON["Cursors"];
295 json iconsJSON = dataListJSON["Icons"];
296 json spriteIconsJSON = dataListJSON["SpriteIcons"];
297 json spriteIcons3DJSON = dataListJSON["SpriteIcons3D"];
298 json includesJSON = dataListJSON["Includes"];
299 json shadersJSON = dataListJSON["Shaders"];
300 json fontsJSON = dataListJSON["Fonts"];
301 json guiSkinJSON = dataListJSON["GUISkin"];
302 json splashScreenJSON = dataListJSON["SplashScreen"];
303
304 const Path rawSkinFolder = sInputFolder + BuiltinResources::SKIN_FOLDER;
305 const Path rawAnimatedSpritesFolder = sInputFolder + BuiltinResources::ANIMATED_SPRITES_FOLDER;
306 const Path rawCursorFolder = sInputFolder + BuiltinResources::CURSOR_FOLDER;
307 const Path rawIconFolder = sInputFolder + BuiltinResources::ICON_FOLDER;
308 const Path rawIcon3DFolder = sInputFolder + BuiltinResources::ICON3D_FOLDER;
309 const Path rawShaderFolder = sInputFolder + BuiltinResources::SHADER_FOLDER;
310 const Path rawShaderIncludeFolder = sInputFolder + BuiltinResources::SHADER_INCLUDE_FOLDER;
311
312 // Update DataList.json if needed
313 bool updatedDataLists = false;
314
315 if(!cursorsJSON.is_null())
316 {
317 updatedDataLists |= BuiltinResourcesHelper::updateJSON(
318 rawCursorFolder,
319 BuiltinResourcesHelper::AssetType::Normal,
320 cursorsJSON);
321 }
322
323 if(!iconsJSON.is_null())
324 {
325 updatedDataLists |= BuiltinResourcesHelper::updateJSON(
326 rawIconFolder,
327 BuiltinResourcesHelper::AssetType::Normal,
328 iconsJSON);
329 }
330
331 if(!spriteIconsJSON.is_null())
332 {
333 updatedDataLists |= BuiltinResourcesHelper::updateJSON(
334 rawIconFolder,
335 BuiltinResourcesHelper::AssetType::Sprite,
336 spriteIconsJSON);
337 }
338
339 if(!spriteIcons3DJSON.is_null())
340 {
341 updatedDataLists |= BuiltinResourcesHelper::updateJSON(
342 rawIcon3DFolder,
343 BuiltinResourcesHelper::AssetType::Sprite,
344 spriteIcons3DJSON);
345 }
346
347 if(!includesJSON.is_null())
348 {
349 updatedDataLists |= BuiltinResourcesHelper::updateJSON(
350 rawShaderIncludeFolder,
351 BuiltinResourcesHelper::AssetType::Normal,
352 includesJSON);
353 }
354
355 if(!shadersJSON.is_null())
356 {
357 updatedDataLists |= BuiltinResourcesHelper::updateJSON(
358 rawShaderFolder,
359 BuiltinResourcesHelper::AssetType::Normal,
360 shadersJSON);
361 }
362
363 if(!skinJSON.is_null())
364 {
365 updatedDataLists |= BuiltinResourcesHelper::updateJSON(
366 rawSkinFolder,
367 BuiltinResourcesHelper::AssetType::Sprite,
368 skinJSON);
369 }
370
371 dataListStream->close();
372
373 if(updatedDataLists)
374 {
375 FileSystem::remove(dataListsFilePath);
376
377 if(!skinJSON.is_null())
378 dataListJSON["Skin"] = skinJSON;
379
380 if(!animatedSpritesJSON.is_null())
381 dataListJSON["AnimatedSprites"] = animatedSpritesJSON;
382
383 if(!cursorsJSON.is_null())
384 dataListJSON["Cursors"] = cursorsJSON;
385
386 if(!iconsJSON.is_null())
387 dataListJSON["Icons"] = iconsJSON;
388
389 if(!spriteIconsJSON.is_null())
390 dataListJSON["SpriteIcons"] = spriteIconsJSON;
391
392 if(!spriteIcons3DJSON.is_null())
393 dataListJSON["SpriteIcons3D"] = spriteIcons3DJSON;
394
395 if(!includesJSON.is_null())
396 dataListJSON["Includes"] = includesJSON;
397
398 if(!shadersJSON.is_null())
399 dataListJSON["Shaders"] = shadersJSON;
400
401 if(!fontsJSON.is_null())
402 dataListJSON["Fonts"] = fontsJSON;
403
404 if(!guiSkinJSON.is_null())
405 dataListJSON["GUISkin"] = guiSkinJSON;
406
407 if(!splashScreenJSON.is_null())
408 dataListJSON["SplashScreen"] = splashScreenJSON;
409
410 String jsonString = dataListJSON.dump(4).c_str();
411 dataListStream = FileSystem::createAndOpenFile(dataListsFilePath);
412 dataListStream->writeString(jsonString);
413 dataListStream->close();
414 }
415
416 const Path skinFolder = sOutputFolder + BuiltinResources::SKIN_FOLDER;
417 const Path animatedSpriteFolder = sOutputFolder + BuiltinResources::ANIMATED_SPRITES_FOLDER;
418 const Path cursorFolder = sOutputFolder + BuiltinResources::CURSOR_FOLDER;
419 const Path iconFolder = sOutputFolder + BuiltinResources::ICON_FOLDER;
420 const Path icon3DFolder = sOutputFolder + BuiltinResources::ICON3D_FOLDER;
421 const Path shaderFolder = sOutputFolder + BuiltinResources::SHADER_FOLDER;
422 const Path shaderIncludeFolder = sOutputFolder + BuiltinResources::SHADER_INCLUDE_FOLDER;
423 const Path shaderDependenciesFile = sInputFolder + DEPENDENCIES_JSON_NAME;
424
425 // If forcing import, clear all data folders since everything will be recreated anyway
426 if(forceImport)
427 {
428 if(FileSystem::exists(cursorFolder))
429 FileSystem::remove(cursorFolder);
430
431 if(FileSystem::exists(iconFolder))
432 FileSystem::remove(iconFolder);
433
434 if(FileSystem::exists(icon3DFolder))
435 FileSystem::remove(icon3DFolder);
436
437 if(FileSystem::exists(shaderIncludeFolder))
438 FileSystem::remove(shaderIncludeFolder);
439
440 if(FileSystem::exists(shaderFolder))
441 FileSystem::remove(shaderFolder);
442
443 if(FileSystem::exists(skinFolder))
444 FileSystem::remove(skinFolder);
445
446 if(FileSystem::exists(animatedSpriteFolder))
447 FileSystem::remove(animatedSpriteFolder);
448
449 FileSystem::remove(shaderDependenciesFile);
450 }
451
452 // Read shader dependencies JSON
453 json shaderDependenciesJSON;
454 if(FileSystem::exists(shaderDependenciesFile))
455 {
456 SPtr<DataStream> stream = FileSystem::openFile(shaderDependenciesFile);
457 shaderDependenciesJSON = json::parse(stream->getAsString().c_str());
458 stream->close();
459 }
460
461 // Import cursors
462 if(!cursorsJSON.is_null())
463 {
464 BuiltinResourcesHelper::updateManifest(
465 cursorFolder,
466 cursorsJSON,
467 sManifest,
468 BuiltinResourcesHelper::AssetType::Normal);
469
470 Vector<bool> importFlags = BuiltinResourcesHelper::generateImportFlags(
471 cursorsJSON,
472 rawCursorFolder,
473 lastUpdateTime,
474 forceImport);
475
476 BuiltinResourcesHelper::importAssets(
477 cursorsJSON,
478 importFlags,
479 rawCursorFolder,
480 cursorFolder,
481 sManifest,
482 BuiltinResourcesHelper::AssetType::Normal);
483 }
484
485 // Import icons
486 if(!iconsJSON.is_null())
487 {
488 BuiltinResourcesHelper::updateManifest(
489 iconFolder,
490 iconsJSON,
491 sManifest,
492 BuiltinResourcesHelper::AssetType::Normal);
493
494 Vector<bool> importFlags = BuiltinResourcesHelper::generateImportFlags(
495 iconsJSON,
496 rawIconFolder,
497 lastUpdateTime,
498 forceImport);
499
500 BuiltinResourcesHelper::importAssets(
501 iconsJSON,
502 importFlags,
503 rawIconFolder,
504 iconFolder,
505 sManifest,
506 BuiltinResourcesHelper::AssetType::Normal);
507 }
508
509 // Import sprite icons
510 if(!spriteIconsJSON.is_null())
511 {
512 BuiltinResourcesHelper::updateManifest(
513 iconFolder,
514 spriteIconsJSON,
515 sManifest,
516 BuiltinResourcesHelper::AssetType::Sprite);
517
518 Vector<bool> importFlags = BuiltinResourcesHelper::generateImportFlags(
519 spriteIconsJSON,
520 rawIconFolder,
521 lastUpdateTime,
522 forceImport);
523
524 BuiltinResourcesHelper::importAssets(
525 spriteIconsJSON,
526 importFlags,
527 rawIconFolder,
528 iconFolder,
529 sManifest,
530 BuiltinResourcesHelper::AssetType::Sprite);
531 }
532
533 // Import 3D sprite icons
534 if(!spriteIcons3DJSON.is_null())
535 {
536 BuiltinResourcesHelper::updateManifest(
537 icon3DFolder,
538 spriteIcons3DJSON,
539 sManifest,
540 BuiltinResourcesHelper::AssetType::Sprite);
541
542 Vector<bool> importFlags = BuiltinResourcesHelper::generateImportFlags(
543 spriteIcons3DJSON,
544 rawIcon3DFolder,
545 lastUpdateTime,
546 forceImport);
547
548 BuiltinResourcesHelper::importAssets(
549 spriteIcons3DJSON,
550 importFlags,
551 rawIcon3DFolder,
552 icon3DFolder,
553 sManifest,
554 BuiltinResourcesHelper::AssetType::Sprite,
555 nullptr, false, true);
556 }
557
558 // Import shaders
559 if(!shadersJSON.is_null() && !includesJSON.is_null())
560 {
561 BuiltinResourcesHelper::updateManifest(
562 shaderIncludeFolder,
563 includesJSON,
564 sManifest,
565 BuiltinResourcesHelper::AssetType::Normal);
566
567 BuiltinResourcesHelper::updateManifest(
568 shaderFolder,
569 shadersJSON,
570 sManifest,
571 BuiltinResourcesHelper::AssetType::Normal);
572
573 Vector<bool> includeImportFlags = BuiltinResourcesHelper::generateImportFlags(
574 includesJSON,
575 rawShaderIncludeFolder,
576 lastUpdateTime,
577 forceImport);
578
579 Vector<bool> shaderImportFlags = BuiltinResourcesHelper::generateImportFlags(
580 shadersJSON,
581 rawShaderFolder,
582 lastUpdateTime,
583 forceImport,
584 &shaderDependenciesJSON,
585 rawShaderIncludeFolder);
586
587 // Hidden dependency: Includes must be imported before shaders, but import flags for shaders must be generated
588 // before includes are imported, since the process checks if imports changed
589 BuiltinResourcesHelper::importAssets(
590 includesJSON,
591 includeImportFlags,
592 rawShaderIncludeFolder,
593 shaderIncludeFolder,
594 sManifest,
595 BuiltinResourcesHelper::AssetType::Normal,
596 nullptr,
597 true);
598
599
600 BuiltinResourcesHelper::importAssets(
601 shadersJSON,
602 shaderImportFlags,
603 rawShaderFolder,
604 shaderFolder,
605 sManifest,
606 BuiltinResourcesHelper::AssetType::Normal,
607 &shaderDependenciesJSON,
608 true);
609 }
610
611 // Import GUI sprites
612 if(!skinJSON.is_null())
613 {
614 BuiltinResourcesHelper::updateManifest(
615 skinFolder,
616 skinJSON,
617 sManifest,
618 BuiltinResourcesHelper::AssetType::Sprite);
619
620 Vector<bool> skinImportFlags = BuiltinResourcesHelper::generateImportFlags(
621 skinJSON,
622 rawSkinFolder,
623 lastUpdateTime,
624 forceImport);
625
626 BuiltinResourcesHelper::importAssets(
627 skinJSON,
628 skinImportFlags,
629 rawSkinFolder,
630 skinFolder,
631 sManifest,
632 BuiltinResourcesHelper::AssetType::Sprite);
633 }
634
635 // Import animated sprites
636 if(!animatedSpritesJSON.is_null())
637 {
638 BuiltinResourcesHelper::updateManifest(
639 animatedSpriteFolder,
640 animatedSpritesJSON,
641 sManifest,
642 BuiltinResourcesHelper::AssetType::Sprite);
643
644 Vector<bool> importFlags = BuiltinResourcesHelper::generateImportFlags(
645 animatedSpritesJSON,
646 rawAnimatedSpritesFolder,
647 lastUpdateTime,
648 forceImport);
649
650 BuiltinResourcesHelper::importAssets(
651 animatedSpritesJSON,
652 importFlags,
653 rawAnimatedSpritesFolder,
654 animatedSpriteFolder,
655 sManifest,
656 BuiltinResourcesHelper::AssetType::Sprite);
657 }
658
659 // Update shader dependencies JSON
660 {
661 String jsonString = shaderDependenciesJSON.dump(4).c_str();
662
663 dataListStream = FileSystem::createAndOpenFile(shaderDependenciesFile);
664 dataListStream->writeString(jsonString);
665 dataListStream->close();
666 }
667
668 // Import fonts
669 if(!fontsJSON.is_null())
670 {
671 for (auto& entry : fontsJSON)
672 {
673 std::string path = entry["Path"];
674 std::string name = entry["Name"];
675 std::string uuidStr = entry["UUID"];
676 const bool antialiasing = entry["Antialiasing"];
677
678 json fontSizesJSON = entry["Sizes"];
679 Vector<UINT32> fontSizes;
680 for (auto& sizeEntry : fontSizesJSON)
681 fontSizes.push_back(sizeEntry);
682
683 String inputName(path.data(), path.size());
684 String outputName(name.data(), name.size());
685 UUID UUID(String(uuidStr.data(), uuidStr.size()));
686
687 const Path fontSourcePath = sInputFolder + inputName;
688
689 BuiltinResourcesHelper::importFont(fontSourcePath, outputName, sOutputFolder, fontSizes, antialiasing, UUID,
690 sManifest);
691 }
692 }
693
694 // Generate & save GUI skin
695 if(!guiSkinJSON.is_null())
696 {
697 std::string name = guiSkinJSON["Path"];
698 std::string uuidStr = guiSkinJSON["UUID"];
699
700 String fileName(name.data(), name.size());
701 UUID UUID(String(uuidStr.data(), uuidStr.size()));
702
703 const SPtr<GUISkin> skin = generateGUISkin();
704 const Path outputPath = sOutputFolder + (fileName + u8".asset");
705
706 HResource skinResource = gResources()._createResourceHandle(skin, UUID);
707
708 gResources().save(skinResource, outputPath, true);
709 sManifest->registerResource(skinResource.getUUID(), outputPath);
710 }
711
712 // Generate & save splash screen
713 if(!splashScreenJSON.is_null())
714 {
715 std::string name = splashScreenJSON["Path"];
716 String fileName(name.data(), name.size());
717
718 Path inputPath = sInputFolder + fileName;
719 Path outputPath = sOutputFolder + (fileName + ".asset");
720
721 auto textureIO = gImporter().createImportOptions<TextureImportOptions>(inputPath);
722 textureIO->cpuCached = true;
723 textureIO->generateMips = false;
724 HTexture splashTexture = gImporter().import<Texture>(inputPath, textureIO);
725
726 SPtr<PixelData> splashPixelData = splashTexture->getProperties().allocBuffer(0, 0);
727 splashTexture->readCachedData(*splashPixelData);
728
729 FileEncoder fe(outputPath);
730 fe.encode(splashPixelData.get());
731 }
732 }
733}