void UK2Node_FunctionEntry::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema(); UEdGraphPin* OldStartExecPin = nullptr; if(Pins[0]->LinkedTo.Num()) { OldStartExecPin = Pins[0]->LinkedTo[0]; } UEdGraphPin* LastActiveOutputPin = Pins[0]; // Only look for FunctionEntry nodes who were duplicated and have a source object if ( UK2Node_FunctionEntry* OriginalNode = Cast<UK2Node_FunctionEntry>(CompilerContext.MessageLog.FindSourceObject(this)) ) { check(OriginalNode->GetOuter()); // Find the associated UFunction UFunction* Function = FindField<UFunction>(CompilerContext.Blueprint->SkeletonGeneratedClass, *OriginalNode->GetOuter()->GetName()); for (TFieldIterator<UProperty> It(Function); It; ++It) { if (const UProperty* Property = *It) { for (auto& LocalVar : LocalVariables) { if (LocalVar.VarName == Property->GetFName() && !LocalVar.DefaultValue.IsEmpty()) { // Add a variable set node for the local variable and hook it up immediately following the entry node or the last added local variable UK2Node_VariableSet* VariableSetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableSet>(this, SourceGraph); VariableSetNode->SetFromProperty(Property, false); Schema->ConfigureVarNode(VariableSetNode, LocalVar.VarName, Function, CompilerContext.Blueprint); VariableSetNode->AllocateDefaultPins(); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(VariableSetNode, this); if(UEdGraphPin* SetPin = VariableSetNode->FindPin(Property->GetName())) { if(LocalVar.VarType.bIsArray) { TSharedPtr<FStructOnScope> StructData = MakeShareable(new FStructOnScope(Function)); FBlueprintEditorUtils::PropertyValueFromString(Property, LocalVar.DefaultValue, StructData->GetStructMemory()); // Create a Make Array node to setup the array's defaults UK2Node_MakeArray* MakeArray = CompilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(this, SourceGraph); MakeArray->AllocateDefaultPins(); MakeArray->GetOutputPin()->MakeLinkTo(SetPin); MakeArray->PostReconstructNode(); const UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property); check(ArrayProperty); FScriptArrayHelper_InContainer ArrayHelper(ArrayProperty, StructData->GetStructMemory()); FScriptArrayHelper_InContainer DefaultArrayHelper(ArrayProperty, StructData->GetStructMemory()); uint8* StructDefaults = NULL; UStructProperty* StructProperty = dynamic_cast<UStructProperty*>(ArrayProperty->Inner); if ( StructProperty != NULL ) { checkSlow(StructProperty->Struct); StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize()); StructProperty->InitializeValue(StructDefaults); } // Go through each element in the array to set the default value for( int32 ArrayIndex = 0 ; ArrayIndex < ArrayHelper.Num() ; ArrayIndex++ ) { uint8* PropData = ArrayHelper.GetRawPtr(ArrayIndex); // Always use struct defaults if the inner is a struct, for symmetry with the import of array inner struct defaults uint8* PropDefault = ( StructProperty != NULL ) ? StructDefaults : ( ( StructData->GetStructMemory() && DefaultArrayHelper.Num() > ArrayIndex ) ? DefaultArrayHelper.GetRawPtr(ArrayIndex) : NULL ); // Retrieve the element's default value FString DefaultValue; FBlueprintEditorUtils::PropertyValueToString(ArrayProperty->Inner, PropData, DefaultValue); if(ArrayIndex > 0) { MakeArray->AddInputPin(); } // Add one to the index for the pin to set the default on to skip the output pin Schema->TrySetDefaultValue(*MakeArray->Pins[ArrayIndex + 1], DefaultValue); } } else { // Set the default value Schema->TrySetDefaultValue(*SetPin, LocalVar.DefaultValue); } } LastActiveOutputPin->BreakAllPinLinks(); LastActiveOutputPin->MakeLinkTo(VariableSetNode->Pins[0]); LastActiveOutputPin = VariableSetNode->Pins[1]; } } } } // Finally, hook up the last node to the old node the function entry node was connected to if(OldStartExecPin) { LastActiveOutputPin->MakeLinkTo(OldStartExecPin); } } }
/** * Creates new copies of components * * @param Data pointer to the address of the instanced object referenced by this UComponentProperty * @param DefaultData pointer to the address of the default value of the instanced object referenced by this UComponentProperty * @param Owner the object that contains this property's data * @param InstanceGraph contains the mappings of instanced objects and components to their templates */ void UArrayProperty::InstanceSubobjects( void* Data, void const* DefaultData, UObject* Owner, FObjectInstancingGraph* InstanceGraph ) { if( Data && Inner->ContainsInstancedObjectProperty()) { FScriptArrayHelper ArrayHelper(this, Data); FScriptArrayHelper DefaultArrayHelper(this, DefaultData); for( int32 ElementIndex = 0; ElementIndex < ArrayHelper.Num(); ElementIndex++ ) { uint8* DefaultValue = (DefaultData && ElementIndex < DefaultArrayHelper.Num()) ? DefaultArrayHelper.GetRawPtr(ElementIndex) : NULL; Inner->InstanceSubobjects( ArrayHelper.GetRawPtr(ElementIndex), DefaultValue, Owner, InstanceGraph ); } } }
void UArrayProperty::ExportTextItem( FString& ValueStr, const void* PropertyValue, const void* DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope ) const { checkSlow(Inner); FScriptArrayHelper ArrayHelper(this, PropertyValue); FScriptArrayHelper DefaultArrayHelper(this, DefaultValue); uint8* StructDefaults = NULL; UStructProperty* StructProperty = Cast<UStructProperty>(Inner); if ( StructProperty != NULL ) { checkSlow(StructProperty->Struct); StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize()); StructProperty->InitializeValue(StructDefaults); } const bool bReadableForm = (0 != (PPF_BlueprintDebugView & PortFlags)); int32 Count = 0; for( int32 i=0; i<ArrayHelper.Num(); i++ ) { ++Count; if(!bReadableForm) { if ( Count == 1 ) { ValueStr += TCHAR('('); } else { ValueStr += TCHAR(','); } } else { if(Count > 1) { ValueStr += TCHAR('\n'); } ValueStr += FString::Printf(TEXT("[%i] "), i); } uint8* PropData = ArrayHelper.GetRawPtr(i); uint8* PropDefault = (DefaultValue && DefaultArrayHelper.Num() > i) ? DefaultArrayHelper.GetRawPtr(i) : StructDefaults; // Do not re-export duplicate data from superclass when exporting to .int file if ( (PortFlags & PPF_LocalizedOnly) != 0 && Inner->Identical(PropData, PropDefault) ) { continue; } Inner->ExportTextItem( ValueStr, PropData, PropDefault, Parent, PortFlags|PPF_Delimited, ExportRootScope ); } if ((Count > 0) && !bReadableForm) { ValueStr += TEXT(")"); } if (StructDefaults) { StructProperty->DestroyValue(StructDefaults); FMemory::Free(StructDefaults); } }
void UArrayProperty::ExportTextItem( FString& ValueStr, const void* PropertyValue, const void* DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope ) const { checkSlow(Inner); if (0 != (PortFlags & PPF_ExportCpp)) { FString ExtendedTypeText; FString TypeText = GetCPPType(&ExtendedTypeText, EPropertyExportCPPFlags::CPPF_BlueprintCppBackend); ValueStr += FString::Printf(TEXT("%s%s()"), *TypeText, *ExtendedTypeText); return; } FScriptArrayHelper ArrayHelper(this, PropertyValue); FScriptArrayHelper DefaultArrayHelper(this, DefaultValue); uint8* StructDefaults = NULL; UStructProperty* StructProperty = dynamic_cast<UStructProperty*>(Inner); if ( StructProperty != NULL ) { checkSlow(StructProperty->Struct); StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize()); StructProperty->InitializeValue(StructDefaults); } const bool bReadableForm = (0 != (PPF_BlueprintDebugView & PortFlags)); int32 Count = 0; for( int32 i=0; i<ArrayHelper.Num(); i++ ) { ++Count; if(!bReadableForm) { if ( Count == 1 ) { ValueStr += TCHAR('('); } else { ValueStr += TCHAR(','); } } else { if(Count > 1) { ValueStr += TCHAR('\n'); } ValueStr += FString::Printf(TEXT("[%i] "), i); } uint8* PropData = ArrayHelper.GetRawPtr(i); // Always use struct defaults if the inner is a struct, for symmetry with the import of array inner struct defaults uint8* PropDefault = ( StructProperty != NULL ) ? StructDefaults : ( ( DefaultValue && DefaultArrayHelper.Num() > i ) ? DefaultArrayHelper.GetRawPtr(i) : NULL ); Inner->ExportTextItem( ValueStr, PropData, PropDefault, Parent, PortFlags|PPF_Delimited, ExportRootScope ); } if ((Count > 0) && !bReadableForm) { ValueStr += TEXT(")"); } if (StructDefaults) { StructProperty->DestroyValue(StructDefaults); FMemory::Free(StructDefaults); } }