TranslationAsset.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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 <AzCore/PlatformIncl.h>
  9. #include <AzCore/Component/ComponentApplicationBus.h>
  10. #include <AzCore/IO/FileIO.h>
  11. #include <AzCore/IO/SystemFile.h>
  12. #include <AzCore/JSON/document.h>
  13. #include <AzCore/JSON/error/en.h>
  14. #include <AzCore/JSON/error/error.h>
  15. #include <AzCore/JSON/prettywriter.h>
  16. #include <AzCore/JSON/rapidjson.h>
  17. #include <AzCore/Serialization/SerializeContext.h>
  18. #include <AzCore/Serialization/EditContextConstants.inl>
  19. #include <AzCore/Serialization/EditContext.h>
  20. #include <AzCore/Serialization/Json/RegistrationContext.h>
  21. #include <AzCore/Serialization/Json/JsonSerialization.h>
  22. #include <AzCore/Serialization/Json/BasicContainerSerializer.h>
  23. #include <AzFramework/FileFunc/FileFunc.h>
  24. #include <Translation/TranslationAsset.h>
  25. #include <Translation/TranslationBus.h>
  26. #include <Translation/TranslationSerializer.h>
  27. namespace GraphCanvas
  28. {
  29. void TranslationAsset::Reflect(AZ::ReflectContext* context)
  30. {
  31. if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
  32. {
  33. jsonContext->Serializer<TranslationFormatSerializer>()->HandlesType<TranslationFormat>();
  34. }
  35. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  36. {
  37. serializeContext->Class<TranslationFormat>()
  38. ->Version(1)
  39. ->Field("m_database", &TranslationFormat::m_database)
  40. ;
  41. serializeContext->Class<TranslationAsset>()
  42. ->Version(0)
  43. ;
  44. }
  45. }
  46. TranslationAsset::TranslationAsset(const AZ::Data::AssetId& assetId /*= AZ::Data::AssetId()*/, AZ::Data::AssetData::AssetStatus status /*= AZ::Data::AssetData::AssetStatus::NotLoaded*/)
  47. : AZ::Data::AssetData(assetId, status)
  48. {
  49. }
  50. TranslationAssetHandler::TranslationAssetHandler()
  51. {
  52. AZ::SerializeContext* serializeContext = nullptr;
  53. AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
  54. AZ::JsonRegistrationContext* jsonRegistrationContext;
  55. AZ::ComponentApplicationBus::BroadcastResult(jsonRegistrationContext, &AZ::ComponentApplicationBus::Events::GetJsonRegistrationContext);
  56. auto reportCallback = [](AZStd::string_view /*message*/, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view /*target*/)->
  57. AZ::JsonSerializationResult::ResultCode
  58. {
  59. return result;
  60. };
  61. m_serializationSettings = AZStd::make_unique<AZ::JsonSerializerSettings>();
  62. m_serializationSettings->m_serializeContext = serializeContext;
  63. m_serializationSettings->m_registrationContext = jsonRegistrationContext;
  64. m_serializationSettings->m_reporting = reportCallback;
  65. m_deserializationSettings = AZStd::make_unique<AZ::JsonDeserializerSettings>();
  66. m_deserializationSettings->m_serializeContext = serializeContext;
  67. m_deserializationSettings->m_registrationContext = jsonRegistrationContext;
  68. m_deserializationSettings->m_reporting = reportCallback;
  69. m_jsonSerializationContext = AZStd::make_unique<AZ::JsonSerializerContext>(*m_serializationSettings, m_jsonAllocator);
  70. m_jsonDeserializationContext = AZStd::make_unique<AZ::JsonDeserializerContext>(*m_deserializationSettings);
  71. m_serializer = AZStd::make_unique<TranslationFormatSerializer>();
  72. }
  73. TranslationAssetHandler::~TranslationAssetHandler()
  74. {
  75. Unregister();
  76. }
  77. AZ::Data::AssetPtr TranslationAssetHandler::CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type)
  78. {
  79. AZ_UNUSED(type);
  80. AZ_Assert(type == GetAssetType(), "Invalid asset type! TranslationAssetHandler will handle only 'TranslationAsset'");
  81. // Look up the asset path to ensure it's actually a behavior tree library.
  82. if (!CanHandleAsset(id))
  83. {
  84. return nullptr;
  85. }
  86. return aznew TranslationAsset;
  87. }
  88. AZ::Data::AssetType TranslationAssetHandler::GetAssetType() const
  89. {
  90. return AZ::AzTypeInfo<TranslationAsset>::Uuid();
  91. }
  92. const char* TranslationAssetHandler::GetAssetTypeDisplayName() const
  93. {
  94. return "Names";
  95. }
  96. const char* TranslationAssetHandler::GetGroup() const
  97. {
  98. return "Names";
  99. }
  100. const char* TranslationAssetHandler::GetBrowserIcon() const
  101. {
  102. return "Icons/AssetBrowser/Default_16.svg";
  103. }
  104. AZ::Uuid TranslationAssetHandler::GetComponentTypeId() const
  105. {
  106. return AZ::Uuid::CreateNull();
  107. }
  108. void TranslationAssetHandler::GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions)
  109. {
  110. extensions.push_back("names");
  111. }
  112. AZ::Data::AssetHandler::LoadResult TranslationAssetHandler::LoadAssetData(
  113. [[maybe_unused]] const AZ::Data::Asset<AZ::Data::AssetData>& asset, AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
  114. const AZ::Data::AssetFilterCB&)
  115. {
  116. AZ::Data::AssetHandler::LoadResult result = AZ::Data::AssetHandler::LoadResult::LoadComplete;
  117. auto sizeBytes = stream->GetLoadedSize();
  118. AZStd::unique_ptr<char[]> buffer = AZStd::make_unique<char[]>(sizeBytes + 1);
  119. if (stream->Read(sizeBytes, buffer.get()))
  120. {
  121. buffer[sizeBytes] = '\0';
  122. rapidjson::Document document;
  123. bool failure = false;
  124. if (document.Parse(buffer.get()).HasParseError())
  125. {
  126. failure = true;
  127. AZStd::string errorStr = AZStd::string::format(
  128. "Error parsing JSON contents (offset %zu): %s", document.GetErrorOffset(),
  129. rapidjson::GetParseError_En(document.GetParseError()));
  130. AZ_Error("TranslationDatabase", false, "Parse error in %s (%s)", asset.GetHint().c_str(), errorStr.c_str());
  131. result = AssetHandler::LoadResult::Error;
  132. }
  133. else
  134. {
  135. const rapidjson::Value& rootValue = document.GetObject();
  136. if (!document.IsObject())
  137. {
  138. failure = true;
  139. }
  140. if (!failure)
  141. {
  142. using namespace AZ::JsonSerializationResult;
  143. TranslationFormat translationFormat;
  144. ResultCode serializerResult = m_serializer->Load(
  145. &translationFormat, azrtti_typeid<TranslationFormat>(), rootValue, *m_jsonDeserializationContext);
  146. if (serializerResult.GetOutcome() == Outcomes::Success)
  147. {
  148. // Add the newly loaded translation data into the global database
  149. bool warnings = false;
  150. TranslationRequestBus::BroadcastResult(warnings, &TranslationRequests::Add, translationFormat);
  151. if (warnings)
  152. {
  153. AZ_Warning("TranslationAsset", false, "Unable to add translation data to database for file: %s", asset.GetHint().c_str());
  154. }
  155. }
  156. else
  157. {
  158. AZ_Warning("TranslationAsset", false, "Serialization of the TranslationFormat failed for: %s", asset.GetHint().c_str());
  159. }
  160. }
  161. }
  162. }
  163. return result;
  164. }
  165. void TranslationAssetHandler::DestroyAsset(AZ::Data::AssetPtr ptr)
  166. {
  167. delete ptr;
  168. }
  169. void TranslationAssetHandler::GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes)
  170. {
  171. assetTypes.push_back(GetAssetType());
  172. }
  173. void TranslationAssetHandler::Register()
  174. {
  175. AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!");
  176. auto assetType = GetAssetType();
  177. AZ::Data::AssetManager::Instance().RegisterHandler(this, assetType);
  178. // Use AssetCatalog service to register ScriptEvent asset type and extension
  179. AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddAssetType, assetType);
  180. AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnableCatalogForAsset, assetType);
  181. AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, TranslationAsset::GetFileFilter());
  182. AZ::AssetTypeInfoBus::MultiHandler::BusConnect(assetType);
  183. }
  184. void TranslationAssetHandler::Unregister()
  185. {
  186. AZ::AssetTypeInfoBus::MultiHandler::BusDisconnect();
  187. m_serializer.reset();
  188. if (AZ::Data::AssetManager::IsReady())
  189. {
  190. AZ::Data::AssetManager::Instance().UnregisterHandler(this);
  191. }
  192. }
  193. bool TranslationAssetHandler::CanHandleAsset(const AZ::Data::AssetId&) const
  194. {
  195. return true;
  196. }
  197. }