ProceduralAssetHandler.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 <PrefabGroup/ProceduralAssetHandler.h>
  9. #include <AzCore/Asset/AssetTypeInfoBus.h>
  10. #include <AzCore/std/smart_ptr/make_shared.h>
  11. #include <AzFramework/FileFunc/FileFunc.h>
  12. #include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
  13. #include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
  14. #include <AzToolsFramework/Prefab/Procedural/ProceduralPrefabAsset.h>
  15. #include <AzCore/Serialization/Json/JsonUtils.h>
  16. namespace AZ::Prefab
  17. {
  18. // AssetTypeInfoHandler
  19. class PrefabGroupAssetHandler::AssetTypeInfoHandler final
  20. : public AZ::AssetTypeInfoBus::Handler
  21. {
  22. public:
  23. AZ_CLASS_ALLOCATOR(AssetTypeInfoHandler, AZ::SystemAllocator, 0);
  24. AssetTypeInfoHandler();
  25. ~AssetTypeInfoHandler() override;
  26. AZ::Data::AssetType GetAssetType() const override;
  27. const char* GetAssetTypeDisplayName() const override;
  28. const char* GetGroup() const override;
  29. const char* GetBrowserIcon() const override;
  30. void GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions) override;
  31. };
  32. PrefabGroupAssetHandler::AssetTypeInfoHandler::AssetTypeInfoHandler()
  33. {
  34. AZ::AssetTypeInfoBus::Handler::BusConnect(azrtti_typeid<ProceduralPrefabAsset>());
  35. }
  36. PrefabGroupAssetHandler::AssetTypeInfoHandler::~AssetTypeInfoHandler()
  37. {
  38. AZ::AssetTypeInfoBus::Handler::BusDisconnect(azrtti_typeid<ProceduralPrefabAsset>());
  39. }
  40. AZ::Data::AssetType PrefabGroupAssetHandler::AssetTypeInfoHandler::GetAssetType() const
  41. {
  42. return azrtti_typeid<ProceduralPrefabAsset>();
  43. }
  44. const char* PrefabGroupAssetHandler::AssetTypeInfoHandler::GetAssetTypeDisplayName() const
  45. {
  46. return "Procedural Prefab";
  47. }
  48. const char* PrefabGroupAssetHandler::AssetTypeInfoHandler::GetGroup() const
  49. {
  50. return "Prefab";
  51. }
  52. const char* PrefabGroupAssetHandler::AssetTypeInfoHandler::GetBrowserIcon() const
  53. {
  54. return "Icons/Components/Box.png";
  55. }
  56. void PrefabGroupAssetHandler::AssetTypeInfoHandler::GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions)
  57. {
  58. extensions.push_back(PrefabGroupAssetHandler::s_Extension);
  59. }
  60. // PrefabGroupAssetHandler
  61. AZStd::string_view PrefabGroupAssetHandler::s_Extension{ "procprefab" };
  62. PrefabGroupAssetHandler::PrefabGroupAssetHandler()
  63. {
  64. auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler();
  65. if (assetCatalog)
  66. {
  67. assetCatalog->EnableCatalogForAsset(azrtti_typeid<ProceduralPrefabAsset>());
  68. assetCatalog->AddExtension(s_Extension.data());
  69. }
  70. if (AZ::Data::AssetManager::IsReady())
  71. {
  72. AZ::Data::AssetManager::Instance().RegisterHandler(this, azrtti_typeid<ProceduralPrefabAsset>());
  73. }
  74. m_assetTypeInfoHandler = AZStd::make_shared<AssetTypeInfoHandler>();
  75. }
  76. PrefabGroupAssetHandler::~PrefabGroupAssetHandler()
  77. {
  78. m_assetTypeInfoHandler.reset();
  79. if (AZ::Data::AssetManager::IsReady())
  80. {
  81. AZ::Data::AssetManager::Instance().UnregisterHandler(this);
  82. }
  83. }
  84. AZ::Data::AssetData* PrefabGroupAssetHandler::CreateAsset([[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& type)
  85. {
  86. if (type != azrtti_typeid<ProceduralPrefabAsset>())
  87. {
  88. AZ_Error("prefab", false, "Invalid asset type! Only handle 'ProceduralPrefabAsset'");
  89. return nullptr;
  90. }
  91. return aznew ProceduralPrefabAsset{};
  92. }
  93. void PrefabGroupAssetHandler::DestroyAsset(AZ::Data::AssetData* ptr)
  94. {
  95. // Note: the PrefabLoaderInterface will handle the lifetime of the Prefab Template
  96. delete ptr;
  97. }
  98. void PrefabGroupAssetHandler::GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes)
  99. {
  100. assetTypes.push_back(azrtti_typeid<ProceduralPrefabAsset>());
  101. }
  102. AZ::Data::AssetHandler::LoadResult PrefabGroupAssetHandler::LoadAssetData(
  103. const AZ::Data::Asset<AZ::Data::AssetData>& asset,
  104. AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
  105. [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB)
  106. {
  107. using namespace AzToolsFramework::Prefab;
  108. auto* proceduralPrefabAsset = asset.GetAs<ProceduralPrefabAsset>();
  109. if (!proceduralPrefabAsset)
  110. {
  111. AZ_Error("prefab", false, "This should be a ProceduralPrefabAsset type, as this is the only type we process!");
  112. return LoadResult::Error;
  113. }
  114. AZStd::string buffer;
  115. buffer.resize(stream->GetLoadedSize());
  116. stream->Read(stream->GetLoadedSize(), buffer.data());
  117. auto jsonOutcome = AZ::JsonSerializationUtils::ReadJsonString(buffer);
  118. if (jsonOutcome.IsSuccess() == false)
  119. {
  120. AZ_Error("prefab", false, "Asset JSON failed to compile %s", jsonOutcome.GetError().c_str());
  121. return LoadResult::Error;
  122. }
  123. const auto& jsonDoc = jsonOutcome.GetValue();
  124. if (jsonDoc.IsObject() == false)
  125. {
  126. return LoadResult::Error;
  127. }
  128. if (jsonDoc.FindMember("Source") == jsonDoc.MemberEnd())
  129. {
  130. return LoadResult::Error;
  131. }
  132. const auto& templateName = jsonDoc["Source"];
  133. AZStd::string stringJson;
  134. auto stringOutcome = AZ::JsonSerializationUtils::WriteJsonString(jsonDoc, stringJson);
  135. if (stringOutcome.IsSuccess() == false)
  136. {
  137. AZ_Error("prefab", false, "Could not write to JSON string %s", stringOutcome.GetError().c_str());
  138. return LoadResult::Error;
  139. }
  140. // prepare the template
  141. auto* prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
  142. if (!prefabLoaderInterface)
  143. {
  144. return LoadResult::Error;
  145. }
  146. auto templateId = prefabLoaderInterface->LoadTemplateFromString(stringJson.data(), templateName.GetString());
  147. if (templateId == InvalidTemplateId)
  148. {
  149. return LoadResult::Error;
  150. }
  151. proceduralPrefabAsset->SetTemplateId(templateId);
  152. proceduralPrefabAsset->SetTemplateName(templateName.GetString());
  153. return LoadResult::LoadComplete;
  154. }
  155. AZStd::unique_ptr<PrefabGroupAssetHandler> s_PrefabGroupAssetHandler;
  156. }