MeshAdvancedRule.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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/Serialization/SerializeContext.h>
  9. #include <AzCore/std/algorithm.h>
  10. #include <AzCore/std/smart_ptr/make_shared.h>
  11. #include <AzToolsFramework/Debug/TraceContext.h>
  12. #include <SceneAPI/SceneCore/Containers/Scene.h>
  13. #include <SceneAPI/SceneCore/Containers/SceneGraph.h>
  14. #include <SceneAPI/SceneCore/Containers/SceneManifest.h>
  15. #include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
  16. #include <SceneAPI/SceneCore/Utilities/Reporting.h>
  17. #include <SceneAPI/SceneCore/DataTypes/Groups/IMeshGroup.h>
  18. #include <SceneAPI/SceneCore/DataTypes/Groups/ISceneNodeGroup.h>
  19. #include <SceneAPI/SceneCore/DataTypes/Groups/ISkinGroup.h>
  20. #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexUVData.h>
  21. #include <SceneAPI/SceneCore/DataTypes/GraphData/IMeshVertexColorData.h>
  22. #include <SceneAPI/SceneData/Rules/StaticMeshAdvancedRule.h>
  23. #include <SceneAPI/SceneData/Rules/SkinMeshAdvancedRule.h>
  24. #include <SceneAPI/SceneData/Behaviors/MeshAdvancedRule.h>
  25. namespace AZ
  26. {
  27. namespace SceneAPI
  28. {
  29. namespace Behaviors
  30. {
  31. void MeshAdvancedRule::Activate()
  32. {
  33. Events::ManifestMetaInfoBus::Handler::BusConnect();
  34. Events::AssetImportRequestBus::Handler::BusConnect();
  35. }
  36. void MeshAdvancedRule::Deactivate()
  37. {
  38. Events::AssetImportRequestBus::Handler::BusDisconnect();
  39. Events::ManifestMetaInfoBus::Handler::BusDisconnect();
  40. }
  41. void MeshAdvancedRule::Reflect(ReflectContext* context)
  42. {
  43. SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
  44. if (serializeContext)
  45. {
  46. serializeContext->Class<MeshAdvancedRule, BehaviorComponent>()->Version(1);
  47. }
  48. }
  49. void MeshAdvancedRule::InitializeObject(const Containers::Scene& scene, DataTypes::IManifestObject& target)
  50. {
  51. AZStd::string firstVertexColorStream = GetFirstVertexColorStream(scene);
  52. if (target.RTTI_IsTypeOf(DataTypes::ISceneNodeGroup::TYPEINFO_Uuid()))
  53. {
  54. if (!firstVertexColorStream.empty())
  55. {
  56. if (target.RTTI_IsTypeOf(DataTypes::ISkinGroup::TYPEINFO_Uuid()))
  57. {
  58. AZStd::shared_ptr<SceneData::SkinMeshAdvancedRule> rule = AZStd::make_shared<SceneData::SkinMeshAdvancedRule>();
  59. rule->SetVertexColorStreamName(firstVertexColorStream.empty() ?
  60. DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream));
  61. DataTypes::ISceneNodeGroup* sceneNodeGroup = azrtti_cast<DataTypes::ISceneNodeGroup*>(&target);
  62. sceneNodeGroup->GetRuleContainer().AddRule(AZStd::move(rule));
  63. }
  64. else if (target.RTTI_IsTypeOf(DataTypes::IMeshGroup::TYPEINFO_Uuid()))
  65. {
  66. AZStd::shared_ptr<SceneData::StaticMeshAdvancedRule> rule = AZStd::make_shared<SceneData::StaticMeshAdvancedRule>();
  67. rule->SetVertexColorStreamName(firstVertexColorStream.empty() ?
  68. DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream));
  69. DataTypes::ISceneNodeGroup* sceneNodeGroup = azrtti_cast<DataTypes::ISceneNodeGroup*>(&target);
  70. sceneNodeGroup->GetRuleContainer().AddRule(AZStd::move(rule));
  71. }
  72. }
  73. }
  74. else if (target.RTTI_IsTypeOf(SceneData::StaticMeshAdvancedRule::TYPEINFO_Uuid()))
  75. {
  76. SceneData::StaticMeshAdvancedRule* rule = azrtti_cast<SceneData::StaticMeshAdvancedRule*>(&target);
  77. rule->SetVertexColorStreamName(firstVertexColorStream.empty() ?
  78. DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream));
  79. }
  80. else if (target.RTTI_IsTypeOf(SceneData::SkinMeshAdvancedRule::TYPEINFO_Uuid()))
  81. {
  82. SceneData::SkinMeshAdvancedRule* rule = azrtti_cast<SceneData::SkinMeshAdvancedRule*>(&target);
  83. rule->SetVertexColorStreamName(firstVertexColorStream.empty() ?
  84. DataTypes::s_advancedDisabledString : AZStd::move(firstVertexColorStream));
  85. }
  86. }
  87. Events::ProcessingResult MeshAdvancedRule::UpdateManifest(Containers::Scene& scene, ManifestAction action,
  88. RequestingApplication requester)
  89. {
  90. AZ_UNUSED(requester);
  91. if (action == ManifestAction::Update)
  92. {
  93. UpdateMeshAdvancedRules(scene);
  94. return Events::ProcessingResult::Success;
  95. }
  96. else
  97. {
  98. return Events::ProcessingResult::Ignored;
  99. }
  100. }
  101. void MeshAdvancedRule::UpdateMeshAdvancedRules(Containers::Scene& scene) const
  102. {
  103. Containers::SceneManifest& manifest = scene.GetManifest();
  104. auto valueStorage = manifest.GetValueStorage();
  105. auto view = Containers::MakeDerivedFilterView<DataTypes::ISceneNodeGroup>(valueStorage);
  106. for (DataTypes::ISceneNodeGroup& group : view)
  107. {
  108. AZ_TraceContext("Scene node group", group.GetName());
  109. Containers::RuleContainer& rules = group.GetRuleContainer();
  110. const size_t ruleCount = rules.GetRuleCount();
  111. // The Mesh Advanced Rules were previously invalidly applied to any group containing a vertex color stream, and should be cleaned up if unnecessarily added to existing data.
  112. // We use a list to track indices of rules to remove in a separate pass since the RuleContainer does not have direct iterator access.
  113. bool isValidGroupType = group.RTTI_IsTypeOf(DataTypes::IMeshGroup::TYPEINFO_Uuid()) || group.RTTI_IsTypeOf(DataTypes::ISkinGroup::TYPEINFO_Uuid());
  114. AZStd::vector<size_t> rulesToRemove;
  115. for (size_t index = 0; index < ruleCount; ++index)
  116. {
  117. DataTypes::IMeshAdvancedRule* rule = azrtti_cast<DataTypes::IMeshAdvancedRule*>(rules.GetRule(index).get());
  118. if (rule)
  119. {
  120. if (isValidGroupType)
  121. {
  122. UpdateMeshAdvancedRule(scene, rule);
  123. }
  124. else
  125. {
  126. rulesToRemove.push_back(index);
  127. }
  128. }
  129. }
  130. // Remove in reversed order, as otherwise the indices will be wrong. For example if we remove index 3, then index 6 would really be 5 afterwards.
  131. // By doing this in reversed order we remove items at the end of the list first so it won't impact the indices of previous ones.
  132. for (AZStd::vector<size_t>::reverse_iterator it = rulesToRemove.rbegin(); it != rulesToRemove.rend(); ++it)
  133. {
  134. rules.RemoveRule(*it);
  135. }
  136. }
  137. }
  138. void MeshAdvancedRule::UpdateMeshAdvancedRule(Containers::Scene& scene, DataTypes::IMeshAdvancedRule* rule) const
  139. {
  140. if (!rule)
  141. {
  142. return;
  143. }
  144. SceneData::SkinMeshAdvancedRule* skinRule = azrtti_cast<SceneData::SkinMeshAdvancedRule*>(rule);
  145. SceneData::StaticMeshAdvancedRule* meshRule = azrtti_cast<SceneData::StaticMeshAdvancedRule*>(rule);
  146. if (!(skinRule || meshRule))
  147. {
  148. return;
  149. }
  150. const AZStd::string& vertexColorStreamName = rule->GetVertexColorStreamName();
  151. bool foundColorStream = vertexColorStreamName == DataTypes::s_advancedDisabledString;
  152. const Containers::SceneGraph& graph = scene.GetGraph();
  153. Containers::SceneGraph::NameStorageConstData graphNames = graph.GetNameStorage();
  154. for (auto it = graphNames.begin(); it != graphNames.end(); ++it)
  155. {
  156. if (foundColorStream)
  157. {
  158. break;
  159. }
  160. const char* nodeName = it->GetName();
  161. if (!foundColorStream && vertexColorStreamName == nodeName)
  162. {
  163. foundColorStream = true;
  164. }
  165. }
  166. if (!foundColorStream)
  167. {
  168. AZStd::string newColorStreamName = GetFirstVertexColorStream(scene);
  169. AZ_TracePrintf(Utilities::WarningWindow, "Old vertex color stream name not found so renamed from '%s' to '%s'.",
  170. vertexColorStreamName.c_str(), newColorStreamName.c_str());
  171. if (skinRule)
  172. {
  173. skinRule->SetVertexColorStreamName(newColorStreamName.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(newColorStreamName));
  174. }
  175. else if (meshRule)
  176. {
  177. meshRule->SetVertexColorStreamName(newColorStreamName.empty() ? DataTypes::s_advancedDisabledString : AZStd::move(newColorStreamName));
  178. }
  179. }
  180. }
  181. AZStd::string MeshAdvancedRule::GetFirstVertexColorStream(const Containers::Scene& scene) const
  182. {
  183. const Containers::SceneGraph& graph = scene.GetGraph();
  184. Containers::SceneGraph::ContentStorageConstData graphContent = graph.GetContentStorage();
  185. auto vertexColorData = AZStd::find_if(graphContent.begin(), graphContent.end(),
  186. Containers::DerivedTypeFilter<DataTypes::IMeshVertexColorData>());
  187. if (vertexColorData != graphContent.end())
  188. {
  189. return graph.GetNodeName(graph.ConvertToNodeIndex(vertexColorData)).GetName();
  190. }
  191. else
  192. {
  193. return AZStd::string();
  194. }
  195. }
  196. } // namespace Behaviors
  197. } // namespace SceneAPI
  198. } // namespace AZ