AssetBuilderInfo.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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 <native/utilities/AssetBuilderInfo.h>
  9. #include <AzCore/Component/Entity.h>
  10. namespace AssetProcessor
  11. {
  12. #ifdef AZ_PLATFORM_WINDOWS
  13. const char* const s_assetBuilderRelativePath = "AssetBuilder.exe";
  14. #else
  15. const char* const s_assetBuilderRelativePath = "AssetBuilder";
  16. #endif
  17. ExternalModuleAssetBuilderInfo::ExternalModuleAssetBuilderInfo(const QString& modulePath)
  18. : m_builderName(modulePath)
  19. , m_entity(nullptr)
  20. , m_componentDescriptorList()
  21. , m_initializeModuleFunction(nullptr)
  22. , m_moduleRegisterDescriptorsFunction(nullptr)
  23. , m_moduleAddComponentsFunction(nullptr)
  24. , m_uninitializeModuleFunction(nullptr)
  25. , m_library(modulePath)
  26. {
  27. }
  28. const QString& ExternalModuleAssetBuilderInfo::GetName() const
  29. {
  30. return m_builderName;
  31. }
  32. QString ExternalModuleAssetBuilderInfo::GetModuleFullPath() const
  33. {
  34. return m_library.fileName();
  35. }
  36. //! Sanity check for the module's status
  37. bool ExternalModuleAssetBuilderInfo::IsLoaded() const
  38. {
  39. return m_library.isLoaded();
  40. }
  41. void ExternalModuleAssetBuilderInfo::Initialize()
  42. {
  43. AZ_Error(AssetProcessor::ConsoleChannel, IsLoaded(), "External module %s not loaded.", GetName().toUtf8().data());
  44. if (GetAssetBuilderType() == AssetBuilderType::Valid)
  45. {
  46. m_initializeModuleFunction(AZ::Environment::GetInstance());
  47. m_moduleRegisterDescriptorsFunction();
  48. AZStd::string entityName = AZStd::string::format("%s Entity", GetName().toUtf8().data());
  49. m_entity = aznew AZ::Entity(entityName.c_str());
  50. m_moduleAddComponentsFunction(m_entity);
  51. AZ_TracePrintf(AssetProcessor::DebugChannel, "Init Entity %s", GetName().toUtf8().data());
  52. m_entity->Init();
  53. //Activate all the components
  54. m_entity->Activate();
  55. }
  56. }
  57. void ExternalModuleAssetBuilderInfo::UnInitialize()
  58. {
  59. AZ_Error(AssetProcessor::ConsoleChannel, IsLoaded(), "External module %s not loaded.", GetName().toUtf8().data());
  60. AZ_TracePrintf(AssetProcessor::DebugChannel, "Uninitializing builder: %s\n", GetModuleFullPath().toUtf8().data());
  61. if (m_entity)
  62. {
  63. m_entity->Deactivate();
  64. delete m_entity;
  65. m_entity = nullptr;
  66. }
  67. for (AZ::ComponentDescriptor* componentDesc : m_componentDescriptorList)
  68. {
  69. componentDesc->ReleaseDescriptor();
  70. }
  71. m_componentDescriptorList.clear();
  72. for (const AZ::Uuid& builderDescID : m_registeredBuilderDescriptorIDs)
  73. {
  74. AssetBuilderRegistrationBus::Broadcast(&AssetBuilderRegistrationBusTraits::UnRegisterBuilderDescriptor, builderDescID);
  75. }
  76. m_registeredBuilderDescriptorIDs.clear();
  77. m_uninitializeModuleFunction();
  78. if (IsLoaded())
  79. {
  80. m_library.unload();
  81. }
  82. }
  83. AssetBuilderType ExternalModuleAssetBuilderInfo::GetAssetBuilderType()
  84. {
  85. QStringList missingFunctionsList;
  86. ResolveModuleFunction<QFunctionPointer>("IsAssetBuilder", missingFunctionsList);
  87. InitializeModuleFunction initializeModuleAddress = ResolveModuleFunction<InitializeModuleFunction>("InitializeModule", missingFunctionsList);
  88. ModuleRegisterDescriptorsFunction moduleRegisterDescriptorsAddress = ResolveModuleFunction<ModuleRegisterDescriptorsFunction>("ModuleRegisterDescriptors", missingFunctionsList);
  89. ModuleAddComponentsFunction moduleAddComponentsAddress = ResolveModuleFunction<ModuleAddComponentsFunction>("ModuleAddComponents", missingFunctionsList);
  90. UninitializeModuleFunction uninitializeModuleAddress = ResolveModuleFunction<UninitializeModuleFunction>("UninitializeModule", missingFunctionsList);
  91. if (missingFunctionsList.size() == 0)
  92. {
  93. //if we are here then it is a builder
  94. m_initializeModuleFunction = initializeModuleAddress;
  95. m_moduleRegisterDescriptorsFunction = moduleRegisterDescriptorsAddress;
  96. m_moduleAddComponentsFunction = moduleAddComponentsAddress;
  97. m_uninitializeModuleFunction = uninitializeModuleAddress;
  98. return AssetBuilderType::Valid;
  99. }
  100. else if (missingFunctionsList.size() > 0 && missingFunctionsList.contains("IsAssetBuilder"))
  101. {
  102. // This DLL is not a builder and should be ignored.
  103. return AssetBuilderType::None;
  104. }
  105. else
  106. {
  107. // This is supposed to be a builder but is invalid
  108. QString errorMessage = QString("Builder library %1 is missing one or more exported functions: %2").arg(QString(GetName()), missingFunctionsList.join(','));
  109. AZ_TracePrintf(AssetBuilderSDK::ErrorWindow, "One or more builder functions is missing in the library: %s\n", errorMessage.toUtf8().data());
  110. return AssetBuilderType::Invalid;
  111. }
  112. }
  113. AssetBuilderType ExternalModuleAssetBuilderInfo::Load()
  114. {
  115. if (IsLoaded())
  116. {
  117. // This builder is already loaded - ignore the duplicate
  118. AZ_Warning(AssetProcessor::ConsoleChannel, false, "External module %s already loaded.", GetName().toUtf8().data());
  119. return AssetBuilderType::None;
  120. }
  121. if (!m_library.load())
  122. {
  123. // Invalid builder - unable to load
  124. AZ_TracePrintf(AssetProcessor::DebugChannel, "Unable to load builder : %s\n", GetName().toUtf8().data());
  125. return AssetBuilderType::Invalid;
  126. }
  127. return GetAssetBuilderType();
  128. }
  129. void ExternalModuleAssetBuilderInfo::RegisterBuilderDesc(const AZ::Uuid& builderDescID)
  130. {
  131. if (m_registeredBuilderDescriptorIDs.find(builderDescID) != m_registeredBuilderDescriptorIDs.end())
  132. {
  133. AZ_Warning(AssetBuilderSDK::InfoWindow,
  134. false,
  135. "Builder description id '%s' already registered to external builder module %s",
  136. builderDescID.ToString<AZStd::string>().c_str(),
  137. GetName().toUtf8().data());
  138. return;
  139. }
  140. m_registeredBuilderDescriptorIDs.insert(builderDescID);
  141. }
  142. void ExternalModuleAssetBuilderInfo::RegisterComponentDesc(AZ::ComponentDescriptor* descriptor)
  143. {
  144. m_componentDescriptorList.push_back(descriptor);
  145. }
  146. template<typename T>
  147. T ExternalModuleAssetBuilderInfo::ResolveModuleFunction(const char* functionName, QStringList& missingFunctionsList)
  148. {
  149. T functionAddr = reinterpret_cast<T>(m_library.resolve(functionName));
  150. if (!functionAddr)
  151. {
  152. missingFunctionsList.append(QString(functionName));
  153. }
  154. return functionAddr;
  155. }
  156. }