You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
9.2 KiB
C++
222 lines
9.2 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
|
#include <SceneAPI/SceneCore/Containers/SceneGraph.h>
|
|
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
|
|
|
|
#include <SceneAPI/SceneCore/DataTypes/Groups/IMeshGroup.h>
|
|
|
|
#include <Pipeline/SceneAPIExt/ClothRuleBehavior.h>
|
|
#include <Pipeline/SceneAPIExt/ClothRule.h>
|
|
|
|
namespace NvCloth
|
|
{
|
|
namespace Pipeline
|
|
{
|
|
void ClothRuleBehavior::Activate()
|
|
{
|
|
AZ::SceneAPI::Events::ManifestMetaInfoBus::Handler::BusConnect();
|
|
AZ::SceneAPI::Events::AssetImportRequestBus::Handler::BusConnect();
|
|
}
|
|
|
|
void ClothRuleBehavior::Deactivate()
|
|
{
|
|
AZ::SceneAPI::Events::AssetImportRequestBus::Handler::BusDisconnect();
|
|
AZ::SceneAPI::Events::ManifestMetaInfoBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
void ClothRuleBehavior::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
ClothRule::Reflect(context);
|
|
|
|
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
|
if (serializeContext)
|
|
{
|
|
serializeContext->Class<ClothRuleBehavior, BehaviorComponent>()->Version(1);
|
|
}
|
|
}
|
|
|
|
void ClothRuleBehavior::GetAvailableModifiers(
|
|
AZ::SceneAPI::Events::ManifestMetaInfo::ModifiersList& modifiers,
|
|
const AZ::SceneAPI::Containers::Scene& scene,
|
|
const AZ::SceneAPI::DataTypes::IManifestObject& target)
|
|
{
|
|
AZ_UNUSED(scene);
|
|
if (target.RTTI_IsTypeOf(AZ::SceneAPI::DataTypes::ISceneNodeGroup::TYPEINFO_Uuid()))
|
|
{
|
|
const AZ::SceneAPI::DataTypes::ISceneNodeGroup* group = azrtti_cast<const AZ::SceneAPI::DataTypes::ISceneNodeGroup*>(&target);
|
|
if (IsValidGroupType(*group))
|
|
{
|
|
modifiers.push_back(ClothRule::TYPEINFO_Uuid());
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClothRuleBehavior::InitializeObject(
|
|
[[maybe_unused]] const AZ::SceneAPI::Containers::Scene& scene,
|
|
AZ::SceneAPI::DataTypes::IManifestObject& target)
|
|
{
|
|
// When a cloth rule is created in the Scene Settings...
|
|
if (target.RTTI_IsTypeOf(ClothRule::TYPEINFO_Uuid()))
|
|
{
|
|
ClothRule* clothRule = azrtti_cast<ClothRule*>(&target);
|
|
|
|
// Set default values
|
|
clothRule->SetMeshNodeName(ClothRule::DefaultChooseNodeName);
|
|
clothRule->SetInverseMassesStreamName(ClothRule::DefaultInverseMassesString);
|
|
clothRule->SetMotionConstraintsStreamName(ClothRule::DefaultMotionConstraintsString);
|
|
clothRule->SetBackstopStreamName(ClothRule::DefaultBackstopString);
|
|
}
|
|
}
|
|
|
|
AZ::SceneAPI::Events::ProcessingResult ClothRuleBehavior::UpdateManifest(
|
|
AZ::SceneAPI::Containers::Scene& scene,
|
|
ManifestAction action,
|
|
RequestingApplication requester)
|
|
{
|
|
AZ_UNUSED(requester);
|
|
// When the manifest is updated let's check the content is still valid for cloth rules
|
|
if (action == ManifestAction::Update)
|
|
{
|
|
bool updated = UpdateClothRules(scene);
|
|
return updated ? AZ::SceneAPI::Events::ProcessingResult::Success : AZ::SceneAPI::Events::ProcessingResult::Ignored;
|
|
}
|
|
else
|
|
{
|
|
return AZ::SceneAPI::Events::ProcessingResult::Ignored;
|
|
}
|
|
}
|
|
|
|
bool ClothRuleBehavior::IsValidGroupType(const AZ::SceneAPI::DataTypes::ISceneNodeGroup& group) const
|
|
{
|
|
// Cloth rules are available in Mesh Groups
|
|
return group.RTTI_IsTypeOf(AZ::SceneAPI::DataTypes::IMeshGroup::TYPEINFO_Uuid());
|
|
}
|
|
|
|
bool ClothRuleBehavior::UpdateClothRules(AZ::SceneAPI::Containers::Scene& scene)
|
|
{
|
|
bool rulesUpdated = false;
|
|
|
|
auto& manifest = scene.GetManifest();
|
|
auto valueStorage = manifest.GetValueStorage();
|
|
auto view = AZ::SceneAPI::Containers::MakeDerivedFilterView<AZ::SceneAPI::DataTypes::ISceneNodeGroup>(valueStorage);
|
|
|
|
// For each scene group...
|
|
for (auto& group : view)
|
|
{
|
|
bool isValidGroupType = IsValidGroupType(group);
|
|
|
|
AZStd::vector<size_t> rulesToRemove;
|
|
|
|
auto& groupRules = group.GetRuleContainer();
|
|
for (size_t index = 0; index < groupRules.GetRuleCount(); ++index)
|
|
{
|
|
ClothRule* clothRule = azrtti_cast<ClothRule*>(groupRules.GetRule(index).get());
|
|
if (clothRule)
|
|
{
|
|
if (isValidGroupType)
|
|
{
|
|
rulesUpdated = UpdateClothRule(scene.GetGraph(), group, *clothRule) || rulesUpdated;
|
|
}
|
|
else
|
|
{
|
|
// Cloth rule found in a group that shouldn't have cloth rules, add for removal.
|
|
rulesToRemove.push_back(index);
|
|
rulesUpdated = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
// 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.
|
|
for (AZStd::vector<size_t>::reverse_iterator it = rulesToRemove.rbegin(); it != rulesToRemove.rend(); ++it)
|
|
{
|
|
groupRules.RemoveRule(*it);
|
|
}
|
|
}
|
|
|
|
return rulesUpdated;
|
|
}
|
|
|
|
bool ClothRuleBehavior::UpdateClothRule(const AZ::SceneAPI::Containers::SceneGraph& graph, const AZ::SceneAPI::DataTypes::ISceneNodeGroup& group, ClothRule& clothRule)
|
|
{
|
|
bool ruleUpdated = false;
|
|
|
|
if (clothRule.GetMeshNodeName() != ClothRule::DefaultChooseNodeName)
|
|
{
|
|
bool foundMeshNode = false;
|
|
const AZStd::string& meshNodeName = clothRule.GetMeshNodeName();
|
|
|
|
if (!meshNodeName.empty())
|
|
{
|
|
const auto& selectedNodesList = group.GetSceneNodeSelectionList();
|
|
for (size_t i = 0; i < selectedNodesList.GetSelectedNodeCount(); ++i)
|
|
{
|
|
if (meshNodeName == selectedNodesList.GetSelectedNode(i))
|
|
{
|
|
foundMeshNode = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Mesh node selected in the cloth rule is not part of the list of selected nodes anymore, set the default value.
|
|
if (!foundMeshNode)
|
|
{
|
|
clothRule.SetMeshNodeName(ClothRule::DefaultChooseNodeName);
|
|
ruleUpdated = true;
|
|
}
|
|
}
|
|
|
|
// If the Vertex Color Stream selected for the inverse masses doesn't exist anymore, set the default value.
|
|
if (!clothRule.IsInverseMassesStreamDisabled() &&
|
|
!ContainsVertexColorStream(graph, clothRule.GetInverseMassesStreamName()))
|
|
{
|
|
clothRule.SetInverseMassesStreamName(ClothRule::DefaultInverseMassesString);
|
|
ruleUpdated = true;
|
|
}
|
|
|
|
// If the Vertex Color Stream selected for the motion constraints doesn't exist anymore, set the default value.
|
|
if (!clothRule.IsMotionConstraintsStreamDisabled() &&
|
|
!ContainsVertexColorStream(graph, clothRule.GetMotionConstraintsStreamName()))
|
|
{
|
|
clothRule.SetMotionConstraintsStreamName(ClothRule::DefaultMotionConstraintsString);
|
|
ruleUpdated = true;
|
|
}
|
|
|
|
// If the Vertex Color Stream selected for the backstop doesn't exist anymore, set the default value.
|
|
if (!clothRule.IsBackstopStreamDisabled() &&
|
|
!ContainsVertexColorStream(graph, clothRule.GetBackstopStreamName()))
|
|
{
|
|
clothRule.SetBackstopStreamName(ClothRule::DefaultBackstopString);
|
|
ruleUpdated = true;
|
|
}
|
|
|
|
return ruleUpdated;
|
|
}
|
|
|
|
bool ClothRuleBehavior::ContainsVertexColorStream(const AZ::SceneAPI::Containers::SceneGraph& graph, const AZStd::string& streamName) const
|
|
{
|
|
if (streamName.empty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
auto graphNames = graph.GetNameStorage();
|
|
|
|
auto graphNameIt = AZStd::find_if(graphNames.cbegin(), graphNames.cend(),
|
|
[&streamName](const AZ::SceneAPI::Containers::SceneGraph::NameStorageType& graphName)
|
|
{
|
|
return streamName == graphName.GetName();
|
|
});
|
|
|
|
return graphNameIt != graphNames.cend();
|
|
}
|
|
} // namespace Pipeline
|
|
} // namespace NvCloth
|