Files
UnrealEngine/Engine/Source/Editor/PhysicsAssetEditor/Private/PhysicsAssetGraph/PhysicsAssetGraph.cpp
2025-05-18 13:04:45 +08:00

168 lines
6.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PhysicsAssetGraph/PhysicsAssetGraph.h"
#include "PhysicsAssetGraph/PhysicsAssetGraphNode.h"
#include "PhysicsAssetGraph/PhysicsAssetGraphSchema.h"
#include "PhysicsEngine/PhysicsAsset.h"
#include "IEditableSkeleton.h"
#include "PhysicsEngine/PhysicsConstraintTemplate.h"
#include "PhysicsEngine/SkeletalBodySetup.h"
#include "PhysicsAssetGraph/PhysicsAssetGraphNode_Bone.h"
#include "PhysicsAssetGraph/PhysicsAssetGraphNode_Constraint.h"
#include "Algo/Transform.h"
#include "BoneProxy.h"
UPhysicsAssetGraph::UPhysicsAssetGraph(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, bRefreshLayout(false)
{
}
void UPhysicsAssetGraph::Initialize(const TSharedRef<FPhysicsAssetEditor>& InPhysicsAssetEditor, UPhysicsAsset* InPhysicsAsset, const TSharedRef<IEditableSkeleton>& InEditableSkeleton)
{
WeakPhysicsAssetEditor = InPhysicsAssetEditor;
WeakPhysicsAsset = InPhysicsAsset;
WeakEditableSkeleton = InEditableSkeleton;
}
const UPhysicsAssetGraphSchema* UPhysicsAssetGraph::GetPhysicsAssetGraphSchema()
{
return CastChecked<const UPhysicsAssetGraphSchema>(GetSchema());
}
void UPhysicsAssetGraph::RebuildGraph()
{
RemoveAllNodes();
ConstructNodes();
NotifyGraphChanged();
}
void UPhysicsAssetGraph::ConstructNodes()
{
RootNodes.Reset();
if (WeakPhysicsAsset.IsValid())
{
UPhysicsAsset* PhysicsAsset = WeakPhysicsAsset.Get();
TSharedRef<IEditableSkeleton> EditableSkeleton = WeakEditableSkeleton.Pin().ToSharedRef();
const FReferenceSkeleton& RefSkeleton = EditableSkeleton->GetSkeleton().GetReferenceSkeleton();
TSet<const UEdGraphNode*> NewSelection;
// Add Root bone nodes
check(SelectedBodies.Num() == SelectedBodyIndices.Num());
for (int32 SelectedBodyIndex = 0; SelectedBodyIndex < SelectedBodies.Num(); ++SelectedBodyIndex)
{
USkeletalBodySetup* SelectedBody = SelectedBodies[SelectedBodyIndex];
UPhysicsAssetGraphNode_Bone* RootNode = GetPhysicsAssetGraphSchema()->CreateGraphNodesForBone(this, SelectedBody, SelectedBodyIndices[SelectedBodyIndex], PhysicsAsset);
RootNodes.Add(RootNode);
if(InitiallySelectedBodies.Find(SelectedBody) != INDEX_NONE)
{
NewSelection.Add(RootNode);
}
// add constraints for this bone
for (int32 ConstraintIndex = 0; ConstraintIndex < PhysicsAsset->ConstraintSetup.Num(); ++ConstraintIndex)
{
const FConstraintInstance& ConstraintInstance = PhysicsAsset->ConstraintSetup[ConstraintIndex]->DefaultInstance;
if (ConstraintInstance.ConstraintBone1 == SelectedBody->BoneName || ConstraintInstance.ConstraintBone2 == SelectedBody->BoneName)
{
UPhysicsAssetGraphNode_Constraint* ConstraintNode = GetPhysicsAssetGraphSchema()->CreateGraphNodesForConstraint(this, PhysicsAsset->ConstraintSetup[ConstraintIndex], ConstraintIndex, PhysicsAsset);
RootNode->GetOutputPin().MakeLinkTo(&ConstraintNode->GetInputPin());
RootNode->GetOutputPin().bHidden = false;
ConstraintNode->GetInputPin().bHidden = false;
FName OtherBoneName = ConstraintInstance.ConstraintBone1 == SelectedBody->BoneName ? ConstraintInstance.ConstraintBone2 : ConstraintInstance.ConstraintBone1;
USkeletalBodySetup* BodySetup = nullptr;
int32 LinkedBodyIndex = INDEX_NONE;
for (int32 BodyIndex = 0; BodyIndex < PhysicsAsset->SkeletalBodySetups.Num(); ++BodyIndex)
{
USkeletalBodySetup* CheckBodySetup = PhysicsAsset->SkeletalBodySetups[BodyIndex];
if (CheckBodySetup && CheckBodySetup->BoneName == OtherBoneName)
{
BodySetup = CheckBodySetup;
LinkedBodyIndex = BodyIndex;
break;
}
}
if(SelectedConstraints.Find(PhysicsAsset->ConstraintSetup[ConstraintIndex]) != INDEX_NONE)
{
NewSelection.Add(ConstraintNode);
}
if (BodySetup != nullptr && LinkedBodyIndex != INDEX_NONE)
{
UPhysicsAssetGraphNode_Bone* BoneNode = GetPhysicsAssetGraphSchema()->CreateGraphNodesForBone(this, BodySetup, LinkedBodyIndex, PhysicsAsset);
ConstraintNode->GetOutputPin().MakeLinkTo(&BoneNode->GetInputPin());
ConstraintNode->GetOutputPin().bHidden = false;
BoneNode->GetInputPin().bHidden = false;
}
}
}
}
SelectNodeSet(NewSelection);
}
}
void UPhysicsAssetGraph::RemoveAllNodes()
{
TArray<UEdGraphNode*> NodesToRemove = Nodes;
for (int32 NodeIndex = 0; NodeIndex < NodesToRemove.Num(); ++NodeIndex)
{
RemoveNode(NodesToRemove[NodeIndex]);
}
}
void UPhysicsAssetGraph::SelectObjects(const TArray<USkeletalBodySetup*>& InBodies, const TArray<UPhysicsConstraintTemplate*>& InConstraints)
{
if (WeakPhysicsAsset.IsValid())
{
UPhysicsAsset* PhysicsAsset = WeakPhysicsAsset.Get();
InitiallySelectedBodies = InBodies;
SelectedBodies = InBodies;
SelectedConstraints = InConstraints;
// Add unique bodies in constraints to SelectedBodies too
for (int32 SelectedConstraintIndex = 0; SelectedConstraintIndex < InConstraints.Num(); ++SelectedConstraintIndex)
{
const FConstraintInstance& ConstraintInstance = InConstraints[SelectedConstraintIndex]->DefaultInstance;
for (int32 BodyIndex = 0; BodyIndex < PhysicsAsset->SkeletalBodySetups.Num(); ++BodyIndex)
{
USkeletalBodySetup* CheckBodySetup = PhysicsAsset->SkeletalBodySetups[BodyIndex];
if (CheckBodySetup && (CheckBodySetup->BoneName == ConstraintInstance.ConstraintBone1 || CheckBodySetup->BoneName == ConstraintInstance.ConstraintBone2))
{
SelectedBodies.AddUnique(CheckBodySetup);
break;
}
}
}
SelectedBodyIndices.Reset(SelectedBodies.Num());
SelectedBodyIndices.SetNum(SelectedBodies.Num());
for (int32 SelectedBodyIndex = 0; SelectedBodyIndex < SelectedBodies.Num(); ++SelectedBodyIndex)
{
SelectedBodyIndices[SelectedBodyIndex] = INDEX_NONE;
for (int32 BodyIndex = 0; BodyIndex < PhysicsAsset->SkeletalBodySetups.Num(); ++BodyIndex)
{
if (SelectedBodies[SelectedBodyIndex] == PhysicsAsset->SkeletalBodySetups[BodyIndex])
{
SelectedBodyIndices[SelectedBodyIndex] = BodyIndex;
break;
}
}
// Check we have actually found this body
check(SelectedBodyIndices[SelectedBodyIndex] != INDEX_NONE);
}
RebuildGraph();
}
}