// Copyright Epic Games, Inc. All Rights Reserved. #include "MVVMBlueprintViewBinding.h" #include "Bindings/MVVMConversionFunctionHelper.h" #include "K2Node_CallFunction.h" #include "MVVMBlueprintView.h" #include "MVVMWidgetBlueprintExtension_View.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(MVVMBlueprintViewBinding) FName FMVVMBlueprintViewBinding::GetFName() const { return *BindingId.ToString(EGuidFormats::DigitsWithHyphensLower); } namespace UE::MVVM::Private { void AppendViewModelPathString(const UMVVMBlueprintView* BlueprintView, const FMVVMBlueprintPropertyPath& ViewModelPath, FStringBuilderBase& PathBuilder) { if (ViewModelPath.IsEmpty()) { PathBuilder << TEXT(""); return; } const FMVVMBlueprintViewModelContext* ViewModel = BlueprintView != nullptr ? BlueprintView->FindViewModel(ViewModelPath.GetViewModelId()) : nullptr; if (ViewModel) { PathBuilder << ViewModel->GetDisplayName().ToString(); } else { PathBuilder << TEXT(""); } const FString PropertyPath = ViewModelPath.GetBasePropertyPath(); if (!PropertyPath.IsEmpty()) { PathBuilder << TEXT("."); PathBuilder << PropertyPath; } } FString GetBindingViewModelName(const UWidgetBlueprint* WidgetBlueprint, const FMVVMBlueprintViewBinding& Binding) { UMVVMWidgetBlueprintExtension_View* ExtensionView = UMVVMWidgetBlueprintExtension_View::GetExtension(WidgetBlueprint); UMVVMBlueprintView* BlueprintView = ExtensionView->GetBlueprintView(); TStringBuilder<256> NameBuilder; if (UEdGraph* Graph = ConversionFunctionHelper::GetGraph(WidgetBlueprint, Binding, true)) { if (const UK2Node_CallFunction* CallFunctionNode = ConversionFunctionHelper::GetFunctionNode(Graph)) { NameBuilder << CallFunctionNode->GetFunctionName(); NameBuilder << TEXT("("); bool bFirst = true; for (const UEdGraphPin* Pin : CallFunctionNode->Pins) { if (Pin->PinName == UEdGraphSchema_K2::PN_Self || Pin->Direction != EGPD_Input) { continue; } if (!bFirst) { NameBuilder << TEXT(", "); } FMVVMBlueprintPropertyPath ArgumentPath = ConversionFunctionHelper::GetPropertyPathForArgument(WidgetBlueprint, CallFunctionNode, Pin->GetFName(), true); if (!ArgumentPath.IsEmpty()) { AppendViewModelPathString(BlueprintView, ArgumentPath, NameBuilder); } else { NameBuilder << Pin->GetDefaultAsString(); } bFirst = false; } NameBuilder << TEXT(")"); } else { NameBuilder << TEXT(""); } } else if (!Binding.Conversion.SourceToDestinationFunction.GetMemberName().IsNone()) { if (const UFunction* SourceToDestFunction = Binding.Conversion.SourceToDestinationFunction.ResolveMember(WidgetBlueprint->SkeletonGeneratedClass)) { NameBuilder << SourceToDestFunction->GetName(); NameBuilder << TEXT("("); AppendViewModelPathString(BlueprintView, Binding.SourcePath, NameBuilder); NameBuilder << TEXT(")"); } else { NameBuilder << Binding.Conversion.SourceToDestinationFunction.GetMemberName(); NameBuilder << TEXT("()"); } } else if (!Binding.SourcePath.IsEmpty()) { AppendViewModelPathString(BlueprintView, Binding.SourcePath, NameBuilder); } FString Name = NameBuilder.ToString(); if (Name.IsEmpty()) { Name = TEXT(""); } return Name; } void AppendWidgetPathString(const UWidgetBlueprint* WidgetBlueprint, const FMVVMBlueprintPropertyPath& WidgetPath, FStringBuilderBase& PathBuilder) { if (WidgetBlueprint == nullptr || WidgetPath.GetWidgetName().IsNone()) { PathBuilder << TEXT(""); } else if (WidgetBlueprint->GetFName() == WidgetPath.GetWidgetName()) { PathBuilder << TEXT("self"); } else { PathBuilder << WidgetPath.GetWidgetName(); } const FString PropertyPath = WidgetPath.GetBasePropertyPath(); if (!PropertyPath.IsEmpty()) { PathBuilder << TEXT("."); PathBuilder << PropertyPath; } } FString GetBindingWidgetName(const UWidgetBlueprint* WidgetBlueprint, const FMVVMBlueprintViewBinding& Binding) { TStringBuilder<256> NameBuilder; if (UEdGraph* Graph = ConversionFunctionHelper::GetGraph(WidgetBlueprint, Binding, false)) { if (const UK2Node_CallFunction* CallFunctionNode = ConversionFunctionHelper::GetFunctionNode(Graph)) { NameBuilder << CallFunctionNode->GetFunctionName(); NameBuilder << TEXT("("); bool bFirst = true; for (const UEdGraphPin* Pin : CallFunctionNode->Pins) { if (Pin->Direction == EGPD_Input) { if (!bFirst) { NameBuilder << TEXT(", "); } FMVVMBlueprintPropertyPath ArgumentPath = ConversionFunctionHelper::GetPropertyPathForArgument(WidgetBlueprint, CallFunctionNode, Pin->GetFName(), true); if (!ArgumentPath.IsEmpty()) { AppendWidgetPathString(WidgetBlueprint, ArgumentPath, NameBuilder); } else { NameBuilder << Pin->GetDefaultAsString(); } } bFirst = false; } NameBuilder << TEXT(")"); } else { NameBuilder << TEXT(""); } } else if (!Binding.Conversion.DestinationToSourceFunction.GetMemberName().IsNone()) { if (const UFunction* DestToSourceFunction = Binding.Conversion.DestinationToSourceFunction.ResolveMember(WidgetBlueprint->SkeletonGeneratedClass)) { NameBuilder << DestToSourceFunction->GetName(); NameBuilder << TEXT("("); AppendWidgetPathString(WidgetBlueprint, Binding.DestinationPath, NameBuilder); NameBuilder << TEXT(")"); } else { NameBuilder << Binding.Conversion.SourceToDestinationFunction.GetMemberName(); NameBuilder << TEXT("()"); } } else if (!Binding.DestinationPath.IsEmpty()) { AppendWidgetPathString(WidgetBlueprint, Binding.DestinationPath, NameBuilder); } FString Name = NameBuilder.ToString(); if (Name.IsEmpty()) { Name = TEXT(""); } return Name; } } FString FMVVMBlueprintViewBinding::GetDisplayNameString(const UWidgetBlueprint* WidgetBlueprint) const { check(WidgetBlueprint); TStringBuilder<256> NameBuilder; NameBuilder << UE::MVVM::Private::GetBindingWidgetName(WidgetBlueprint, *this); if (BindingType == EMVVMBindingMode::TwoWay) { NameBuilder << TEXT(" <-> "); } else if (UE::MVVM::IsForwardBinding(BindingType)) { NameBuilder << TEXT(" <- "); } else if (UE::MVVM::IsBackwardBinding(BindingType)) { NameBuilder << TEXT(" -> "); } else { NameBuilder << TEXT(" ??? "); // shouldn't happen } NameBuilder << UE::MVVM::Private::GetBindingViewModelName(WidgetBlueprint, *this); return NameBuilder.ToString(); }