// Copyright Epic Games, Inc. All Rights Reserved. #include "RigVMModel/RigVMBuildData.h" FRigVMReferenceNodeData::FRigVMReferenceNodeData(URigVMFunctionReferenceNode* InReferenceNode) { check(InReferenceNode); ReferenceNodePtr = TSoftObjectPtr(InReferenceNode); ReferenceNodePath = ReferenceNodePtr.ToString(); LibraryNodePtr = TSoftObjectPtr(InReferenceNode->GetReferencedNode()); ReferencedFunctionPath = LibraryNodePtr.ToString(); } TSoftObjectPtr FRigVMReferenceNodeData::GetReferenceNodeObjectPath() { if(ReferenceNodePtr.IsNull()) { ReferenceNodePtr = TSoftObjectPtr(ReferenceNodePath); } return ReferenceNodePtr; } TSoftObjectPtr FRigVMReferenceNodeData::GetReferencedFunctionObjectPath() { if(LibraryNodePtr.IsNull()) { LibraryNodePtr = TSoftObjectPtr(ReferencedFunctionPath); } return LibraryNodePtr; } URigVMFunctionReferenceNode* FRigVMReferenceNodeData::GetReferenceNode() { if(ReferenceNodePtr.IsNull()) { ReferenceNodePtr = TSoftObjectPtr(ReferenceNodePath); } if(!ReferenceNodePtr.IsValid()) { ReferenceNodePtr.LoadSynchronous(); } if(ReferenceNodePtr.IsValid()) { return ReferenceNodePtr.Get(); } return nullptr; } URigVMLibraryNode* FRigVMReferenceNodeData::GetReferencedFunction() { if(LibraryNodePtr.IsNull()) { LibraryNodePtr = TSoftObjectPtr(ReferencedFunctionPath); } if(!LibraryNodePtr.IsValid()) { LibraryNodePtr.LoadSynchronous(); } if(LibraryNodePtr.IsValid()) { return LibraryNodePtr.Get(); } return nullptr; } URigVMBuildData::URigVMBuildData() : UObject() , bIsRunningUnitTest(false) { } const FRigVMFunctionReferenceArray* URigVMBuildData::FindFunctionReferences(const URigVMLibraryNode* InFunction) const { check(InFunction); const TSoftObjectPtr Key(InFunction); return FunctionReferences.Find(Key); } void URigVMBuildData::ForEachFunctionReference(const URigVMLibraryNode* InFunction, TFunction PerReferenceFunction) const { check(InFunction); if (const FRigVMFunctionReferenceArray* ReferencesEntry = FindFunctionReferences(InFunction)) { for (int32 ReferenceIndex = 0; ReferenceIndex < ReferencesEntry->Num(); ReferenceIndex++) { const TSoftObjectPtr& Reference = ReferencesEntry->operator [](ReferenceIndex); if (!Reference.IsValid()) { Reference.LoadSynchronous(); } if (Reference.IsValid()) { PerReferenceFunction(Reference.Get()); } } } } void URigVMBuildData::ForEachFunctionReferenceSoftPtr(const URigVMLibraryNode* InFunction, TFunction)> PerReferenceFunction) const { check(InFunction); if (const FRigVMFunctionReferenceArray* ReferencesEntry = FindFunctionReferences(InFunction)) { for (int32 ReferenceIndex = 0; ReferenceIndex < ReferencesEntry->Num(); ReferenceIndex++) { const TSoftObjectPtr& Reference = ReferencesEntry->operator [](ReferenceIndex); PerReferenceFunction(Reference); } } } void URigVMBuildData::UpdateReferencesForFunctionReferenceNode(URigVMFunctionReferenceNode* InReferenceNode) { check(InReferenceNode); if(InReferenceNode->GetOutermost() == GetTransientPackage()) { return; } if(const URigVMLibraryNode* Function = InReferenceNode->GetReferencedNode()) { const TSoftObjectPtr Key(Function); FRigVMFunctionReferenceArray* ReferencesEntry = FunctionReferences.Find(Key); if (ReferencesEntry == nullptr) { Modify(); FunctionReferences.Add(Key); ReferencesEntry = FunctionReferences.Find(Key); } const FString ReferenceNodePathName = InReferenceNode->GetPathName(); for (int32 ReferenceIndex = 0; ReferenceIndex < ReferencesEntry->Num(); ReferenceIndex++) { const TSoftObjectPtr& Reference = ReferencesEntry->operator [](ReferenceIndex); if(Reference.ToString() == ReferenceNodePathName) { return; } } Modify(); ReferencesEntry->FunctionReferences.Add(InReferenceNode); MarkPackageDirty(); } } void URigVMBuildData::RegisterFunctionReference(URigVMLibraryNode* InFunction, URigVMFunctionReferenceNode* InReference) { if(InFunction == nullptr || InReference == nullptr) { return; } const TSoftObjectPtr FunctionKey(InFunction); const TSoftObjectPtr ReferenceKey(InReference); RegisterFunctionReference(FunctionKey, ReferenceKey); } void URigVMBuildData::RegisterFunctionReference(TSoftObjectPtr InFunction, TSoftObjectPtr InReference) { if(InFunction.IsNull() || InReference.IsNull()) { return; } if(FRigVMFunctionReferenceArray* ReferenceEntry = FunctionReferences.Find(InFunction)) { if(ReferenceEntry->FunctionReferences.Contains(InReference)) { return; } Modify(); ReferenceEntry->FunctionReferences.Add(InReference); } else { Modify(); FRigVMFunctionReferenceArray NewReferenceEntry; NewReferenceEntry.FunctionReferences.Add(InReference); FunctionReferences.Add(InFunction, NewReferenceEntry); } MarkPackageDirty(); } void URigVMBuildData::RegisterFunctionReference(FRigVMReferenceNodeData InReferenceNodeData) { RegisterFunctionReference(InReferenceNodeData.GetReferencedFunctionObjectPath(), InReferenceNodeData.GetReferenceNodeObjectPath()); } void URigVMBuildData::UnregisterFunctionReference(URigVMLibraryNode* InFunction, URigVMFunctionReferenceNode* InReference) { if(InFunction == nullptr || InReference == nullptr) { return; } const TSoftObjectPtr FunctionKey(InFunction); const TSoftObjectPtr ReferenceKey(InReference); return UnregisterFunctionReference(FunctionKey, ReferenceKey); } void URigVMBuildData::UnregisterFunctionReference(TSoftObjectPtr InFunction, TSoftObjectPtr InReference) { if(InFunction.IsNull() || InReference.IsNull()) { return; } if(FRigVMFunctionReferenceArray* ReferenceEntry = FunctionReferences.Find(InFunction)) { if(!ReferenceEntry->FunctionReferences.Contains(InReference)) { return; } Modify(); ReferenceEntry->FunctionReferences.Remove(InReference); MarkPackageDirty(); } } void URigVMBuildData::ClearInvalidReferences() { if (bIsRunningUnitTest) { return; } Modify(); // check each function's each reference int32 NumRemoved = 0; for (TTuple, FRigVMFunctionReferenceArray>& FunctionReferenceInfo : FunctionReferences) { FRigVMFunctionReferenceArray* ReferencesEntry = &FunctionReferenceInfo.Value; static FString sTransientPackagePrefix; if(sTransientPackagePrefix.IsEmpty()) { sTransientPackagePrefix = GetTransientPackage()->GetPathName(); } static const FString sTempPrefix = TEXT("/Temp/"); NumRemoved += ReferencesEntry->FunctionReferences.RemoveAll([](TSoftObjectPtr Referencer) { // ignore keys / references within the transient package const FString ReferencerString = Referencer.ToString(); return ReferencerString.StartsWith(sTransientPackagePrefix) || ReferencerString.StartsWith(sTempPrefix); }); } if (NumRemoved > 0) { MarkPackageDirty(); } }