3
0

ClothRuleBehavior.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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 <SceneAPI/SceneCore/Containers/Scene.h>
  9. #include <SceneAPI/SceneCore/Containers/SceneGraph.h>
  10. #include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
  11. #include <SceneAPI/SceneCore/DataTypes/Groups/IMeshGroup.h>
  12. #include <Pipeline/SceneAPIExt/ClothRuleBehavior.h>
  13. #include <Pipeline/SceneAPIExt/ClothRule.h>
  14. namespace NvCloth
  15. {
  16. namespace Pipeline
  17. {
  18. void ClothRuleBehavior::Activate()
  19. {
  20. AZ::SceneAPI::Events::ManifestMetaInfoBus::Handler::BusConnect();
  21. AZ::SceneAPI::Events::AssetImportRequestBus::Handler::BusConnect();
  22. }
  23. void ClothRuleBehavior::Deactivate()
  24. {
  25. AZ::SceneAPI::Events::AssetImportRequestBus::Handler::BusDisconnect();
  26. AZ::SceneAPI::Events::ManifestMetaInfoBus::Handler::BusDisconnect();
  27. }
  28. void ClothRuleBehavior::Reflect(AZ::ReflectContext* context)
  29. {
  30. ClothRule::Reflect(context);
  31. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  32. if (serializeContext)
  33. {
  34. serializeContext->Class<ClothRuleBehavior, BehaviorComponent>()->Version(1);
  35. }
  36. }
  37. void ClothRuleBehavior::GetAvailableModifiers(
  38. AZ::SceneAPI::Events::ManifestMetaInfo::ModifiersList& modifiers,
  39. const AZ::SceneAPI::Containers::Scene& scene,
  40. const AZ::SceneAPI::DataTypes::IManifestObject& target)
  41. {
  42. AZ_UNUSED(scene);
  43. if (target.RTTI_IsTypeOf(AZ::SceneAPI::DataTypes::ISceneNodeGroup::TYPEINFO_Uuid()))
  44. {
  45. const AZ::SceneAPI::DataTypes::ISceneNodeGroup* group = azrtti_cast<const AZ::SceneAPI::DataTypes::ISceneNodeGroup*>(&target);
  46. if (IsValidGroupType(*group))
  47. {
  48. modifiers.push_back(ClothRule::TYPEINFO_Uuid());
  49. }
  50. }
  51. }
  52. void ClothRuleBehavior::InitializeObject(
  53. [[maybe_unused]] const AZ::SceneAPI::Containers::Scene& scene,
  54. AZ::SceneAPI::DataTypes::IManifestObject& target)
  55. {
  56. // When a cloth rule is created in the Scene Settings...
  57. if (target.RTTI_IsTypeOf(ClothRule::TYPEINFO_Uuid()))
  58. {
  59. ClothRule* clothRule = azrtti_cast<ClothRule*>(&target);
  60. // Set default values
  61. clothRule->SetMeshNodeName(ClothRule::DefaultChooseNodeName);
  62. clothRule->SetInverseMassesStreamName(ClothRule::DefaultInverseMassesString);
  63. clothRule->SetMotionConstraintsStreamName(ClothRule::DefaultMotionConstraintsString);
  64. clothRule->SetBackstopStreamName(ClothRule::DefaultBackstopString);
  65. }
  66. }
  67. AZ::SceneAPI::Events::ProcessingResult ClothRuleBehavior::UpdateManifest(
  68. AZ::SceneAPI::Containers::Scene& scene,
  69. ManifestAction action,
  70. RequestingApplication requester)
  71. {
  72. AZ_UNUSED(requester);
  73. // When the manifest is updated let's check the content is still valid for cloth rules
  74. if (action == ManifestAction::Update)
  75. {
  76. bool updated = UpdateClothRules(scene);
  77. return updated ? AZ::SceneAPI::Events::ProcessingResult::Success : AZ::SceneAPI::Events::ProcessingResult::Ignored;
  78. }
  79. else
  80. {
  81. return AZ::SceneAPI::Events::ProcessingResult::Ignored;
  82. }
  83. }
  84. bool ClothRuleBehavior::IsValidGroupType(const AZ::SceneAPI::DataTypes::ISceneNodeGroup& group) const
  85. {
  86. // Cloth rules are available in Mesh Groups
  87. return group.RTTI_IsTypeOf(AZ::SceneAPI::DataTypes::IMeshGroup::TYPEINFO_Uuid());
  88. }
  89. bool ClothRuleBehavior::UpdateClothRules(AZ::SceneAPI::Containers::Scene& scene)
  90. {
  91. bool rulesUpdated = false;
  92. auto& manifest = scene.GetManifest();
  93. auto valueStorage = manifest.GetValueStorage();
  94. auto view = AZ::SceneAPI::Containers::MakeDerivedFilterView<AZ::SceneAPI::DataTypes::ISceneNodeGroup>(valueStorage);
  95. // For each scene group...
  96. for (auto& group : view)
  97. {
  98. bool isValidGroupType = IsValidGroupType(group);
  99. AZStd::vector<size_t> rulesToRemove;
  100. auto& groupRules = group.GetRuleContainer();
  101. for (size_t index = 0; index < groupRules.GetRuleCount(); ++index)
  102. {
  103. ClothRule* clothRule = azrtti_cast<ClothRule*>(groupRules.GetRule(index).get());
  104. if (clothRule)
  105. {
  106. if (isValidGroupType)
  107. {
  108. rulesUpdated = UpdateClothRule(scene.GetGraph(), group, *clothRule) || rulesUpdated;
  109. }
  110. else
  111. {
  112. // Cloth rule found in a group that shouldn't have cloth rules, add for removal.
  113. rulesToRemove.push_back(index);
  114. rulesUpdated = true;
  115. }
  116. }
  117. }
  118. // 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.
  119. // 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.
  120. for (AZStd::vector<size_t>::reverse_iterator it = rulesToRemove.rbegin(); it != rulesToRemove.rend(); ++it)
  121. {
  122. groupRules.RemoveRule(*it);
  123. }
  124. }
  125. return rulesUpdated;
  126. }
  127. bool ClothRuleBehavior::UpdateClothRule(const AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::DataTypes::ISceneNodeGroup& group, ClothRule& clothRule)
  128. {
  129. bool ruleUpdated = false;
  130. if (clothRule.GetMeshNodeName() != ClothRule::DefaultChooseNodeName)
  131. {
  132. bool foundMeshNode = false;
  133. const AZStd::string& meshNodeName = clothRule.GetMeshNodeName();
  134. if (!meshNodeName.empty())
  135. {
  136. const auto& selectedNodesList = group.GetSceneNodeSelectionList();
  137. foundMeshNode = selectedNodesList.IsSelectedNode(meshNodeName);
  138. }
  139. // Mesh node selected in the cloth rule is not part of the list of selected nodes anymore, set the default value.
  140. if (!foundMeshNode)
  141. {
  142. clothRule.SetMeshNodeName(ClothRule::DefaultChooseNodeName);
  143. ruleUpdated = true;
  144. }
  145. }
  146. // If the Vertex Color Stream selected for the inverse masses doesn't exist anymore, set the default value.
  147. if (!clothRule.IsInverseMassesStreamDisabled() &&
  148. !ContainsVertexColorStream(graph, clothRule.GetInverseMassesStreamName()))
  149. {
  150. clothRule.SetInverseMassesStreamName(ClothRule::DefaultInverseMassesString);
  151. ruleUpdated = true;
  152. }
  153. // If the Vertex Color Stream selected for the motion constraints doesn't exist anymore, set the default value.
  154. if (!clothRule.IsMotionConstraintsStreamDisabled() &&
  155. !ContainsVertexColorStream(graph, clothRule.GetMotionConstraintsStreamName()))
  156. {
  157. clothRule.SetMotionConstraintsStreamName(ClothRule::DefaultMotionConstraintsString);
  158. ruleUpdated = true;
  159. }
  160. // If the Vertex Color Stream selected for the backstop doesn't exist anymore, set the default value.
  161. if (!clothRule.IsBackstopStreamDisabled() &&
  162. !ContainsVertexColorStream(graph, clothRule.GetBackstopStreamName()))
  163. {
  164. clothRule.SetBackstopStreamName(ClothRule::DefaultBackstopString);
  165. ruleUpdated = true;
  166. }
  167. return ruleUpdated;
  168. }
  169. bool ClothRuleBehavior::ContainsVertexColorStream(const AZ::SceneAPI::Containers::SceneGraph& graph, const AZStd::string& streamName) const
  170. {
  171. if (streamName.empty())
  172. {
  173. return false;
  174. }
  175. auto graphNames = graph.GetNameStorage();
  176. auto graphNameIt = AZStd::find_if(graphNames.cbegin(), graphNames.cend(),
  177. [&streamName](const AZ::SceneAPI::Containers::SceneGraph::NameStorageType& graphName)
  178. {
  179. return streamName == graphName.GetName();
  180. });
  181. return graphNameIt != graphNames.cend();
  182. }
  183. } // namespace Pipeline
  184. } // namespace NvCloth