void USkookumScriptListener::add_dynamic_function(FName callback_name, UClass * callback_owner_class_p, FNativeFuncPtr exec_p) { // Find the function UFunction * function_p = StaticClass()->FindFunctionByName(callback_name, EIncludeSuperFlag::ExcludeSuper); if (!function_p) { // Duplicate the signature function object // Find callback event object on owner class UMulticastDelegateProperty * event_property_p = CastChecked<UMulticastDelegateProperty>(callback_owner_class_p->FindPropertyByName(callback_name)); // Duplicate it FObjectDuplicationParameters dupe_parameters(event_property_p->SignatureFunction, StaticClass()); //Parameters.CreatedObjects = &DuplicatedObjectList; dupe_parameters.DestName = callback_name; function_p = Cast<UFunction>(StaticDuplicateObjectEx(dupe_parameters)); // Adjust parameters function_p->FunctionFlags |= FUNC_Public | FUNC_BlueprintCallable | FUNC_Native; function_p->SetNativeFunc(exec_p); function_p->StaticLink(true); for (TFieldIterator<UProperty> param_it(function_p); param_it; ++param_it) { // Callback parameters are always inputs (*param_it)->PropertyFlags &= ~CPF_OutParm; } // Make method known to its class function_p->Next = StaticClass()->Children; StaticClass()->Children = function_p; StaticClass()->AddFunctionToFunctionMap(function_p, function_p->GetFName()); } }
// Clones (deep copies) a UEdGraph, including all of it's nodes and pins and their links, // maintaining a mapping from the clone to the source nodes (even across multiple clonings) UEdGraph* FEdGraphUtilities::CloneGraph(UEdGraph* InSource, UObject* NewOuter, FCompilerResultsLog* MessageLog, bool bCloningForCompile) { // Duplicate the graph, keeping track of what was duplicated TMap<UObject*, UObject*> DuplicatedObjectList; UObject* UseOuter = (NewOuter != NULL) ? NewOuter : GetTransientPackage(); FObjectDuplicationParameters Parameters(InSource, UseOuter); Parameters.CreatedObjects = &DuplicatedObjectList; if (bCloningForCompile || (NewOuter == NULL)) { Parameters.ApplyFlags |= RF_Transient; } UEdGraph* ClonedGraph = CastChecked<UEdGraph>(StaticDuplicateObjectEx(Parameters)); // Store backtrack links from each duplicated object to the original source object if (MessageLog != NULL) { for (TMap<UObject*, UObject*>::TIterator It(DuplicatedObjectList); It; ++It) { UObject* const Source = It.Key(); UObject* const Dest = It.Value(); MessageLog->NotifyIntermediateObjectCreation(Dest, Source); } } return ClonedGraph; }
/** * Uses test maps in Engine and/or game content folder which are populated with a few blueprint instances * See InstanceTestMaps entries in the [Automation.Blueprint] config sections * For all blueprint instances in the map: * Duplicates the instance * Compares the duplicated instance properties to the original instance properties */ bool FBlueprintInstancesTest::RunTest(const FString& InParameters) { FBlueprintAutomationTestUtilities::LoadMap(InParameters); // Pause before running test ADD_LATENT_AUTOMATION_COMMAND(FDelayLatentCommand(2.f)); // Grab BP instances from map TSet<AActor*> BlueprintInstances; for ( FActorIterator It(GWorld); It; ++It ) { AActor* Actor = *It; UClass* ActorClass = Actor->GetClass(); if (ActorClass->ClassGeneratedBy && ActorClass->ClassGeneratedBy->IsA( UBlueprint::StaticClass() ) ) { BlueprintInstances.Add(Actor); } } bool bPropertiesMatch = true; FCompilerResultsLog ResultLog; TSet<UPackage*> PackagesUserRefusedToFullyLoad; ObjectTools::FPackageGroupName PGN; for (auto BpIter = BlueprintInstances.CreateIterator(); BpIter; ++BpIter ) { AActor* BPInstance = *BpIter; UObject* BPInstanceOuter = BPInstance ? BPInstance->GetOuter() : NULL; TMap<FString,FString> BPNativePropertyValues; BPInstance->GetNativePropertyValues(BPNativePropertyValues); // Grab the package and save out its dirty state UPackage* ActorPackage = BPInstance->GetOutermost(); FBlueprintAutomationTestUtilities::FPackageCleaner Cleaner(ActorPackage); // Use this when duplicating the object to keep a list of everything that was duplicated //TMap<UObject*, UObject*> DuplicatedObjectList; FObjectDuplicationParameters Parameters(BPInstance, BPInstanceOuter); //Parameters.CreatedObjects = &DuplicatedObjectList; Parameters.DestName = MakeUniqueObjectName( BPInstanceOuter, AActor::StaticClass(), BPInstance->GetFName() ); // Duplicate the object AActor* ClonedInstance = Cast<AActor>(StaticDuplicateObjectEx(Parameters)); if (!FBlueprintAutomationTestUtilities::CompareObjects(BPInstance, ClonedInstance, ResultLog)) { bPropertiesMatch = false; break; } // Ensure we can't save package in editor FBlueprintAutomationTestUtilities::DontSavePackage(ActorPackage); } // Start a new map for now // @todo find a way return to previous map thats a 100% reliably GEditor->CreateNewMapForEditing(); ADD_LATENT_AUTOMATION_COMMAND(FDelayLatentCommand(2.f)); return bPropertiesMatch; }