| 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 | |
| 20 | namespace 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 | |
| 36 | int 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 | |
| 111 | namespace 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 | } |