void UK2Node_SpawnActorFromClass::CreatePinsForClass(UClass* InClass, TArray<UEdGraphPin*>& OutClassPins) { check(InClass != NULL); const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); const UObject* const ClassDefaultObject = InClass->GetDefaultObject(false); for (TFieldIterator<UProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; UClass* PropertyClass = CastChecked<UClass>(Property->GetOuter()); const bool bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance); if( bIsExposedToSpawn && !Property->HasAnyPropertyFlags(CPF_Parm) && bIsSettableExternally && Property->HasAllPropertyFlags(CPF_BlueprintVisible) && !bIsDelegate && (NULL == FindPin(Property->GetName()) ) ) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); const bool bPinGood = (Pin != NULL) && K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType); OutClassPins.Add(Pin); if (ClassDefaultObject && Pin != NULL && K2Schema->PinDefaultValueIsEditable(*Pin)) { FString DefaultValueAsString; const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString); check( bDefaultValueSet ); K2Schema->TrySetDefaultValue(*Pin, DefaultValueAsString); } // Copy tooltip from the property. if (Pin != nullptr) { K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip); } } } // Change class of output pin UEdGraphPin* ResultPin = GetResultPin(); ResultPin->PinType.PinSubCategoryObject = InClass; }
void UK2Node_AddComponent::AllocatePinsForExposedVariables() { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); const UActorComponent* TemplateComponent = GetTemplateFromNode(); const UClass* ComponentClass = TemplateComponent ? TemplateComponent->GetClass() : nullptr; if (ComponentClass != nullptr) { const UObject* ClassDefaultObject = ComponentClass ? ComponentClass->ClassDefaultObject : nullptr; for (TFieldIterator<UProperty> PropertyIt(ComponentClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; const bool bNotDelegate = !Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsVisible = Property->HasAllPropertyFlags(CPF_BlueprintVisible); const bool bNotParam = !Property->HasAllPropertyFlags(CPF_Parm); if(bNotDelegate && bIsExposedToSpawn && bIsVisible && bNotParam) { FEdGraphPinType PinType; K2Schema->ConvertPropertyToPinType(Property, /*out*/ PinType); const bool bIsUnique = (NULL == FindPin(Property->GetName())); if (K2Schema->FindSetVariableByNameFunction(PinType) && bIsUnique) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); Pin->PinType = PinType; bHasExposedVariable = true; if ((ClassDefaultObject != nullptr) && K2Schema->PinDefaultValueIsEditable(*Pin)) { FString DefaultValueAsString; const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString); check(bDefaultValueSet); K2Schema->TrySetDefaultValue(*Pin, DefaultValueAsString); } // Copy tooltip from the property. K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip); } } } } // Hide transform and attachment pins if it is not a scene component const bool bHideTransformPins = (ComponentClass != nullptr) ? !ComponentClass->IsChildOf(USceneComponent::StaticClass()) : false; UEdGraphPin* ManualAttachmentPin = GetManualAttachmentPin(); ManualAttachmentPin->SafeSetHidden(bHideTransformPins); UEdGraphPin* TransformPin = GetRelativeTransformPin(); TransformPin->SafeSetHidden(bHideTransformPins); }
void UK2Node_SpawnActor::CreatePinsForClass(UClass* InClass) { check(InClass != NULL); const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); for (TFieldIterator<UProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; UClass* PropertyClass = CastChecked<UClass>(Property->GetOuter()); const bool bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance); if( bIsExposedToSpawn && !Property->HasAnyPropertyFlags(CPF_Parm) && bIsSettableExternally && Property->HasAllPropertyFlags(CPF_BlueprintVisible) && !bIsDelegate ) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); const bool bPinGood = (Pin != NULL) && K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType); } } // Change class of output pin UEdGraphPin* ResultPin = GetResultPin(); ResultPin->PinType.PinSubCategoryObject = InClass; }
static void CheckOutputsParametersInDelegateSignature(const UFunction* SignatureFunc, const UK2Node * DelegateNode, FCompilerResultsLog& MessageLog) { for (TFieldIterator<UProperty> PropIt(SignatureFunc); PropIt && (PropIt->PropertyFlags & CPF_Parm); ++PropIt) { UProperty* FuncParam = *PropIt; if (FuncParam->HasAllPropertyFlags(CPF_OutParm) && !FuncParam->HasAllPropertyFlags(CPF_ConstParm)) { const bool bIsArray = FuncParam->IsA<UArrayProperty>(); // array is always passed by reference, see FKismetCompilerContext::CreatePropertiesFromList const FString MessageStr = FString::Printf( *LOCTEXT("DelegatesDontSupportRef", "Event Dispatcher: No value will be return by reference. Parameter '%s'. Node '@@'").ToString(), *FuncParam->GetName()); if (bIsArray) { MessageLog.Note(*MessageStr,DelegateNode); } else { MessageLog.Warning(*MessageStr, DelegateNode); } } } }
bool SGraphPinLiveEditVar::IsPropertyPermitedForLiveEditor( UProperty &Property ) { const bool bIsDelegate = Property.IsA(UMulticastDelegateProperty::StaticClass()); //YES (must have all) uint64 MustHaveFlags = CPF_Edit; //NO (must not have any) uint64 MustNotHaveFlags = CPF_BlueprintReadOnly | CPF_DisableEditOnInstance | CPF_EditConst | CPF_Parm; if ( !Property.HasAllPropertyFlags(MustHaveFlags) ) return false; if ( Property.HasAnyPropertyFlags(MustNotHaveFlags) ) return false; if ( bIsDelegate ) return false; return true; }
void RegisterDelegateNet(FKismetFunctionContext& Context, UK2Node_DelegateSet* DelegateNode) { check(DelegateNode); UEdGraphPin* DelegatePin = DelegateNode->GetDelegateOwner(); check(DelegatePin); // Find the property on the specified scope UProperty* BoundProperty = NULL; for (TFieldIterator<UProperty> It(DelegateNode->DelegatePropertyClass, EFieldIteratorFlags::IncludeSuper); It; ++It) { UProperty* Prop = *It; if( Prop->GetFName() == DelegateNode->DelegatePropertyName ) { check(Prop->HasAllPropertyFlags(CPF_BlueprintAssignable)); BoundProperty = Prop; break; } } // Create a term for this property if( BoundProperty != NULL ) { FBPTerminal* Term = new(Context.VariableReferences) FBPTerminal(); Term->CopyFromPin(DelegatePin, DelegatePin->PinName); Term->AssociatedVarProperty = BoundProperty; Context.NetMap.Add(DelegatePin, Term); // Find the context for this term (the object owning the delegate property) FBPTerminal** pContextTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(DelegatePin)); if( pContextTerm ) { Term->Context = *pContextTerm; } else { CompilerContext.MessageLog.Error(*FString(*LOCTEXT("FindDynamicallyBoundDelegate_Error", "Couldn't find target for dynamically bound delegate node @@").ToString()), DelegateNode); } } }
// Finds a property by name, starting in the specified scope, returning NULL if it's not found UProperty* FKismetCompilerUtilities::FindNamedPropertyInScope(UStruct* Scope, FName PropertyName) { while (Scope != NULL) { for (TFieldIterator<UProperty> It(Scope, EFieldIteratorFlags::IncludeSuper); It; ++It) { UProperty* Property = *It; // If we match by name, and var is not deprecated... if (Property->GetFName() == PropertyName && !Property->HasAllPropertyFlags(CPF_Deprecated)) { return Property; } } // Functions don't automatically check their class when using a field iterator UFunction* Function = Cast<UFunction>(Scope); Scope = (Function != NULL) ? Cast<UStruct>(Function->GetOuter()) : NULL; } return NULL; }
UProperty* UK2Node_Variable::GetPropertyForVariable() const { const FName VarName = GetVarName(); UEdGraphPin* VariablePin = FindPin(GetVarNameString()); UProperty* VariableProperty = nullptr; // Need to look at parent Blueprint's skeleton classes to see if the variable property can resolve there. UClass* CurrentGeneratedClass = GetBlueprint()->GeneratedClass; while(CurrentGeneratedClass && VariableProperty == nullptr) { if(UBlueprint* CurrentBlueprint = Cast<UBlueprint>(CurrentGeneratedClass->ClassGeneratedBy)) { VariableProperty = VariableReference.ResolveMember<UProperty>(CurrentBlueprint->SkeletonGeneratedClass); CurrentGeneratedClass = CurrentBlueprint->ParentClass; } else { break; } } // if the variable has been deprecated, don't use it if(VariableProperty != NULL) { if (VariableProperty->HasAllPropertyFlags(CPF_Deprecated)) { VariableProperty = NULL; } // If the variable has been remapped update the pin else if (VariablePin && VarName != GetVarName()) { VariablePin->PinName = GetVarNameString(); } } return VariableProperty; }
UProperty* UK2Node_Variable::GetPropertyForVariable() const { const FName VarName = GetVarName(); UEdGraphPin* VariablePin = FindPin(GetVarNameString()); UProperty* VariableProperty = VariableReference.ResolveMember<UProperty>(GetBlueprintClassFromNode()); // if the variable has been deprecated, don't use it if(VariableProperty != NULL) { if (VariableProperty->HasAllPropertyFlags(CPF_Deprecated)) { VariableProperty = NULL; } // If the variable has been remapped update the pin else if (VariablePin && VarName != GetVarName()) { VariablePin->PinName = GetVarNameString(); } } return VariableProperty; }
void UK2Node_LatentAbilityCall::CreatePinsForClass(UClass* InClass) { check(InClass != NULL); const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); const UObject* const ClassDefaultObject = InClass->GetDefaultObject(false); SpawnParmPins.Empty(); // Tasks can hide spawn parameters by doing meta = (HideSpawnParms="PropertyA,PropertyB") // (For example, hide Instigator in situations where instigator is not relevant to your task) TArray<FString> IgnorePropertyList; { UFunction* ProxyFunction = ProxyFactoryClass->FindFunctionByName(ProxyFactoryFunctionName); FString IgnorePropertyListStr = ProxyFunction->GetMetaData(FName(TEXT("HideSpawnParms"))); if (!IgnorePropertyListStr.IsEmpty()) { IgnorePropertyListStr.ParseIntoArray(IgnorePropertyList, TEXT(","), true); } } for (TFieldIterator<UProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; UClass* PropertyClass = CastChecked<UClass>(Property->GetOuter()); const bool bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance); if (bIsExposedToSpawn && !Property->HasAnyPropertyFlags(CPF_Parm) && bIsSettableExternally && Property->HasAllPropertyFlags(CPF_BlueprintVisible) && !bIsDelegate && !IgnorePropertyList.Contains(Property->GetName()) && (FindPin(Property->GetName()) == nullptr) ) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); const bool bPinGood = (Pin != NULL) && K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType); SpawnParmPins.Add(Pin); if (ClassDefaultObject && Pin && K2Schema->PinDefaultValueIsEditable(*Pin)) { FString DefaultValueAsString; const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString); check(bDefaultValueSet); K2Schema->TrySetDefaultValue(*Pin, DefaultValueAsString); } // Copy tooltip from the property. if (Pin != nullptr) { K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip); } } } }
void SPropertyEditorAsset::Construct( const FArguments& InArgs, const TSharedPtr<FPropertyEditor>& InPropertyEditor ) { PropertyEditor = InPropertyEditor; PropertyHandle = InArgs._PropertyHandle; OnSetObject = InArgs._OnSetObject; OnShouldFilterAsset = InArgs._OnShouldFilterAsset; UProperty* Property = nullptr; if(PropertyEditor.IsValid()) { Property = PropertyEditor->GetPropertyNode()->GetProperty(); UObjectPropertyBase* ObjectProperty = Cast<UObjectPropertyBase>(Property); check(ObjectProperty); bAllowClear = !(Property->PropertyFlags & CPF_NoClear); ObjectClass = ObjectProperty->PropertyClass; bIsActor = ObjectProperty->PropertyClass->IsChildOf( AActor::StaticClass() ); } else { bAllowClear = InArgs._AllowClear; ObjectPath = InArgs._ObjectPath; ObjectClass = InArgs._Class; bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() ); if (PropertyHandle.IsValid() && PropertyHandle->IsValidHandle()) { Property = PropertyHandle->GetProperty(); } else { CustomClassFilters.Add(ObjectClass); } } // Account for the allowed classes specified in the property metadata if (Property) { FString ClassFilterString; if (UArrayProperty* ArrayParent = Cast<UArrayProperty>(Property->GetOuter())) { ClassFilterString = ArrayParent->GetMetaData("AllowedClasses"); } else { ClassFilterString = Property->GetMetaData("AllowedClasses"); } if (ClassFilterString.IsEmpty()) { CustomClassFilters.Add(ObjectClass); } else { TArray<FString> CustomClassFilterNames; ClassFilterString.ParseIntoArray(CustomClassFilterNames, TEXT(","), true); for (auto It = CustomClassFilterNames.CreateConstIterator(); It; ++It) { const FString& ClassName = *It; UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName); if (!Class) { Class = LoadObject<UClass>(nullptr, *ClassName); } if (Class) { // If the class is an interface, expand it to be all classes in memory that implement the class. if (Class->HasAnyClassFlags(CLASS_Interface)) { for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* const ClassWithInterface = (*ClassIt); if (ClassWithInterface->ImplementsInterface(Class)) { CustomClassFilters.Add(ClassWithInterface); } } } else { CustomClassFilters.Add(Class); } } } } } if (InArgs._NewAssetFactories.IsSet()) { NewAssetFactories = InArgs._NewAssetFactories.GetValue(); } else if (CustomClassFilters.Num() > 1 || !CustomClassFilters.Contains(UObject::StaticClass())) { NewAssetFactories = PropertyCustomizationHelpers::GetNewAssetFactoriesForClasses(CustomClassFilters); } TSharedPtr<SHorizontalBox> ValueContentBox = NULL; ChildSlot [ SNew( SAssetDropTarget ) .OnIsAssetAcceptableForDrop( this, &SPropertyEditorAsset::OnAssetDraggedOver ) .OnAssetDropped( this, &SPropertyEditorAsset::OnAssetDropped ) [ SAssignNew( ValueContentBox, SHorizontalBox ) ] ]; TAttribute<bool> IsEnabledAttribute(this, &SPropertyEditorAsset::CanEdit); TAttribute<FText> TooltipAttribute(this, &SPropertyEditorAsset::OnGetToolTip); if (Property && Property->HasAllPropertyFlags(CPF_DisableEditOnTemplate)) { // There are some cases where editing an Actor Property is not allowed, such as when it is contained within a struct or a CDO TArray<UObject*> ObjectList; PropertyEditor->GetPropertyHandle()->GetOuterObjects(ObjectList); // If there is no objects, that means we must have a struct asset managing this property if (ObjectList.Num() == 0) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplate", "Editing this value in structure's defaults is not allowed")); } else { // Go through all the found objects and see if any are a CDO, we can't set an actor in a CDO default. for (UObject* Obj : ObjectList) { if (Obj->HasAllFlags(RF_ClassDefaultObject)) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplateTooltip", "Editing this value in a Class Default Object is not allowed")); break; } } } } AssetComboButton = SNew(SComboButton) .ToolTipText(TooltipAttribute) .ButtonStyle( FEditorStyle::Get(), "PropertyEditor.AssetComboStyle" ) .ForegroundColor(FEditorStyle::GetColor("PropertyEditor.AssetName.ColorAndOpacity")) .OnGetMenuContent( this, &SPropertyEditorAsset::OnGetMenuContent ) .OnMenuOpenChanged( this, &SPropertyEditorAsset::OnMenuOpenChanged ) .IsEnabled( IsEnabledAttribute ) .ContentPadding(2.0f) .ButtonContent() [ // Show the name of the asset or actor SNew(STextBlock) .TextStyle( FEditorStyle::Get(), "PropertyEditor.AssetClass" ) .Font( FEditorStyle::GetFontStyle( PropertyEditorConstants::PropertyFontStyle ) ) .Text(this,&SPropertyEditorAsset::OnGetAssetName) ]; TSharedRef<SHorizontalBox> ButtonBox = SNew( SHorizontalBox ); TSharedPtr<SVerticalBox> CustomContentBox; if( ShouldDisplayThumbnail(InArgs) ) { FObjectOrAssetData Value; GetValue( Value ); AssetThumbnail = MakeShareable( new FAssetThumbnail( Value.AssetData, InArgs._ThumbnailSize.X, InArgs._ThumbnailSize.Y, InArgs._ThumbnailPool ) ); ValueContentBox->AddSlot() .Padding( 0.0f, 0.0f, 2.0f, 0.0f ) .AutoWidth() [ SAssignNew( ThumbnailBorder, SBorder ) .Padding( 5.0f ) .BorderImage( this, &SPropertyEditorAsset::GetThumbnailBorder ) .OnMouseDoubleClick( this, &SPropertyEditorAsset::OnAssetThumbnailDoubleClick ) [ SNew( SBox ) .ToolTipText(TooltipAttribute) .WidthOverride( InArgs._ThumbnailSize.X ) .HeightOverride( InArgs._ThumbnailSize.Y ) [ AssetThumbnail->MakeThumbnailWidget() ] ] ]; ValueContentBox->AddSlot() [ SNew( SBox ) .VAlign( VAlign_Center ) [ SAssignNew( CustomContentBox, SVerticalBox ) + SVerticalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SVerticalBox::Slot() .AutoHeight() .Padding( 0.0f, 2.0f, 4.0f, 2.0f ) [ ButtonBox ] ] ]; } else { ValueContentBox->AddSlot() [ SAssignNew( CustomContentBox, SVerticalBox ) +SVerticalBox::Slot() .VAlign( VAlign_Center ) [ SNew( SHorizontalBox ) + SHorizontalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SHorizontalBox::Slot() .AutoWidth() .Padding( 4.f, 0.f ) [ ButtonBox ] ] ]; } if( InArgs._CustomContentSlot.Widget != SNullWidget::NullWidget ) { CustomContentBox->AddSlot() .VAlign( VAlign_Center ) .Padding( FMargin( 0.0f, 2.0f ) ) [ InArgs._CustomContentSlot.Widget ]; } if( !bIsActor && InArgs._DisplayUseSelected ) { ButtonBox->AddSlot() .VAlign(VAlign_Center) .AutoWidth() .Padding( 2.0f, 0.0f ) [ PropertyCustomizationHelpers::MakeUseSelectedButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnUse ), FText(), IsEnabledAttribute ) ]; } if( InArgs._DisplayBrowse ) { ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ PropertyCustomizationHelpers::MakeBrowseButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnBrowse ), TAttribute<FText>( this, &SPropertyEditorAsset::GetOnBrowseToolTip ) ) ]; } if( bIsActor ) { TSharedRef<SWidget> ActorPicker = PropertyCustomizationHelpers::MakeInteractiveActorPicker( FOnGetAllowedClasses::CreateSP(this, &SPropertyEditorAsset::OnGetAllowedClasses), FOnShouldFilterActor(), FOnActorSelected::CreateSP( this, &SPropertyEditorAsset::OnActorSelected ) ); ActorPicker->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ActorPicker ]; } if( InArgs._ResetToDefaultSlot.Widget != SNullWidget::NullWidget ) { TSharedRef<SWidget> ResetToDefaultWidget = InArgs._ResetToDefaultSlot.Widget; ResetToDefaultWidget->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 4.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ResetToDefaultWidget ]; } }