// Copyright Epic Games, Inc. All Rights Reserved. #include "Dataflow/ChaosFleshKinematicConstraintNode.h" #include "Engine/SkeletalMesh.h" #include "GeometryCollection/Facades/CollectionKinematicBindingFacade.h" #include "GeometryCollection/Facades/CollectionVertexBoneWeightsFacade.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(ChaosFleshKinematicConstraintNode) void FKinematicInitializationDataflowNode::Evaluate(UE::Dataflow::FContext& Context, const FDataflowOutput* Out) const { if (Out->IsA(&Collection)) { DataType InCollection = GetValue(Context, &Collection); if (TManagedArray* Vertices = InCollection.FindAttribute("Vertex", FGeometryCollection::VerticesGroup)) { if (FindInput(&VertexIndicesIn) && FindInput(&VertexIndicesIn)->GetConnection()) { GeometryCollection::Facades::FVertexBoneWeightsFacade VertexBoneWeightsFacade(InCollection); for (int32 SelectionIndex : GetValue>(Context, &VertexIndicesIn)) { if (Vertices->IsValidIndex(SelectionIndex)) { VertexBoneWeightsFacade.SetVertexKinematic(SelectionIndex); } } } else if (TObjectPtr SkeletalMesh = GetValue>(Context, &SkeletalMeshIn)) { int32 IndexValue = GetValue(Context, &BoneIndexIn); if (IndexValue != INDEX_NONE) { TArray ComponentPose; UE::Dataflow::Animation::GlobalTransforms(SkeletalMesh->GetRefSkeleton(), ComponentPose); TArray BranchIndices; if (SkeletalSelectionMode == ESkeletalSeletionMode::Dataflow_SkeletalSelection_Branch) { TArray ToProcess; int32 CurrentIndex = IndexValue; while (SkeletalMesh->GetRefSkeleton().IsValidIndex(CurrentIndex)) { TArray Buffer; SkeletalMesh->GetRefSkeleton().GetDirectChildBones(CurrentIndex, Buffer); if (Buffer.Num()) { ToProcess.Append(Buffer); } BranchIndices.Add(CurrentIndex); CurrentIndex = INDEX_NONE; if (ToProcess.Num()) { CurrentIndex = ToProcess.Pop(); } } } else // ESkeletalSeletionMode::Dataflow_SkeletalSelection_Single { BranchIndices.Add(IndexValue); } TSet ProcessedVertices; for (const int32 Index : BranchIndices) { TArray BoundVerts; TArray BoundWeights; if (0 <= Index && Index < ComponentPose.Num()) { FVector3f BonePosition(ComponentPose[Index].GetTranslation()); int NumVertices = Vertices->Num(); for (int i = Vertices->Num() - 1; i > 0; i--) { if ((BonePosition - (*Vertices)[i]).Length() < Radius) { if (!ProcessedVertices.Contains(i)) { ProcessedVertices.Add(i); BoundVerts.Add(i); BoundWeights.Add(1.0); } } } if (BoundVerts.Num()) { GeometryCollection::Facades::FKinematicBindingFacade Kinematics(InCollection); Kinematics.AddKinematicBinding(Kinematics.SetBoneBindings(Index, BoundVerts, BoundWeights)); } } } GeometryCollection::Facades::FVertexBoneWeightsFacade(InCollection).AddBoneWeightsFromKinematicBindings(); } } } SetValue(Context, MoveTemp(InCollection), &Collection); } }