SceneProcessingConfigSystemComponent.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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/Module/DynamicModuleHandle.h>
  9. #include <AzCore/RTTI/BehaviorContext.h>
  10. #include <AzCore/Serialization/EditContext.h>
  11. #include <Source/SceneProcessingModule.h>
  12. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  13. #include <AzCore/Interface/Interface.h>
  14. #include <AzCore/IO/FileIO.h>
  15. #include <AzCore/std/string/regex.h>
  16. #include <SceneAPI/SceneCore/DataTypes/GraphData/IAnimationData.h>
  17. #include <Config/SettingsObjects/NodeSoftNameSetting.h>
  18. #include <Config/SettingsObjects/FileSoftNameSetting.h>
  19. #include <Config/Components/SceneProcessingConfigSystemComponent.h>
  20. #include <Config/Widgets/GraphTypeSelector.h>
  21. namespace AZ
  22. {
  23. namespace SceneProcessingConfig
  24. {
  25. void SceneProcessingConfigSystemComponentSerializationEvents::OnWriteBegin(void* classPtr)
  26. {
  27. SceneProcessingConfigSystemComponent* component = reinterpret_cast<SceneProcessingConfigSystemComponent*>(classPtr);
  28. component->Clear();
  29. }
  30. SceneProcessingConfigSystemComponent::SceneProcessingConfigSystemComponent()
  31. {
  32. using namespace AZ::SceneAPI::SceneCore;
  33. ActivateSceneModule(SceneProcessing::s_sceneCoreModule);
  34. ActivateSceneModule(SceneProcessing::s_sceneDataModule);
  35. ActivateSceneModule(SceneProcessing::s_sceneBuilderModule);
  36. PopulateSoftNameSettings();
  37. m_UseCustomNormals = true;
  38. }
  39. void SceneProcessingConfigSystemComponent::PopulateSoftNameSettings()
  40. {
  41. bool softNameSettingsFound = false;
  42. auto settingsRegistry = AZ::SettingsRegistry::Get();
  43. if (settingsRegistry)
  44. {
  45. softNameSettingsFound =
  46. AddSoftNameSettingsFromSettingsRegistry<NodeSoftNameSetting>(settingsRegistry, AssetProcessorDefaultNodeSoftNameSettingsKey);
  47. softNameSettingsFound = softNameSettingsFound &&
  48. AddSoftNameSettingsFromSettingsRegistry<FileSoftNameSetting>(settingsRegistry, AssetProcessorDefaultFileSoftNameSettingsKey);
  49. }
  50. AZ_Warning("SceneProcessing", softNameSettingsFound,
  51. "No soft name settings are found from the settings registry. If you want to customize the soft naming conventions, "
  52. "Please override the default values using the Project User Registry or the global machine registry (~/.o3de/Registry/) "
  53. "instead of modifying the default Gems/SceneSettings/Registry/SoftNameSettings.setreg.");
  54. }
  55. template<class SoftNameSettingsType>
  56. bool SceneProcessingConfigSystemComponent::AddSoftNameSettingsFromSettingsRegistry(
  57. AZ::SettingsRegistryInterface* settingsRegistry, AZStd::string_view settingRegistryKey)
  58. {
  59. AZStd::vector<AZStd::unique_ptr<SoftNameSettingsType>> softNameSettings;
  60. if (!settingsRegistry->GetObject(softNameSettings, settingRegistryKey))
  61. {
  62. return false;
  63. }
  64. for (AZStd::unique_ptr<SoftNameSettingsType>& softNameSetting : softNameSettings)
  65. {
  66. AddSoftName(AZStd::move(softNameSetting));
  67. }
  68. return true;
  69. }
  70. void SceneProcessingConfigSystemComponent::Activate()
  71. {
  72. SceneProcessingConfigRequestBus::Handler::BusConnect();
  73. AZ::SceneAPI::Events::AssetImportRequestBus::Handler::BusConnect();
  74. AZ::SceneAPI::Events::ScriptConfigEventBus::Handler::BusConnect();
  75. SceneProcessingConfig::GraphTypeSelector::Register();
  76. LoadScriptSettings();
  77. }
  78. void SceneProcessingConfigSystemComponent::Deactivate()
  79. {
  80. SceneProcessingConfig::GraphTypeSelector::Unregister();
  81. AZ::SceneAPI::Events::ScriptConfigEventBus::Handler::BusDisconnect();
  82. AZ::SceneAPI::Events::AssetImportRequestBus::Handler::BusDisconnect();
  83. SceneProcessingConfigRequestBus::Handler::BusDisconnect();
  84. }
  85. SceneProcessingConfigSystemComponent::~SceneProcessingConfigSystemComponent()
  86. {
  87. Clear();
  88. DeactivateSceneModule(SceneProcessing::s_sceneBuilderModule);
  89. DeactivateSceneModule(SceneProcessing::s_sceneDataModule);
  90. DeactivateSceneModule(SceneProcessing::s_sceneCoreModule);
  91. }
  92. void SceneProcessingConfigSystemComponent::Clear()
  93. {
  94. m_softNames.clear();
  95. m_softNames.shrink_to_fit();
  96. m_scriptConfigList.clear();
  97. m_scriptConfigList.shrink_to_fit();
  98. m_UseCustomNormals = true;
  99. }
  100. const AZStd::vector<AZStd::unique_ptr<SoftNameSetting>>* SceneProcessingConfigSystemComponent::GetSoftNames()
  101. {
  102. return &m_softNames;
  103. }
  104. bool SceneProcessingConfigSystemComponent::AddSoftName(AZStd::unique_ptr<SoftNameSetting> newSoftname)
  105. {
  106. bool success = true;
  107. Crc32 newHash = newSoftname->GetVirtualTypeHash();
  108. for (AZStd::unique_ptr<SoftNameSetting>& softName : m_softNames)
  109. {
  110. //First check whether an item with the same CRC value already exists.
  111. if (newHash == softName->GetVirtualTypeHash() && softName->GetTypeId() == newSoftname->GetTypeId())
  112. {
  113. AZ_Error("SceneProcessing", false, "newSoftname(%s) and existing softName(%s) have the same hash: 0x%X",
  114. newSoftname->GetVirtualType().c_str(), softName->GetVirtualType().c_str(), newHash);
  115. success = false;
  116. break;
  117. }
  118. }
  119. if (success)
  120. {
  121. m_softNames.push_back(AZStd::move(newSoftname));
  122. }
  123. return success;
  124. }
  125. bool SceneProcessingConfigSystemComponent::AddNodeSoftName(const char* pattern,
  126. SceneAPI::SceneCore::PatternMatcher::MatchApproach approach,
  127. const char* virtualType, bool includeChildren)
  128. {
  129. AZStd::unique_ptr<SoftNameSetting> newSoftname = AZStd::make_unique<NodeSoftNameSetting>(pattern, approach, virtualType, includeChildren);
  130. return AddSoftName(AZStd::move(newSoftname));
  131. }
  132. bool SceneProcessingConfigSystemComponent::AddFileSoftName(const char* pattern,
  133. SceneAPI::SceneCore::PatternMatcher::MatchApproach approach,
  134. const char* virtualType, bool inclusive, const AZStd::string& graphObjectTypeName)
  135. {
  136. AZStd::unique_ptr<SoftNameSetting> newSoftname = AZStd::make_unique<FileSoftNameSetting>(
  137. pattern, approach, virtualType, inclusive,
  138. std::initializer_list<FileSoftNameSetting::GraphType>{FileSoftNameSetting::GraphType(graphObjectTypeName)});
  139. return AddSoftName(AZStd::move(newSoftname));
  140. }
  141. void SceneProcessingConfigSystemComponent::LoadScriptSettings()
  142. {
  143. auto* registry = AZ::SettingsRegistry::Get();
  144. AZ_Assert(registry, "AZ::SettingsRegistryInterface should already be active!");
  145. auto* fileIO = AZ::IO::FileIOBase::GetInstance();
  146. AZ_Assert(fileIO, "AZ::IO::FileIOBase should already be active!");
  147. using VisitArgs = AZ::SettingsRegistryInterface::VisitArgs;
  148. using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse;
  149. using VisitAction = AZ::SettingsRegistryInterface::VisitAction;
  150. auto vistor = [this, registry, fileIO](const VisitArgs& args, VisitAction action) -> VisitResponse
  151. {
  152. if (action == VisitAction::Begin)
  153. {
  154. return VisitResponse::Continue;
  155. }
  156. else if (action == VisitAction::End)
  157. {
  158. return VisitResponse::Done;
  159. }
  160. else if (args.m_type != AZ::SettingsRegistryInterface::Type::String)
  161. {
  162. return VisitResponse::Continue;
  163. }
  164. AZStd::string value;
  165. registry->Get(value, args.m_jsonKeyPath);
  166. auto fullPath = fileIO->ResolvePath(value.c_str());
  167. if (!fullPath)
  168. {
  169. AZ_Warning("SceneProcessing", false,
  170. "FileIO could not resolve default builder script path %s for pattern key " AZ_STRING_FORMAT,
  171. value.c_str(),
  172. AZ_STRING_ARG(args.m_jsonKeyPath));
  173. return VisitResponse::Continue;
  174. }
  175. else if (!fileIO->Exists(fullPath->c_str()))
  176. {
  177. AZ_Warning("SceneProcessing", false,
  178. "The full script path %s does not exist when resolving default scene building script name %s for key " AZ_STRING_FORMAT,
  179. fullPath->c_str(),
  180. value.c_str(),
  181. AZ_STRING_ARG(args.m_jsonKeyPath));
  182. return VisitResponse::Continue;
  183. }
  184. AZ::SceneAPI::Events::ScriptConfig scriptConfig;
  185. scriptConfig.m_pattern = args.m_fieldName;
  186. scriptConfig.m_scriptPath = AZStd::move(fullPath.value());
  187. m_scriptConfigList.emplace_back(scriptConfig);
  188. return VisitResponse::Continue;
  189. };
  190. registry->Visit(vistor, AssetProcessorDefaultScriptsKey);
  191. }
  192. void SceneProcessingConfigSystemComponent::GetScriptConfigList(AZStd::vector<SceneAPI::Events::ScriptConfig>& scriptConfigList) const
  193. {
  194. scriptConfigList = m_scriptConfigList;
  195. }
  196. AZStd::optional<SceneAPI::Events::ScriptConfig> SceneProcessingConfigSystemComponent::MatchesScriptConfig(const AZStd::string& sourceFile) const
  197. {
  198. for (const auto& scriptConfig : m_scriptConfigList)
  199. {
  200. AZStd::regex comparer(scriptConfig.m_pattern, AZStd::regex::extended);
  201. AZStd::smatch match;
  202. if (AZStd::regex_search(sourceFile, match, comparer))
  203. {
  204. return AZStd::make_optional(scriptConfig);
  205. }
  206. }
  207. return AZStd::nullopt;
  208. }
  209. void SceneProcessingConfigSystemComponent::AreCustomNormalsUsed(bool &value)
  210. {
  211. value = m_UseCustomNormals;
  212. }
  213. void SceneProcessingConfigSystemComponent::Reflect(AZ::ReflectContext* context)
  214. {
  215. ReflectSceneModule(context, SceneProcessing::s_sceneCoreModule);
  216. ReflectSceneModule(context, SceneProcessing::s_sceneDataModule);
  217. ReflectSceneModule(context, SceneProcessing::s_sceneBuilderModule);
  218. SoftNameSetting::Reflect(context);
  219. NodeSoftNameSetting::Reflect(context);
  220. FileSoftNameSetting::Reflect(context);
  221. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  222. if (serialize)
  223. {
  224. serialize->Class<SceneProcessingConfigSystemComponent, AZ::Component>()
  225. ->Version(3)
  226. ->EventHandler<SceneProcessingConfigSystemComponentSerializationEvents>()
  227. ->Field("softNames", &SceneProcessingConfigSystemComponent::m_softNames)
  228. ->Field("useCustomNormals", &SceneProcessingConfigSystemComponent::m_UseCustomNormals);
  229. if (AZ::EditContext* ec = serialize->GetEditContext())
  230. {
  231. ec->Class<SceneProcessingConfigSystemComponent>("Scene Processing Config", "Use this component to fine tune the defaults for processing of scene files like FBX.")
  232. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  233. ->Attribute(AZ::Edit::Attributes::Category, "Assets")
  234. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
  235. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  236. ->DataElement(AZ::Edit::UIHandlers::Default, &SceneProcessingConfigSystemComponent::m_softNames,
  237. "Soft naming conventions", "Update the naming conventions to suit your project.")
  238. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  239. ->DataElement(AZ::Edit::UIHandlers::Default, &SceneProcessingConfigSystemComponent::m_UseCustomNormals,
  240. "Use Custom Normals", "When enabled, Open 3D Engine will use the DCC assets custom or tangent space normals. When disabled, the normals will be averaged. This setting can be overridden on an individual scene file's asset settings.")
  241. ->Attribute(AZ::Edit::Attributes::AutoExpand, false);
  242. }
  243. }
  244. }
  245. void SceneProcessingConfigSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  246. {
  247. provided.push_back(AZ_CRC_CE("SceneProcessingConfigService"));
  248. }
  249. void SceneProcessingConfigSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  250. {
  251. incompatible.push_back(AZ_CRC_CE("SceneProcessingConfigService"));
  252. }
  253. void SceneProcessingConfigSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  254. {
  255. AZ_UNUSED(required);
  256. }
  257. void SceneProcessingConfigSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
  258. {
  259. AZ_UNUSED(dependent);
  260. }
  261. void SceneProcessingConfigSystemComponent::ReflectSceneModule(AZ::ReflectContext* context,
  262. const AZStd::unique_ptr<AZ::DynamicModuleHandle>& module)
  263. {
  264. using ReflectFunc = void(*)(AZ::SerializeContext*);
  265. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  266. if (serialize)
  267. {
  268. if (module)
  269. {
  270. ReflectFunc reflect = module->GetFunction<ReflectFunc>("Reflect");
  271. if (reflect)
  272. {
  273. (*reflect)(serialize);
  274. }
  275. }
  276. }
  277. using ReflectBehaviorFunc = void(*)(AZ::BehaviorContext*);
  278. AZ::BehaviorContext* behavior = azrtti_cast<AZ::BehaviorContext*>(context);
  279. if (behavior)
  280. {
  281. if (module)
  282. {
  283. ReflectBehaviorFunc reflectBehavior = module->GetFunction<ReflectBehaviorFunc>("ReflectBehavior");
  284. if (reflectBehavior)
  285. {
  286. (*reflectBehavior)(behavior);
  287. }
  288. }
  289. }
  290. }
  291. void SceneProcessingConfigSystemComponent::ActivateSceneModule(const AZStd::unique_ptr<AZ::DynamicModuleHandle>& module)
  292. {
  293. using ActivateFunc = void(*)();
  294. if (module)
  295. {
  296. ActivateFunc activate = module->GetFunction<ActivateFunc>("Activate");
  297. if (activate)
  298. {
  299. (*activate)();
  300. }
  301. }
  302. }
  303. void SceneProcessingConfigSystemComponent::DeactivateSceneModule(const AZStd::unique_ptr<AZ::DynamicModuleHandle>& module)
  304. {
  305. using DeactivateFunc = void(*)();
  306. if (module)
  307. {
  308. DeactivateFunc deactivate = module->GetFunction<DeactivateFunc>("Deactivate");
  309. if (deactivate)
  310. {
  311. (*deactivate)();
  312. }
  313. }
  314. }
  315. } // namespace SceneProcessingConfig
  316. } // namespace AZ