TestAssetBuilderComponent.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Builder/TestAssetBuilderComponent.h>
  9. #include <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Serialization/EditContextConstants.inl>
  11. #include <AzFramework/IO/LocalFileIO.h>
  12. #include <AzFramework/StringFunc/StringFunc.h>
  13. #include <AzCore/Asset/AssetManager.h>
  14. #include <AzCore/Slice/SliceAsset.h>
  15. #include <AzCore/RTTI/TypeInfo.h>
  16. namespace TestAssetBuilder
  17. {
  18. bool failedNetworkConnectionTest = true;
  19. AZ::Data::AssetStreamInfo TestDependentAssetCatalog::GetStreamInfoForLoad(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& type)
  20. {
  21. if (AZ::AzTypeInfo<TestDependentAsset>::Uuid() != type)
  22. {
  23. AZ_Error("TestDependentAssetCatalog", false, "Invalid asset type %s", assetId.ToString<AZStd::string>().c_str());
  24. return {};
  25. }
  26. AZ::Data::AssetInfo assetInfo;
  27. AZStd::string rootFilePath;
  28. AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, assetId);
  29. if (assetInfo.m_assetId.IsValid())
  30. {
  31. AZ::Data::AssetStreamInfo streamInfo;
  32. streamInfo.m_dataOffset = 0;
  33. streamInfo.m_dataLen = assetInfo.m_sizeBytes;
  34. streamInfo.m_streamName = assetInfo.m_relativePath;
  35. streamInfo.m_streamFlags = AZ::IO::OpenMode::ModeRead;
  36. return streamInfo;
  37. }
  38. return {};
  39. }
  40. TestAssetBuilderComponent::TestAssetBuilderComponent()
  41. {
  42. }
  43. TestAssetBuilderComponent::~TestAssetBuilderComponent()
  44. {
  45. }
  46. void TestAssetBuilderComponent::Init()
  47. {
  48. }
  49. void TestAssetBuilderComponent::Activate()
  50. {
  51. AssetBuilderSDK::AssetBuilderDesc builderDescriptor;
  52. builderDescriptor.m_name = "Test Asset Builder";
  53. builderDescriptor.m_version = 2;
  54. builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern("*.source", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
  55. builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern("*.dependent", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
  56. builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern("*.slicetest", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
  57. builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern("*.foldertest", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
  58. builderDescriptor.m_busId = azrtti_typeid<TestAssetBuilderComponent>();
  59. builderDescriptor.m_createJobFunction = AZStd::bind(&TestAssetBuilderComponent::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
  60. builderDescriptor.m_processJobFunction = AZStd::bind(&TestAssetBuilderComponent::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
  61. bool success = false;
  62. AZStd::vector<AZStd::string> assetSafeFolders;
  63. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(success, &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetSafeFolders, assetSafeFolders);
  64. failedNetworkConnectionTest = !success || assetSafeFolders.empty();
  65. BusConnect(builderDescriptor.m_busId);
  66. m_dependentCatalog.reset(aznew TestDependentAssetCatalog());
  67. AZ::Data::AssetManager::Instance().RegisterCatalog(m_dependentCatalog.get(), AZ::AzTypeInfo<TestDependentAsset>::Uuid());
  68. AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor);
  69. }
  70. void TestAssetBuilderComponent::Deactivate()
  71. {
  72. BusDisconnect();
  73. AZ::Data::AssetManager::Instance().UnregisterCatalog(m_dependentCatalog.get());
  74. m_dependentCatalog.reset();
  75. }
  76. void TestAssetBuilderComponent::Reflect(AZ::ReflectContext* context)
  77. {
  78. if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
  79. {
  80. serialize->Class<TestAssetBuilderComponent, AZ::Component>()
  81. ->Version(0)
  82. ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AssetBuilderSDK::ComponentTags::AssetBuilder }))
  83. ;
  84. }
  85. }
  86. void TestAssetBuilderComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  87. {
  88. provided.push_back(AZ_CRC("TestAssetBuilderPluginService", 0xa380f578));
  89. }
  90. void TestAssetBuilderComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  91. {
  92. incompatible.push_back(AZ_CRC("TestAssetBuilderPluginService", 0xa380f578));
  93. }
  94. void TestAssetBuilderComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  95. {
  96. AZ_UNUSED(required);
  97. }
  98. void TestAssetBuilderComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
  99. {
  100. AZ_UNUSED(dependent);
  101. }
  102. void TestAssetBuilderComponent::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response)
  103. {
  104. if (m_isShuttingDown)
  105. {
  106. response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown;
  107. return;
  108. }
  109. if(failedNetworkConnectionTest)
  110. {
  111. AZ_Assert(false, "GetAssetSafeFolders API failed to respond or responded with an empty list. The network connection to AssetProcessor must be established before builder activation.");
  112. return;
  113. }
  114. AZStd::string ext;
  115. AzFramework::StringFunc::Path::GetExtension(request.m_sourceFile.c_str(), ext, false);
  116. if (AzFramework::StringFunc::Equal(ext.c_str(), "dependent"))
  117. {
  118. // Since we're a source file, we also add a job to do the actual compilation (for each enabled platform)
  119. for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
  120. {
  121. AssetBuilderSDK::JobDescriptor descriptor;
  122. descriptor.m_jobKey = "Compile Example";
  123. descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
  124. response.m_createJobOutputs.push_back(descriptor);
  125. }
  126. response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
  127. return;
  128. }
  129. else if (AzFramework::StringFunc::Equal(ext.c_str(), "source"))
  130. {
  131. for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
  132. {
  133. AssetBuilderSDK::JobDescriptor descriptor;
  134. descriptor.m_jobKey = "Compile Example";
  135. descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
  136. // add a dependency on the other job:
  137. AssetBuilderSDK::SourceFileDependency sourceFile;
  138. sourceFile.m_sourceFileDependencyPath = request.m_sourceFile.c_str();
  139. AzFramework::StringFunc::Path::ReplaceExtension(sourceFile.m_sourceFileDependencyPath, "dependent");
  140. descriptor.m_jobDependencyList.push_back({ "Compile Example", platformInfo.m_identifier.c_str(), AssetBuilderSDK::JobDependencyType::Order, sourceFile });
  141. response.m_createJobOutputs.push_back(descriptor);
  142. }
  143. response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
  144. return;
  145. }
  146. else if (AzFramework::StringFunc::Equal(ext.c_str(), "foldertest"))
  147. {
  148. for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
  149. {
  150. AssetBuilderSDK::JobDescriptor descriptor;
  151. descriptor.m_jobKey = "Compile Example";
  152. descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
  153. AZStd::string folderName;
  154. AzFramework::StringFunc::Path::GetFileName(request.m_sourceFile.c_str(), folderName);
  155. AZStd::string baseFolder;
  156. AzFramework::StringFunc::Path::GetFolderPath(request.m_sourceFile.c_str(), baseFolder);
  157. AZStd::string outFolder;
  158. AzFramework::StringFunc::Path::Join(baseFolder.c_str(), folderName.c_str(), outFolder);
  159. AZStd::string folderDep{ outFolder + "/*.dependent" };
  160. // add a dependency on the other job:
  161. AssetBuilderSDK::SourceFileDependency sourceFile;
  162. sourceFile.m_sourceFileDependencyPath = folderDep.c_str();
  163. sourceFile.m_sourceDependencyType = AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards;
  164. descriptor.m_jobDependencyList.push_back({ "Compile Example", platformInfo.m_identifier.c_str(), AssetBuilderSDK::JobDependencyType::Order, sourceFile });
  165. response.m_createJobOutputs.push_back(descriptor);
  166. }
  167. response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
  168. return;
  169. }
  170. else if (AzFramework::StringFunc::Equal(ext.c_str(), "slicetest"))
  171. {
  172. for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
  173. {
  174. AssetBuilderSDK::JobDescriptor descriptor;
  175. descriptor.m_jobKey = "Compile Example";
  176. descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
  177. // add a dependency on the other job:
  178. AssetBuilderSDK::SourceFileDependency sourceFile;
  179. sourceFile.m_sourceFileDependencyPath = request.m_sourceFile.c_str();
  180. AzFramework::StringFunc::Path::ReplaceExtension(sourceFile.m_sourceFileDependencyPath, "slice");
  181. descriptor.m_jobDependencyList.push_back({ "Editor Slice Copy", platformInfo.m_identifier.c_str(), AssetBuilderSDK::JobDependencyType::Order, sourceFile });
  182. response.m_createJobOutputs.push_back(descriptor);
  183. }
  184. response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
  185. return;
  186. }
  187. AZ_Assert(false, "Unhandled extension type in TestAssetBuilderWorker.");
  188. response.m_result = AssetBuilderSDK::CreateJobsResultCode::Failed;
  189. }
  190. void TestAssetBuilderComponent::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response)
  191. {
  192. AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId);
  193. AZ_TracePrintf(AssetBuilderSDK::InfoWindow, "Starting Job.\n");
  194. AZ::IO::FileIOBase* fileIO = AZ::IO::LocalFileIO::GetInstance();
  195. AZStd::string outputData;
  196. AZ::IO::HandleType sourcefileHandle;
  197. if (!fileIO->Open(request.m_fullPath.c_str(), AZ::IO::OpenMode::ModeRead, sourcefileHandle))
  198. {
  199. AZ_Error("AssetBuilder", false, " Unable to open file ( %s ).", request.m_fullPath.c_str());
  200. return;
  201. }
  202. AZ::u64 sourceSizeBytes = 0;
  203. if (fileIO->Size(sourcefileHandle, sourceSizeBytes))
  204. {
  205. outputData.resize(sourceSizeBytes);
  206. if (!fileIO->Read(sourcefileHandle, outputData.data(), sourceSizeBytes))
  207. {
  208. AZ_Error("AssetBuilder", false, " Unable to read file ( %s ).", request.m_fullPath.c_str());
  209. fileIO->Close(sourcefileHandle);
  210. return;
  211. }
  212. }
  213. fileIO->Close(sourcefileHandle);
  214. AZStd::string fileName = request.m_sourceFile.c_str();
  215. AZStd::string ext;
  216. AzFramework::StringFunc::Path::GetExtension(request.m_sourceFile.c_str(), ext, false);
  217. AZ::Data::AssetType outputAssetType = AZ::Data::AssetType::CreateNull();
  218. const AZ::u32 DependentSubID = 2222;
  219. AZ::u32 outputSubId = 0;
  220. if (AzFramework::StringFunc::Equal(ext.c_str(), "source"))
  221. {
  222. AZStd::string sourcePath{ request.m_fullPath };
  223. AZStd::string dependentFile{ fileName };
  224. AzFramework::StringFunc::Path::ReplaceExtension(dependentFile, "dependentprocessed");
  225. // By default fileIO uses @asset@ alias therefore if we give fileIO a filename
  226. // it will try to check in the cache instead of the source folder.
  227. AZ::IO::HandleType dependentfileHandle;
  228. if (!fileIO->Open(dependentFile.c_str(), AZ::IO::OpenMode::ModeRead, dependentfileHandle))
  229. {
  230. AZ_Error("AssetBuilder", false, " Unable to open file in cache ( %s ) while processing source ( %s ) ", dependentFile.c_str(), request.m_sourceFile.c_str());
  231. return;
  232. }
  233. AZ::u64 dependentsizeBytes = 0;
  234. if (fileIO->Size(dependentfileHandle, dependentsizeBytes))
  235. {
  236. outputData.resize(outputData.size() + dependentsizeBytes);
  237. if (!fileIO->Read(dependentfileHandle, outputData.data() + sourceSizeBytes, dependentsizeBytes))
  238. {
  239. AZ_Error("AssetBuilder", false, " Unable to read file data from cache ( %s ).", dependentFile.c_str());
  240. fileIO->Close(dependentfileHandle);
  241. return;
  242. }
  243. }
  244. fileIO->Close(dependentfileHandle);
  245. // Validating AssetCatalogRequest API's here which operates on assetpath and assetid
  246. AZ::Data::AssetId depAssetId;
  247. AZ::Data::AssetCatalogRequestBus::BroadcastResult(depAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, dependentFile.c_str(), AZ::Data::s_invalidAssetType, false);
  248. if (!depAssetId.IsValid())
  249. {
  250. AZ_Error("AssetBuilder", false, "GetAssetIdByPath - Asset id should be valid for this asset ( %s ).", dependentFile.c_str());
  251. return;
  252. }
  253. AZ::Data::AssetInfo depAssetInfo;
  254. AZ::Data::AssetCatalogRequestBus::BroadcastResult(depAssetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, depAssetId);
  255. if (!depAssetInfo.m_assetId.IsValid())
  256. {
  257. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset info should be valid for this asset ( %s ).", depAssetId.ToString<AZStd::string>().c_str());
  258. return;
  259. }
  260. if (depAssetInfo.m_assetType != AZ::AzTypeInfo<TestDependentAsset>::Uuid())
  261. {
  262. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset type not valid for asset ( %s ).", depAssetId.ToString<AZStd::string>().c_str());
  263. return;
  264. }
  265. AZ::Data::AssetStreamInfo resultInfo = AZ::Data::AssetManager::Instance().GetLoadStreamInfoForAsset(depAssetId, AZ::AzTypeInfo<TestDependentAsset>::Uuid());
  266. if (!resultInfo.IsValid())
  267. {
  268. AZ_Error("AssetBuilder", false, "GetLoadStreamInfoForAsset - AssetStreamInfo should be valid for this asset ( %s ).", depAssetId.ToString<AZStd::string>().c_str());
  269. return;
  270. }
  271. if (!AzFramework::StringFunc::Path::IsRelative(resultInfo.m_streamName.c_str()))
  272. {
  273. AZ_Error("AssetBuilder", false, "GetLoadStreamInfoForAsset - Source AssetStreamInfo streamName %s isn't a relative path.", resultInfo.m_streamName.c_str());
  274. return;
  275. }
  276. bool gotSourceInfo{ false };
  277. AZStd::string watchFolder;
  278. AZ::Data::AssetInfo sourcePathAssetInfo;
  279. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gotSourceInfo, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, sourcePath.c_str(), sourcePathAssetInfo, watchFolder);
  280. if (!gotSourceInfo)
  281. {
  282. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Failed to get source info for source ( %s ).", sourcePath.c_str());
  283. return;
  284. }
  285. if (!sourcePathAssetInfo.m_assetId.IsValid())
  286. {
  287. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Asset info should be valid for asset at source path ( %s ).", sourcePath.c_str());
  288. return;
  289. }
  290. if (watchFolder.empty())
  291. {
  292. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Got empty watch folder for asset at source path ( %s ).", sourcePath.c_str());
  293. return;
  294. }
  295. if (AzFramework::StringFunc::Path::IsRelative(watchFolder.c_str()))
  296. {
  297. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Got relative path %s for source asset ( %s ).", watchFolder.c_str(), sourcePath.c_str());
  298. return;
  299. }
  300. bool gotAssetInfo{ false };
  301. AZ::Data::AssetInfo assetSystemDepInfo;
  302. AZStd::string depRootFolder;
  303. const AZStd::string platformName = ""; // Empty for default
  304. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gotAssetInfo, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAssetInfoById, depAssetId, AZ::AzTypeInfo<TestDependentAsset>::Uuid(), platformName, assetSystemDepInfo, depRootFolder);
  305. if (!gotAssetInfo)
  306. {
  307. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Failed to get info for asset ( %s ).", depAssetId.ToString<AZStd::string>().c_str());
  308. return;
  309. }
  310. if (assetSystemDepInfo.m_assetType != AZ::AzTypeInfo<TestDependentAsset>::Uuid())
  311. {
  312. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset type not valid for asset ( %s ).", depAssetId.ToString<AZStd::string>().c_str());
  313. return;
  314. }
  315. // Validating AssetCatalogRequest API's here which operates on assetpath and assetid
  316. AZ::Data::AssetId assetId;
  317. AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, dependentFile.c_str(), AZ::Data::s_invalidAssetType, false);
  318. if (!assetId.IsValid())
  319. {
  320. AZ_Error("AssetBuilder", false, "GetAssetIdByPath - Asset id should be valid for this asset ( %s ).", dependentFile.c_str());
  321. return;
  322. }
  323. AZ::Data::AssetInfo assetInfo;
  324. AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, assetId);
  325. if (!assetInfo.m_assetId.IsValid())
  326. {
  327. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset info should be valid for this asset ( %s ).", assetId.ToString<AZStd::string>().c_str());
  328. return;
  329. }
  330. if (!AzFramework::StringFunc::Path::IsRelative(assetInfo.m_relativePath.c_str()))
  331. {
  332. AZ_Error("AssetBuilder", false, "GetAssetInfoById - assetInfo m_relativePath %s isn't a relative path.", assetInfo.m_relativePath.c_str());
  333. return;
  334. }
  335. if (assetId.m_subId != DependentSubID)
  336. {
  337. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset Info m_subId for %s should be %d.", assetId.ToString<AZStd::string>().c_str(), DependentSubID);
  338. return;
  339. }
  340. if (assetInfo.m_assetId.m_subId != assetId.m_subId)
  341. {
  342. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset Info m_subId for %s should be %d.", assetInfo.m_relativePath.c_str(), assetId.m_subId);
  343. return;
  344. }
  345. AZStd::string assetpath;
  346. AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetpath, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetPathById, assetId);
  347. if (assetpath.empty())
  348. {
  349. AZ_Error("AssetBuilder", false, "Asset path should not be empty for this assetid ( %s ) ( %s )", assetId.ToString<AZStd::string>().c_str(), dependentFile.c_str());
  350. return;
  351. }
  352. if (!AzFramework::StringFunc::Path::IsRelative(assetpath.c_str()))
  353. {
  354. AZ_Error("AssetBuilder", false, "GetAssetPathById - assetInfo m_relativePath %s isn't a relative path.", assetInfo.m_relativePath.c_str());
  355. return;
  356. }
  357. // Validate that we get the products for this asset
  358. bool result = false;
  359. AZStd::vector<AZ::Data::AssetInfo> productsInfo;
  360. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result,
  361. &AzToolsFramework::AssetSystemRequestBus::Events::GetAssetsProducedBySourceUUID,
  362. assetId.m_guid, productsInfo);
  363. if (productsInfo.size() == 0)
  364. {
  365. AZ_Error("AssetBuilder", false,
  366. "GetAssetsProducedBySourceUUID - list of products can't be empty. Assetid ( %s ) ( %s )",
  367. assetId.ToString<AZStd::string>().c_str(), fileName.c_str());
  368. return;
  369. }
  370. AzFramework::StringFunc::Path::ReplaceExtension(fileName, "sourceprocessed");
  371. }
  372. else if (AzFramework::StringFunc::Equal(ext.c_str(), "dependent"))
  373. {
  374. AzFramework::StringFunc::Path::ReplaceExtension(fileName, "dependentprocessed");
  375. outputAssetType = AZ::AzTypeInfo<TestDependentAsset>::Uuid();
  376. outputSubId = DependentSubID;
  377. }
  378. else if (AzFramework::StringFunc::Equal(ext.c_str(), "foldertest"))
  379. {
  380. AzFramework::StringFunc::Path::ReplaceExtension(fileName, "foldertestprocessed");
  381. }
  382. else if (AzFramework::StringFunc::Equal(ext.c_str(), "slicetest"))
  383. {
  384. AzFramework::StringFunc::Path::ReplaceExtension(fileName, "slice");
  385. AZStd::string sourcePath{ request.m_fullPath }; // Sourcepath - full path to source slice
  386. AzFramework::StringFunc::Path::ReplaceExtension(sourcePath, "slice");
  387. AzFramework::StringFunc::Path::Normalize(sourcePath);
  388. // Verify copied slice in cache
  389. AZ::IO::HandleType dependentfileHandle;
  390. if (!fileIO->Open(fileName.c_str(), AZ::IO::OpenMode::ModeRead, dependentfileHandle))
  391. {
  392. AZ_Error("AssetBuilder", false, " Unable to open file in cache ( %s ) while processing source ( %s ) ", fileName.c_str(), request.m_sourceFile.c_str());
  393. return;
  394. }
  395. AZ::u64 dependentsizeBytes = 0;
  396. if (fileIO->Size(dependentfileHandle, dependentsizeBytes))
  397. {
  398. outputData.resize(outputData.size() + dependentsizeBytes);
  399. if (!fileIO->Read(dependentfileHandle, outputData.data() + sourceSizeBytes, dependentsizeBytes))
  400. {
  401. AZ_Error("AssetBuilder", false, " Unable to read file data from cache ( %s ).", fileName.c_str());
  402. fileIO->Close(dependentfileHandle);
  403. return;
  404. }
  405. }
  406. fileIO->Close(dependentfileHandle);
  407. AZ::Data::AssetId depAssetId;
  408. AZ::Data::AssetCatalogRequestBus::BroadcastResult(depAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, fileName.c_str(), AZ::Data::s_invalidAssetType, false);
  409. if (!depAssetId.IsValid())
  410. {
  411. AZ_Error("AssetBuilder", false, "GetAssetIdByPath - Asset id should be valid for this asset ( %s ).", fileName.c_str());
  412. return;
  413. }
  414. AZ::Data::AssetInfo depAssetInfo;
  415. AZ::Data::AssetCatalogRequestBus::BroadcastResult(depAssetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, depAssetId);
  416. if (!depAssetInfo.m_assetId.IsValid())
  417. {
  418. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset info should be valid for this asset ( %s ).", depAssetId.ToString<AZStd::string>().c_str());
  419. return;
  420. }
  421. if (depAssetInfo.m_assetId.m_subId != depAssetId.m_subId)
  422. {
  423. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset Info m_subId for %s shoudl be %d.", depAssetId.ToString<AZStd::string>().c_str(), depAssetId.m_subId);
  424. return;
  425. }
  426. AZ::Data::AssetStreamInfo resultInfo = AZ::Data::AssetManager::Instance().GetLoadStreamInfoForAsset(depAssetId, depAssetInfo.m_assetType);
  427. if (!resultInfo.IsValid())
  428. {
  429. AZ_Error("AssetBuilder", false, "GetLoadStreamInfoForAsset - AssetStreamInfo should be valid for this asset ( %s ).", depAssetId.ToString<AZStd::string>().c_str());
  430. return;
  431. }
  432. if(AzFramework::StringFunc::Path::IsRelative(resultInfo.m_streamName.c_str()))
  433. {
  434. AZ_Error("AssetBuilder", false, "GetLoadStreamInfoForAsset - Source AssetStreamInfo streamName %s is relative but should be absolute.", resultInfo.m_streamName.c_str());
  435. return;
  436. }
  437. if (resultInfo.m_streamName != sourcePath)
  438. {
  439. AZ_Error("AssetBuilder", false, "GetLoadStreamInfoForAsset - AssetStreamInfo streamName %s isn't expected path %s.", resultInfo.m_streamName.c_str(), sourcePath.c_str());
  440. return;
  441. }
  442. AZStd::string relativePath;
  443. bool pathResult{ false };
  444. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(pathResult, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath, sourcePath, relativePath);
  445. if (!pathResult)
  446. {
  447. AZ_Error("AssetBuilder", false, "GetRelativeProductPathFromFullSourceOrProductPath - Couldn't get relative product path for ( %s ).", sourcePath.c_str());
  448. return;
  449. }
  450. if (relativePath != fileName)
  451. {
  452. AZ_Error("AssetBuilder", false, R"(GetRelativeProductPathFromFullSourceOrProductPath - relativePath "%s" and fileName "%s" didn't match for ( %s ).)",
  453. relativePath.c_str(), fileName.c_str(), sourcePath.c_str());
  454. return;
  455. }
  456. AZ::Data::AssetId pathAssetId;
  457. AZ::Data::AssetCatalogRequestBus::BroadcastResult(pathAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, fileName.c_str(), AZ::Data::s_invalidAssetType, false);
  458. if (!pathAssetId.IsValid())
  459. {
  460. AZ_Error("AssetBuilder", false, "GetAssetIdByPath - Asset id should be valid for this asset ( %s ).", fileName.c_str());
  461. return;
  462. }
  463. const AZStd::string platformName = ""; // Empty for default
  464. bool gotAssetSystemInfoByIdFromProduct{ false };
  465. AZStd::string sourcePathFromProduct;
  466. AZ::Data::AssetInfo sliceSourceInfo;
  467. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gotAssetSystemInfoByIdFromProduct, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAssetInfoById,
  468. pathAssetId, AZ::AzTypeInfo<AZ::SliceAsset>::Uuid(), platformName, sliceSourceInfo, sourcePathFromProduct);
  469. if (!gotAssetSystemInfoByIdFromProduct)
  470. {
  471. AZ_Error("AssetBuilder", false, "AssetSystemRequest::GetAssetInfoById - Failed to get asset info for ( %s ).", pathAssetId.ToString<AZStd::string>().c_str());
  472. return;
  473. }
  474. if (pathAssetId.m_subId != sliceSourceInfo.m_assetId.m_subId)
  475. {
  476. AZ_Error("AssetBuilder", false, "AssetSystemRequest::GetAssetInfoById - Response SubID should match for ( %s ) Received SubID %d.", pathAssetId.ToString<AZStd::string>().c_str(), sliceSourceInfo.m_assetId.m_subId);
  477. return;
  478. }
  479. if (sliceSourceInfo.m_assetType != AZ::AzTypeInfo<AZ::SliceAsset>::Uuid())
  480. {
  481. AZ_Error("AssetBuilder", false, "AssetSystemRequest::GetAssetInfoById - Lost asset type info for asset ( %s ).", pathAssetId.ToString<AZStd::string>().c_str());
  482. return;
  483. }
  484. // Now validate failure case
  485. AZ::Data::AssetId badAssetId;
  486. badAssetId.m_guid = AZ::Uuid::Create();
  487. badAssetId.m_subId = sliceSourceInfo.m_assetId.m_subId;
  488. gotAssetSystemInfoByIdFromProduct = false;
  489. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gotAssetSystemInfoByIdFromProduct, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAssetInfoById,
  490. badAssetId, AZ::AzTypeInfo<AZ::SliceAsset>::Uuid(), platformName, sliceSourceInfo, sourcePathFromProduct);
  491. if (gotAssetSystemInfoByIdFromProduct)
  492. {
  493. AZ_Error("AssetBuilder", false, "AssetSystemRequest::GetAssetInfoById - Got a valid result for invalid asset ( %s ).", badAssetId.ToString<AZStd::string>().c_str());
  494. return;
  495. }
  496. if (sliceSourceInfo.m_assetId.IsValid())
  497. {
  498. AZ_Error("AssetBuilder", false, R"(AssetSystemRequest::GetAssetInfoById - Response AssetID should not be valid for ( %s ). Received Asset ID "%s")",
  499. badAssetId.ToString<AZStd::string>().c_str(), sliceSourceInfo.m_assetId.ToString<AZStd::string>().c_str());
  500. return;
  501. }
  502. if (badAssetId.m_subId == sliceSourceInfo.m_assetId.m_subId)
  503. {
  504. AZ_Error("AssetBuilder", false, "AssetSystemRequest::GetAssetInfoById - Response SubID should not match for ( %s ) Received SubID %d.",
  505. badAssetId.ToString<AZStd::string>().c_str(), sliceSourceInfo.m_assetId.m_subId);
  506. return;
  507. }
  508. if (sliceSourceInfo.m_assetType != AZ::Data::s_invalidAssetType)
  509. {
  510. AZ_Error("AssetBuilder", false, R"(AssetSystemRequest::GetAssetInfoById - Response AssetType should not be valid for ( %s ). Received AssetType "%s")",
  511. badAssetId.ToString<AZStd::string>().c_str(), sliceSourceInfo.m_assetType.ToString<AZStd::string>().c_str());
  512. return;
  513. }
  514. bool gotSourceInfo{ false };
  515. AZStd::string watchFolder;
  516. AZ::Data::AssetInfo sourcePathAssetInfo;
  517. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gotSourceInfo, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, sourcePath.c_str(), sourcePathAssetInfo, watchFolder);
  518. if (!gotSourceInfo)
  519. {
  520. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Failed to get source info for source ( %s ).", sourcePath.c_str());
  521. return;
  522. }
  523. if (!sourcePathAssetInfo.m_assetId.IsValid())
  524. {
  525. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Asset info should be valid for asset at source path ( %s ).", sourcePath.c_str());
  526. return;
  527. }
  528. if (watchFolder.empty())
  529. {
  530. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Got empty watch folder for asset at source path ( %s ).", sourcePath.c_str());
  531. return;
  532. }
  533. if (AzFramework::StringFunc::Path::IsRelative(watchFolder.c_str()))
  534. {
  535. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourcePath - Got relative path %s for source asset ( %s ).", watchFolder.c_str(), sourcePath.c_str());
  536. return;
  537. }
  538. AZ::Data::AssetId sourceAssetId{ sourcePathAssetInfo.m_assetId };
  539. AZStd::string rootPath;
  540. bool gotResultAssetInfo{ false };
  541. AZ::Data::AssetInfo systemAssetInfo;
  542. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gotResultAssetInfo, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAssetInfoById, sourceAssetId, sourcePathAssetInfo.m_assetType, platformName, systemAssetInfo, rootPath);
  543. if (!gotResultAssetInfo)
  544. {
  545. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Failed to get asset info for ( %s ).", sourceAssetId.ToString<AZStd::string>().c_str());
  546. return;
  547. }
  548. if (!systemAssetInfo.m_assetId.IsValid())
  549. {
  550. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Asset info should be valid for this asset ( %s ).", sourceAssetId.ToString<AZStd::string>().c_str());
  551. return;
  552. }
  553. if (rootPath.empty())
  554. {
  555. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Failed to get root path for ( %s ).", sourceAssetId.ToString<AZStd::string>().c_str());
  556. return;
  557. }
  558. if (watchFolder != rootPath)
  559. {
  560. AZ_Error("AssetBuilder", false, "GetAssetInfoById - Watch folder and root path don't match( %s vs %s ).", watchFolder.c_str(), rootPath.c_str());
  561. return;
  562. }
  563. watchFolder.clear();
  564. AZ::Data::AssetInfo sourcePathAssetInfoByUUID;
  565. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gotSourceInfo, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourceUUID, sourceAssetId.m_guid, sourcePathAssetInfoByUUID, watchFolder);
  566. if (!gotSourceInfo)
  567. {
  568. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourceUUID - Asset info should be valid for asset with uuid ( %s ).", sourceAssetId.m_guid.ToString<AZ::OSString>().c_str());
  569. return;
  570. }
  571. if (!sourcePathAssetInfo.m_assetId.IsValid())
  572. {
  573. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourceUUID - Asset info should be valid for asset with uuid ( %s ).", sourceAssetId.m_guid.ToString<AZ::OSString>().c_str());
  574. return;
  575. }
  576. if (watchFolder.empty())
  577. {
  578. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourceUUID - Got empty watch folder for asset with uuid ( %s ).", sourceAssetId.m_guid.ToString<AZ::OSString>().c_str());
  579. return;
  580. }
  581. if (watchFolder != rootPath)
  582. {
  583. AZ_Error("AssetBuilder", false, "GetSourceInfoBySourceUUID - Watch folder and root path don't match( %s vs %s ).", watchFolder.c_str(), rootPath.c_str());
  584. return;
  585. }
  586. AZ::Data::AssetStreamInfo sourceStreamInfo = AZ::Data::AssetManager::Instance().GetLoadStreamInfoForAsset(sourceAssetId, sourcePathAssetInfo.m_assetType);
  587. if (!resultInfo.IsValid())
  588. {
  589. AZ_Error("AssetBuilder", false, "GetLoadStreamInfoForAsset - Source AssetStreamInfo should be valid for this asset ( %s ).", sourceAssetId.ToString<AZStd::string>().c_str());
  590. return;
  591. }
  592. if (sourceStreamInfo.m_streamName != sourcePath)
  593. {
  594. AZ_Error("AssetBuilder", false, "GetLoadStreamInfoForAsset - Stream name doesn't match source path (%s vs %s ).", sourceStreamInfo.m_streamName.c_str(), sourcePath.c_str());
  595. return;
  596. };
  597. AzFramework::StringFunc::Path::ReplaceExtension(fileName, "slicetestout");
  598. }
  599. // write the file to the cache at (temppath)/filenameOnly
  600. AZStd::string destPath;
  601. AZStd::string fileNameOnly;
  602. AzFramework::StringFunc::Path::GetFullFileName(fileName.c_str(), fileNameOnly); // this removes the path from fileName.
  603. AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), fileNameOnly.c_str(), destPath, true);
  604. // Check if we are cancelled or shutting down before doing intensive processing on this source file
  605. if (jobCancelListener.IsCancelled())
  606. {
  607. AZ_TracePrintf(AssetBuilderSDK::WarningWindow, "Cancel was requested for job %s.\n", request.m_fullPath.c_str());
  608. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
  609. return;
  610. }
  611. if (m_isShuttingDown)
  612. {
  613. AZ_TracePrintf(AssetBuilderSDK::WarningWindow, "Cancelled job %s because shutdown was requested.\n", request.m_fullPath.c_str());
  614. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
  615. return;
  616. }
  617. AZ::IO::HandleType assetfileHandle;
  618. if (!fileIO->Open(destPath.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, assetfileHandle))
  619. {
  620. AZ_Error("AssetBuilder", false, " Unable to open file for writing ( %s ).", destPath.c_str());
  621. return;
  622. }
  623. if (!fileIO->Write(assetfileHandle, outputData.data(), outputData.size()))
  624. {
  625. AZ_Error("AssetBuilder", false, " Unable to write to file data ( %s ).", destPath.c_str());
  626. fileIO->Close(assetfileHandle);
  627. return;
  628. }
  629. fileIO->Close(assetfileHandle);
  630. AssetBuilderSDK::JobProduct jobProduct(fileNameOnly, outputAssetType, outputSubId);
  631. jobProduct.m_dependenciesHandled = true; // This builder has no product dependencies
  632. // once you've filled up the details of the product in jobProduct, add it to the result list:
  633. response.m_outputProducts.push_back(jobProduct);
  634. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
  635. }
  636. void TestAssetBuilderComponent::ShutDown()
  637. {
  638. m_isShuttingDown = true;
  639. }
  640. } // namespace TestAssetBuilder